diff --git a/README.md b/README.md index 3c3a28fa..95dbcfa4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## 로또 미션 1-2단계 +## 로또 미션 1-5단계 ### 기능 요구사항 @@ -23,6 +23,13 @@ - 소수점 둘째 자리까지 표시한다. - 1미만시 손해이고 1이상이면 이득이다. -### 추가된 기능 요구사항 -1. 모든 원시 값과 문자열을 포장한다. -2. 일급 컬렉션을 쓴다 +#### 3단계 +- 보너스볼이 들어온다 +- 5개 일치 + 보너스볼 일치: 30000000원 +- 5개 일치 + 보너스볼 일치하지 않음 : 1500000원 + +#### 4단계 +- 사용자는 수동으로 구매할 로또 수를 입력할 수 있다. + +#### 5단계 +- 리팩토링하기 diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 1e7c5020..cfcad44e 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -2,7 +2,6 @@ public class Main { public static void main(String[] args) { - LottoController lottoController = new LottoController(); lottoController.run(); } diff --git a/src/main/java/controller/LottoController.java b/src/main/java/controller/LottoController.java index 0e40df72..8cbf4f7c 100644 --- a/src/main/java/controller/LottoController.java +++ b/src/main/java/controller/LottoController.java @@ -1,56 +1,137 @@ package controller; -import domain.*; +import domain.Lotto; +import domain.LottoNumber; +import domain.LottoService; +import domain.LottoTicketCount; +import domain.Lottos; +import domain.LottoTotalPrice; +import domain.Money; +import domain.MatchCount; +import domain.ProfitRate; import view.InputView; import view.OutputView; import view.ResultView; +import java.util.ArrayList; +import java.util.List; + public class LottoController { + OutputView outputView = new OutputView(); InputView inputView = new InputView(); ResultView resultView = new ResultView(); public void run() { outputView.printWonMessage(); - Money money = new Money(inputView.inputMoney()); + Money money; + while (true) { + try { + money = new Money(inputView.inputMoney()); + break; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("다시 입력해주세요."); + } + } - LottoTickets lottoTickets = buyLotto(money); + Lottos lottoTickets = buyLotto(money); checkLotto(lottoTickets, money); } - public LottoTickets buyLotto(Money money) { - - LottoTicketCount ticketNumber = Money.getTicketCount(money); + public Lottos buyLotto(Money money) { + LottoTicketCount ticketNumber = money.getTicketCount(); resultView.printTicketNumbers(ticketNumber.getCount()); + outputView.printManualCount(); + int manualCount; + + while (true) { + try { + manualCount = inputView.inputManualCount(); + ticketNumber.validateManualCount(manualCount); + break; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("다시 입력해주세요."); + } + } + + List manualLottos = new ArrayList<>(); + outputView.printManualNumbers(); + + LottoService lottoService = new LottoService(); + for (int i = 0; i < manualCount; i++) { + while (true) { + try { + String manualNumbers = inputView.inputManualNumbers(); + Lotto lotto = lottoService.parseLottoAnswer(manualNumbers); + manualLottos.add(lotto); + break; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("다시 입력해주세요."); + } + } + } + + int autoCount = ticketNumber.getCount() - manualCount; + + resultView.printManualAuto(manualCount, autoCount); outputView.lottoResult(); + Lottos lottoTickets = Lottos.createMixedTickets(manualLottos, autoCount); - LottoTickets lottoTickets = new LottoTickets(ticketNumber); for (Lotto lotto : lottoTickets.getTickets()) { System.out.println(lotto); } + return lottoTickets; } - public void checkLotto(LottoTickets lottoTickets, Money money) { + + public void checkLotto(Lottos ticketAutoCount, Money money) { outputView.printLottoAnswer(); LottoService lottoService = new LottoService(); - String lottoAnswer = inputView.inputLottoAnswer(); + + Lotto lottoAnswerObj = null; + while (lottoAnswerObj == null) { + try { + String lottoAnswer = inputView.inputLottoAnswer(); + lottoAnswerObj = lottoService.parseLottoAnswer(lottoAnswer); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("다시 입력해주세요."); + } + } + outputView.printBonusMessage(); - int bonusBallNumber = inputView.inputBonusNumber(); - LottoNumber bonuseBall = new LottoNumber(bonusBallNumber); - Lotto lottoAnswerObj = lottoService.parseLottoAnswer(lottoAnswer); - MatchCount matchCount = lottoService.calculateMatchCount(lottoTickets.getTickets(), lottoAnswerObj, bonuseBall); + LottoNumber bonusBall; + while (true) { + try { + int bonusBallNumber = inputView.inputBonusNumber(); + bonusBall = new LottoNumber(bonusBallNumber); + lottoService.validateBonusBall(lottoAnswerObj, bonusBall); + break; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("다시 입력해주세요."); + } + } + + MatchCount matchCount = lottoService.calculateMatchCount( + ticketAutoCount.getTickets(), + lottoAnswerObj, + bonusBall); - int totalSum = LottoProfit.LottoSum(matchCount); -// ProfitRate profitRate = new ProfitRate(money, new LottoTotalPrice(totalSum)); ProfitRate profitRate = new ProfitRate(money, new LottoTotalPrice(matchCount)); + outputView.lottoResult(); resultView.printLottoMatch(matchCount); resultView.printLottoProfit(profitRate.getProfitRate()); } + } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index aa2f6632..cab213b2 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -4,17 +4,22 @@ import java.util.TreeSet; public class Lotto { + private final SortedSet numbers; public Lotto(SortedSet numbers) { - if (numbers.size() != 6) { + validateSize(numbers); + this.numbers = new TreeSet<>(numbers); + } + + private void validateSize(SortedSet numbers) { + if (numbers.size() != createList.LOTTO_NUMBER_COUNT) { throw new IllegalArgumentException("로또 숫자는 6개여야 하며, 중복될 수 없습니다."); } - this.numbers = new TreeSet<>(numbers); } public int contains(LottoNumber number) { - if(numbers.contains(number)) return 1; + if (numbers.contains(number)) return 1; return 0; } diff --git a/src/main/java/domain/LottoNumber.java b/src/main/java/domain/LottoNumber.java index 6619b6b8..27e029cc 100644 --- a/src/main/java/domain/LottoNumber.java +++ b/src/main/java/domain/LottoNumber.java @@ -1,10 +1,11 @@ package domain; public class LottoNumber implements Comparable { + private final int number; public LottoNumber(int number) { - if (number < createList.LOTTO_MIN_NUMBER|| number > createList.LOTTO_MAX_NUMBER) { + if (number < createList.LOTTO_MIN_NUMBER || number > createList.LOTTO_MAX_NUMBER) { throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 합니다."); } this.number = number; @@ -35,4 +36,5 @@ public int hashCode() { public String toString() { return String.valueOf(number); } + } diff --git a/src/main/java/domain/LottoPrice.java b/src/main/java/domain/LottoPrice.java index 89d5154d..8aff73af 100644 --- a/src/main/java/domain/LottoPrice.java +++ b/src/main/java/domain/LottoPrice.java @@ -16,4 +16,5 @@ public enum LottoPrice { public int getPrice() { return price; } + } diff --git a/src/main/java/domain/LottoProfit.java b/src/main/java/domain/LottoProfit.java deleted file mode 100644 index 0af781f1..00000000 --- a/src/main/java/domain/LottoProfit.java +++ /dev/null @@ -1,21 +0,0 @@ -package domain; - -public class LottoProfit { - - public static int LottoSum(MatchCount matchCount) { - int match3Count = matchCount.getCount(LottoPrice.MATCH_3); - int match4Count = matchCount.getCount(LottoPrice.MATCH_4); - int match5Count = matchCount.getCount(LottoPrice.MATCH_5); - int match5BonusCount = matchCount.getCount(LottoPrice.MATCH_5_BONUS); - int match6Count = matchCount.getCount(LottoPrice.MATCH_6); - - int lottoSum = (match3Count * LottoPrice.MATCH_3.getPrice()) + (match4Count * LottoPrice.MATCH_4.getPrice()) - + (match5Count * LottoPrice.MATCH_5.getPrice()) +(match5BonusCount * LottoPrice.MATCH_5_BONUS.getPrice()) - + (match6Count * LottoPrice.MATCH_6.getPrice()); - return lottoSum; - } - - public static double LottoProfit(int money, int lottoSum) { - return (double) lottoSum / money; - } -} diff --git a/src/main/java/domain/LottoService.java b/src/main/java/domain/LottoService.java index 61a1f46a..854d8d8f 100644 --- a/src/main/java/domain/LottoService.java +++ b/src/main/java/domain/LottoService.java @@ -1,12 +1,11 @@ package domain; -import java.util.Arrays; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; -import java.util.stream.Collectors; public class LottoService { + public Lotto parseLottoAnswer(String lottoAnswer) { SortedSet numbers = new TreeSet<>(); for (String num : lottoAnswer.split(",")) { @@ -15,11 +14,15 @@ public Lotto parseLottoAnswer(String lottoAnswer) { return new Lotto(numbers); } + public void validateBonusBall(Lotto answer, LottoNumber bonusBall) { + if (answer.getNumbers().contains(bonusBall)) { + throw new IllegalArgumentException("보너스 볼은 당첨 번호와 중복될 수 없습니다."); + } + } + public MatchCount calculateMatchCount(List tickets, Lotto answer, LottoNumber bonusBall) { - MatchCount matchCount = MatchCount.countAllMatches(tickets, answer); - MatchCount bonusCount = MatchCount.countBonusBallMatches(tickets, answer, bonusBall); - matchCount.merge(bonusCount); - return matchCount; + return MatchCount.calculateStatistics(tickets, answer, bonusBall); } + } diff --git a/src/main/java/domain/LottoTicketCount.java b/src/main/java/domain/LottoTicketCount.java index 2a014f3b..150b3a82 100644 --- a/src/main/java/domain/LottoTicketCount.java +++ b/src/main/java/domain/LottoTicketCount.java @@ -1,13 +1,24 @@ package domain; public class LottoTicketCount { + private final int count; public LottoTicketCount(int count) { + if(count < 0) { + throw new IllegalArgumentException("로또 티켓 수는 0장 이상이어야 합니다."); + } this.count = count; } public int getCount() { return count; } + + public void validateManualCount(int manualCount) { + if (manualCount < 0 || manualCount > count) { + throw new IllegalArgumentException("수동으로 구매할 로또 수는 0 이상이여야 하며, 구매 가능한 티켓 수를 초과할 수 없습니다."); + } + } + } diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java deleted file mode 100644 index 5ce0d20e..00000000 --- a/src/main/java/domain/LottoTickets.java +++ /dev/null @@ -1,23 +0,0 @@ -package domain; - -import java.util.*; -import java.util.stream.Collectors; - -public class LottoTickets { - private final List tickets; - - public LottoTickets(LottoTicketCount count) { - this.tickets = new ArrayList<>(); - for (int i = 0; i < count.getCount(); i++) { - Set lottoNumbers = createList.generateLottoNumbers(); - SortedSet lottoNumberObjects = lottoNumbers.stream() - .map(LottoNumber::new) - .collect(Collectors.toCollection(TreeSet::new)); - tickets.add(new Lotto(lottoNumberObjects)); - } - } - - public List getTickets() { - return tickets; - } -} diff --git a/src/main/java/domain/LottoTotalPrice.java b/src/main/java/domain/LottoTotalPrice.java index 4617ed71..c3b3a2bf 100644 --- a/src/main/java/domain/LottoTotalPrice.java +++ b/src/main/java/domain/LottoTotalPrice.java @@ -1,21 +1,20 @@ package domain; -import java.util.Arrays; - public class LottoTotalPrice { + private final long totalSum; public LottoTotalPrice(MatchCount matchCount) { - this.totalSum = calculateTotalSum(matchCount); - } - - private long calculateTotalSum(MatchCount matchCount) { - return Arrays.stream(LottoPrice.values()) - .mapToLong(price -> (long) matchCount.getCount(price) * price.getPrice()) - .sum(); + this.totalSum = + ((long) matchCount.getCount(LottoPrice.MATCH_3) * LottoPrice.MATCH_3.getPrice()) + + ((long) matchCount.getCount(LottoPrice.MATCH_4) * LottoPrice.MATCH_4.getPrice()) + + ((long) matchCount.getCount(LottoPrice.MATCH_5) * LottoPrice.MATCH_5.getPrice()) + + ((long) matchCount.getCount(LottoPrice.MATCH_5_BONUS) * LottoPrice.MATCH_5_BONUS.getPrice()) + + ((long) matchCount.getCount(LottoPrice.MATCH_6) * LottoPrice.MATCH_6.getPrice()); } public long getTotalSum() { return totalSum; } + } diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java new file mode 100644 index 00000000..dfe1047c --- /dev/null +++ b/src/main/java/domain/Lottos.java @@ -0,0 +1,39 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.stream.Collectors; + +public class Lottos { + + private List tickets; + + public Lottos() { + this.tickets = new ArrayList<>(); + } + + public static Lottos createMixedTickets(List manualLottos, int autoCount) { + Lottos lottoTickets = new Lottos(); + lottoTickets.tickets.addAll(manualLottos); + + for (int i = 0; i < autoCount; i++) { + Set generatedNumbers = createList.generateLottoNumbers(); + if (generatedNumbers.size() != 6) { + throw new IllegalArgumentException("로또 번호에 중복된 숫자가 있습니다."); + } + SortedSet lottoNumbers = generatedNumbers.stream().map(LottoNumber::new) + .collect(Collectors.toCollection(TreeSet::new)); + lottoTickets.tickets.add(new Lotto(lottoNumbers)); + } + + return lottoTickets; + } + + public List getTickets() { + return tickets; + } + +} diff --git a/src/main/java/domain/Match.java b/src/main/java/domain/Match.java index 84c8f0cb..7bf7eb3d 100644 --- a/src/main/java/domain/Match.java +++ b/src/main/java/domain/Match.java @@ -12,4 +12,5 @@ public static int getMatchCount(Lotto lotto, Lotto lottoAnswer) { } return matchCount; } + } diff --git a/src/main/java/domain/MatchCount.java b/src/main/java/domain/MatchCount.java index 081b987e..5bf66f35 100644 --- a/src/main/java/domain/MatchCount.java +++ b/src/main/java/domain/MatchCount.java @@ -2,9 +2,9 @@ import java.util.EnumMap; import java.util.List; -import domain.Lotto; public class MatchCount { + private final EnumMap counts = new EnumMap<>(LottoPrice.class); public MatchCount() { @@ -21,32 +21,42 @@ public int getCount(LottoPrice price) { return counts.get(price); } - public static MatchCount countAllMatches(List tickets, Lotto answer) { + public static MatchCount calculateStatistics(List tickets, Lotto answer, LottoNumber bonusBall) { MatchCount matchCount = new MatchCount(); + for (Lotto lotto : tickets) { int match = Match.getMatchCount(lotto, answer); - try { - LottoPrice price = LottoPrice.valueOf("MATCH_" + match); + + boolean hasBonusBall = (lotto.contains(bonusBall) == 1); + + LottoPrice price = determineLottoPrice(match, hasBonusBall); + + if (price != null) { matchCount.addCount(price, 1); - } catch (IllegalArgumentException e) { } } return matchCount; } - public static MatchCount countBonusBallMatches(List tickets, Lotto answer, LottoNumber bonusBall) { - MatchCount matchCount = new MatchCount(); - for (Lotto lotto : tickets) { - int match = Match.getMatchCount(lotto, answer); - if (match == 5 && lotto.contains(bonusBall)==1) { - matchCount.addCount(LottoPrice.MATCH_5_BONUS, 1); + + public static LottoPrice determineLottoPrice(int match, boolean hasBonus) { + if (match == 6) { + return LottoPrice.MATCH_6; + } + if (match == 5) { + if (hasBonus) { + return LottoPrice.MATCH_5_BONUS; } + return LottoPrice.MATCH_5; } - return matchCount; - } - public void merge(MatchCount bonusCount) { - for (LottoPrice price : LottoPrice.values()) { - this.addCount(price, bonusCount.getCount(price)); + if (match == 4) { + return LottoPrice.MATCH_4; + } + if (match == 3) { + return LottoPrice.MATCH_3; } + return null; } + } + diff --git a/src/main/java/domain/Money.java b/src/main/java/domain/Money.java index 2b5f2440..e195ed3c 100644 --- a/src/main/java/domain/Money.java +++ b/src/main/java/domain/Money.java @@ -1,6 +1,7 @@ package domain; public class Money { + private static final int LOTTO_PRICE = 1000; private final int money; @@ -10,8 +11,8 @@ public Money(int money) { } private void validate(int money) { - if (money < 0) { - throw new IllegalArgumentException("금액은 0보다 커야 합니다."); + if (money < 1000) { + throw new IllegalArgumentException("로또 구매를 위해서는 금액은 1000원 보다 커야 합니다."); } } @@ -19,7 +20,8 @@ public int getMoney() { return money; } - public static LottoTicketCount getTicketCount(Money money) { - return new LottoTicketCount(money.getMoney() / LOTTO_PRICE); + public LottoTicketCount getTicketCount() { + return new LottoTicketCount(this.money / LOTTO_PRICE); } + } diff --git a/src/main/java/domain/ProfitRate.java b/src/main/java/domain/ProfitRate.java index c2ab9ab6..85e10fde 100644 --- a/src/main/java/domain/ProfitRate.java +++ b/src/main/java/domain/ProfitRate.java @@ -1,13 +1,15 @@ package domain; public class ProfitRate { + private final double profitRate; - public ProfitRate(Money money, LottoTotalPrice totalPrize) { - this.profitRate = (double) totalPrize.getTotalSum() / money.getMoney(); + public ProfitRate(Money money, LottoTotalPrice totalPrice) { + this.profitRate = (double) totalPrice.getTotalSum() / money.getMoney(); } public double getProfitRate() { return profitRate; } + } diff --git a/src/main/java/domain/createList.java b/src/main/java/domain/createList.java index bed2fa6b..7ad3960f 100644 --- a/src/main/java/domain/createList.java +++ b/src/main/java/domain/createList.java @@ -4,9 +4,10 @@ import java.util.Set; public class createList { + public static final int LOTTO_MIN_NUMBER = 1; public static final int LOTTO_MAX_NUMBER = 45; - private static final int LOTTO_NUMBER_COUNT=6; + public static final int LOTTO_NUMBER_COUNT = 6; public static Set generateLottoNumbers() { Set numbers = new HashSet<>(); @@ -16,4 +17,5 @@ public static Set generateLottoNumbers() { } return numbers; } + } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a27d17ae..d7951901 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,22 +1,37 @@ package view; + import java.util.Scanner; public class InputView { + Scanner scanner = new Scanner(System.in); public int inputMoney() { - int money= scanner.nextInt(); + int money = scanner.nextInt(); + scanner.nextLine(); return money; } public String inputLottoAnswer() { - scanner.nextLine(); String lottoAnswer = scanner.nextLine(); return lottoAnswer; } public int inputBonusNumber() { int bonusNumber = scanner.nextInt(); + scanner.nextLine(); return bonusNumber; } + + public int inputManualCount() { + int manualCount = scanner.nextInt(); + scanner.nextLine(); + return manualCount; + } + + public String inputManualNumbers() { + String manualNumbers = scanner.nextLine(); + return manualNumbers; + } + } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9d41abd0..7017b1d2 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -19,4 +19,13 @@ public void lottoResult() { public void printBonusMessage() { System.out.println("보너스 볼을 입력해 주세요."); } + + public void printManualCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + } + + public void printManualNumbers() { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + } + } diff --git a/src/main/java/view/ResultView.java b/src/main/java/view/ResultView.java index 790bfe88..aaa004bd 100644 --- a/src/main/java/view/ResultView.java +++ b/src/main/java/view/ResultView.java @@ -7,25 +7,30 @@ public class ResultView { public void printTicketNumbers(int ticketNumber) { System.out.println(); - System.out.println(ticketNumber+"개를 구매했습니다."); + System.out.println(ticketNumber + "개를 구매했습니다."); + } + + + public void printManualAuto(int manualCount, int autoCount) { + System.out.println("수동으로 " + manualCount + "장, 자동으로 " + autoCount + "개를 구매했습니다."); } public void printLottoMatch(MatchCount matchCount) { - int match3Count = matchCount.getCount(LottoPrice.MATCH_3); - int match4Count = matchCount.getCount(LottoPrice.MATCH_4); - int match5Count = matchCount.getCount(LottoPrice.MATCH_5); - int matchSecond = matchCount.getCount(LottoPrice.MATCH_5); - int match6Count = matchCount.getCount(LottoPrice.MATCH_6); - - - System.out.println("3개 일치 (5000원) - " + match3Count + "개"); - System.out.println("4개 일치 (50000원) - " + match4Count + "개"); - System.out.println("5개 일치 (1500000원) - " + match5Count + "개"); - System.out.println("5개 일, 보너스 볼 일치 (30000000) - "+ matchSecond + "개"); - System.out.println("6개 일치 (2000000000원) - " + match6Count + "개"); + int matchFifth = matchCount.getCount(LottoPrice.MATCH_3); + int matchFourth = matchCount.getCount(LottoPrice.MATCH_4); + int matcThird = matchCount.getCount(LottoPrice.MATCH_5); + int matchSecond = matchCount.getCount(LottoPrice.MATCH_5_BONUS); + int matchFirst = matchCount.getCount(LottoPrice.MATCH_6); + + + System.out.println("3개 일치 (5000원) - " + matchFifth + "개"); + System.out.println("4개 일치 (50000원) - " + matchFourth + "개"); + System.out.println("5개 일치 (1500000원) - " + matcThird + "개"); + System.out.println("5개 일치, 보너스 볼 일치 (30000000) - " + matchSecond + "개"); + System.out.println("6개 일치 (2000000000원) - " + matchFirst + "개"); } public void printLottoProfit(double profitRate) { - System.out.printf("총 수익률은 %.2f입니다.%n",profitRate); + System.out.printf("총 수익률은 %.2f입니다.%n", profitRate); } } diff --git a/src/test/java/CashTest.java b/src/test/java/CashTest.java index b5f772d8..3e8e0f05 100644 --- a/src/test/java/CashTest.java +++ b/src/test/java/CashTest.java @@ -1,54 +1,67 @@ -import domain.*; +import domain.LottoPrice; +import domain.Money; +import domain.LottoTicketCount; +import domain.LottoTotalPrice; +import domain.MatchCount; +import domain.ProfitRate; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; public class CashTest { @Test @DisplayName("금액 입력 시 올바른 로또 갯수가 출력되는지 확인") - - void testCashToTicket(){ + void testCashToTicket() { Money money = new Money(5500); - LottoTicketCount ticketNumber = Money.getTicketCount(money); - assertEquals(5,ticketNumber.getCount()); + LottoTicketCount ticketNumber = money.getTicketCount(); + assertEquals(5, ticketNumber.getCount()); } @Test @DisplayName("금액 입력이 올바르지 않을 시 예외처리") - void testInvalidCash(){ - try { - Money money = new Money(-5000); - } catch (IllegalArgumentException e) { - assertEquals("금액은 0보다 커야 합니다.", e.getMessage()); - } + void testInvalidCash() { + assertThrows(IllegalArgumentException.class, () -> new Money(-5000)); } @Test @DisplayName("최종 당첨 금액 합계가 올바른지 확인") - void totalSum(){ + void totalSum() { MatchCount matchCount = new MatchCount(); matchCount.addCount(LottoPrice.MATCH_3, 2); matchCount.addCount(LottoPrice.MATCH_4, 1); - matchCount.addCount(LottoPrice.MATCH_5, 0); + matchCount.addCount(LottoPrice.MATCH_5, 1); matchCount.addCount(LottoPrice.MATCH_6, 1); - int expectedSum = LottoPrice.MATCH_3.getPrice()*2+ - LottoPrice.MATCH_4.getPrice()*1+ - LottoPrice.MATCH_5.getPrice()*0+ - LottoPrice.MATCH_6.getPrice()*1; - int sum = LottoProfit.LottoSum(matchCount); + long expectedSum = LottoPrice.MATCH_3.getPrice() * 2 + + LottoPrice.MATCH_4.getPrice() * 1 + + LottoPrice.MATCH_5.getPrice() * 1 + + LottoPrice.MATCH_6.getPrice() * 1; + + LottoTotalPrice totalPrice = new LottoTotalPrice(matchCount); + long sum = totalPrice.getTotalSum(); assertEquals(expectedSum, sum); } @Test @DisplayName("수익률이 올바른지 확인") - void profitRate(){ - int totalSum = 48000000; - int purchaseAmount = 24000; - double profitRate = LottoProfit.LottoProfit(purchaseAmount, totalSum); - assertEquals((double) totalSum /purchaseAmount, profitRate); + void profitRate() { + final int totalSumValue = 48000000; + final int purchaseAmount = 24000; + + Money money = new Money(purchaseAmount); + LottoTotalPrice fixedTotalPrice = new LottoTotalPrice(new MatchCount()) { + @Override + public long getTotalSum() { + return totalSumValue; + } + }; + + ProfitRate profitRate = new ProfitRate(money, fixedTotalPrice); + assertEquals((double) totalSumValue / purchaseAmount, profitRate.getProfitRate()); } } diff --git a/src/test/java/LottoTest.java b/src/test/java/LottoTest.java index 5f49e664..cb1adb48 100644 --- a/src/test/java/LottoTest.java +++ b/src/test/java/LottoTest.java @@ -4,22 +4,65 @@ import java.util.Arrays; import java.util.List; import java.util.SortedSet; +import java.util.TreeSet; -import domain.*; +import domain.Lotto; +import domain.LottoNumber; +import domain.LottoService; +import domain.MatchCount; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -//실패코드 작성 public class LottoTest { @Test @DisplayName("로또 숫자가 1~45 사이의 숫자가 아닐 경우 예외가 발생한다") void testLottoRange() { - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { - List outOfRange = Arrays.asList(new LottoNumber(0), new LottoNumber(2), new LottoNumber(3), new LottoNumber(4), new LottoNumber(5), new LottoNumber(6)); - new Lotto((SortedSet) outOfRange); - }); + IllegalArgumentException e = assertThrows( + IllegalArgumentException.class, () -> { + List outOfRange = Arrays.asList( + new LottoNumber(0), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + ); + new Lotto((SortedSet) outOfRange); + } + ); assertEquals("로또 번호는 1부터 45 사이의 숫자여야 합니다.", e.getMessage()); } + + @Test + @DisplayName("보너스볼 숫자가 기존 당첨번호와 중복될 경우 예외가 발생한다.") + void bonusBallDuplicate() { + LottoService lottoService = new LottoService(); + Lotto lottoAnswer = lottoService.parseLottoAnswer("1,2,3,4,5,6"); + IllegalArgumentException e = assertThrows( + IllegalArgumentException.class, () -> { + lottoService.validateBonusBall(lottoAnswer, new LottoNumber(1)); + } + ); + assertEquals("보너스 볼은 당첨 번호와 중복될 수 없습니다.", e.getMessage()); + } + + @Test + @DisplayName("로또 번호 수동 입력 시 중복된 숫자가 들어올 경우 예외가 발생한다.") + void manualLottoDuplicate() { + SortedSet duplicateNumbers = new TreeSet<>(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(5) + )); + + assertThatThrownBy(() -> new Lotto(duplicateNumbers)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("로또 숫자는 6개여야 하며, 중복될 수 없습니다."); + } + } diff --git a/src/test/java/MatchCountTest.java b/src/test/java/MatchCountTest.java index aa3d2975..a1b3782c 100644 --- a/src/test/java/MatchCountTest.java +++ b/src/test/java/MatchCountTest.java @@ -1,34 +1,48 @@ import domain.Lotto; -import domain.LottoPrice; import domain.LottoNumber; -import domain.Match; +import domain.MatchCount; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.api.Test; + import java.util.Arrays; +import java.util.List; +import java.util.TreeSet; + import static org.junit.jupiter.api.Assertions.*; class MatchCountTest { - @ParameterizedTest - @CsvSource({ - "1,2,3,4,5,6,1,2,3,4,5,6,MATCH_6", - "1,2,3,4,5,7,1,2,3,4,5,6,MATCH_5", - "1,2,3,4,8,9,1,2,3,4,5,6,MATCH_4" - }) - @DisplayName("당첨 통계 테스트") - void Match(int n1, int n2, int n3, int n4, int n5, int n6, - int w1, int w2, int w3, int w4, int w5, int w6, - LottoPrice expectedRank) { - Lotto lotto = new Lotto(new java.util.TreeSet<>(Arrays.asList( - new LottoNumber(n1), new LottoNumber(n2), new LottoNumber(n3), - new LottoNumber(n4), new LottoNumber(n5), new LottoNumber(n6) - ))); - Lotto winningLotto = new Lotto(new java.util.TreeSet<>(Arrays.asList( - new LottoNumber(w1), new LottoNumber(w2), new LottoNumber(w3), - new LottoNumber(w4), new LottoNumber(w5), new LottoNumber(w6) - ))); - int matchCount = Match.getMatchCount(lotto, winningLotto); - LottoPrice actualRank = LottoPrice.valueOf("MATCH_" + matchCount); - assertEquals(expectedRank, actualRank); + + @Test + @DisplayName("구매한 로또 티켓들의 당첨 통계를 올바르게 계산한다") + void calculateStatisticsTest() { + + Lotto winningLotto = createLotto(1, 2, 3, 4, 5, 6); + LottoNumber bonusBall = new LottoNumber(7); + + List tickets = Arrays.asList( + createLotto(1, 2, 3, 4, 5, 6), + createLotto(1, 2, 3, 4, 5, 7), + createLotto(1, 2, 3, 4, 5, 8), + createLotto(1, 2, 3, 4, 10, 11), + createLotto(1, 2, 3, 12, 13, 14) + ); + + MatchCount result = MatchCount.calculateStatistics(tickets, winningLotto, bonusBall); + + assertEquals(1, result.getCount(domain.LottoPrice.MATCH_6)); + assertEquals(1, result.getCount(domain.LottoPrice.MATCH_5_BONUS)); + assertEquals(1, result.getCount(domain.LottoPrice.MATCH_5)); + assertEquals(1, result.getCount(domain.LottoPrice.MATCH_4)); + assertEquals(1, result.getCount(domain.LottoPrice.MATCH_3)); + } + + private Lotto createLotto(int... numbers) { + return new Lotto( + new TreeSet<>( + Arrays.stream(numbers) + .mapToObj(LottoNumber::new) + .toList() + ) + ); } }