diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5385ed1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,80 @@
+### 프로그램 분석
+
+---
+
+**로또 기본 룰**
+
+- 로또의 기본적인 규칙은 45개의 숫자 중에서 6개를 선택하는 방식입니다. 1등에 당첨되기 위해서는 6자리의 숫자가 맞으면 1등에 당첨입니다. 당첨번호 5개 + 보너스 번호 1개에 맞으면 2등이며 보너스 번호는 2등에만 해당됩니다.
+1. 입력한 금액 % 1000 만큼의 로또 개수 발급
+ - 구입한 금액은 저장해야함. → Or 발급 개수를 저장.
+ - 나중에 수익률 계산할 때 사용.
+2. 당첨번호를 입력 받아야함.
+ - 당첨 번호 + 보너스 번호
+3. 발급된 각 로또 번호와 당첨번호를 매칭해서 개수 일치 카운팅
+ - 일치 카운트의 로또 개수 리턴 해아함.
+
+ 상금
+
+ - 5등
+ - 3개 일치 : 5000원
+ - 4등
+ - 4개 일치 : 50000원
+ - 3등
+ - 5개 일치 : 1500000원
+ - 2등
+ - 5개 일치, 보너스 볼 일치 : 30000000원
+ - 1등
+ - 6개 일치 : 20000000000원
+4. 3번 내용 바탕으로 총 수익률 계산.
+
+### 요구사항 분석
+
+---
+
+- 결과 값들에 대해서는 배열 보단 `ArrayList`로 일급 컬렉션으로 관리하기.
+- `JAVA ENUM`을 활용하기 → 상금을 활용하면 좋을 듯??
+- 규칙 3 : 모든 원시값과 문자열을 포장한다.
+- 규칙 5 : 줄여쓰지 않는다.
+- 규칙 8 : 일급 컬렉션을 쓴다.
+ - 배열 대신 `ArrayList`로 결과 값을 일급 컬렉션으로 관리하는 것이 좋음
+
+### 객체 설명
+
+|클래스|역할과 책임|
+|------|---|
+|Money|로또 진행에 필요한 돈을 관리하는 불변 객체.
티켓을 구매, 티켓 구매 가능 여부 판단.|
+|LottoShop|로또 티켓을 발급해주는 객체.
수동 티켓과 자동 로또 티켓 발급.|
+|LottoNumberGenerator|로또 번호를 랜덤으로 발급해주는 객체.
로또 상점에서 발급되는 티켓을 생성해줌.
입력된 숫자를 로또 번호 객체로 변환.|
+|LottoNumber|로또 번호를 관리하는 객체.
로또번호인 1~45 사이 값만 생성할 수 있도록 강제함.|
+|LottoTicket|실제 추첨에 사용될 수 있는 로또 티켓을 관리하는 객체.
로또 게임에 유효한 티켓만 발급될 수 있도록 강제.
로또 티켓을 당첨 번호와 비교하며 당첨 결과를 알려줌.|
+|WinningTicket|당첨 번호(보너스 번호 포함)를 관리하는 객체.|
+|LottoTickets|실제 추첨에 사용될 수 있는 로또 티켓들을 관리하는 객체.
모든 티켓을 당첨 번호와 비교하며 당첨 결과를 알려줌.|
+|LottoRank|당첨 순위에 대한 정보를 담고 있는 열거 객체.|
+|LottoResult|최종 로또 추첨 결과를 가지고 있는 객체.|
+|WinningStatistics| 추첨 결과에 따른 통계량을 구해주는 객체.|
+
+
+
+### 힌트
+
+---
+
+- 로또 자동 생성은 `Collections.shuffle()` 메소드 활용
+- `Collections.sort()` 메소드를 활용해 정렬 가능
+- `ArrayList`의 `Contains()` 메소드를 활용하면 어떤 값이 존재하는지 유무를 판단할 수 있음
+
+
+#### 로또 흐름
+ - 시작! 돈을 넣어라.
+ - 게임에 참여하는 돈을 입력 받음
+ - 돈을 주고, 티켓을 받음.
+ - 자동으로 1000당 한 개씩 반환해줌.
+ - 복권 번호는 1~45번까지 있고 총 6개의 번호를 반환.
+ - 중복번호 없어야 하고, 각 티켓은 Shuffle되서 반환되어야 함
+ - 당첨 결과를 알려줘!
+ - 당첨번호와 보너스 번호가 입력을 받음
+ - 당첨 번호와 보너스 번호는 중복되면 안됨.
+ - 발급받은 티켓에 대한 당첨 결과를 알려줘
+ - 각 티켓별 결과 반환
+ - 당첨결과에 따른 통계량을 계산해서 출력해줘!
+ - 당첨 결과를 계산해주고 출력
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 44e7c4d..1094d7d 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Thu May 21 18:30:01 KST 2020
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/src/main/java/com/javabom/lotto/LottoApplication.java b/src/main/java/com/javabom/lotto/LottoApplication.java
index 13f852e..8cbca84 100644
--- a/src/main/java/com/javabom/lotto/LottoApplication.java
+++ b/src/main/java/com/javabom/lotto/LottoApplication.java
@@ -1,7 +1,35 @@
package com.javabom.lotto;
+import com.javabom.lotto.domain.result.LottoResult;
+import com.javabom.lotto.domain.result.WinningStatistics;
+import com.javabom.lotto.domain.shop.LottoNumbersGenerator;
+import com.javabom.lotto.domain.shop.LottoShop;
+import com.javabom.lotto.domain.ticket.LottoTickets;
+import com.javabom.lotto.domain.ticket.WinningTicket;
+import com.javabom.lotto.domain.vo.Money;
+import com.javabom.lotto.dto.InputDto;
+import com.javabom.lotto.dto.WinningNumbersDto;
+import com.javabom.lotto.dto.WinningStatisticsDto;
+import com.javabom.lotto.view.InputView;
+import com.javabom.lotto.view.OutputView;
+
public class LottoApplication {
public static void main(String[] args) {
+ InputDto inputDto = InputView.askInputMoneyAndManual();
+ LottoShop lottoShop = new LottoShop(new LottoNumbersGenerator());
+
+ LottoTickets manualTickets = lottoShop.buyTicketsByManualInLottoShop(inputDto.getManualNumbers());
+ Money remainMoney = lottoShop.getRemainMoney(manualTickets, inputDto.getMoney());
+ LottoTickets automaticTickets = lottoShop.buyTicketsByAutomaticInLottoShop(remainMoney);
+
+ OutputView.printLotteryTickets(automaticTickets, manualTickets);
+ WinningNumbersDto winningNumbersDto = InputView.askWinningNumbers();
+ WinningTicket winningTicket = new WinningTicket(winningNumbersDto.getWinningNumbers(),
+ winningNumbersDto.getBonusNumber());
+
+ LottoTickets allTickets = manualTickets.joinTickets(automaticTickets);
+ LottoResult lottoResult = allTickets.getLottoResult(winningTicket);
+ OutputView.printWinningStatistics(new WinningStatisticsDto(new WinningStatistics(lottoResult)));
}
}
diff --git a/src/main/java/com/javabom/lotto/domain/result/LottoRank.java b/src/main/java/com/javabom/lotto/domain/result/LottoRank.java
new file mode 100644
index 0000000..e7edac3
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/result/LottoRank.java
@@ -0,0 +1,40 @@
+package com.javabom.lotto.domain.result;
+
+import java.util.Arrays;
+
+public enum LottoRank {
+ FIFTH_PLACE(5000, 3),
+ FOURTH_PLACE(50000, 4),
+ THIRD_PLACE(1500000, 5),
+ SECOND_PLACE(30000000, 5),
+ FIRST_PLACE(2000000000, 6),
+ FAIL(0, 0);
+
+ private int prizeMoney;
+ private int sameCount;
+
+ LottoRank(int prizeMoney, int sameCount) {
+ this.prizeMoney = prizeMoney;
+ this.sameCount = sameCount;
+ }
+
+ public static LottoRank findBySameCount(int sameCount) {
+ return Arrays.stream(LottoRank.values())
+ .filter(rankInfo -> rankInfo.sameCount == sameCount)
+ .findAny()
+ .orElse(FAIL);
+ }
+
+ public static LottoRank findLottoRank(int sameCount, boolean hasBonusNumber) {
+ if (sameCount == 5 && hasBonusNumber) {
+ return LottoRank.SECOND_PLACE;
+ }
+
+ return findBySameCount(sameCount);
+ }
+
+ public int getPrizeMoney() {
+ return prizeMoney;
+ }
+
+}
diff --git a/src/main/java/com/javabom/lotto/domain/result/LottoResult.java b/src/main/java/com/javabom/lotto/domain/result/LottoResult.java
new file mode 100644
index 0000000..c27389a
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/result/LottoResult.java
@@ -0,0 +1,27 @@
+package com.javabom.lotto.domain.result;
+
+import java.util.Collections;
+import java.util.List;
+
+public class LottoResult {
+
+ private final List results;
+
+ public LottoResult(List results) {
+ this.results = results;
+ }
+
+ public int getRankCount(LottoRank rank) {
+ return (int) results.stream()
+ .filter(lottoRank -> lottoRank.equals(rank))
+ .count();
+ }
+
+ public List getResults() {
+ return Collections.unmodifiableList(results);
+ }
+
+ public int size() {
+ return results.size();
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/result/WinningStatistics.java b/src/main/java/com/javabom/lotto/domain/result/WinningStatistics.java
new file mode 100644
index 0000000..28e0aba
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/result/WinningStatistics.java
@@ -0,0 +1,33 @@
+package com.javabom.lotto.domain.result;
+
+import com.javabom.lotto.domain.shop.LottoShop;
+
+public class WinningStatistics {
+
+ private final LottoResult results;
+
+ public WinningStatistics(LottoResult results) {
+ this.results = results;
+ }
+
+ private long calculateRevenue() {
+ long revenue = 0;
+ for (LottoRank result : results.getResults()) {
+ revenue += result.getPrizeMoney();
+ }
+ return revenue;
+ }
+
+ public int calculateProfitRatio() {
+ long revenue = calculateRevenue();
+ return (int) ((revenue / (double) calculateCostMoney()) * 100);
+ }
+
+ private long calculateCostMoney() {
+ return results.size() * LottoShop.TICKET_PRICE.getValue();
+ }
+
+ public LottoResult getResults() {
+ return results;
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/shop/LottoNumbersGenerator.java b/src/main/java/com/javabom/lotto/domain/shop/LottoNumbersGenerator.java
new file mode 100644
index 0000000..4ac8efa
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/shop/LottoNumbersGenerator.java
@@ -0,0 +1,31 @@
+package com.javabom.lotto.domain.shop;
+
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import com.javabom.lotto.domain.ticket.LottoTicket;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class LottoNumbersGenerator {
+
+ private final List lottoNum;
+
+ public LottoNumbersGenerator() {
+ lottoNum = IntStream.rangeClosed(LottoNumber.NUMBER_BEGIN, LottoNumber.NUMBER_END)
+ .mapToObj(LottoNumber::new)
+ .collect(Collectors.toList());
+ }
+
+ public List generate() {
+ Collections.shuffle(lottoNum);
+ return new ArrayList(lottoNum.subList(0, LottoTicket.LOTTO_NUMBER_COUNT)) {
+ };
+ }
+
+ public static List convertToLottoNumbers(List numbers) {
+ return numbers.stream()
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/shop/LottoShop.java b/src/main/java/com/javabom/lotto/domain/shop/LottoShop.java
new file mode 100644
index 0000000..c994f73
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/shop/LottoShop.java
@@ -0,0 +1,57 @@
+package com.javabom.lotto.domain.shop;
+
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import com.javabom.lotto.domain.ticket.LottoTicket;
+import com.javabom.lotto.domain.ticket.LottoTickets;
+import com.javabom.lotto.domain.vo.Money;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class LottoShop {
+
+ public final static Money TICKET_PRICE = new Money(1000);
+ private final LottoNumbersGenerator numberGenerator;
+
+ public LottoShop(LottoNumbersGenerator generator) {
+ this.numberGenerator = generator;
+ }
+
+
+ public LottoTickets buyTicketsByAutomaticInLottoShop(Money money) {
+ List lottoTickets = new ArrayList<>();
+ Money currentMoney = money;
+
+ while (currentMoney.canSpendMoney(TICKET_PRICE)) {
+ lottoTickets.add(generateTicket());
+ currentMoney = currentMoney.spendMoney(TICKET_PRICE);
+ }
+
+ return new LottoTickets(lottoTickets);
+ }
+
+ private LottoTicket generateTicket() {
+ return new LottoTicket(numberGenerator.generate());
+ }
+
+ public LottoTickets buyTicketsByManualInLottoShop(List> manualLottoNumbers) {
+ List manualTickets = new ArrayList<>();
+
+ for (List lottoNumber : manualLottoNumbers) {
+ manualTickets.add(giveLottoTicket(lottoNumber));
+ }
+
+ return new LottoTickets(manualTickets);
+ }
+
+ private LottoTicket giveLottoTicket(List lottoNumbers) {
+ return new LottoTicket(lottoNumbers);
+ }
+
+ public Money getRemainMoney(LottoTickets lottoTickets, Money money) {
+ int price = lottoTickets.size() * TICKET_PRICE.getValue();
+
+ return money.spendMoney(new Money(price));
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoNumber.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoNumber.java
new file mode 100644
index 0000000..a62bdff
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoNumber.java
@@ -0,0 +1,40 @@
+package com.javabom.lotto.domain.ticket;
+
+import java.util.Objects;
+
+public class LottoNumber {
+
+ private final int number;
+ public final static int NUMBER_BEGIN = 1;
+ public final static int NUMBER_END = 45;
+
+
+ public LottoNumber(int number) {
+ this.number = number;
+ validLottoNumber();
+ }
+
+ public int getNumber() {
+ return this.number;
+ }
+
+ private void validLottoNumber() {
+ if (number < NUMBER_BEGIN || number > NUMBER_END) {
+ throw new IllegalArgumentException(String.format("로또 번호가 아닙니다. - %s", number));
+ }
+
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ LottoNumber that = (LottoNumber) o;
+ return number == that.number;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(number);
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoTicket.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicket.java
new file mode 100644
index 0000000..171e4b0
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicket.java
@@ -0,0 +1,75 @@
+package com.javabom.lotto.domain.ticket;
+
+import com.javabom.lotto.domain.result.LottoRank;
+
+import java.util.*;
+
+public class LottoTicket {
+
+ public static final int LOTTO_NUMBER_COUNT = 6;
+
+ private final List lottoNumbers;
+
+ public LottoTicket(List lottoNumbers) {
+ this.lottoNumbers = lottoNumbers;
+ validNumbers(this.lottoNumbers);
+ }
+
+ public static void validNumbers(List lottoNumbers) {
+ validLottoNumberCount(lottoNumbers);
+ validDuplicatedNumber(lottoNumbers);
+ }
+
+ private static void validDuplicatedNumber(List lottoNumbers) {
+ HashSet setNumbers = new HashSet<>(lottoNumbers);
+ if (setNumbers.size() < LOTTO_NUMBER_COUNT) {
+ throw new IllegalArgumentException("로또번호 중 중복된 번호가 존재합니다.");
+ }
+ }
+
+ private static void validLottoNumberCount(List lottoNumbers) {
+ if (lottoNumbers.size() != LOTTO_NUMBER_COUNT) {
+ throw new IllegalArgumentException("입력된 로또 번호 수가 6개가 아닙니다.");
+ }
+ }
+
+ public LottoRank findLottoRank(WinningTicket winningTicket) {
+ int sameCount = getSameCount(winningTicket);
+ boolean hasBonusNumber = winningTicket.isSameBonusNumber(getLastNumber());
+
+ return LottoRank.findLottoRank(sameCount, hasBonusNumber);
+ }
+
+ private LottoNumber getLastNumber() {
+ return getLottoNumbers().get(lottoNumbers.size() - 1);
+ }
+
+ private int getSameCount(WinningTicket winningTicket) {
+ int sameCount = 0;
+ List winningNumbers = winningTicket.getWinningNumbers();
+
+ for (int i = 0; i < lottoNumbers.size(); i++) {
+ boolean isSame = lottoNumbers.get(i).equals(winningNumbers.get(i));
+ sameCount += (isSame ? 1 : 0);
+ }
+
+ return sameCount;
+ }
+
+ public List getLottoNumbers() {
+ return Collections.unmodifiableList(lottoNumbers);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ LottoTicket that = (LottoTicket) o;
+ return Objects.equals(getLottoNumbers(), that.getLottoNumbers());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getLottoNumbers());
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoTickets.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoTickets.java
new file mode 100644
index 0000000..c095e6f
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoTickets.java
@@ -0,0 +1,38 @@
+package com.javabom.lotto.domain.ticket;
+
+import com.javabom.lotto.domain.result.LottoResult;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class LottoTickets {
+
+ private final List tickets;
+
+ public LottoTickets(List lottoTickets) {
+ tickets = lottoTickets;
+ }
+
+ public LottoResult getLottoResult(WinningTicket winningTicket) {
+ return new LottoResult(tickets.stream()
+ .map(lottoTicket -> lottoTicket.findLottoRank(winningTicket))
+ .collect(Collectors.toList()));
+ }
+
+ public LottoTickets joinTickets(LottoTickets lottoTickets) {
+ List joinTickets = new ArrayList<>();
+ joinTickets.addAll(this.tickets);
+ joinTickets.addAll(lottoTickets.getTickets());
+ return new LottoTickets(joinTickets);
+ }
+
+ public List getTickets() {
+ return Collections.unmodifiableList(tickets);
+ }
+
+ public int size() {
+ return tickets.size();
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/ticket/WinningTicket.java b/src/main/java/com/javabom/lotto/domain/ticket/WinningTicket.java
new file mode 100644
index 0000000..c38d837
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/ticket/WinningTicket.java
@@ -0,0 +1,34 @@
+package com.javabom.lotto.domain.ticket;
+
+import java.util.List;
+
+public class WinningTicket {
+
+ private final List winningNumbers;
+
+ private final LottoNumber bonusNumber;
+
+ public WinningTicket(List winningNumbers, LottoNumber bonusNumber) {
+ this.winningNumbers = winningNumbers;
+ this.bonusNumber = bonusNumber;
+ validDuplicatedNumbers();
+ }
+
+ private void validDuplicatedNumbers() {
+ if (winningNumbers.contains(bonusNumber)) {
+ throw new IllegalArgumentException("당첨번호에 보너스 번호가 중복된 번호가 존재합니다.");
+ }
+ }
+
+ public boolean contains(final LottoNumber lottoNumber) {
+ return winningNumbers.contains(lottoNumber);
+ }
+
+ public boolean isSameBonusNumber(LottoNumber lottoNumber) {
+ return bonusNumber.equals(lottoNumber);
+ }
+
+ public List getWinningNumbers() {
+ return winningNumbers;
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/domain/vo/Money.java b/src/main/java/com/javabom/lotto/domain/vo/Money.java
new file mode 100644
index 0000000..3ec41e8
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/domain/vo/Money.java
@@ -0,0 +1,29 @@
+package com.javabom.lotto.domain.vo;
+
+public class Money {
+
+ private final int value;
+
+ public Money(int value) {
+ this.value = value;
+ }
+
+ private void checkSpendMoney(Money money) {
+ if (this.getValue() < money.getValue()) {
+ throw new IllegalArgumentException("잔액이 부족합니다.");
+ }
+ }
+
+ public Money spendMoney(Money price) {
+ checkSpendMoney(price);
+ return new Money(value - price.getValue());
+ }
+
+ public boolean canSpendMoney(Money price) {
+ return this.getValue() >= price.getValue();
+ }
+
+ public int getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/dto/InputDto.java b/src/main/java/com/javabom/lotto/dto/InputDto.java
new file mode 100644
index 0000000..6053d0c
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/dto/InputDto.java
@@ -0,0 +1,90 @@
+package com.javabom.lotto.dto;
+
+import com.javabom.lotto.domain.shop.LottoNumbersGenerator;
+import com.javabom.lotto.domain.shop.LottoShop;
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import com.javabom.lotto.domain.ticket.LottoTicket;
+import com.javabom.lotto.domain.vo.Money;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class InputDto {
+
+ private Money money;
+
+ private int manualCount;
+
+ private List> manualNumbers;
+
+ public InputDto(String money, String manualCount) {
+ validInputValue(money, manualCount);
+ this.money = new Money(Integer.parseInt(money));
+ this.manualCount = Integer.parseInt(manualCount);
+ validMoney();
+ }
+
+ private void validMoney() {
+ int ticketPrice = manualCount * LottoShop.TICKET_PRICE.getValue();
+ int inputMoney = money.getValue();
+ if (ticketPrice > inputMoney || !money.canSpendMoney(LottoShop.TICKET_PRICE)) {
+ throw new IllegalArgumentException(
+ String.format("로또를 구매할 금액이 부족합니다. - Money : %d, Ticket Price : %d", inputMoney, ticketPrice));
+ }
+ }
+
+ private void validInputValue(String money, String manualCount) {
+ validNumberFormat(money);
+ validNegativeNumber(money);
+ validNumberFormat(manualCount);
+ validNegativeNumber(manualCount);
+ }
+
+ private void validNegativeNumber(String number) {
+ if (Integer.parseInt(number) < 0) {
+ throw new IllegalArgumentException(String.format("양수 값을 입력 해주세요. - %s", number));
+ }
+ }
+
+ public void setManualNumbers(List> manualNumbers) {
+ this.manualNumbers = convertLottoNumbers(manualNumbers);
+ }
+
+ private List> convertLottoNumbers(List> manualNumbers) {
+ return manualNumbers.stream()
+ .map(this::parseIntNumbers)
+ .map(LottoNumbersGenerator::convertToLottoNumbers)
+ .peek(LottoTicket::validNumbers)
+ .collect(Collectors.toList());
+ }
+
+ private List parseIntNumbers(List numbers) {
+ return numbers.stream()
+ .map(number -> {
+ validNumberFormat(number);
+ return Integer.parseInt(number);
+ })
+ .collect(Collectors.toList());
+ }
+
+ private void validNumberFormat(String number) {
+ try {
+ Integer.parseInt(number);
+ } catch (NumberFormatException e) {
+ throw new NumberFormatException(String.format("숫자 값을 입력해주세요. - %s", number));
+ }
+ }
+
+
+ public List> getManualNumbers() {
+ return manualNumbers;
+ }
+
+ public int getManualCount() {
+ return manualCount;
+ }
+
+ public Money getMoney() {
+ return money;
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/dto/WinningNumbersDto.java b/src/main/java/com/javabom/lotto/dto/WinningNumbersDto.java
new file mode 100644
index 0000000..7ff6238
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/dto/WinningNumbersDto.java
@@ -0,0 +1,47 @@
+package com.javabom.lotto.dto;
+
+import com.javabom.lotto.domain.shop.LottoNumbersGenerator;
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import com.javabom.lotto.domain.ticket.LottoTicket;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class WinningNumbersDto {
+
+ private final List winningNumbers;
+
+ private final LottoNumber bonusNumber;
+
+ public WinningNumbersDto(List numbers, String bonusNumber) {
+ validNumberFormat(bonusNumber);
+ this.bonusNumber = new LottoNumber(Integer.parseInt(bonusNumber));
+ this.winningNumbers = LottoNumbersGenerator.convertToLottoNumbers(parseIntNumbers(numbers));
+ LottoTicket.validNumbers(this.winningNumbers);
+ }
+
+ private List parseIntNumbers(List numbers) {
+ return numbers.stream()
+ .map(number -> {
+ validNumberFormat(number);
+ return Integer.parseInt(number);
+ })
+ .collect(Collectors.toList());
+ }
+
+ private void validNumberFormat(String number) {
+ try {
+ Integer.parseInt(number);
+ } catch (NumberFormatException e) {
+ throw new NumberFormatException(String.format("정수가 아닌 값이 입력 되었습니다. - %s", number));
+ }
+ }
+
+ public List getWinningNumbers() {
+ return winningNumbers;
+ }
+
+ public LottoNumber getBonusNumber() {
+ return bonusNumber;
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/dto/WinningStatisticsDto.java b/src/main/java/com/javabom/lotto/dto/WinningStatisticsDto.java
new file mode 100644
index 0000000..2f76264
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/dto/WinningStatisticsDto.java
@@ -0,0 +1,34 @@
+package com.javabom.lotto.dto;
+
+import com.javabom.lotto.domain.result.LottoRank;
+import com.javabom.lotto.domain.result.LottoResult;
+import com.javabom.lotto.domain.result.WinningStatistics;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+public class WinningStatisticsDto {
+
+ private final LottoResult results;
+
+ private final int profitRatio;
+
+ public WinningStatisticsDto(WinningStatistics winningStatistics) {
+ this.results = winningStatistics.getResults();
+ this.profitRatio = winningStatistics.calculateProfitRatio();
+ }
+
+ public Map getEachLottoRankCount() {
+ Map lottoRankMap = new LinkedHashMap<>();
+ for (LottoRank lottoRank : LottoRank.values()) {
+ lottoRankMap.put(lottoRank, results.getRankCount(lottoRank));
+ }
+ lottoRankMap.remove(LottoRank.FAIL);
+ return lottoRankMap;
+ }
+
+ public int getProfitRatio() {
+ return profitRatio;
+ }
+}
diff --git a/src/main/java/com/javabom/lotto/view/InputView.java b/src/main/java/com/javabom/lotto/view/InputView.java
new file mode 100644
index 0000000..96c6157
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/view/InputView.java
@@ -0,0 +1,59 @@
+package com.javabom.lotto.view;
+
+import com.javabom.lotto.dto.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+
+public class InputView {
+
+ private static final Scanner SCANNER = new Scanner(System.in);
+
+ public static final String DELIMITER = ",";
+
+ public static InputDto askInputMoneyAndManual() {
+ InputDto inputDto = new InputDto(getMoney(), getManualCount());
+ inputDto.setManualNumbers(getManualLottoNumbers(inputDto.getManualCount()));
+
+ return inputDto;
+ }
+
+ public static List> getManualLottoNumbers(int count) {
+ System.out.println();
+ System.out.println("수동으로 구매할 번호를 입력해 주세요.");
+ List> lottoNumbers = new ArrayList<>();
+
+ for (int i = 0; i < count; i++) {
+ lottoNumbers.add(Arrays.asList(SCANNER.nextLine().split(DELIMITER)));
+ }
+
+ return lottoNumbers;
+ }
+
+ private static String getManualCount() {
+ System.out.println("수동으로 구매할 로또 수를 입력해 주세요.");
+ return SCANNER.nextLine();
+ }
+
+ private static String getMoney() {
+ System.out.println("투입금액을 입력해 주세요.");
+ return SCANNER.nextLine();
+ }
+
+ public static WinningNumbersDto askWinningNumbers() {
+ System.out.println("\n지난 주 당첨 번호를 입력해 주세요.");
+ return new WinningNumbersDto(getWinningNumbers(), getBonusNumber());
+ }
+
+ private static List getWinningNumbers() {
+ return Arrays.asList(SCANNER.nextLine().split(DELIMITER));
+ }
+
+ private static String getBonusNumber() {
+ System.out.println("보너스 볼을 입력해 주세요.");
+ return SCANNER.nextLine();
+ }
+
+}
diff --git a/src/main/java/com/javabom/lotto/view/OutputView.java b/src/main/java/com/javabom/lotto/view/OutputView.java
new file mode 100644
index 0000000..616388d
--- /dev/null
+++ b/src/main/java/com/javabom/lotto/view/OutputView.java
@@ -0,0 +1,53 @@
+package com.javabom.lotto.view;
+
+import com.javabom.lotto.dto.WinningStatisticsDto;
+import com.javabom.lotto.domain.result.LottoRank;
+import com.javabom.lotto.domain.ticket.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class OutputView {
+
+ public static void printLotteryTickets(LottoTickets automaticTickets, LottoTickets manualTickets) {
+ System.out.println();
+ System.out.println(manualTickets.size() + "장, 자동으로 " + automaticTickets.size() + "개를 구매했습니다.");
+
+ for (LottoTicket ticket : manualTickets.getTickets()) {
+ printLottoNumber(ticket);
+ }
+
+ for (LottoTicket number : automaticTickets.getTickets()) {
+ printLottoNumber(number);
+ }
+ }
+
+ public static void printLottoNumber(LottoTicket lottoTicket) {
+ List numbers = lottoTicket.getLottoNumbers().stream()
+ .map(LottoNumber::getNumber)
+ .map(Object::toString)
+ .collect(Collectors.toList());
+ System.out.println("[" + String.join(", ", numbers) + "]");
+ }
+
+ public static void printWinningStatistics(WinningStatisticsDto winningStatisticsDto) {
+ System.out.println("\n당첨 통계");
+ System.out.println("----------");
+ printWinningNumberCount(winningStatisticsDto);
+ printProfitRatio(winningStatisticsDto.getProfitRatio());
+ }
+
+ private static void printProfitRatio(int profitRatio) {
+ System.out.printf("총 수익률은 %d%%입니다.\n", profitRatio);
+ }
+
+ private static void printWinningNumberCount(WinningStatisticsDto winningStatisticsDto) {
+ Map eachLottoRankCount = winningStatisticsDto.getEachLottoRankCount();
+ System.out.println("3개 일치(" + LottoRank.FIFTH_PLACE.getPrizeMoney() + "원) - " + eachLottoRankCount.get(LottoRank.FIFTH_PLACE) + "개");
+ System.out.println("4개 일치(" + LottoRank.FOURTH_PLACE.getPrizeMoney() + "원) - " + eachLottoRankCount.get(LottoRank.FOURTH_PLACE) + "개");
+ System.out.println("5개 일치(" + LottoRank.THIRD_PLACE.getPrizeMoney() + "원) - " + eachLottoRankCount.get(LottoRank.THIRD_PLACE) + "개");
+ System.out.println("5개 일치, 보너스 볼 일치(" + LottoRank.SECOND_PLACE.getPrizeMoney() + "원) - " + eachLottoRankCount.get(LottoRank.SECOND_PLACE) + "개");
+ System.out.println("6개 일치(" + LottoRank.FIRST_PLACE.getPrizeMoney() + "원) - " + eachLottoRankCount.get(LottoRank.FIRST_PLACE) + "개");
+ }
+}
diff --git a/src/test/java/com/javabom/lotto/domain/result/LottoResultTest.java b/src/test/java/com/javabom/lotto/domain/result/LottoResultTest.java
new file mode 100644
index 0000000..78e73da
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/result/LottoResultTest.java
@@ -0,0 +1,31 @@
+package com.javabom.lotto.domain.result;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class LottoResultTest {
+
+ @Test
+ void getRankCountTest() {
+ List ranks = new ArrayList<>();
+ ranks.add(LottoRank.FIFTH_PLACE);
+ ranks.add(LottoRank.FIFTH_PLACE);
+ LottoResult result = new LottoResult(ranks);
+
+ assertEquals(2, result.getRankCount(LottoRank.FIFTH_PLACE));
+ }
+
+ @Test
+ void getResultsTest() {
+ List ranks = new ArrayList<>();
+ ranks.add(LottoRank.FIFTH_PLACE);
+ ranks.add(LottoRank.FIFTH_PLACE);
+ LottoResult result = new LottoResult(ranks);
+
+ assertEquals(2, result.getResults().size());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/shop/LottoNumberShufflerTest.java b/src/test/java/com/javabom/lotto/domain/shop/LottoNumberShufflerTest.java
new file mode 100644
index 0000000..7428131
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/shop/LottoNumberShufflerTest.java
@@ -0,0 +1,56 @@
+package com.javabom.lotto.domain.shop;
+
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import com.javabom.lotto.domain.ticket.LottoTicket;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class LottoNumberShufflerTest {
+
+ @Test
+ @DisplayName("자동으로 로또 번호 6개를 생성하는지 확인.")
+ void generateNumberCountTest() {
+ LottoNumbersGenerator shuffler = new LottoNumbersGenerator();
+
+ assertEquals(LottoTicket.LOTTO_NUMBER_COUNT, shuffler.generate().size());
+ }
+
+ @Test
+ @DisplayName("설정된 로또 번호 범위에 맞게 생성하는지 확인.")
+ void generateTest() {
+ LottoNumbersGenerator shuffler = new LottoNumbersGenerator();
+ List generate = shuffler.generate();
+ int maxNumber = generate.stream()
+ .max(Comparator.comparing(LottoNumber::getNumber))
+ .get()
+ .getNumber();
+
+ int minNumber = generate.stream()
+ .min(Comparator.comparing(LottoNumber::getNumber))
+ .get()
+ .getNumber();
+
+ assertTrue(maxNumber <= LottoNumber.NUMBER_END);
+ assertTrue(minNumber >= LottoNumber.NUMBER_BEGIN);
+ }
+
+ @Test
+ @DisplayName("입력된 숫자값을 로또번호로 변환하는지 확인.")
+ public void convertLottoNumberTest() {
+ List lottoNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ List convertToLottoNumbers = LottoNumbersGenerator.convertToLottoNumbers(Arrays.asList(1, 2, 3, 4, 5, 6));
+ assertEquals(lottoNumbers, convertToLottoNumbers);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/shop/LottoShopTest.java b/src/test/java/com/javabom/lotto/domain/shop/LottoShopTest.java
new file mode 100644
index 0000000..a024a9d
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/shop/LottoShopTest.java
@@ -0,0 +1,75 @@
+package com.javabom.lotto.domain.shop;
+
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import com.javabom.lotto.domain.ticket.LottoTicket;
+import com.javabom.lotto.domain.ticket.LottoTickets;
+import com.javabom.lotto.domain.vo.Money;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class LottoShopTest {
+
+ @Test
+ @DisplayName("입력한 금액만큼 로또 티켓을 반환하는지 확인.")
+ void buyTicketsByAutomaticInLottoShop() {
+ Money money = new Money(5000);
+ LottoShop lottoShop = new LottoShop(new LottoNumbersGenerator());
+
+ LottoTickets lottoTickets = lottoShop.buyTicketsByAutomaticInLottoShop(money);
+
+ assertEquals(5, lottoTickets.size());
+ }
+
+ @Test
+ @DisplayName("입력한 로또 수동번호 만큼 로또 티켓을 반환하는지 확인.")
+ void buyTicketsByManualInLottoShop() {
+ List> manualNumbers = createLottoNumbers();
+ LottoShop lottoShop = new LottoShop(new LottoNumbersGenerator());
+
+ LottoTickets lottoTickets = lottoShop.buyTicketsByManualInLottoShop(manualNumbers);
+
+ assertEquals(2, lottoTickets.size());
+ }
+
+ private List> createLottoNumbers() {
+ List> lottoNumbers = new ArrayList<>();
+ List numbers1 = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ List numbers2 = Stream.of(7, 8, 9, 10, 11, 12)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ lottoNumbers.add(numbers1);
+ lottoNumbers.add(numbers2);
+ return lottoNumbers;
+ }
+
+ @Test
+ @DisplayName("입력한 금액에서 구매한 티켓 금액만큼 차감 후 잔액을 반환하는지 확인.")
+ void getRemainMoney() {
+ LottoShop lottoShop = new LottoShop(new LottoNumbersGenerator());
+ LottoTickets lottoTickets = getLottoTickets();
+ Money money = new Money(5000);
+ Money remainMoney = lottoShop.getRemainMoney(lottoTickets, money);
+ assertEquals(3000, remainMoney.getValue());
+ }
+
+ private LottoTickets getLottoTickets() {
+ List> lottoNumbers = createLottoNumbers();
+ List lottoTickets = new ArrayList<>();
+ LottoTicket lottoTicket1 = new LottoTicket(lottoNumbers.get(0));
+ LottoTicket lottoTicket2 = new LottoTicket(lottoNumbers.get(1));
+ lottoTickets.add(lottoTicket1);
+ lottoTickets.add(lottoTicket2);
+
+ return new LottoTickets(lottoTickets);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberTest.java
new file mode 100644
index 0000000..60c4574
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberTest.java
@@ -0,0 +1,18 @@
+package com.javabom.lotto.domain.ticket;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class LottoNumberTest {
+
+ @ParameterizedTest
+ @ValueSource(ints = {0, 46})
+ public void 로또번호가_아닌값_입력시_예외처리(int number) {
+ // given
+ assertThatThrownBy(() -> new LottoNumber(number))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage(String.format("로또 번호가 아닙니다. - %d", number));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketTest.java
new file mode 100644
index 0000000..85014c4
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketTest.java
@@ -0,0 +1,73 @@
+package com.javabom.lotto.domain.ticket;
+
+import com.javabom.lotto.domain.result.LottoRank;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LottoTicketTest {
+
+ @Test
+ @DisplayName("요구사항에 맞게 당첨 결과를 반환하는지 확인.(당첨로또의 번호 순서와 발급받은 티켓의 번호순서까지 완벽하게 일치할때 1개 일치)")
+ void findLottoRankTest() {
+ WinningTicket winningTicket = createWinningNumbers();
+
+ List lottoNumbers1 = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ List lottoNumbers2 = Stream.of(1, 2, 3, 4, 6, 5)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ LottoTicket lottoTicket1 = new LottoTicket(lottoNumbers1);
+ LottoTicket lottoTicket2 = new LottoTicket(lottoNumbers2);
+
+ assertEquals(LottoRank.FIRST_PLACE, lottoTicket1.findLottoRank(winningTicket));
+ assertEquals(LottoRank.FOURTH_PLACE, lottoTicket2.findLottoRank(winningTicket));
+ }
+
+ @ParameterizedTest
+ @DisplayName("입력되는 로또번호가 6개가 아닐시 예외처리.")
+ @ValueSource(strings = {"1,2,3,4,5", "1,2,3,4,5,6,7"})
+ void validLottoCountTest(String numbers) {
+ List lottoNumbers = Arrays.stream(numbers.split(","))
+ .map(Integer::parseInt)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ assertThatThrownBy(() -> new LottoTicket(lottoNumbers))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("입력된 로또 번호 수가 6개가 아닙니다.");
+ }
+
+ @Test
+ @DisplayName("입력되는 로또번호가 6개가 아닐시 예외처리.")
+ void validDuplicatedTest() {
+ List lottoNumbers = Arrays.stream("1,2,3,4,5,5".split(","))
+ .map(Integer::parseInt)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ assertThatThrownBy(() -> new LottoTicket(lottoNumbers))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("로또번호 중 중복된 번호가 존재합니다.");
+ }
+
+ private WinningTicket createWinningNumbers() {
+ List winningNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ LottoNumber bonusNumber = new LottoNumber(7);
+ return new WinningTicket(winningNumbers, bonusNumber);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketsTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketsTest.java
new file mode 100644
index 0000000..b82176f
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketsTest.java
@@ -0,0 +1,71 @@
+package com.javabom.lotto.domain.ticket;
+
+import com.javabom.lotto.domain.result.LottoRank;
+import com.javabom.lotto.domain.result.LottoResult;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LottoTicketsTest {
+
+ @Test
+ @DisplayName("로또 당첨 결과 반환 테스트.")
+ void getLottoResult() {
+ LottoTickets lottoTickets = createLottoTickets();
+ List lottoNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ LottoNumber bonusNumber = new LottoNumber(7);
+
+ WinningTicket winningTicket = new WinningTicket(lottoNumbers, bonusNumber);
+ LottoResult lottoResult = lottoTickets.getLottoResult(winningTicket);
+ List lottoRanks = new ArrayList<>();
+ lottoRanks.add(LottoRank.FIRST_PLACE);
+ lottoRanks.add(LottoRank.SECOND_PLACE);
+
+ assertEquals(lottoRanks, lottoResult.getResults());
+ }
+
+ LottoTickets createLottoTickets() {
+ List lottoTickets = new ArrayList<>();
+ List lottoNumbers1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6))
+ .stream()
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ LottoTicket lottoTicket1 = new LottoTicket(lottoNumbers1);
+
+ List lottoNumbers2 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 7))
+ .stream()
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ LottoTicket lottoTicket2 = new LottoTicket(lottoNumbers2);
+ lottoTickets.add(lottoTicket1);
+ lottoTickets.add(lottoTicket2);
+ return new LottoTickets(lottoTickets);
+ }
+
+ @Test
+ void sizeTest() {
+ LottoTickets lottoTickets = createLottoTickets();
+ assertEquals(2, lottoTickets.size());
+ }
+
+ @Test
+ @DisplayName("매개변수로 받은 티켓을 합쳐 반환하는지 확인.")
+ public void joinTicketsTest() {
+ LottoTickets lottoTickets1 = createLottoTickets();
+ LottoTickets lottoTickets2 = createLottoTickets();
+ LottoTickets joinTickets = lottoTickets1.joinTickets(lottoTickets2);
+
+ assertEquals(4, joinTickets.size());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/ticket/WinningTicketTest.java b/src/test/java/com/javabom/lotto/domain/ticket/WinningTicketTest.java
new file mode 100644
index 0000000..0b0ef33
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/ticket/WinningTicketTest.java
@@ -0,0 +1,49 @@
+package com.javabom.lotto.domain.ticket;
+
+import com.javabom.lotto.dto.WinningNumbersDto;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class WinningTicketTest {
+
+ @Test
+ @DisplayName("당첨번호에 보너스 번호 중복된 번호가 존재시 예외처리.")
+ void validDuplicatedTest() {
+ List winningNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ LottoNumber bonusNumber = new LottoNumber(5);
+ assertThatThrownBy(() -> new WinningTicket(winningNumbers, bonusNumber))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("당첨번호에 보너스 번호가 중복된 번호가 존재합니다.");
+ }
+
+ @Test
+ void containsTest() {
+ List winningNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ LottoNumber bonusNumber = new LottoNumber(7);
+ WinningTicket winningTicket = new WinningTicket(winningNumbers, bonusNumber);
+ LottoNumber lottoNumber = new LottoNumber(5);
+ assertTrue(winningTicket.contains(lottoNumber));
+ }
+
+ @Test
+ void isSameBonusNumber() {
+ List winningNumbers = Stream.of(1, 2, 3, 4, 5, 6)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+ LottoNumber bonusNumber = new LottoNumber(7);
+ WinningTicket winningTicket = new WinningTicket(winningNumbers, bonusNumber);
+ LottoNumber lottoNumber = new LottoNumber(7);
+ assertTrue(winningTicket.isSameBonusNumber(lottoNumber));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/domain/vo/MoneyTest.java b/src/test/java/com/javabom/lotto/domain/vo/MoneyTest.java
new file mode 100644
index 0000000..a4626c3
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/domain/vo/MoneyTest.java
@@ -0,0 +1,37 @@
+package com.javabom.lotto.domain.vo;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.InstanceOfAssertFactories.atomicReferenceArray;
+import static org.junit.jupiter.api.Assertions.*;
+
+class MoneyTest {
+
+ @Test
+ @DisplayName("보유한 금액보다 많은 소비를 할 시 예외")
+ public void validRemainMoney() {
+ Money money = new Money(500);
+ assertThatThrownBy(() -> money.spendMoney(new Money(10000)))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("잔액이 부족합니다.");
+ }
+
+ @Test
+ @DisplayName("구입한 가격만큼 소비했는지 확인.")
+ void spendMoneyTest() {
+ Money money = new Money(5000);
+ Money remainMoney = money.spendMoney(new Money(3000));
+ assertEquals(new Money(2000).getValue(), remainMoney.getValue());
+ }
+
+ @Test
+ @DisplayName("잔액에 맞게 구매 가능여부 확인.")
+ void canSpendMoney() {
+ Money money = new Money(5000);
+
+ assertTrue(money.canSpendMoney(new Money(3000)));
+ assertFalse(money.canSpendMoney(new Money(10000)));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/dto/InputDtoTest.java b/src/test/java/com/javabom/lotto/dto/InputDtoTest.java
new file mode 100644
index 0000000..4550d03
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/dto/InputDtoTest.java
@@ -0,0 +1,92 @@
+package com.javabom.lotto.dto;
+
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.*;
+
+class InputDtoTest {
+
+ @Test
+ @DisplayName("입력한 금액이 수동으로 구매할 금액보다 적으면 예외처리.")
+ public void validMoneyTest() {
+ assertThatThrownBy(() -> new InputDto("1000", "2"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("로또를 구매할 금액이 부족합니다. - Money : 1000, Ticket Price : 2000");
+
+ }
+
+ @Test
+ @DisplayName("음수 값이 들어올 경우 예외처리.")
+ public void validNegativeValueTest() {
+ // given
+ assertThatThrownBy(() -> new InputDto("1000", "-1"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("양수 값을 입력 해주세요. - -1");
+ }
+
+ @Test
+ @DisplayName("정수 값이 아닌 값이 들어올 경우 예외처리.")
+ public void validNumberFormatTest() {
+ // given
+ assertThatThrownBy(() -> new InputDto("1000", "a"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("숫자 값을 입력해주세요. - a");
+ }
+
+ @Test
+ @DisplayName("입력받은 수동 로또 번호 중 중복된 번호가 있으면 예외처리.")
+ void validManualNumbers() {
+ InputDto inputDto = new InputDto("1000", "1");
+ List> manualNumbers = new ArrayList<>();
+ List manualNumber = Arrays.asList("1", "2", "3", "5", "5", "6");
+ manualNumbers.add(manualNumber);
+
+ assertThatThrownBy(() -> inputDto.setManualNumbers(manualNumbers))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("로또번호 중 중복된 번호가 존재합니다.");
+ }
+
+ @DisplayName("입력받은 수동 로또 번호가 6개가 아니면 예외처리.")
+ @ParameterizedTest
+ @ValueSource(strings = {"1,2,3,4,5", "1,2,3,4,5,6,7"})
+ void validManualNumbersCount(String inputManuals) {
+ InputDto inputDto = new InputDto("1000", "1");
+ List> manualNumbers = new ArrayList<>();
+
+ List manualNumber = Arrays.asList(inputManuals.split(","));
+ manualNumbers.add(manualNumber);
+
+ assertThatThrownBy(() -> inputDto.setManualNumbers(manualNumbers))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("입력된 로또 번호 수가 6개가 아닙니다.");
+ }
+
+ @DisplayName("입력받은 수동번호의 문자열 값을 로또번호 객체로 변환하는지 확인.")
+ @Test
+ public void convertLottoNumberTest() {
+ InputDto inputDto = new InputDto("1000", "1");
+ List> manualNumbers = new ArrayList<>();
+ List manualNumber = Arrays.asList("1", "2", "3", "4", "5", "6");
+ manualNumbers.add(manualNumber);
+
+ inputDto.setManualNumbers(manualNumbers);
+ List convertNumbers = manualNumber
+ .stream()
+ .map(Integer::parseInt)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ assertEquals(convertNumbers, inputDto.getManualNumbers().get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/dto/WinningNumbersDtoTest.java b/src/test/java/com/javabom/lotto/dto/WinningNumbersDtoTest.java
new file mode 100644
index 0000000..cb08ab7
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/dto/WinningNumbersDtoTest.java
@@ -0,0 +1,48 @@
+package com.javabom.lotto.dto;
+
+import com.javabom.lotto.domain.ticket.LottoNumber;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class WinningNumbersDtoTest {
+
+ @DisplayName("입력받은 당첨번호 문자열 값을 로또번호 객체로 변환하는지 확인.")
+ @Test
+ public void convertLottoNumberTest() {
+ List winningNumbers = Arrays.asList("1", "2", "3", "4", "5", "6");
+ WinningNumbersDto winningNumbersDto = new WinningNumbersDto(winningNumbers, "3");
+
+ List lottoNumbers = winningNumbers.stream()
+ .map(Integer::parseInt)
+ .map(LottoNumber::new)
+ .collect(Collectors.toList());
+
+ assertEquals(lottoNumbers, winningNumbersDto.getWinningNumbers());
+ }
+
+ @DisplayName("입력받은 당첨번호 값에 정수가 아닌 값이 들어간 경우 예외 처리.")
+ @Test
+ public void validWinningNumberTest() {
+ List winningNumbers = Arrays.asList("1", "2", "a", "4", "5", "6");
+ assertThatThrownBy(() -> new WinningNumbersDto(winningNumbers, "3"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("정수가 아닌 값이 입력 되었습니다. - a");
+ }
+
+ @DisplayName("입력받은 당첨번호 값에 로또 번호 범위가 아닌 값(1~45)이 들어간 경우 예외 처리.")
+ @Test
+ public void validWinningNumberRangeTest() {
+ List winningNumbers = Arrays.asList("1", "2", "3", "4", "5", "46");
+ assertThatThrownBy(() -> new WinningNumbersDto(winningNumbers, "3"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("로또 번호가 아닙니다. - 46");
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/javabom/lotto/dto/WinningStatisticsDtoTest.java b/src/test/java/com/javabom/lotto/dto/WinningStatisticsDtoTest.java
new file mode 100644
index 0000000..c4af5fd
--- /dev/null
+++ b/src/test/java/com/javabom/lotto/dto/WinningStatisticsDtoTest.java
@@ -0,0 +1,39 @@
+package com.javabom.lotto.dto;
+
+import com.javabom.lotto.domain.result.LottoRank;
+import com.javabom.lotto.domain.result.LottoResult;
+import com.javabom.lotto.domain.result.WinningStatistics;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class WinningStatisticsDtoTest {
+
+ @Test
+ void getEachLottoRankCountTest() {
+ List ranks = new ArrayList<>();
+ ranks.add(LottoRank.FIFTH_PLACE);
+ WinningStatistics winningStatistics = new WinningStatistics(new LottoResult(ranks));
+ WinningStatisticsDto winningStatisticsDto = new WinningStatisticsDto(winningStatistics);
+
+ Map eachLottoRankCount = winningStatisticsDto.getEachLottoRankCount();
+ assertEquals(1, eachLottoRankCount.get(LottoRank.FIFTH_PLACE));
+ }
+
+ @Test
+ void getProfitRatioTest() {
+ List ranks = new ArrayList<>();
+ ranks.add(LottoRank.FIFTH_PLACE);
+
+ WinningStatistics winningStatistics = new WinningStatistics(new LottoResult(ranks));
+ WinningStatisticsDto winningStatisticsDto = new WinningStatisticsDto(winningStatistics);
+ int profitRatio = winningStatisticsDto.getProfitRatio();
+
+ assertEquals(500, profitRatio);
+
+ }
+}
\ No newline at end of file