From 12bedd757bdd468876a0292fa17bf35c311e1a84 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Fri, 31 Jul 2026 14:20:47 +0900 Subject: [PATCH 01/58] =?UTF-8?q?feat:=20=EA=B8=B0=EB=B3=B8=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 9 ++++++ src/main/java/domain/Lotto.java | 6 ++++ src/main/java/domain/LottoTicketCount.java | 14 ++++++++++ src/main/java/domain/LottoTickets.java | 6 ++++ src/main/java/view/InputView.java | 32 ++++++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/domain/Lotto.java create mode 100644 src/main/java/domain/LottoTicketCount.java create mode 100644 src/main/java/domain/LottoTickets.java create mode 100644 src/main/java/view/InputView.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 000000000..2a046b2cd --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,9 @@ +import java.util.Scanner; +import view.InputView; + +public class Application { + + public static void main(String[] args) { + + } +} diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java new file mode 100644 index 000000000..362c740b7 --- /dev/null +++ b/src/main/java/domain/Lotto.java @@ -0,0 +1,6 @@ +package domain; + +public class Lotto { + //한 장에 들어있는 숫자들을 갖고있으면 됨 + +} diff --git a/src/main/java/domain/LottoTicketCount.java b/src/main/java/domain/LottoTicketCount.java new file mode 100644 index 000000000..a2a2498d6 --- /dev/null +++ b/src/main/java/domain/LottoTicketCount.java @@ -0,0 +1,14 @@ +package domain; + +public class LottoTicketCount { //로또 금액 들어오면 비즈니스 규칙에 알맞게 수량을 정수로 반환해줌 + public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; + int lottoTicketCount; + + public int convertLottoPriceToTickets(int totalLottoPrice) { + lottoTicketCount = totalLottoPrice / PRICE_PER_ONE_LOTTO_TICKET; + + return lottoTicketCount; + } + + +} diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java new file mode 100644 index 000000000..360c1cf42 --- /dev/null +++ b/src/main/java/domain/LottoTickets.java @@ -0,0 +1,6 @@ +package domain; + +public class LottoTickets { + //로또 타입의 객체를 특정 수량만큼 초기화할수있는, 모아둘수있는 일급컬렉션 + +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 000000000..2d974537c --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,32 @@ +package view; + +import java.util.Scanner; + +public final class InputView { + + private InputView() { + + } + + public static int inputLottoTotalPrice(){ + System.out.println("구입 금액을 입력해 주세요."); + Scanner lottoScanner = new Scanner(System.in); + String stringLottoTotalPrice; + int validLottoTotalPrice; + + try { + stringLottoTotalPrice = lottoScanner.nextLine(); + + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("정수로 입력해주세요"); + } + + validLottoTotalPrice = Integer.parseInt(stringLottoTotalPrice); + + return validLottoTotalPrice; + } + + public static void closeScanner(Scanner scanner) { + closeScanner(scanner); + } +} From 601eb714f24d09e5ba23d420d6810014a54d893b Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sat, 1 Aug 2026 14:09:34 +0900 Subject: [PATCH 02/58] =?UTF-8?q?feat:=20Lotto=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 362c740b7..4b0c69a94 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -1,6 +1,24 @@ package domain; +import java.util.Random; +import java.util.TreeSet; + public class Lotto { - //한 장에 들어있는 숫자들을 갖고있으면 됨 + public static final int LOTTO_NUMBER_BOUND = 45; + public static final int LOTTO_NUBER_COUNT = 6; + + TreeSet randomNumberSet = new TreeSet<>(); + Random random = new Random(); + + public Lotto() { // 로또 한장 생성자 + setLottoNumber(); + } + + private void setLottoNumber(){ + while (randomNumberSet.size() < LOTTO_NUBER_COUNT) { + randomNumberSet.add(random.nextInt(LOTTO_NUMBER_BOUND + 1)); + } + + } } From 7d6e0c48fae26019fff75c375b6f18e250a36757 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sat, 1 Aug 2026 14:26:04 +0900 Subject: [PATCH 03/58] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EC=9E=85=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=EB=B0=9B?= =?UTF-8?q?=EC=95=84=EC=84=9C=20=EC=88=98=EB=9F=89=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 8 ++++++++ src/main/java/view/OutputView.java | 13 +++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/main/java/view/OutputView.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 2a046b2cd..3615d93e1 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,9 +1,17 @@ +import domain.LottoTicketCount; import java.util.Scanner; import view.InputView; +import view.OutputView; public class Application { public static void main(String[] args) { + LottoTicketCount lottoTicketCount = new LottoTicketCount(); + int lottoTicketTotalCount; + lottoTicketTotalCount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); + OutputView.printLottoCount(lottoTicketTotalCount); + + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 000000000..24c7b7f48 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,13 @@ +package view; + +public final class OutputView { + //로또 몇장 사는지를 받아서 "~~개를 구매했습니다." 출력 + private OutputView() { + + } + + public static void printLottoCount(int lottoCount) { + System.out.println(lottoCount + "개를 구매했습니다"); + } + +} From 5bc11909f68a2849e18c6efb7e4d3c71b49dad7e Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sat, 1 Aug 2026 14:51:10 +0900 Subject: [PATCH 04/58] =?UTF-8?q?feat:=201=EB=8B=A8=EA=B3=84=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=EC=9E=90=EB=8F=99=EA=B5=AC=EB=A7=A4=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 5 +++++ src/main/java/domain/Lotto.java | 4 ++++ src/main/java/domain/LottoTicketCount.java | 6 ++---- src/main/java/domain/LottoTickets.java | 19 +++++++++++++++++++ src/main/java/view/OutputView.java | 8 ++++++++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 3615d93e1..4af594337 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,4 +1,5 @@ import domain.LottoTicketCount; +import domain.LottoTickets; import java.util.Scanner; import view.InputView; import view.OutputView; @@ -11,6 +12,10 @@ public static void main(String[] args) { lottoTicketTotalCount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); OutputView.printLottoCount(lottoTicketTotalCount); + LottoTickets lottoTickets = new LottoTickets(); + lottoTickets.makeLottos(lottoTicketTotalCount); + OutputView.printLottoNumbers(lottoTickets); + } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 4b0c69a94..363839762 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -21,4 +21,8 @@ private void setLottoNumber(){ } + public TreeSet getRandomNumberSet() { + return this.randomNumberSet; + } + } diff --git a/src/main/java/domain/LottoTicketCount.java b/src/main/java/domain/LottoTicketCount.java index a2a2498d6..cbfcab35b 100644 --- a/src/main/java/domain/LottoTicketCount.java +++ b/src/main/java/domain/LottoTicketCount.java @@ -2,13 +2,11 @@ public class LottoTicketCount { //로또 금액 들어오면 비즈니스 규칙에 알맞게 수량을 정수로 반환해줌 public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; - int lottoTicketCount; + private int lottoTicketCount; - public int convertLottoPriceToTickets(int totalLottoPrice) { + public int convertLottoPriceToTicketCount(int totalLottoPrice) { lottoTicketCount = totalLottoPrice / PRICE_PER_ONE_LOTTO_TICKET; - return lottoTicketCount; } - } diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index 360c1cf42..3d8c3c06b 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -1,6 +1,25 @@ package domain; +import java.util.ArrayList; + public class LottoTickets { //로또 타입의 객체를 특정 수량만큼 초기화할수있는, 모아둘수있는 일급컬렉션 + ArrayList lottoArrayList = new ArrayList<>(); + + public LottoTickets() { //생성자 + + } + + //정적 팩토리 패턴 + public ArrayList makeLottos(int lottoTotalCount){ + for (int i = 0; i < lottoTotalCount; i++) { + lottoArrayList.add(new Lotto()); + } + return lottoArrayList; + } + + public ArrayList getLottoArrayList(){ + return new ArrayList<>(lottoArrayList); + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 24c7b7f48..20e8272c4 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,5 +1,7 @@ package view; +import domain.LottoTickets; + public final class OutputView { //로또 몇장 사는지를 받아서 "~~개를 구매했습니다." 출력 private OutputView() { @@ -10,4 +12,10 @@ public static void printLottoCount(int lottoCount) { System.out.println(lottoCount + "개를 구매했습니다"); } + public static void printLottoNumbers(LottoTickets lottoTickets) { + for(int i = 0; i< lottoTickets.getLottoArrayList().size(); i++) { + System.out.println(lottoTickets.getLottoArrayList().get(i).getRandomNumberSet()); + } + } + } From 809289de6c53fa56d0ea3f3d71f90d3cc86275eb Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sat, 1 Aug 2026 14:52:03 +0900 Subject: [PATCH 05/58] =?UTF-8?q?chore:=20=EC=B6=9C=EB=A0=A5=ED=98=95?= =?UTF-8?q?=EC=8B=9D=20=EC=A4=80=EC=88=98=20-=20=EC=A4=84=EB=B0=94?= =?UTF-8?q?=EA=BF=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 20e8272c4..572ca82f8 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -10,6 +10,7 @@ private OutputView() { public static void printLottoCount(int lottoCount) { System.out.println(lottoCount + "개를 구매했습니다"); + System.out.println(); } public static void printLottoNumbers(LottoTickets lottoTickets) { From 8a8fe2b8f70f7006a2abec9ab2451dbfe63ff259 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 00:54:40 +0900 Subject: [PATCH 06/58] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B0=8F=20=EB=8B=B9=EC=B2=A8=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 22 ++++++-- src/main/java/domain/Lotto.java | 2 +- src/main/java/domain/LottoChecker.java | 77 ++++++++++++++++++++++++++ src/main/java/domain/LottoResult.java | 50 +++++++++++++++++ src/main/java/domain/LottoTickets.java | 9 ++- src/main/java/view/InputView.java | 12 +++- src/main/java/view/OutputView.java | 22 +++++++- 7 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 src/main/java/domain/LottoChecker.java create mode 100644 src/main/java/domain/LottoResult.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 4af594337..4818770ff 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,8 @@ +import domain.LottoChecker; +import domain.LottoResult; import domain.LottoTicketCount; import domain.LottoTickets; +import java.util.Map; import java.util.Scanner; import view.InputView; import view.OutputView; @@ -8,14 +11,25 @@ public class Application { public static void main(String[] args) { LottoTicketCount lottoTicketCount = new LottoTicketCount(); - int lottoTicketTotalCount; - lottoTicketTotalCount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); - OutputView.printLottoCount(lottoTicketTotalCount); + int lottoTicketTotalAmount; + lottoTicketTotalAmount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); + OutputView.printLottoCount(lottoTicketTotalAmount); LottoTickets lottoTickets = new LottoTickets(); - lottoTickets.makeLottos(lottoTicketTotalCount); + lottoTickets.makeLottos(lottoTicketTotalAmount); OutputView.printLottoNumbers(lottoTickets); + String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); + // todo: 사용자가 입력한 지난주 당첨번호가 6개가 아니라면,, -> 예외처리? 어디에서? + + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets); + Map countedMatches = lottoChecker.countMatches(lottoChecker.checkAllTickets()); + OutputView.printMatchCount(countedMatches); + + LottoResult lottoResult = new LottoResult(countedMatches, lottoTicketTotalAmount); + + OutputView.printRateOfReturn(lottoResult.calculateProfitRate()); + } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 363839762..f7464cb8e 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -16,7 +16,7 @@ public Lotto() { // 로또 한장 생성자 private void setLottoNumber(){ while (randomNumberSet.size() < LOTTO_NUBER_COUNT) { - randomNumberSet.add(random.nextInt(LOTTO_NUMBER_BOUND + 1)); + randomNumberSet.add(random.nextInt(1, LOTTO_NUMBER_BOUND + 1)); } } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java new file mode 100644 index 000000000..4573708ab --- /dev/null +++ b/src/main/java/domain/LottoChecker.java @@ -0,0 +1,77 @@ +package domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class LottoChecker { + private final ArrayList winningLottoNumbers; + private final LottoTickets lottoTickets; + + public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTickets) { + this.winningLottoNumbers = wrappingToIntegerLottoNumbers(lastWeekWinnerLottoNumbers); + this.lottoTickets = lottoTickets; + } + + private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { + return (ArrayList) Arrays.stream(stringWinnerNumbers) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } + + public ArrayList checkAllTickets() { + ArrayList matchCounts = new ArrayList<>(); + + for (int i = 0; i < lottoTickets.getSize(); i++) { + matchCounts.add(calculateMatchCountForTicket(i)); + } + + return matchCounts; + } + + private int calculateMatchCountForTicket(int lottoTicketIndex) { + int matchCount = 0; + + for (int winningNumber : winningLottoNumbers) { + matchCount += getMatchScore(lottoTicketIndex, winningNumber); + } + + return matchCount; + } + + private int getMatchScore(int lottoTicketIndex, int winningNumber) { + if (lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(winningNumber)) { + return 1; + } + return 0; + } + + public Map countMatches(ArrayList matchCounts) { + Map matchStatistics = new HashMap<>(); + + for (int matchCount : matchCounts) { + updateStatistics(matchStatistics, matchCount); + } + + return matchStatistics; + } + + private void updateStatistics(Map matchStatistics, int matchCount) { + if (matchCount < 3) { + return; + } + + if (matchStatistics.containsKey(matchCount)) { + int currentCount = matchStatistics.get(matchCount); + matchStatistics.put(matchCount, currentCount + 1); + return; + } + + matchStatistics.put(matchCount, 1); + } + + +} diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java new file mode 100644 index 000000000..dfbe9428f --- /dev/null +++ b/src/main/java/domain/LottoResult.java @@ -0,0 +1,50 @@ +package domain; + +import java.util.Map; + +public class LottoResult { + private static final long PRIZE_3_MATCH = 5000; + private static final long PRIZE_4_MATCH = 50000; + private static final long PRIZE_5_MATCH = 1500000; + private static final long PRIZE_6_MATCH = 2000000000; + public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; + + private final Map matchStatistics; + private final int purchaseAmount; + + public LottoResult(Map matchStatistics, int purchaseAmount) { + this.matchStatistics = matchStatistics; + this.purchaseAmount = purchaseAmount * PRICE_PER_ONE_LOTTO_TICKET; + } + + private long calculateTotalPrize() { + long totalPrize = 0; + + if (matchStatistics.containsKey(3)) { + totalPrize += PRIZE_3_MATCH * matchStatistics.get(3); + } + if (matchStatistics.containsKey(4)) { + totalPrize += PRIZE_4_MATCH * matchStatistics.get(4); + } + if (matchStatistics.containsKey(5)) { + totalPrize += PRIZE_5_MATCH * matchStatistics.get(5); + } + if (matchStatistics.containsKey(6)) { + totalPrize += PRIZE_6_MATCH * matchStatistics.get(6); + } + + return totalPrize; + } + + public double calculateProfitRate() { + long totalWinningPrize = calculateTotalPrize(); + + if (totalWinningPrize == 0) { + return 0.0; + } + + double profitRate = (double) totalWinningPrize / purchaseAmount; + + return profitRate; + } +} diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index 3d8c3c06b..cf2a76c87 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -1,6 +1,7 @@ package domain; import java.util.ArrayList; +import java.util.TreeSet; public class LottoTickets { //로또 타입의 객체를 특정 수량만큼 초기화할수있는, 모아둘수있는 일급컬렉션 @@ -18,8 +19,12 @@ public ArrayList makeLottos(int lottoTotalCount){ return lottoArrayList; } - public ArrayList getLottoArrayList(){ - return new ArrayList<>(lottoArrayList); + public TreeSet getLottoTreeSet(int lottoTicketNumber){ + return new TreeSet<>(lottoArrayList.get(lottoTicketNumber).getRandomNumberSet()); } + + public int getSize() { + return lottoArrayList.size(); + } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 2d974537c..5fb9c227c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -3,14 +3,14 @@ import java.util.Scanner; public final class InputView { + private static final Scanner lottoScanner = new Scanner(System.in); private InputView() { - } public static int inputLottoTotalPrice(){ System.out.println("구입 금액을 입력해 주세요."); - Scanner lottoScanner = new Scanner(System.in); + String stringLottoTotalPrice; int validLottoTotalPrice; @@ -26,6 +26,14 @@ public static int inputLottoTotalPrice(){ return validLottoTotalPrice; } + public static String inputWinningLottoNumbers(){ + + System.out.println("\n지난 주 당첨번호를 입력해 주세요"); + String winningLottoNumbers = lottoScanner.nextLine(); + + return winningLottoNumbers; + } + public static void closeScanner(Scanner scanner) { closeScanner(scanner); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 572ca82f8..7f3dd9e3c 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,9 +1,11 @@ package view; import domain.LottoTickets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public final class OutputView { - //로또 몇장 사는지를 받아서 "~~개를 구매했습니다." 출력 private OutputView() { } @@ -14,9 +16,23 @@ public static void printLottoCount(int lottoCount) { } public static void printLottoNumbers(LottoTickets lottoTickets) { - for(int i = 0; i< lottoTickets.getLottoArrayList().size(); i++) { - System.out.println(lottoTickets.getLottoArrayList().get(i).getRandomNumberSet()); + for(int i = 0; i< lottoTickets.getSize(); i++) { + System.out.println(lottoTickets.getLottoTreeSet(i)); } } + public static void printMatchCount(Map matchStatistics) { + System.out.println("\n당첨 통계"); + System.out.println("---------"); + + System.out.println("3개 일치 (5000원)- " + matchStatistics.get(3) + "개"); + System.out.println("4개 일치 (50000원)- " + matchStatistics.get(4) + "개"); + System.out.println("5개 일치 (1500000원)- " + matchStatistics.get(5) + "개"); + System.out.println("6개 일치 (2000000000원)- " + matchStatistics.get(6) + "개"); + } + + public static void printRateOfReturn(double rateOfReturn) { + System.out.printf("총 수익률은 %.2f입니다.", rateOfReturn); + } + } From ba04b5d5bbf760873bfcc5432858cfa063db5245 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 16:08:25 +0900 Subject: [PATCH 07/58] =?UTF-8?q?feat:=20=EA=B0=81=20=EB=A7=A4=EC=B9=AD?= =?UTF-8?q?=EA=B0=9C=EC=88=98=EB=B3=84=20enum=20=EB=A7=8C=EB=93=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoWinningType.java | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/domain/LottoWinningType.java diff --git a/src/main/java/domain/LottoWinningType.java b/src/main/java/domain/LottoWinningType.java new file mode 100644 index 000000000..1c4231d19 --- /dev/null +++ b/src/main/java/domain/LottoWinningType.java @@ -0,0 +1,25 @@ +package domain; + +import java.util.function.Function; + +public enum LottoWinningTypePrize { + PRIZE_3_MATCH(originMatchCount -> originMatchCount * 5000), + PRIZE_4_MATCH(originMatchCount -> originMatchCount * 50000), + PRIZE_5_MATCH(originMatchCount -> originMatchCount * 1500000), + PRIZE_5_MATCH_AND_1_BONUS_BALL_MATCH(originMatchCount -> originMatchCount * 30000000), + PRIZE_6_MATCH(originMatchCount -> originMatchCount * 2000000000); + + private final Function expression; + + LottoWinningTypePrize(Function expression) { + this.expression = expression; + } + + public long calculatePrize(int originMatchCount) { + return expression.apply(originMatchCount); + } + + + + +} From 27467927833b376c7db205acecf9e1dc80c09264 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 16:13:48 +0900 Subject: [PATCH 08/58] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=EA=B8=88?= =?UTF-8?q?=EC=9D=B4=20=EC=97=86=EB=8A=94=20=ED=83=80=EC=9E=85=EC=9D=BC?= =?UTF-8?q?=EB=95=8C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...WinningType.java => LottoWinningTypePrize.java} | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) rename src/main/java/domain/{LottoWinningType.java => LottoWinningTypePrize.java} (60%) diff --git a/src/main/java/domain/LottoWinningType.java b/src/main/java/domain/LottoWinningTypePrize.java similarity index 60% rename from src/main/java/domain/LottoWinningType.java rename to src/main/java/domain/LottoWinningTypePrize.java index 1c4231d19..2bedb9501 100644 --- a/src/main/java/domain/LottoWinningType.java +++ b/src/main/java/domain/LottoWinningTypePrize.java @@ -1,5 +1,6 @@ package domain; +import java.util.Arrays; import java.util.function.Function; public enum LottoWinningTypePrize { @@ -7,7 +8,8 @@ public enum LottoWinningTypePrize { PRIZE_4_MATCH(originMatchCount -> originMatchCount * 50000), PRIZE_5_MATCH(originMatchCount -> originMatchCount * 1500000), PRIZE_5_MATCH_AND_1_BONUS_BALL_MATCH(originMatchCount -> originMatchCount * 30000000), - PRIZE_6_MATCH(originMatchCount -> originMatchCount * 2000000000); + PRIZE_6_MATCH(originMatchCount -> originMatchCount * 2000000000), + NO_PRIZE(originMatchCount -> 0L); private final Function expression; @@ -16,10 +18,14 @@ public enum LottoWinningTypePrize { } public long calculatePrize(int originMatchCount) { - return expression.apply(originMatchCount); + return expression.apply((long) originMatchCount); } - - + public static LottoWinningTypePrize findLottoWinningType(String winningType){ + return Arrays.stream(LottoWinningTypePrize.values()) + .filter(lottoWinningTypePrize -> lottoWinningTypePrize.name().equals(winningType)) + .findAny() + .orElse(NO_PRIZE); + } } From bc789de56abceb832394d7794bf9439d1d560347 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 16:22:40 +0900 Subject: [PATCH 09/58] =?UTF-8?q?feat:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=B0=8F=20LottoChecker=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 2 ++ src/main/java/domain/LottoChecker.java | 8 +++++++- src/main/java/domain/LottoResult.java | 19 ------------------- src/main/java/view/InputView.java | 7 +++++++ 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 4818770ff..3ca107bb1 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -22,6 +22,8 @@ public static void main(String[] args) { String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); // todo: 사용자가 입력한 지난주 당첨번호가 6개가 아니라면,, -> 예외처리? 어디에서? + String bonusNumber = InputView.inputBonusBallNumber(); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets); Map countedMatches = lottoChecker.countMatches(lottoChecker.checkAllTickets()); OutputView.printMatchCount(countedMatches); diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 4573708ab..16069846f 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -10,10 +10,12 @@ public class LottoChecker { private final ArrayList winningLottoNumbers; private final LottoTickets lottoTickets; + private final String bonusNumber; - public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTickets) { + public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTickets, String bonusNumber) { this.winningLottoNumbers = wrappingToIntegerLottoNumbers(lastWeekWinnerLottoNumbers); this.lottoTickets = lottoTickets; + this.bonusNumber = bonusNumber; } private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { @@ -22,6 +24,10 @@ private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNu .collect(Collectors.toList()); } + private Integer wrappingToIntegerBonusNumber(String bonusNumber) { + return Integer.getInteger(bonusNumber); + } + public ArrayList checkAllTickets() { ArrayList matchCounts = new ArrayList<>(); diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index dfbe9428f..151694254 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -3,10 +3,6 @@ import java.util.Map; public class LottoResult { - private static final long PRIZE_3_MATCH = 5000; - private static final long PRIZE_4_MATCH = 50000; - private static final long PRIZE_5_MATCH = 1500000; - private static final long PRIZE_6_MATCH = 2000000000; public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; private final Map matchStatistics; @@ -18,22 +14,7 @@ public LottoResult(Map matchStatistics, int purchaseAmount) { } private long calculateTotalPrize() { - long totalPrize = 0; - if (matchStatistics.containsKey(3)) { - totalPrize += PRIZE_3_MATCH * matchStatistics.get(3); - } - if (matchStatistics.containsKey(4)) { - totalPrize += PRIZE_4_MATCH * matchStatistics.get(4); - } - if (matchStatistics.containsKey(5)) { - totalPrize += PRIZE_5_MATCH * matchStatistics.get(5); - } - if (matchStatistics.containsKey(6)) { - totalPrize += PRIZE_6_MATCH * matchStatistics.get(6); - } - - return totalPrize; } public double calculateProfitRate() { diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 5fb9c227c..41d98a1b5 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -34,6 +34,13 @@ public static String inputWinningLottoNumbers(){ return winningLottoNumbers; } + public static String inputBonusBallNumber(){ + System.out.println("\n보너스 볼을 입력해 주세요."); + String bonusNumber = lottoScanner.nextLine(); + + return bonusNumber; + } + public static void closeScanner(Scanner scanner) { closeScanner(scanner); } From 7298be7db1ad9c5ea29e27262dbbe5b725871331 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 16:46:04 +0900 Subject: [PATCH 10/58] =?UTF-8?q?chore:=20=EC=98=A4=ED=83=80=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index f7464cb8e..aae0a80c3 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -5,7 +5,7 @@ public class Lotto { public static final int LOTTO_NUMBER_BOUND = 45; - public static final int LOTTO_NUBER_COUNT = 6; + public static final int LOTTO_NUMBER_COUNT = 6; TreeSet randomNumberSet = new TreeSet<>(); Random random = new Random(); @@ -15,7 +15,7 @@ public Lotto() { // 로또 한장 생성자 } private void setLottoNumber(){ - while (randomNumberSet.size() < LOTTO_NUBER_COUNT) { + while (randomNumberSet.size() < LOTTO_NUMBER_COUNT) { randomNumberSet.add(random.nextInt(1, LOTTO_NUMBER_BOUND + 1)); } From ef22e9137221dd1e58135551cc411d57574f2600 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 16:48:30 +0900 Subject: [PATCH 11/58] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=A7=80=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoTickets.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index cf2a76c87..c47a3f68d 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -4,14 +4,8 @@ import java.util.TreeSet; public class LottoTickets { - //로또 타입의 객체를 특정 수량만큼 초기화할수있는, 모아둘수있는 일급컬렉션 ArrayList lottoArrayList = new ArrayList<>(); - public LottoTickets() { //생성자 - - } - - //정적 팩토리 패턴 public ArrayList makeLottos(int lottoTotalCount){ for (int i = 0; i < lottoTotalCount; i++) { lottoArrayList.add(new Lotto()); From c7b225217a13e12839527d706c910047fa210329 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 17:25:13 +0900 Subject: [PATCH 12/58] =?UTF-8?q?feat:=20enum=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EB=93=B1=EC=88=98=EB=B3=84=20=EC=84=A4=EB=AA=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/LottoWinningTypePrize.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/main/java/domain/LottoWinningTypePrize.java b/src/main/java/domain/LottoWinningTypePrize.java index 2bedb9501..043da9aee 100644 --- a/src/main/java/domain/LottoWinningTypePrize.java +++ b/src/main/java/domain/LottoWinningTypePrize.java @@ -3,22 +3,24 @@ import java.util.Arrays; import java.util.function.Function; -public enum LottoWinningTypePrize { - PRIZE_3_MATCH(originMatchCount -> originMatchCount * 5000), - PRIZE_4_MATCH(originMatchCount -> originMatchCount * 50000), - PRIZE_5_MATCH(originMatchCount -> originMatchCount * 1500000), - PRIZE_5_MATCH_AND_1_BONUS_BALL_MATCH(originMatchCount -> originMatchCount * 30000000), - PRIZE_6_MATCH(originMatchCount -> originMatchCount * 2000000000), - NO_PRIZE(originMatchCount -> 0L); - - private final Function expression; - - LottoWinningTypePrize(Function expression) { - this.expression = expression; +public enum LottoWinningType { + FIRST_PLACE("6개 일치 (2000000000원)- ", tickets -> tickets * 2000000000), + SECOND_PLACE("5개 일치, 보너스 볼 일치(30000000원)- ", tickets -> tickets * 30000000), + THIRD_PLACE("5개 일치 (1500000원)- ", tickets -> tickets * 1500000), + FOURTH_PLACE("4개 일치 (50000원)- ", tickets -> tickets * 50000), + FIFTH_PLACE("3개 일치 (5000원)- ", tickets -> tickets * 5000); + + private String winningDescription; + private Function prizeExpression; + + + LottoWinningType(String winningDescription, Function prizeExpression) { + this.winningDescription = winningDescription; + } - public long calculatePrize(int originMatchCount) { - return expression.apply((long) originMatchCount); + public long calculatePrize(double matchingTickets) { + return prizeExpression.apply((long) matchingTickets); } public static LottoWinningTypePrize findLottoWinningType(String winningType){ From 07dfdff6f0ff4cfda0ce9385e69d599eba646faa Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 17:26:04 +0900 Subject: [PATCH 13/58] =?UTF-8?q?chore:=20=ED=83=80=EC=9E=85=20=EC=98=AC?= =?UTF-8?q?=EB=B0=94=EB=A5=B4=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoWinningTypePrize.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/LottoWinningTypePrize.java b/src/main/java/domain/LottoWinningTypePrize.java index 043da9aee..66a43e11a 100644 --- a/src/main/java/domain/LottoWinningTypePrize.java +++ b/src/main/java/domain/LottoWinningTypePrize.java @@ -19,8 +19,8 @@ public enum LottoWinningType { } - public long calculatePrize(double matchingTickets) { - return prizeExpression.apply((long) matchingTickets); + public double prizeExpression(double matchingTickets) { + return prizeExpression.apply(matchingTickets); } public static LottoWinningTypePrize findLottoWinningType(String winningType){ From abc19c4cac9b74f3044e9aef638e695183ea85d8 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 17:29:39 +0900 Subject: [PATCH 14/58] =?UTF-8?q?chore:=20enum=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{LottoWinningTypePrize.java => LottoWinningType.java} | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename src/main/java/domain/{LottoWinningTypePrize.java => LottoWinningType.java} (84%) diff --git a/src/main/java/domain/LottoWinningTypePrize.java b/src/main/java/domain/LottoWinningType.java similarity index 84% rename from src/main/java/domain/LottoWinningTypePrize.java rename to src/main/java/domain/LottoWinningType.java index 66a43e11a..f4b06f3fc 100644 --- a/src/main/java/domain/LottoWinningTypePrize.java +++ b/src/main/java/domain/LottoWinningType.java @@ -8,7 +8,8 @@ public enum LottoWinningType { SECOND_PLACE("5개 일치, 보너스 볼 일치(30000000원)- ", tickets -> tickets * 30000000), THIRD_PLACE("5개 일치 (1500000원)- ", tickets -> tickets * 1500000), FOURTH_PLACE("4개 일치 (50000원)- ", tickets -> tickets * 50000), - FIFTH_PLACE("3개 일치 (5000원)- ", tickets -> tickets * 5000); + FIFTH_PLACE("3개 일치 (5000원)- ", tickets -> tickets * 5000), + NO_PRIZE("2개 이하 일치 (0원)- ", tickets -> 0d); private String winningDescription; private Function prizeExpression; @@ -23,8 +24,8 @@ public double prizeExpression(double matchingTickets) { return prizeExpression.apply(matchingTickets); } - public static LottoWinningTypePrize findLottoWinningType(String winningType){ - return Arrays.stream(LottoWinningTypePrize.values()) + public static LottoWinningType findLottoWinningType(String winningType){ + return Arrays.stream(LottoWinningType.values()) .filter(lottoWinningTypePrize -> lottoWinningTypePrize.name().equals(winningType)) .findAny() .orElse(NO_PRIZE); From de6a9bdd70c1cb92ce2f6d7db475aeca826249fd Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 18:23:17 +0900 Subject: [PATCH 15/58] fix --- src/main/java/domain/LottoRankChecker.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/domain/LottoRankChecker.java diff --git a/src/main/java/domain/LottoRankChecker.java b/src/main/java/domain/LottoRankChecker.java new file mode 100644 index 000000000..8610a2585 --- /dev/null +++ b/src/main/java/domain/LottoRankChecker.java @@ -0,0 +1,4 @@ +package domain; + +public class LottoRankChecker { +} From 7aa9f9f5abaad1a6c0cf1533a1901f53201911bc Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:17:40 +0900 Subject: [PATCH 16/58] =?UTF-8?q?feat:=20enum=EC=9D=84=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20LottoStatistics=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 29 ++++++------ src/main/java/domain/LottoChecker.java | 53 ++++++---------------- src/main/java/domain/LottoRankChecker.java | 4 -- src/main/java/domain/LottoResult.java | 23 ++++++---- src/main/java/domain/LottoStatistics.java | 26 +++++++++++ src/main/java/domain/LottoWinningType.java | 14 ++++++ src/main/java/view/OutputView.java | 25 +++++++--- 7 files changed, 102 insertions(+), 72 deletions(-) delete mode 100644 src/main/java/domain/LottoRankChecker.java create mode 100644 src/main/java/domain/LottoStatistics.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 3ca107bb1..2db401aaf 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,9 +1,12 @@ import domain.LottoChecker; import domain.LottoResult; +import domain.LottoStatistics; import domain.LottoTicketCount; import domain.LottoTickets; +import domain.LottoWinningType; + +import java.util.ArrayList; import java.util.Map; -import java.util.Scanner; import view.InputView; import view.OutputView; @@ -11,28 +14,28 @@ public class Application { public static void main(String[] args) { LottoTicketCount lottoTicketCount = new LottoTicketCount(); - int lottoTicketTotalAmount; - lottoTicketTotalAmount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); + int lottoTicketTotalAmount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); OutputView.printLottoCount(lottoTicketTotalAmount); LottoTickets lottoTickets = new LottoTickets(); lottoTickets.makeLottos(lottoTicketTotalAmount); OutputView.printLottoNumbers(lottoTickets); - String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); - // todo: 사용자가 입력한 지난주 당첨번호가 6개가 아니라면,, -> 예외처리? 어디에서? - + String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); String bonusNumber = InputView.inputBonusBallNumber(); - LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets); - Map countedMatches = lottoChecker.countMatches(lottoChecker.checkAllTickets()); - OutputView.printMatchCount(countedMatches); - - LottoResult lottoResult = new LottoResult(countedMatches, lottoTicketTotalAmount); - - OutputView.printRateOfReturn(lottoResult.calculateProfitRate()); + // 1. 체크 로직을 통해 티켓들의 당첨 상태를 리스트로 반환받음 + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + ArrayList checkedTickets = lottoChecker.checkAllTickets(); + // 2. 통계 객체에 넘겨 개수를 카운트함 + LottoStatistics lottoStatistics = new LottoStatistics(); + Map countedMatches = lottoStatistics.countMatches(checkedTickets); + OutputView.printMatchCount(countedMatches); + // 3. 수익률 계산 및 출력 + LottoResult lottoResult = new LottoResult(lottoStatistics, lottoTicketTotalAmount); + OutputView.printRateOfReturn(lottoResult.calculateProfitRate()); } } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 16069846f..188c496d9 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -2,20 +2,19 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public class LottoChecker { private final ArrayList winningLottoNumbers; private final LottoTickets lottoTickets; - private final String bonusNumber; + + private final int bonusNumber; public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTickets, String bonusNumber) { this.winningLottoNumbers = wrappingToIntegerLottoNumbers(lastWeekWinnerLottoNumbers); this.lottoTickets = lottoTickets; - this.bonusNumber = bonusNumber; + + this.bonusNumber = Integer.parseInt(bonusNumber); } private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { @@ -24,27 +23,23 @@ private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNu .collect(Collectors.toList()); } - private Integer wrappingToIntegerBonusNumber(String bonusNumber) { - return Integer.getInteger(bonusNumber); - } - - public ArrayList checkAllTickets() { - ArrayList matchCounts = new ArrayList<>(); + public ArrayList checkAllTickets() { + ArrayList winningTypes = new ArrayList<>(); for (int i = 0; i < lottoTickets.getSize(); i++) { - matchCounts.add(calculateMatchCountForTicket(i)); - } + int matchCount = calculateMatchCountForTicket(i); + boolean matchBonus = hasBonusNumber(i); - return matchCounts; + winningTypes.add(LottoWinningType.valueOf(matchCount, matchBonus)); + } + return winningTypes; } private int calculateMatchCountForTicket(int lottoTicketIndex) { int matchCount = 0; - for (int winningNumber : winningLottoNumbers) { matchCount += getMatchScore(lottoTicketIndex, winningNumber); } - return matchCount; } @@ -55,29 +50,7 @@ private int getMatchScore(int lottoTicketIndex, int winningNumber) { return 0; } - public Map countMatches(ArrayList matchCounts) { - Map matchStatistics = new HashMap<>(); - - for (int matchCount : matchCounts) { - updateStatistics(matchStatistics, matchCount); - } - - return matchStatistics; + public boolean hasBonusNumber(int lottoTicketIndex) { + return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); } - - private void updateStatistics(Map matchStatistics, int matchCount) { - if (matchCount < 3) { - return; - } - - if (matchStatistics.containsKey(matchCount)) { - int currentCount = matchStatistics.get(matchCount); - matchStatistics.put(matchCount, currentCount + 1); - return; - } - - matchStatistics.put(matchCount, 1); - } - - } diff --git a/src/main/java/domain/LottoRankChecker.java b/src/main/java/domain/LottoRankChecker.java deleted file mode 100644 index 8610a2585..000000000 --- a/src/main/java/domain/LottoRankChecker.java +++ /dev/null @@ -1,4 +0,0 @@ -package domain; - -public class LottoRankChecker { -} diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index 151694254..dd5eb94e2 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -5,27 +5,32 @@ public class LottoResult { public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; - private final Map matchStatistics; + private final LottoStatistics lottoStatistics; private final int purchaseAmount; - public LottoResult(Map matchStatistics, int purchaseAmount) { - this.matchStatistics = matchStatistics; + public LottoResult(LottoStatistics lottoStatistics, int purchaseAmount) { + this.lottoStatistics = lottoStatistics; this.purchaseAmount = purchaseAmount * PRICE_PER_ONE_LOTTO_TICKET; } private long calculateTotalPrize() { - + long totalPrize = 0; + Map stats = lottoStatistics.getMatchStatistics(); + + for (Map.Entry entry : stats.entrySet()) { + LottoWinningType type = entry.getKey(); + int count = entry.getValue(); + // Enum의 함수형 인터페이스 호출 + totalPrize += (long) type.prizeExpression((double) count); + } + return totalPrize; } public double calculateProfitRate() { long totalWinningPrize = calculateTotalPrize(); - if (totalWinningPrize == 0) { return 0.0; } - - double profitRate = (double) totalWinningPrize / purchaseAmount; - - return profitRate; + return (double) totalWinningPrize / purchaseAmount; } } diff --git a/src/main/java/domain/LottoStatistics.java b/src/main/java/domain/LottoStatistics.java new file mode 100644 index 000000000..8e9e40e92 --- /dev/null +++ b/src/main/java/domain/LottoStatistics.java @@ -0,0 +1,26 @@ +package domain; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class LottoStatistics { + private Map matchStatistics = new HashMap<>(); + + public LottoStatistics() { + for (LottoWinningType type : LottoWinningType.values()) { + matchStatistics.put(type, 0); + } + } + + public Map countMatches(ArrayList winningTypes) { + for (LottoWinningType type : winningTypes) { + matchStatistics.put(type, matchStatistics.get(type) + 1); + } + return matchStatistics; + } + + public Map getMatchStatistics() { + return matchStatistics; + } +} diff --git a/src/main/java/domain/LottoWinningType.java b/src/main/java/domain/LottoWinningType.java index f4b06f3fc..29016674e 100644 --- a/src/main/java/domain/LottoWinningType.java +++ b/src/main/java/domain/LottoWinningType.java @@ -17,6 +17,7 @@ public enum LottoWinningType { LottoWinningType(String winningDescription, Function prizeExpression) { this.winningDescription = winningDescription; + this.prizeExpression = prizeExpression; } @@ -24,6 +25,19 @@ public double prizeExpression(double matchingTickets) { return prizeExpression.apply(matchingTickets); } + public String getWinningDescription() { + return winningDescription; + } + + public static LottoWinningType valueOf(int matchCount, boolean matchBonus) { + if (matchCount == 6) return FIRST_PLACE; + if (matchCount == 5 && matchBonus) return SECOND_PLACE; + if (matchCount == 5) return THIRD_PLACE; + if (matchCount == 4) return FOURTH_PLACE; + if (matchCount == 3) return FIFTH_PLACE; + return NO_PRIZE; + } + public static LottoWinningType findLottoWinningType(String winningType){ return Arrays.stream(LottoWinningType.values()) .filter(lottoWinningTypePrize -> lottoWinningTypePrize.name().equals(winningType)) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 7f3dd9e3c..9a986c8c7 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import domain.LottoTickets; +import domain.LottoWinningType; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -21,18 +22,30 @@ public static void printLottoNumbers(LottoTickets lottoTickets) { } } - public static void printMatchCount(Map matchStatistics) { + public static void printMatchCount(Map matchStatistics) { System.out.println("\n당첨 통계"); System.out.println("---------"); - System.out.println("3개 일치 (5000원)- " + matchStatistics.get(3) + "개"); - System.out.println("4개 일치 (50000원)- " + matchStatistics.get(4) + "개"); - System.out.println("5개 일치 (1500000원)- " + matchStatistics.get(5) + "개"); - System.out.println("6개 일치 (2000000000원)- " + matchStatistics.get(6) + "개"); + LottoWinningType[] printOrder = { + LottoWinningType.FIFTH_PLACE, + LottoWinningType.FOURTH_PLACE, + LottoWinningType.THIRD_PLACE, + LottoWinningType.SECOND_PLACE, + LottoWinningType.FIRST_PLACE + }; + + for (LottoWinningType type : printOrder) { + System.out.println(type.getWinningDescription() + matchStatistics.get(type) + "개"); + } } public static void printRateOfReturn(double rateOfReturn) { - System.out.printf("총 수익률은 %.2f입니다.", rateOfReturn); + if (rateOfReturn < 1) { + System.out.printf("총 수익률은 %.2f입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)\n", rateOfReturn); + } + if (rateOfReturn >= 1) { + System.out.printf("총 수익률은 %.2f입니다.(기준이 1이기 때문에 결과적으로 이득이라는 의미임)\n", rateOfReturn); + } } } From af23a2ab1cd0b8772923721f3fa01d7c469a68ff Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:21:29 +0900 Subject: [PATCH 17/58] =?UTF-8?q?chore:=203=EB=8B=A8=EA=B3=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20-=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EC=9E=84=ED=8F=AC=ED=8A=B8=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=A7=80=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoResult.java | 1 - src/main/java/domain/LottoTicketCount.java | 2 +- src/main/java/domain/LottoTickets.java | 1 - src/main/java/view/OutputView.java | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index dd5eb94e2..a2a4f7cc8 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -20,7 +20,6 @@ private long calculateTotalPrize() { for (Map.Entry entry : stats.entrySet()) { LottoWinningType type = entry.getKey(); int count = entry.getValue(); - // Enum의 함수형 인터페이스 호출 totalPrize += (long) type.prizeExpression((double) count); } return totalPrize; diff --git a/src/main/java/domain/LottoTicketCount.java b/src/main/java/domain/LottoTicketCount.java index cbfcab35b..73eeaf805 100644 --- a/src/main/java/domain/LottoTicketCount.java +++ b/src/main/java/domain/LottoTicketCount.java @@ -1,6 +1,6 @@ package domain; -public class LottoTicketCount { //로또 금액 들어오면 비즈니스 규칙에 알맞게 수량을 정수로 반환해줌 +public class LottoTicketCount { public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; private int lottoTicketCount; diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index c47a3f68d..addbe7d7b 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -17,7 +17,6 @@ public TreeSet getLottoTreeSet(int lottoTicketNumber){ return new TreeSet<>(lottoArrayList.get(lottoTicketNumber).getRandomNumberSet()); } - public int getSize() { return lottoArrayList.size(); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9a986c8c7..2fcc3eaf6 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,8 +2,6 @@ import domain.LottoTickets; import domain.LottoWinningType; -import java.util.ArrayList; -import java.util.List; import java.util.Map; public final class OutputView { From b59ec31b4e170375b57018557cc2057324134844 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:24:47 +0900 Subject: [PATCH 18/58] =?UTF-8?q?refactor:=20scanner=20close=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 7 ++++--- src/main/java/view/InputView.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 2db401aaf..ed6bc58d5 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,3 +1,5 @@ +import static view.InputView.lottoScanner; + import domain.LottoChecker; import domain.LottoResult; import domain.LottoStatistics; @@ -24,18 +26,17 @@ public static void main(String[] args) { String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); String bonusNumber = InputView.inputBonusBallNumber(); - // 1. 체크 로직을 통해 티켓들의 당첨 상태를 리스트로 반환받음 LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); ArrayList checkedTickets = lottoChecker.checkAllTickets(); - // 2. 통계 객체에 넘겨 개수를 카운트함 LottoStatistics lottoStatistics = new LottoStatistics(); Map countedMatches = lottoStatistics.countMatches(checkedTickets); OutputView.printMatchCount(countedMatches); - // 3. 수익률 계산 및 출력 LottoResult lottoResult = new LottoResult(lottoStatistics, lottoTicketTotalAmount); OutputView.printRateOfReturn(lottoResult.calculateProfitRate()); + + InputView.closeScanner(lottoScanner); } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 41d98a1b5..d9d01bdfd 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -3,7 +3,7 @@ import java.util.Scanner; public final class InputView { - private static final Scanner lottoScanner = new Scanner(System.in); + public static Scanner lottoScanner = new Scanner(System.in); private InputView() { } From be8d61ad0e0a3273e9a68ff2610aa34711b2c785 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:28:51 +0900 Subject: [PATCH 19/58] =?UTF-8?q?fix:=20scanner=20close=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=98=A4=ED=83=80=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=83=9D=EC=98=A4=EB=B2=84=ED=94=8C=EB=A1=9C=EC=9A=B0?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index d9d01bdfd..3d129c1ad 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -42,6 +42,8 @@ public static String inputBonusBallNumber(){ } public static void closeScanner(Scanner scanner) { - closeScanner(scanner); + if (scanner != null) { + scanner.close(); + } } } From c86563ab0faabb4d864910e47ff658c7c2d7d2a4 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:40:34 +0900 Subject: [PATCH 20/58] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=A7=81=EC=A0=91=20=EC=9E=85=EB=A0=A5=ED=95=9C?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B0=9B=EB=8A=94=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index aae0a80c3..ec5039680 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -1,5 +1,6 @@ package domain; +import java.util.List; import java.util.Random; import java.util.TreeSet; @@ -10,10 +11,14 @@ public class Lotto { TreeSet randomNumberSet = new TreeSet<>(); Random random = new Random(); - public Lotto() { // 로또 한장 생성자 + public Lotto() { setLottoNumber(); } + public Lotto(List userSelectedNumbers) { + this.randomNumberSet.addAll(userSelectedNumbers); + } + private void setLottoNumber(){ while (randomNumberSet.size() < LOTTO_NUMBER_COUNT) { randomNumberSet.add(random.nextInt(1, LOTTO_NUMBER_BOUND + 1)); From 922eb104a3d7e06be45fb6c437c65aca7ddf3ed8 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:41:52 +0900 Subject: [PATCH 21/58] =?UTF-8?q?fix:=20=EA=B8=88=EC=95=A1=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index a2a4f7cc8..0bbefd241 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -10,7 +10,7 @@ public class LottoResult { public LottoResult(LottoStatistics lottoStatistics, int purchaseAmount) { this.lottoStatistics = lottoStatistics; - this.purchaseAmount = purchaseAmount * PRICE_PER_ONE_LOTTO_TICKET; + this.purchaseAmount = purchaseAmount; } private long calculateTotalPrize() { From 047f5fd67442530bc3c4480dd751fb769d256cb6 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:43:58 +0900 Subject: [PATCH 22/58] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=20=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=B0=9B?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 3d129c1ad..8d591dd6d 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,5 +1,6 @@ package view; +import java.util.ArrayList; import java.util.Scanner; public final class InputView { @@ -26,6 +27,20 @@ public static int inputLottoTotalPrice(){ return validLottoTotalPrice; } + public static int inputManualLottoCount() { + System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요."); + return Integer.parseInt(lottoScanner.nextLine()); + } + + public static ArrayList inputManualLottoNumbers(int userSelectedNumbersCount) { + System.out.println("\n수동으로 구매할 번호를 입력해 주세요."); + ArrayList userSelectedNumbers = new ArrayList<>(); + for (int i = 0; i < userSelectedNumbersCount; i++) { + userSelectedNumbers.add(lottoScanner.nextLine()); + } + return userSelectedNumbers; + } + public static String inputWinningLottoNumbers(){ System.out.println("\n지난 주 당첨번호를 입력해 주세요"); From d569fd4b0a9e9636ba37179d6b1b355d12c1a5dd Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:44:27 +0900 Subject: [PATCH 23/58] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EC=9E=A5=EC=88=98=20=EA=B5=AC=EB=B6=84=ED=95=B4?= =?UTF-8?q?=EC=84=9C=20=EC=B6=9C=EB=A0=A5=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 2fcc3eaf6..e10f79da6 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -9,9 +9,8 @@ private OutputView() { } - public static void printLottoCount(int lottoCount) { - System.out.println(lottoCount + "개를 구매했습니다"); - System.out.println(); + public static void printLottoCount(int userSelectedCount, int autoCount) { + System.out.printf("\n수동으로 %d장, 자동으로 %d개를 구매했습니다.\n", userSelectedCount, autoCount); } public static void printLottoNumbers(LottoTickets lottoTickets) { From 4095f4f95c335e10da7379d42a4fe8d6f19db041 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 21:45:14 +0900 Subject: [PATCH 24/58] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EB=B2=88=ED=98=B8=EB=A5=BC=20=EB=B0=9B=EC=95=84?= =?UTF-8?q?=EC=99=80=EC=84=9C=20LottoTickets=EC=97=90=EC=84=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoTickets.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index addbe7d7b..bf178d711 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -1,16 +1,27 @@ package domain; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.TreeSet; +import java.util.stream.Collectors; public class LottoTickets { ArrayList lottoArrayList = new ArrayList<>(); - public ArrayList makeLottos(int lottoTotalCount){ - for (int i = 0; i < lottoTotalCount; i++) { + public void addUserSelectedLottos(List userSelectedNumbersInput) { + for (String numbersString : userSelectedNumbersInput) { + List numbers = Arrays.stream(numbersString.split(", ")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + lottoArrayList.add(new Lotto(numbers)); + } + } + + public void addAutoLottos(int autoCount) { + for (int i = 0; i < autoCount; i++) { lottoArrayList.add(new Lotto()); } - return lottoArrayList; } public TreeSet getLottoTreeSet(int lottoTicketNumber){ From 1dd8f86a517163bcc379eb5d776292cf9b756f01 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 22:37:01 +0900 Subject: [PATCH 25/58] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 8d591dd6d..e121f0153 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -27,12 +27,12 @@ public static int inputLottoTotalPrice(){ return validLottoTotalPrice; } - public static int inputManualLottoCount() { + public static int inputUserSelectedLottoCount() { System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요."); return Integer.parseInt(lottoScanner.nextLine()); } - public static ArrayList inputManualLottoNumbers(int userSelectedNumbersCount) { + public static ArrayList inputUserSelectedLottoNumbers(int userSelectedNumbersCount) { System.out.println("\n수동으로 구매할 번호를 입력해 주세요."); ArrayList userSelectedNumbers = new ArrayList<>(); for (int i = 0; i < userSelectedNumbersCount; i++) { From 11d0438959a91b398d2ef0a113a2dad868ab7d9d Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 22:37:38 +0900 Subject: [PATCH 26/58] =?UTF-8?q?refactor:=204=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=EC=88=98=EB=8F=99=EC=9E=85=EB=A0=A5=20main=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=20=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index ed6bc58d5..203e8685f 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -8,6 +8,7 @@ import domain.LottoWinningType; import java.util.ArrayList; +import java.util.List; import java.util.Map; import view.InputView; import view.OutputView; @@ -16,11 +17,19 @@ public class Application { public static void main(String[] args) { LottoTicketCount lottoTicketCount = new LottoTicketCount(); - int lottoTicketTotalAmount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); - OutputView.printLottoCount(lottoTicketTotalAmount); + int totalCount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); + + int manualCount = InputView.inputUserSelectedLottoCount(); + List userSelectedNumbersInput = InputView.inputUserSelectedLottoNumbers(manualCount); + + int autoCount = totalCount - manualCount; + + OutputView.printLottoCount(manualCount, autoCount); LottoTickets lottoTickets = new LottoTickets(); - lottoTickets.makeLottos(lottoTicketTotalAmount); + lottoTickets.addUserSelectedLottos(userSelectedNumbersInput); + lottoTickets.addAutoLottos(autoCount); + OutputView.printLottoNumbers(lottoTickets); String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); @@ -34,7 +43,7 @@ public static void main(String[] args) { OutputView.printMatchCount(countedMatches); - LottoResult lottoResult = new LottoResult(lottoStatistics, lottoTicketTotalAmount); + LottoResult lottoResult = new LottoResult(lottoStatistics, (totalCount * LottoResult.PRICE_PER_ONE_LOTTO_TICKET)); OutputView.printRateOfReturn(lottoResult.calculateProfitRate()); InputView.closeScanner(lottoScanner); From f8fdd968a3507db1a255b594baa4178b827d5adc Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 23:21:56 +0900 Subject: [PATCH 27/58] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 3 +++ src/main/java/domain/LottoChecker.java | 13 ++++++++++++- src/main/java/view/InputView.java | 25 +++++++++++-------------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index ec5039680..6e2e55819 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -16,6 +16,9 @@ public Lotto() { } public Lotto(List userSelectedNumbers) { + if (userSelectedNumbers.size() != LOTTO_NUMBER_COUNT) { + throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + } this.randomNumberSet.addAll(userSelectedNumbers); } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 188c496d9..174e21f9c 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -13,10 +13,21 @@ public class LottoChecker { public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTickets, String bonusNumber) { this.winningLottoNumbers = wrappingToIntegerLottoNumbers(lastWeekWinnerLottoNumbers); this.lottoTickets = lottoTickets; - + validateBonusNumber(bonusNumber); this.bonusNumber = Integer.parseInt(bonusNumber); } + private void validateBonusNumber(String bonusNumber) { + try { + int number = Integer.parseInt(bonusNumber); + if (number < 1 || number > 45) { + throw new IllegalArgumentException("보너스 볼은 1과 45 사이의 숫자여야 합니다."); + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("보너스 볼은 숫자여야 합니다."); + } + } + private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { return (ArrayList) Arrays.stream(stringWinnerNumbers) .map(Integer::parseInt) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index e121f0153..e8d5bbc0a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -11,25 +11,20 @@ private InputView() { public static int inputLottoTotalPrice(){ System.out.println("구입 금액을 입력해 주세요."); - - String stringLottoTotalPrice; - int validLottoTotalPrice; - try { - stringLottoTotalPrice = lottoScanner.nextLine(); - - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("정수로 입력해주세요"); + return Integer.parseInt(lottoScanner.nextLine()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("구입 금액은 숫자로만 입력해야 합니다."); } - - validLottoTotalPrice = Integer.parseInt(stringLottoTotalPrice); - - return validLottoTotalPrice; } public static int inputUserSelectedLottoCount() { System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요."); - return Integer.parseInt(lottoScanner.nextLine()); + try { + return Integer.parseInt(lottoScanner.nextLine()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("로또 개수는 숫자로만 입력해야 합니다."); + } } public static ArrayList inputUserSelectedLottoNumbers(int userSelectedNumbersCount) { @@ -52,7 +47,9 @@ public static String inputWinningLottoNumbers(){ public static String inputBonusBallNumber(){ System.out.println("\n보너스 볼을 입력해 주세요."); String bonusNumber = lottoScanner.nextLine(); - + if (bonusNumber.contains(" ") || bonusNumber.contains(",")) { + throw new IllegalArgumentException("보너스 볼은 하나의 숫자만 입력해야 합니다."); + } return bonusNumber; } From e9513b6efd880db816cb142597740a46bac1b59c Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 2 Aug 2026 23:36:37 +0900 Subject: [PATCH 28/58] =?UTF-8?q?docs:=20readme=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..ddf23d137 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# 로또 (Lotto) 미션 + +## 기능 요구 사항 +- 로또 구입 금액에 맞춰 자동 및 수동 로또 발행 +- 당첨 번호(6개) 및 보너스 번호(1개) 입력 +- 사용자가 구매한 로또와 당첨 번호를 비교하여 당첨 내역(1~5등) 통계 산출 +- 총 당첨금을 기반으로 수익률 계산 및 출력 + +--- + +## 클래스별 역할 + +### Controller +- **`Application`**: 사용자 입력, 비즈니스 로직 처리, 결과 출력으로 이어지는 전체 애플리케이션의 흐름을 순차적으로 제어합니다. + +### Domain +- **`Lotto`**: 6개의 로또 번호를 `TreeSet`으로 래핑하여 규칙을 보장하는 도메인 객체입니다. +- **`LottoTickets`**: 여러 장의 `Lotto` 객체를 `ArrayList`로 감싸고 있는 일급 컬렉션으로, 수동 및 자동 로또의 추가와 관리를 담당합니다. +- **`LottoTicketCount`**: 로또 1장 가격(1,000원) 상수를 기반으로 구입 금액 대비 발행 가능한 티켓 수를 계산합니다. +- **`LottoChecker`**: 구매한 `LottoTickets`와 당첨/보너스 번호를 비교하여 각 티켓의 당첨 등수(`LottoWinningType`)를 판별합니다. +- **`LottoStatistics`**: `LottoChecker`의 판별 결과를 바탕으로 등수별 당첨 개수를 `Map` 형태로 통계 냅니다. +- **`LottoResult`**: 최종 통계 데이터를 넘겨받아 총 당첨금을 산출하고 최종 수익률을 계산합니다. +- **`LottoWinningType` (Enum)**: 당첨 등수 판별 조건(일치 개수, 보너스 여부)과 상금 계산식을 캡슐화한 열거형 클래스입니다. + +### View +- **`InputView`**: 구입 금액, 수동 로또 개수 및 번호, 당첨 번호, 보너스 번호 등을 사용자로부터 입력받고 원시 타입으로 반환합니다. +- **`OutputView`**: 구매 내역(로또 번호들), 당첨 통계, 최종 수익률을 사용자에게 알맞은 포맷으로 출력합니다. + +--- +## 추가 구현 및 예외 처리 정책 + +### 1. 사용자 입력 예외 처리 (`InputView`) +* **숫자 포맷 검증**: 구입 금액 및 수동 로또 개수 입력 시 문자가 입력되면 `NumberFormatException`을 가로채어 명확한 안내 문구와 함께 `IllegalArgumentException` 발생 +* **보너스 볼 형식 검증**: 보너스 번호 입력 시 공백이나 쉼표(`,`)가 포함되어 있으면 하나의 숫자만 입력하라는 문구가 출력되도록 예외 처리 +### 2. 수익률 결과 출력 정책 (`OutputView`) +* **기준값(1.0) 기반 손익 안내**: 수익률이 1(원금 기준)을 미만일 경우 손해, 1 이상일 경우 이득임을 사용자가 인지할 수 있도록 부가 설명 메시지를 함께 포맷팅하여 출력 From 2096b3cd75495917ad7839ecf60f404781186319 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 13:59:33 +0900 Subject: [PATCH 29/58] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EA=B0=9C=EC=88=98=20-=20=EB=B3=80=EA=B2=BD=EB=B2=94?= =?UTF-8?q?=EC=9C=84=20=EC=A4=84=EC=9D=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 6e2e55819..32fa94665 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -17,7 +17,7 @@ public Lotto() { public Lotto(List userSelectedNumbers) { if (userSelectedNumbers.size() != LOTTO_NUMBER_COUNT) { - throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + throw new IllegalArgumentException("로또 번호는" + LOTTO_NUMBER_COUNT + "개여야 합니다."); } this.randomNumberSet.addAll(userSelectedNumbers); } From 7aa2362f8526cd3bb0ae09ae3774b592c88153bf Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 14:15:05 +0900 Subject: [PATCH 30/58] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=83=81=ED=95=9C=20=ED=95=98=ED=95=9C=20=EC=83=81?= =?UTF-8?q?=EC=88=98=ED=99=94=20-=20=EB=A7=A4=EC=A7=81=EB=84=98=EB=B2=84?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 3 ++- src/main/java/domain/LottoChecker.java | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 32fa94665..36fe58123 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -5,6 +5,7 @@ import java.util.TreeSet; public class Lotto { + public static final int LOTTO_NUMBER_LOWER_BOUND = 1; public static final int LOTTO_NUMBER_BOUND = 45; public static final int LOTTO_NUMBER_COUNT = 6; @@ -24,7 +25,7 @@ public Lotto(List userSelectedNumbers) { private void setLottoNumber(){ while (randomNumberSet.size() < LOTTO_NUMBER_COUNT) { - randomNumberSet.add(random.nextInt(1, LOTTO_NUMBER_BOUND + 1)); + randomNumberSet.add(random.nextInt(LOTTO_NUMBER_LOWER_BOUND, LOTTO_NUMBER_BOUND + 1)); } } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 174e21f9c..e4f707400 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -5,6 +5,9 @@ import java.util.stream.Collectors; public class LottoChecker { + public static final int LOTTO_NUMBER_LOWER_BOUND = 1; + public static final int LOTTO_NUMBER_BOUND = 45; + private final ArrayList winningLottoNumbers; private final LottoTickets lottoTickets; @@ -20,8 +23,8 @@ public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTicke private void validateBonusNumber(String bonusNumber) { try { int number = Integer.parseInt(bonusNumber); - if (number < 1 || number > 45) { - throw new IllegalArgumentException("보너스 볼은 1과 45 사이의 숫자여야 합니다."); + if (number < LOTTO_NUMBER_LOWER_BOUND || number > LOTTO_NUMBER_BOUND) { + throw new IllegalArgumentException("보너스 볼은" + LOTTO_NUMBER_LOWER_BOUND + "과" + LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); } } catch (NumberFormatException e) { throw new IllegalArgumentException("보너스 볼은 숫자여야 합니다."); From 793fefed6fe7586396088cf27adf2c1cbe512ec2 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 14:57:33 +0900 Subject: [PATCH 31/58] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A4=91=EC=8B=AC=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20readme=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 64 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index ddf23d137..89fb283d5 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,44 @@ # 로또 (Lotto) 미션 -## 기능 요구 사항 -- 로또 구입 금액에 맞춰 자동 및 수동 로또 발행 -- 당첨 번호(6개) 및 보너스 번호(1개) 입력 -- 사용자가 구매한 로또와 당첨 번호를 비교하여 당첨 내역(1~5등) 통계 산출 -- 총 당첨금을 기반으로 수익률 계산 및 출력 +## 기능 요구사항 + +- 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또 티켓을 발급합니다. +- 사용자가 수동으로 로또 번호를 입력할 수 있어야 합니다. + - 수동으로 구매할 로또 수를 입력받고, 그 수만큼 로또 번호를 입력받습니다. + - 수동 구매 후 남은 금액만큼 자동으로 로또를 발급합니다. +- 지난 주 당첨 번호 6개와 보너스 볼 1개를 입력받습니다. +- 로또 번호와 당첨 번호를 비교하여 당첨 결과를 결정합니다. +- 최종적으로 당첨 통계와 수익률을 계산하여 출력합니다. + - 수익률이 1 미만일 경우 손해임을 명시합니다. + - 수익률이 1 이상일 경우 이득임을 명시합니다. (임의 설정) --- -## 클래스별 역할 - -### Controller -- **`Application`**: 사용자 입력, 비즈니스 로직 처리, 결과 출력으로 이어지는 전체 애플리케이션의 흐름을 순차적으로 제어합니다. - -### Domain -- **`Lotto`**: 6개의 로또 번호를 `TreeSet`으로 래핑하여 규칙을 보장하는 도메인 객체입니다. -- **`LottoTickets`**: 여러 장의 `Lotto` 객체를 `ArrayList`로 감싸고 있는 일급 컬렉션으로, 수동 및 자동 로또의 추가와 관리를 담당합니다. -- **`LottoTicketCount`**: 로또 1장 가격(1,000원) 상수를 기반으로 구입 금액 대비 발행 가능한 티켓 수를 계산합니다. -- **`LottoChecker`**: 구매한 `LottoTickets`와 당첨/보너스 번호를 비교하여 각 티켓의 당첨 등수(`LottoWinningType`)를 판별합니다. -- **`LottoStatistics`**: `LottoChecker`의 판별 결과를 바탕으로 등수별 당첨 개수를 `Map` 형태로 통계 냅니다. -- **`LottoResult`**: 최종 통계 데이터를 넘겨받아 총 당첨금을 산출하고 최종 수익률을 계산합니다. -- **`LottoWinningType` (Enum)**: 당첨 등수 판별 조건(일치 개수, 보너스 여부)과 상금 계산식을 캡슐화한 열거형 클래스입니다. - -### View -- **`InputView`**: 구입 금액, 수동 로또 개수 및 번호, 당첨 번호, 보너스 번호 등을 사용자로부터 입력받고 원시 타입으로 반환합니다. -- **`OutputView`**: 구매 내역(로또 번호들), 당첨 통계, 최종 수익률을 사용자에게 알맞은 포맷으로 출력합니다. +## 비즈니스 규칙 + +- **로또 구매 규칙** + - 로또 1장의 가격은 1,000원입니다. + - 구매 금액은 1,000원 단위로 입력해야 합니다. +- **로또 번호 규칙** + - 로또 번호는 1부터 45 사이의 숫자입니다. + - 로또 한 장은 중복되지 않는 6개의 숫자로 구성됩니다. + - 수동으로 로또를 구매할 때 6개의 번호를 입력하지 않으면 오류가 발생합니다. +- **당첨 조건 및 상금** + - 1등: 6개 번호 일치 (2,000,000,000원) + - 2등: 5개 번호 일치 + 보너스 볼 일치 (30,000,000원) + - 3등: 5개 번호 일치 (1,500,000원) + - 4등: 4개 번호 일치 (50,000원) + - 5등: 3개 번호 일치 (5,000원) --- -## 추가 구현 및 예외 처리 정책 -### 1. 사용자 입력 예외 처리 (`InputView`) -* **숫자 포맷 검증**: 구입 금액 및 수동 로또 개수 입력 시 문자가 입력되면 `NumberFormatException`을 가로채어 명확한 안내 문구와 함께 `IllegalArgumentException` 발생 -* **보너스 볼 형식 검증**: 보너스 번호 입력 시 공백이나 쉼표(`,`)가 포함되어 있으면 하나의 숫자만 입력하라는 문구가 출력되도록 예외 처리 -### 2. 수익률 결과 출력 정책 (`OutputView`) -* **기준값(1.0) 기반 손익 안내**: 수익률이 1(원금 기준)을 미만일 경우 손해, 1 이상일 경우 이득임을 사용자가 인지할 수 있도록 부가 설명 메시지를 함께 포맷팅하여 출력 +## 프로그래밍 요구사항 + +- **코드 컨벤션**: 자바 코드 컨벤션을 지키면서 프로그래밍합니다. +- **들여쓰기**: `indent`(인덴트, 들여쓰기) depth를 1까지만 허용합니다. (메서드 분리로 해결) +- **`else` 사용 금지**: `else` 예약어, `switch/case`, 3항 연산자를 사용하지 않습니다. (if문에서 값 반환으로 해결) +- **메서드 분리**: + - 함수(또는 메서드)의 길이는 10라인을 넘어가지 않도록 구현합니다. + - 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만듭니다. +- **자료구조**: 배열이 아닌 컬렉션을 사용합니다. +- **축약 금지**: 변수명, 클래스명, 메서드명 등에 축약을 사용하지 않습니다. From 0bb6ac2bc6cccf8a49e35963f608e517fc497d58 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 14:59:52 +0900 Subject: [PATCH 32/58] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A4=91=EC=8B=AC=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20readme=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 89fb283d5..7afa57c02 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # 로또 (Lotto) 미션 +## 프로젝트 소개 + +이 프로그램은 주어진 기능 및 프로그래밍 요구사항을 만족하는 콘솔 기반의 로또 게임을 구현하는 것을 목표로 합니다. +사용자는 로또를 수동 또는 자동으로 구매하고, 당첨 번호와 비교하여 당첨금 관련 결과를 확인할 수 있습니다. + +--- + ## 기능 요구사항 - 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또 티켓을 발급합니다. From cd808b346bcfebce6de126d08ab809b0b5bb8855 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 15:09:10 +0900 Subject: [PATCH 33/58] =?UTF-8?q?refactor:=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=20=EB=82=B4=EB=B6=80=20=ED=98=B8=EC=B6=9C=20=EC=88=9C=EC=84=9C?= =?UTF-8?q?=EB=8C=80=EB=A1=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8=20=EB=B0=8F=20=EC=A0=91=EA=B7=BC=EC=A0=9C=EC=96=B4=20?= =?UTF-8?q?=ED=81=B0=20=EB=B2=94=EC=9C=84=EB=B6=80=ED=84=B0=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B0=B0=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoChecker.java | 22 +++++++++++++--------- src/main/java/domain/LottoResult.java | 17 +++++++++-------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index e4f707400..90f5072e0 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -20,22 +20,24 @@ public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTicke this.bonusNumber = Integer.parseInt(bonusNumber); } + private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { + return (ArrayList) Arrays.stream(stringWinnerNumbers) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } + private void validateBonusNumber(String bonusNumber) { try { int number = Integer.parseInt(bonusNumber); if (number < LOTTO_NUMBER_LOWER_BOUND || number > LOTTO_NUMBER_BOUND) { - throw new IllegalArgumentException("보너스 볼은" + LOTTO_NUMBER_LOWER_BOUND + "과" + LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); + throw new IllegalArgumentException( + "보너스 볼은" + LOTTO_NUMBER_LOWER_BOUND + "과" + LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); } } catch (NumberFormatException e) { throw new IllegalArgumentException("보너스 볼은 숫자여야 합니다."); } } - private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { - return (ArrayList) Arrays.stream(stringWinnerNumbers) - .map(Integer::parseInt) - .collect(Collectors.toList()); - } public ArrayList checkAllTickets() { ArrayList winningTypes = new ArrayList<>(); @@ -49,6 +51,10 @@ public ArrayList checkAllTickets() { return winningTypes; } + public boolean hasBonusNumber(int lottoTicketIndex) { + return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); + } + private int calculateMatchCountForTicket(int lottoTicketIndex) { int matchCount = 0; for (int winningNumber : winningLottoNumbers) { @@ -64,7 +70,5 @@ private int getMatchScore(int lottoTicketIndex, int winningNumber) { return 0; } - public boolean hasBonusNumber(int lottoTicketIndex) { - return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); - } + } diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index 0bbefd241..3fabe5582 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -13,6 +13,14 @@ public LottoResult(LottoStatistics lottoStatistics, int purchaseAmount) { this.purchaseAmount = purchaseAmount; } + public double calculateProfitRate() { + long totalWinningPrize = calculateTotalPrize(); + if (totalWinningPrize == 0) { + return 0.0; + } + return (double) totalWinningPrize / purchaseAmount; + } + private long calculateTotalPrize() { long totalPrize = 0; Map stats = lottoStatistics.getMatchStatistics(); @@ -20,16 +28,9 @@ private long calculateTotalPrize() { for (Map.Entry entry : stats.entrySet()) { LottoWinningType type = entry.getKey(); int count = entry.getValue(); - totalPrize += (long) type.prizeExpression((double) count); + totalPrize += (long) type.prizeExpression(count); } return totalPrize; } - public double calculateProfitRate() { - long totalWinningPrize = calculateTotalPrize(); - if (totalWinningPrize == 0) { - return 0.0; - } - return (double) totalWinningPrize / purchaseAmount; - } } From 8a34a7938328d8633863284508cabc1acb33b96e Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 15:11:58 +0900 Subject: [PATCH 34/58] =?UTF-8?q?refactor:=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=20=EB=82=B4=EB=B6=80=20=ED=98=B8=EC=B6=9C=20=EC=88=9C=EC=84=9C?= =?UTF-8?q?=EB=8C=80=EB=A1=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8=20=EB=B0=8F=20=EC=A0=91=EA=B7=BC=EC=A0=9C=EC=96=B4=20?= =?UTF-8?q?=ED=81=B0=20=EB=B2=94=EC=9C=84=EB=B6=80=ED=84=B0=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B0=B0=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 8 +++--- src/main/java/domain/LottoChecker.java | 34 ++++++++++++-------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 36fe58123..2ce1ff214 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -23,6 +23,10 @@ public Lotto(List userSelectedNumbers) { this.randomNumberSet.addAll(userSelectedNumbers); } + public TreeSet getRandomNumberSet() { + return this.randomNumberSet; + } + private void setLottoNumber(){ while (randomNumberSet.size() < LOTTO_NUMBER_COUNT) { randomNumberSet.add(random.nextInt(LOTTO_NUMBER_LOWER_BOUND, LOTTO_NUMBER_BOUND + 1)); @@ -30,8 +34,4 @@ private void setLottoNumber(){ } - public TreeSet getRandomNumberSet() { - return this.randomNumberSet; - } - } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 90f5072e0..5137609cf 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -20,6 +20,22 @@ public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTicke this.bonusNumber = Integer.parseInt(bonusNumber); } + public ArrayList checkAllTickets() { + ArrayList winningTypes = new ArrayList<>(); + + for (int i = 0; i < lottoTickets.getSize(); i++) { + int matchCount = calculateMatchCountForTicket(i); + boolean matchBonus = hasBonusNumber(i); + + winningTypes.add(LottoWinningType.valueOf(matchCount, matchBonus)); + } + return winningTypes; + } + + public boolean hasBonusNumber(int lottoTicketIndex) { + return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); + } + private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { return (ArrayList) Arrays.stream(stringWinnerNumbers) .map(Integer::parseInt) @@ -38,23 +54,6 @@ private void validateBonusNumber(String bonusNumber) { } } - - public ArrayList checkAllTickets() { - ArrayList winningTypes = new ArrayList<>(); - - for (int i = 0; i < lottoTickets.getSize(); i++) { - int matchCount = calculateMatchCountForTicket(i); - boolean matchBonus = hasBonusNumber(i); - - winningTypes.add(LottoWinningType.valueOf(matchCount, matchBonus)); - } - return winningTypes; - } - - public boolean hasBonusNumber(int lottoTicketIndex) { - return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); - } - private int calculateMatchCountForTicket(int lottoTicketIndex) { int matchCount = 0; for (int winningNumber : winningLottoNumbers) { @@ -70,5 +69,4 @@ private int getMatchScore(int lottoTicketIndex, int winningNumber) { return 0; } - } From aa09b3fae96ecd0050c3c148c18d0d82243735d3 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 15:23:26 +0900 Subject: [PATCH 35/58] =?UTF-8?q?refactor:=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EA=B0=84=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=EC=84=A0=EC=96=B8=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20public=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=ED=99=9C=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 2 +- src/main/java/domain/LottoChecker.java | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 2ce1ff214..be7f5e68c 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -7,7 +7,7 @@ public class Lotto { public static final int LOTTO_NUMBER_LOWER_BOUND = 1; public static final int LOTTO_NUMBER_BOUND = 45; - public static final int LOTTO_NUMBER_COUNT = 6; + private static final int LOTTO_NUMBER_COUNT = 6; TreeSet randomNumberSet = new TreeSet<>(); Random random = new Random(); diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 5137609cf..f6043596f 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -5,8 +5,6 @@ import java.util.stream.Collectors; public class LottoChecker { - public static final int LOTTO_NUMBER_LOWER_BOUND = 1; - public static final int LOTTO_NUMBER_BOUND = 45; private final ArrayList winningLottoNumbers; private final LottoTickets lottoTickets; @@ -45,9 +43,9 @@ private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNu private void validateBonusNumber(String bonusNumber) { try { int number = Integer.parseInt(bonusNumber); - if (number < LOTTO_NUMBER_LOWER_BOUND || number > LOTTO_NUMBER_BOUND) { + if (number < Lotto.LOTTO_NUMBER_LOWER_BOUND || number > Lotto.LOTTO_NUMBER_BOUND) { throw new IllegalArgumentException( - "보너스 볼은" + LOTTO_NUMBER_LOWER_BOUND + "과" + LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); + "보너스 볼은" + Lotto.LOTTO_NUMBER_LOWER_BOUND + "과" + Lotto.LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); } } catch (NumberFormatException e) { throw new IllegalArgumentException("보너스 볼은 숫자여야 합니다."); From 6322c11d5d3afe91acf4d4f62ea9074f27cd83fe Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 15:24:18 +0900 Subject: [PATCH 36/58] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=EC=83=81=EC=88=98=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=EA=B0=84=20=EC=A4=91=EB=B3=B5=EC=84=A0=EC=96=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20public=20=EC=83=81=EC=88=98=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 2 +- src/main/java/domain/LottoResult.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 203e8685f..4756fd9ae 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -43,7 +43,7 @@ public static void main(String[] args) { OutputView.printMatchCount(countedMatches); - LottoResult lottoResult = new LottoResult(lottoStatistics, (totalCount * LottoResult.PRICE_PER_ONE_LOTTO_TICKET)); + LottoResult lottoResult = new LottoResult(lottoStatistics, (totalCount * LottoTicketCount.PRICE_PER_ONE_LOTTO_TICKET)); OutputView.printRateOfReturn(lottoResult.calculateProfitRate()); InputView.closeScanner(lottoScanner); diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index 3fabe5582..bd53562b7 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -3,7 +3,6 @@ import java.util.Map; public class LottoResult { - public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; private final LottoStatistics lottoStatistics; private final int purchaseAmount; From 5b11507241e22e6785650337957ea24a03224b85 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 19:26:06 +0900 Subject: [PATCH 37/58] =?UTF-8?q?test:=20Lotto=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EB=8B=A8=EC=9C=84=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/LottoTest.java | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/test/java/domain/LottoTest.java diff --git a/src/test/java/domain/LottoTest.java b/src/test/java/domain/LottoTest.java new file mode 100644 index 000000000..79ff3f159 --- /dev/null +++ b/src/test/java/domain/LottoTest.java @@ -0,0 +1,59 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoTest { + + @DisplayName("자동으로 로또를 생성하면 설정된 개수만큼 랜덤로또번호가 생성된다.") + @Test + void createLottoAutomatically() { + Lotto lotto = new Lotto(); + + assertThat(lotto.getRandomNumberSet()).hasSize(Lotto.LOTTO_NUMBER_COUNT); + } + + @DisplayName("자동으로 생성된 로또 번호는 1과 45 사이의 값이다.") + @Test + void validateNumberRange() { + Lotto lotto = new Lotto(); + + assertThat(lotto.getRandomNumberSet()).allMatch(number -> number >= Lotto.LOTTO_NUMBER_LOWER_BOUND && number <= Lotto.LOTTO_NUMBER_BOUND); + } + + @DisplayName("수동으로 로또를 생성한다.") + @Test + void createLottoManually() { + List userSelectedNumbers = List.of(1, 2, 3, 4, 5, 6); + + Lotto lotto = new Lotto(userSelectedNumbers); + + assertThat(lotto.getRandomNumberSet()).hasSize(Lotto.LOTTO_NUMBER_COUNT); + assertThat(lotto.getRandomNumberSet()).containsAll(userSelectedNumbers); + } + + @DisplayName("수동으로 로또를 생성할 때 번호가 6개가 아니면 예외가 발생한다.") + @Test + void throwExceptionWhenManualLottoHasInvalidSize() { + List numbers = List.of(1, 2, 3, 4, 5); + + assertThatThrownBy(() -> new Lotto(numbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 번호는" + Lotto.LOTTO_NUMBER_COUNT + "개여야 합니다."); + } + + @DisplayName("수동으로 로또를 생성할 때 중복된 번호가 있으면 예외가 발생한다.") + @Test + void throwExceptionWhenManualLottoHasDuplicateNumbers() { + List numbers = List.of(1, 2, 3, 4, 5, 5); + + assertThatThrownBy(() -> new Lotto(numbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 번호는 중복될 수 없습니다."); + } +} From daddef87f9c500bdccf7dae8101d3b78ba75e312 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Mon, 3 Aug 2026 19:26:49 +0900 Subject: [PATCH 38/58] =?UTF-8?q?feat:=20Lotto=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=EA=B8=88=EC=A7=80=EA=B4=80=EB=A0=A8=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index be7f5e68c..c732b80a8 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -7,7 +7,7 @@ public class Lotto { public static final int LOTTO_NUMBER_LOWER_BOUND = 1; public static final int LOTTO_NUMBER_BOUND = 45; - private static final int LOTTO_NUMBER_COUNT = 6; + public static final int LOTTO_NUMBER_COUNT = 6; TreeSet randomNumberSet = new TreeSet<>(); Random random = new Random(); @@ -21,6 +21,9 @@ public Lotto(List userSelectedNumbers) { throw new IllegalArgumentException("로또 번호는" + LOTTO_NUMBER_COUNT + "개여야 합니다."); } this.randomNumberSet.addAll(userSelectedNumbers); + if (this.randomNumberSet.size() != LOTTO_NUMBER_COUNT) { + throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); + } } public TreeSet getRandomNumberSet() { From f8053a09b36e6e5071feb927113995f02968a645 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:27:28 +0900 Subject: [PATCH 39/58] =?UTF-8?q?feat:=20=EA=B8=88=EC=95=A1=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EC=8B=9C=201000=EC=9B=90=EC=9D=B4=EC=83=81=EC=9D=98?= =?UTF-8?q?=201000=EC=9B=90=EB=8B=A8=EC=9C=84=EA=B0=80=20=EC=95=84?= =?UTF-8?q?=EB=8B=88=EB=9D=BC=EB=A9=B4=20=EC=9E=AC=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index e8d5bbc0a..2ff29d30b 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -4,17 +4,33 @@ import java.util.Scanner; public final class InputView { + public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; public static Scanner lottoScanner = new Scanner(System.in); private InputView() { } - public static int inputLottoTotalPrice(){ + public static int inputLottoTotalPrice() { System.out.println("구입 금액을 입력해 주세요."); - try { - return Integer.parseInt(lottoScanner.nextLine()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("구입 금액은 숫자로만 입력해야 합니다."); + while (true) { + try { + int price = Integer.parseInt(lottoScanner.nextLine()); + validatePurchaseAmount(price); + return price; + } catch (NumberFormatException e) { + System.out.println("구입 금액은 숫자로만 입력해야 합니다."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private static void validatePurchaseAmount(int price) { + if (price < PRICE_PER_ONE_LOTTO_TICKET) { + throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); + } + if (price % PRICE_PER_ONE_LOTTO_TICKET != 0) { + throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 단위로 입력해야 합니다."); } } From 576427f633d0b16027ee2edb0b41e8fc09d43dae Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:30:45 +0900 Subject: [PATCH 40/58] =?UTF-8?q?test:=20LottoTicketCount=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/LottoCheckerTest.java | 177 +++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 src/test/java/domain/LottoCheckerTest.java diff --git a/src/test/java/domain/LottoCheckerTest.java b/src/test/java/domain/LottoCheckerTest.java new file mode 100644 index 000000000..3bbf76181 --- /dev/null +++ b/src/test/java/domain/LottoCheckerTest.java @@ -0,0 +1,177 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("LottoChecker 클래스") +class LottoCheckerTest { + + private String[] winningNumbers; + private String bonusNumber; + + @BeforeEach + void setUp() { + winningNumbers = new String[]{"1", "2", "3", "4", "5", "6"}; + bonusNumber = "7"; + } + + private LottoTickets createLottoTickets(List numberStrings) { + LottoTickets lottoTickets = new LottoTickets(); + lottoTickets.addUserSelectedLottos(numberStrings); + return lottoTickets; + } + + @Nested + @DisplayName("생성자 유효성 검사") + class ConstructorValidation { + + @Test + @DisplayName("보너스 볼이 숫자가 아닐 경우 예외가 발생한다.") + void throwExceptionWhenBonusNumberIsNotNumeric() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 6")); + String invalidBonusNumber = "a"; + + // when & then + assertThatThrownBy(() -> new LottoChecker(winningNumbers, lottoTickets, invalidBonusNumber)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("보너스 볼은 숫자여야 합니다."); + } + + @Test + @DisplayName("보너스 볼이 범위를 벗어날 경우 예외가 발생한다.") + void throwExceptionWhenBonusNumberIsOutOfRange() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 6")); + String invalidBonusNumber = "46"; + + // when & then + assertThatThrownBy(() -> new LottoChecker(winningNumbers, lottoTickets, invalidBonusNumber)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("보너스 볼은" + Lotto.LOTTO_NUMBER_LOWER_BOUND + "과" + Lotto.LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); + } + } + + @Nested + @DisplayName("단일 티켓 당첨 결과 확인") + class SingleTicketResult { + + @Test + @DisplayName("1등 당첨을 확인한다.") + void checkFirstPrize() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 6")); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly(LottoWinningType.FIRST_PLACE); + } + + @Test + @DisplayName("2등 당첨을 확인한다.") + void checkSecondPrize() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 7")); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly(LottoWinningType.SECOND_PLACE); + } + + @Test + @DisplayName("3등 당첨을 확인한다.") + void checkThirdPrize() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 8")); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly(LottoWinningType.THIRD_PLACE); + } + + @Test + @DisplayName("4등 당첨을 확인한다.") + void checkFourthPrize() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 8, 9")); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly(LottoWinningType.FOURTH_PLACE); + } + + @Test + @DisplayName("5등 당첨을 확인한다.") + void checkFifthPrize() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 8, 9, 10")); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly(LottoWinningType.FIFTH_PLACE); + } + + @Test + @DisplayName("꽝을 확인한다.") + void checkMiss() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 8, 9, 10, 11")); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly(LottoWinningType.NO_PRIZE); + } + } + + @Nested + @DisplayName("여러 티켓 당첨 결과 확인") + class MultipleTicketsResult { + + @Test + @DisplayName("여러 티켓의 당첨 결과를 확인한다.") + void checkMultipleTickets() { + // given + LottoTickets lottoTickets = createLottoTickets(List.of( + "1, 2, 3, 4, 5, 6", + "10, 11, 12, 13, 14, 15", + "1, 2, 3, 8, 9, 10" + )); + LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + + // when + List results = lottoChecker.checkAllTickets(); + + // then + assertThat(results).containsExactly( + LottoWinningType.FIRST_PLACE, + LottoWinningType.NO_PRIZE, + LottoWinningType.FIFTH_PLACE + ); + } + } +} From 1dd83543e3e7bee7aac8f2156d832a5a7813c467 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:41:41 +0900 Subject: [PATCH 41/58] =?UTF-8?q?feat:=20=EA=B5=AC=EC=9E=85=EA=B8=88?= =?UTF-8?q?=EC=95=A1=201000=EC=9B=90=20=EC=9D=B4=EC=83=81=EC=9D=98=201000?= =?UTF-8?q?=EC=9B=90=EB=8B=A8=EC=9C=84=EB=A1=9C=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoTicketCount.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/domain/LottoTicketCount.java b/src/main/java/domain/LottoTicketCount.java index 73eeaf805..abfba7a87 100644 --- a/src/main/java/domain/LottoTicketCount.java +++ b/src/main/java/domain/LottoTicketCount.java @@ -5,8 +5,17 @@ public class LottoTicketCount { private int lottoTicketCount; public int convertLottoPriceToTicketCount(int totalLottoPrice) { + validatePurchaseAmount(totalLottoPrice); lottoTicketCount = totalLottoPrice / PRICE_PER_ONE_LOTTO_TICKET; return lottoTicketCount; } + private void validatePurchaseAmount(int price) { + if (price < PRICE_PER_ONE_LOTTO_TICKET) { + throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); + } + if (price % PRICE_PER_ONE_LOTTO_TICKET != 0) { + throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 단위로 입력해야 합니다."); + } + } } From 0db8025652af8eda3708cbef35de1e74bbc3aa8f Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:42:42 +0900 Subject: [PATCH 42/58] =?UTF-8?q?test:=20LottoTicketCount=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=8B=A8=EC=9C=84=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/LottoTicketCountTest.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/test/java/domain/LottoTicketCountTest.java diff --git a/src/test/java/domain/LottoTicketCountTest.java b/src/test/java/domain/LottoTicketCountTest.java new file mode 100644 index 000000000..0072888e1 --- /dev/null +++ b/src/test/java/domain/LottoTicketCountTest.java @@ -0,0 +1,62 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("LottoTicketCount 클래스") +class LottoTicketCountTest { + + private LottoTicketCount lottoTicketCount; + + @BeforeEach + void setUp() { + lottoTicketCount = new LottoTicketCount(); + } + + @Nested + @DisplayName("정상적인 금액 입력 시") + class ValidAmount { + @DisplayName("구매 금액을 로또 티켓 수로 변환한다.") + @ParameterizedTest + @CsvSource({ + "14000, 14", + "1000, 1", + "2000, 2" + }) + void shouldConvertPriceToTicketCountCorrectly(int price, int expectedCount) { + int actualCount = lottoTicketCount.convertLottoPriceToTicketCount(price); + + assertThat(actualCount).isEqualTo(expectedCount); + } + } + + @Nested + @DisplayName("유효하지 않은 금액 입력 시") + class InvalidAmount { + + @DisplayName("1000원 미만일 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(ints = {0, 100, 999}) + void shouldThrowExceptionForAmountLessThan1000(int price) { + assertThatThrownBy(() -> lottoTicketCount.convertLottoPriceToTicketCount(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("구입 금액은 " + LottoTicketCount.PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); + } + + @DisplayName("1000원 단위가 아닐 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(ints = {1001, 1500, 2999}) + void shouldThrowExceptionForAmountNotMultipleOf1000(int price) { + assertThatThrownBy(() -> lottoTicketCount.convertLottoPriceToTicketCount(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("구입 금액은 " + LottoTicketCount.PRICE_PER_ONE_LOTTO_TICKET + "원 단위로 입력해야 합니다."); + } + } +} From d574ef3cfc66c7590b15a08de604274211d42a1b Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:43:24 +0900 Subject: [PATCH 43/58] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/LottoCheckerTest.java | 25 ---------------------- 1 file changed, 25 deletions(-) diff --git a/src/test/java/domain/LottoCheckerTest.java b/src/test/java/domain/LottoCheckerTest.java index 3bbf76181..3ab65ae3a 100644 --- a/src/test/java/domain/LottoCheckerTest.java +++ b/src/test/java/domain/LottoCheckerTest.java @@ -35,11 +35,9 @@ class ConstructorValidation { @Test @DisplayName("보너스 볼이 숫자가 아닐 경우 예외가 발생한다.") void throwExceptionWhenBonusNumberIsNotNumeric() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 6")); String invalidBonusNumber = "a"; - // when & then assertThatThrownBy(() -> new LottoChecker(winningNumbers, lottoTickets, invalidBonusNumber)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("보너스 볼은 숫자여야 합니다."); @@ -48,11 +46,9 @@ void throwExceptionWhenBonusNumberIsNotNumeric() { @Test @DisplayName("보너스 볼이 범위를 벗어날 경우 예외가 발생한다.") void throwExceptionWhenBonusNumberIsOutOfRange() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 6")); String invalidBonusNumber = "46"; - // when & then assertThatThrownBy(() -> new LottoChecker(winningNumbers, lottoTickets, invalidBonusNumber)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("보너스 볼은" + Lotto.LOTTO_NUMBER_LOWER_BOUND + "과" + Lotto.LOTTO_NUMBER_BOUND + "사이의 숫자여야 합니다."); @@ -66,84 +62,66 @@ class SingleTicketResult { @Test @DisplayName("1등 당첨을 확인한다.") void checkFirstPrize() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 6")); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly(LottoWinningType.FIRST_PLACE); } @Test @DisplayName("2등 당첨을 확인한다.") void checkSecondPrize() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 7")); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly(LottoWinningType.SECOND_PLACE); } @Test @DisplayName("3등 당첨을 확인한다.") void checkThirdPrize() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 5, 8")); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly(LottoWinningType.THIRD_PLACE); } @Test @DisplayName("4등 당첨을 확인한다.") void checkFourthPrize() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 4, 8, 9")); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly(LottoWinningType.FOURTH_PLACE); } @Test @DisplayName("5등 당첨을 확인한다.") void checkFifthPrize() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 3, 8, 9, 10")); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly(LottoWinningType.FIFTH_PLACE); } @Test @DisplayName("꽝을 확인한다.") void checkMiss() { - // given LottoTickets lottoTickets = createLottoTickets(List.of("1, 2, 8, 9, 10, 11")); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly(LottoWinningType.NO_PRIZE); } } @@ -155,7 +133,6 @@ class MultipleTicketsResult { @Test @DisplayName("여러 티켓의 당첨 결과를 확인한다.") void checkMultipleTickets() { - // given LottoTickets lottoTickets = createLottoTickets(List.of( "1, 2, 3, 4, 5, 6", "10, 11, 12, 13, 14, 15", @@ -163,10 +140,8 @@ void checkMultipleTickets() { )); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); - // when List results = lottoChecker.checkAllTickets(); - // then assertThat(results).containsExactly( LottoWinningType.FIRST_PLACE, LottoWinningType.NO_PRIZE, From 82d8d6999de296462e93a3ceafe244b4956100ea Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:44:01 +0900 Subject: [PATCH 44/58] =?UTF-8?q?test:=20LottoStatistics=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/LottoResultTest.java | 59 +++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/test/java/domain/LottoResultTest.java diff --git a/src/test/java/domain/LottoResultTest.java b/src/test/java/domain/LottoResultTest.java new file mode 100644 index 000000000..18558187f --- /dev/null +++ b/src/test/java/domain/LottoResultTest.java @@ -0,0 +1,59 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class LottoResultTest { + + @DisplayName("수익률을 계산한다.") + @Test + void calculateProfitRate() { + ArrayList winningTypes = new ArrayList<>(List.of(LottoWinningType.FIFTH_PLACE)); + LottoStatistics lottoStatistics = new LottoStatistics(); + lottoStatistics.countMatches(winningTypes); + + int purchaseAmount = 8000; + LottoResult lottoResult = new LottoResult(lottoStatistics, purchaseAmount); + + double profitRate = lottoResult.calculateProfitRate(); + + assertThat(profitRate).isEqualTo(0.625); + } + + @DisplayName("여러 당첨 건에 대한 수익률을 계산한다.") + @Test + void calculateProfitRateWithMultipleWinnings() { + ArrayList winningTypes = new ArrayList<>(List.of( + LottoWinningType.FOURTH_PLACE, + LottoWinningType.FIFTH_PLACE + )); + LottoStatistics lottoStatistics = new LottoStatistics(); + lottoStatistics.countMatches(winningTypes); + + int purchaseAmount = 10000; + LottoResult lottoResult = new LottoResult(lottoStatistics, purchaseAmount); + + double profitRate = lottoResult.calculateProfitRate(); + assertThat(profitRate).isEqualTo(5.5); + } + + @DisplayName("당첨금이 없을 때 수익률은 0이다.") + @Test + void calculateProfitRateWithNoWinnings() { + ArrayList winningTypes = new ArrayList<>(); + LottoStatistics lottoStatistics = new LottoStatistics(); + lottoStatistics.countMatches(winningTypes); + + int purchaseAmount = 1000; + LottoResult lottoResult = new LottoResult(lottoStatistics, purchaseAmount); + + double profitRate = lottoResult.calculateProfitRate(); + + assertThat(profitRate).isEqualTo(0.0); + } +} From d6361eab6c264ea2c2e1cab7a3236655f8db0568 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:45:01 +0900 Subject: [PATCH 45/58] =?UTF-8?q?test:=20Statistics=EC=99=80=20Tickets?= =?UTF-8?q?=EC=99=80=20Enum=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/LottoStatisticsTest.java | 68 +++++++++++++++ src/test/java/domain/LottoTicketsTest.java | 85 +++++++++++++++++++ .../java/domain/LottoWinningTypeTest.java | 76 +++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 src/test/java/domain/LottoStatisticsTest.java create mode 100644 src/test/java/domain/LottoTicketsTest.java create mode 100644 src/test/java/domain/LottoWinningTypeTest.java diff --git a/src/test/java/domain/LottoStatisticsTest.java b/src/test/java/domain/LottoStatisticsTest.java new file mode 100644 index 000000000..9774dfcd5 --- /dev/null +++ b/src/test/java/domain/LottoStatisticsTest.java @@ -0,0 +1,68 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("LottoStatistics 클래스") +class LottoStatisticsTest { + + private LottoStatistics lottoStatistics; + + @BeforeEach + void setUp() { + lottoStatistics = new LottoStatistics(); + } + + @Test + @DisplayName("당첨 결과를 집계한다.") + void shouldCountMatchesCorrectly() { + ArrayList winningTypes = new ArrayList<>(List.of( + LottoWinningType.FIRST_PLACE, + LottoWinningType.FIFTH_PLACE, + LottoWinningType.NO_PRIZE, + LottoWinningType.FIFTH_PLACE, + LottoWinningType.NO_PRIZE, + LottoWinningType.NO_PRIZE + )); + + Map stats = lottoStatistics.countMatches(winningTypes); + + assertThat(stats.get(LottoWinningType.FIRST_PLACE)).isEqualTo(1); + assertThat(stats.get(LottoWinningType.SECOND_PLACE)).isEqualTo(0); + assertThat(stats.get(LottoWinningType.THIRD_PLACE)).isEqualTo(0); + assertThat(stats.get(LottoWinningType.FOURTH_PLACE)).isEqualTo(0); + assertThat(stats.get(LottoWinningType.FIFTH_PLACE)).isEqualTo(2); + assertThat(stats.get(LottoWinningType.NO_PRIZE)).isEqualTo(3); + } + + @Test + @DisplayName("빈 당첨 결과 리스트를 전달하면 모든 횟수는 0으로 유지된다.") + void shouldHandleEmptyWinningList() { + ArrayList winningTypes = new ArrayList<>(); + + Map stats = lottoStatistics.countMatches(winningTypes); + + assertThat(stats.values()).allMatch(count -> count == 0); + } + + @Test + @DisplayName("getMatchStatistics는 현재 통계를 반환한다.") + void getMatchStatisticsShouldReturnCurrentStats() { + ArrayList winningTypes = new ArrayList<>(List.of( + LottoWinningType.FOURTH_PLACE + )); + lottoStatistics.countMatches(winningTypes); + + Map stats = lottoStatistics.getMatchStatistics(); + + assertThat(stats.get(LottoWinningType.FOURTH_PLACE)).isEqualTo(1); + assertThat(stats.get(LottoWinningType.FIFTH_PLACE)).isEqualTo(0); + } +} diff --git a/src/test/java/domain/LottoTicketsTest.java b/src/test/java/domain/LottoTicketsTest.java new file mode 100644 index 000000000..0aaae8aa8 --- /dev/null +++ b/src/test/java/domain/LottoTicketsTest.java @@ -0,0 +1,85 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.TreeSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("LottoTickets 클래스") +class LottoTicketsTest { + + private LottoTickets lottoTickets; + + @BeforeEach + void setUp() { + lottoTickets = new LottoTickets(); + } + + @Nested + @DisplayName("addUserSelectedLottos 메소드는") + class AddUserSelectedLottos { + + @Test + @DisplayName("수동 번호 리스트를 받아 로또를 생성하고 추가한다.") + void shouldAddUserSelectedLottos() { + List numberStrings = List.of("1, 2, 3, 4, 5, 6", "7, 8, 9, 10, 11, 12"); + + lottoTickets.addUserSelectedLottos(numberStrings); + + assertThat(lottoTickets.getSize()).isEqualTo(2); + assertThat(lottoTickets.getLottoTreeSet(0)).containsExactly(1, 2, 3, 4, 5, 6); + assertThat(lottoTickets.getLottoTreeSet(1)).containsExactly(7, 8, 9, 10, 11, 12); + } + + @Test + @DisplayName("잘못된 형식의 번호를 받으면 예외를 발생시킨다.") + void shouldThrowExceptionForInvalidNumbers() { + List invalidNumberStrings = List.of("1, 2, 3, 4, 5"); + + assertThatThrownBy(() -> lottoTickets.addUserSelectedLottos(invalidNumberStrings)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 번호는" + Lotto.LOTTO_NUMBER_COUNT + "개여야 합니다."); + } + } + + @Nested + @DisplayName("addAutoLottos 메소드는") + class AddAutoLottos { + + @Test + @DisplayName("주어진 개수만큼 자동 로또를 생성하고 추가한다.") + void shouldAddAutoLottos() { + int autoCount = 3; + + lottoTickets.addAutoLottos(autoCount); + + assertThat(lottoTickets.getSize()).isEqualTo(3); + + for (int i = 0; i < autoCount; i++) { + assertThat(lottoTickets.getLottoTreeSet(i)).hasSize(Lotto.LOTTO_NUMBER_COUNT); + } + } + } + + @Nested + @DisplayName("getLottoTreeSet 메소드는") + class GetLottoTreeSet { + + @Test + @DisplayName("지정된 인덱스의 로또 번호 Set을 반환한다.") + void shouldReturnCorrectLottoSet() { + lottoTickets.addAutoLottos(1); + lottoTickets.addUserSelectedLottos(List.of("1, 2, 3, 4, 5, 6")); + + TreeSet manualLottoSet = lottoTickets.getLottoTreeSet(1); + + assertThat(manualLottoSet).containsExactly(1, 2, 3, 4, 5, 6); + } + } +} diff --git a/src/test/java/domain/LottoWinningTypeTest.java b/src/test/java/domain/LottoWinningTypeTest.java new file mode 100644 index 000000000..c024fbf5a --- /dev/null +++ b/src/test/java/domain/LottoWinningTypeTest.java @@ -0,0 +1,76 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("LottoWinningType Enum") +class LottoWinningTypeTest { + + @Nested + @DisplayName("valueOf 메소드는") + class ValueOfTest { + + @DisplayName("일치 개수와 보너스 여부에 따라 정확한 등수를 반환한다.") + @ParameterizedTest + @CsvSource({ + "6, false, FIRST_PLACE", + "5, true, SECOND_PLACE", + "5, false, THIRD_PLACE", + "4, false, FOURTH_PLACE", + "3, false, FIFTH_PLACE", + "2, false, NO_PRIZE", + "1, false, NO_PRIZE", + "0, false, NO_PRIZE" + }) + void returnsCorrectWinningType(int matchCount, boolean matchBonus, LottoWinningType expectedType) { + LottoWinningType actualType = LottoWinningType.valueOf(matchCount, matchBonus); + + assertThat(actualType).isEqualTo(expectedType); + } + } + + @Nested + @DisplayName("prizeExpression 메소드는") + class PrizeExpressionTest { + + @Test + @DisplayName("각 등수별 정확한 상금을 계산한다.") + void calculatesCorrectPrize() { + assertThat(LottoWinningType.FIRST_PLACE.prizeExpression(1)).isEqualTo(2_000_000_000); + assertThat(LottoWinningType.SECOND_PLACE.prizeExpression(1)).isEqualTo(30_000_000); + assertThat(LottoWinningType.THIRD_PLACE.prizeExpression(1)).isEqualTo(1_500_000); + assertThat(LottoWinningType.FOURTH_PLACE.prizeExpression(1)).isEqualTo(50_000); + assertThat(LottoWinningType.FIFTH_PLACE.prizeExpression(1)).isEqualTo(5_000); + assertThat(LottoWinningType.NO_PRIZE.prizeExpression(1)).isEqualTo(0); + } + + @Test + @DisplayName("여러 티켓 당첨 시 총 상금을 계산한다.") + void calculatesCorrectTotalPrizeForMultipleTickets() { + assertThat(LottoWinningType.FIFTH_PLACE.prizeExpression(3)).isEqualTo(15_000); + } + } + + @Nested + @DisplayName("findLottoWinningType 메소드는") + class FindLottoWinningTypeTest { + + @Test + @DisplayName("문자열에 해당하는 enum 상수를 찾는다.") + void findsCorrectEnumConstant() { + assertThat(LottoWinningType.findLottoWinningType("FIRST_PLACE")).isEqualTo(LottoWinningType.FIRST_PLACE); + assertThat(LottoWinningType.findLottoWinningType("SECOND_PLACE")).isEqualTo(LottoWinningType.SECOND_PLACE); + } + + @Test + @DisplayName("존재하지 않는 문자열에 대해서는 NO_PRIZE를 반환한다.") + void returnsNoPrizeForNonExistentConstant() { + assertThat(LottoWinningType.findLottoWinningType("INVALID_TYPE")).isEqualTo(LottoWinningType.NO_PRIZE); + } + } +} From 3b6dd3fa9cf1635ba8e9e3e397f7133a4fe48891 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 10:54:41 +0900 Subject: [PATCH 46/58] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=EC=8B=9C=20=EA=B3=B5=EB=B0=B1=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=EC=99=80=20=EC=83=81=EA=B4=80=EC=97=86?= =?UTF-8?q?=EC=9D=B4=20=EC=98=AC=EB=B0=94=EB=A5=B4=EA=B2=8C=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EC=B2=98=EB=A6=AC=20=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 2 +- src/main/java/domain/LottoTickets.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 4756fd9ae..3ab3df08f 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -32,7 +32,7 @@ public static void main(String[] args) { OutputView.printLottoNumbers(lottoTickets); - String[] winningNumbers = InputView.inputWinningLottoNumbers().split(", "); + String[] winningNumbers = InputView.inputWinningLottoNumbers().split(",\\s*"); String bonusNumber = InputView.inputBonusBallNumber(); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index bf178d711..3157b9934 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -11,7 +11,7 @@ public class LottoTickets { public void addUserSelectedLottos(List userSelectedNumbersInput) { for (String numbersString : userSelectedNumbersInput) { - List numbers = Arrays.stream(numbersString.split(", ")) + List numbers = Arrays.stream(numbersString.split(",\\s*")) .map(Integer::parseInt) .collect(Collectors.toList()); lottoArrayList.add(new Lotto(numbers)); From 954fb8b1cfecb5e80fa48b8bbee5201d17550fd8 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 11:04:31 +0900 Subject: [PATCH 47/58] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EC=98=88=EC=99=B8=ED=84=B0=EC=A7=80?= =?UTF-8?q?=EB=A9=B4=20=EC=9E=AC=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 90 ++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 2ff29d30b..dc76448c8 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,7 +1,11 @@ package view; +import domain.Lotto; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Scanner; +import java.util.stream.Collectors; public final class InputView { public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; @@ -14,13 +18,14 @@ public static int inputLottoTotalPrice() { System.out.println("구입 금액을 입력해 주세요."); while (true) { try { - int price = Integer.parseInt(lottoScanner.nextLine()); + String input = lottoScanner.nextLine(); + int price = Integer.parseInt(input); validatePurchaseAmount(price); return price; } catch (NumberFormatException e) { - System.out.println("구입 금액은 숫자로만 입력해야 합니다."); + System.out.println("구입 금액은 숫자로만 입력해야 합니다. 다시 입력해 주세요."); } catch (IllegalArgumentException e) { - System.out.println(e.getMessage()); + System.out.println(e.getMessage() + " 다시 입력해 주세요."); } } } @@ -36,10 +41,19 @@ private static void validatePurchaseAmount(int price) { public static int inputUserSelectedLottoCount() { System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요."); - try { - return Integer.parseInt(lottoScanner.nextLine()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("로또 개수는 숫자로만 입력해야 합니다."); + while (true) { + try { + String input = lottoScanner.nextLine(); + int manualCount = Integer.parseInt(input); + if (manualCount < 0) { + throw new IllegalArgumentException("수동 구매 개수는 0 이상이어야 합니다."); + } + return manualCount; + } catch (NumberFormatException e) { + System.out.println("로또 개수는 숫자로만 입력해야 합니다. 다시 입력해 주세요."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage() + " 다시 입력해 주세요."); + } } } @@ -47,26 +61,66 @@ public static ArrayList inputUserSelectedLottoNumbers(int userSelectedNu System.out.println("\n수동으로 구매할 번호를 입력해 주세요."); ArrayList userSelectedNumbers = new ArrayList<>(); for (int i = 0; i < userSelectedNumbersCount; i++) { - userSelectedNumbers.add(lottoScanner.nextLine()); + while (true) { + try { + String numbersString = lottoScanner.nextLine(); + List numbers = Arrays.stream(numbersString.split(",\\s*")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + new Lotto(numbers); + userSelectedNumbers.add(numbersString); + break; + } catch (NumberFormatException e) { + System.out.println("로또 번호는 숫자로만 구성되어야 합니다. 해당 라인을 다시 입력해 주세요."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage() + " 해당 라인을 다시 입력해 주세요."); + } + } } return userSelectedNumbers; } - public static String inputWinningLottoNumbers(){ - + public static String inputWinningLottoNumbers() { System.out.println("\n지난 주 당첨번호를 입력해 주세요"); - String winningLottoNumbers = lottoScanner.nextLine(); - - return winningLottoNumbers; + while (true) { + try { + String winningLottoNumbers = lottoScanner.nextLine(); + List numbers = Arrays.stream(winningLottoNumbers.split(",\\s*")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + new Lotto(numbers); + return winningLottoNumbers; + } catch (NumberFormatException e) { + System.out.println("당첨 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage() + " 다시 입력해 주세요."); + } + } } - public static String inputBonusBallNumber(){ + public static String inputBonusBallNumber() { System.out.println("\n보너스 볼을 입력해 주세요."); - String bonusNumber = lottoScanner.nextLine(); - if (bonusNumber.contains(" ") || bonusNumber.contains(",")) { - throw new IllegalArgumentException("보너스 볼은 하나의 숫자만 입력해야 합니다."); + while (true) { + try { + String bonusNumberStr = lottoScanner.nextLine(); + if (bonusNumberStr == null || bonusNumberStr.trim().isEmpty()) { + throw new IllegalArgumentException("보너스 볼 번호를 입력해야 합니다."); + } + if (bonusNumberStr.contains(" ") || bonusNumberStr.contains(",")) { + throw new IllegalArgumentException("보너스 볼은 하나의 숫자만 입력해야 합니다."); + } + int bonusNumber = Integer.parseInt(bonusNumberStr); + if (bonusNumber < Lotto.LOTTO_NUMBER_LOWER_BOUND || bonusNumber > Lotto.LOTTO_NUMBER_BOUND) { + throw new IllegalArgumentException("보너스 볼은 " + Lotto.LOTTO_NUMBER_LOWER_BOUND + "과 " + + Lotto.LOTTO_NUMBER_BOUND + " 사이의 숫자여야 합니다."); + } + return bonusNumberStr; + } catch (NumberFormatException e) { + System.out.println("보너스 볼은 숫자로만 입력해야 합니다. 다시 입력해 주세요."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage() + " 다시 입력해 주세요."); + } } - return bonusNumber; } public static void closeScanner(Scanner scanner) { From b6546b222661c01214508128985e54cedd48e176 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Tue, 4 Aug 2026 11:14:09 +0900 Subject: [PATCH 48/58] =?UTF-8?q?refactor:=20InputView=20public=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=B6=80=ED=84=B0=20=EB=B0=B0=EC=B9=98?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 112 +++++++++++++++++------------- 1 file changed, 62 insertions(+), 50 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index dc76448c8..0ec0761cf 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -23,36 +23,25 @@ public static int inputLottoTotalPrice() { validatePurchaseAmount(price); return price; } catch (NumberFormatException e) { - System.out.println("구입 금액은 숫자로만 입력해야 합니다. 다시 입력해 주세요."); + System.out.println("[ERROR] 구입 금액은 숫자로만 입력해야 합니다. 다시 입력해 주세요."); } catch (IllegalArgumentException e) { - System.out.println(e.getMessage() + " 다시 입력해 주세요."); + System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); } } } - private static void validatePurchaseAmount(int price) { - if (price < PRICE_PER_ONE_LOTTO_TICKET) { - throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); - } - if (price % PRICE_PER_ONE_LOTTO_TICKET != 0) { - throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 단위로 입력해야 합니다."); - } - } - public static int inputUserSelectedLottoCount() { System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요."); while (true) { try { String input = lottoScanner.nextLine(); int manualCount = Integer.parseInt(input); - if (manualCount < 0) { - throw new IllegalArgumentException("수동 구매 개수는 0 이상이어야 합니다."); - } + validateManualCount(manualCount); return manualCount; } catch (NumberFormatException e) { - System.out.println("로또 개수는 숫자로만 입력해야 합니다. 다시 입력해 주세요."); + System.out.println("[ERROR] 로또 개수는 숫자로만 입력해야 합니다. 다시 입력해 주세요."); } catch (IllegalArgumentException e) { - System.out.println(e.getMessage() + " 다시 입력해 주세요."); + System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); } } } @@ -61,21 +50,7 @@ public static ArrayList inputUserSelectedLottoNumbers(int userSelectedNu System.out.println("\n수동으로 구매할 번호를 입력해 주세요."); ArrayList userSelectedNumbers = new ArrayList<>(); for (int i = 0; i < userSelectedNumbersCount; i++) { - while (true) { - try { - String numbersString = lottoScanner.nextLine(); - List numbers = Arrays.stream(numbersString.split(",\\s*")) - .map(Integer::parseInt) - .collect(Collectors.toList()); - new Lotto(numbers); - userSelectedNumbers.add(numbersString); - break; - } catch (NumberFormatException e) { - System.out.println("로또 번호는 숫자로만 구성되어야 합니다. 해당 라인을 다시 입력해 주세요."); - } catch (IllegalArgumentException e) { - System.out.println(e.getMessage() + " 해당 라인을 다시 입력해 주세요."); - } - } + userSelectedNumbers.add(readSingleLottoLine()); } return userSelectedNumbers; } @@ -85,15 +60,12 @@ public static String inputWinningLottoNumbers() { while (true) { try { String winningLottoNumbers = lottoScanner.nextLine(); - List numbers = Arrays.stream(winningLottoNumbers.split(",\\s*")) - .map(Integer::parseInt) - .collect(Collectors.toList()); - new Lotto(numbers); + validateLottoNumbers(winningLottoNumbers); return winningLottoNumbers; } catch (NumberFormatException e) { - System.out.println("당첨 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); + System.out.println("[ERROR] 당첨 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); } catch (IllegalArgumentException e) { - System.out.println(e.getMessage() + " 다시 입력해 주세요."); + System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); } } } @@ -103,22 +75,12 @@ public static String inputBonusBallNumber() { while (true) { try { String bonusNumberStr = lottoScanner.nextLine(); - if (bonusNumberStr == null || bonusNumberStr.trim().isEmpty()) { - throw new IllegalArgumentException("보너스 볼 번호를 입력해야 합니다."); - } - if (bonusNumberStr.contains(" ") || bonusNumberStr.contains(",")) { - throw new IllegalArgumentException("보너스 볼은 하나의 숫자만 입력해야 합니다."); - } - int bonusNumber = Integer.parseInt(bonusNumberStr); - if (bonusNumber < Lotto.LOTTO_NUMBER_LOWER_BOUND || bonusNumber > Lotto.LOTTO_NUMBER_BOUND) { - throw new IllegalArgumentException("보너스 볼은 " + Lotto.LOTTO_NUMBER_LOWER_BOUND + "과 " + - Lotto.LOTTO_NUMBER_BOUND + " 사이의 숫자여야 합니다."); - } + validateBonusBall(bonusNumberStr); return bonusNumberStr; } catch (NumberFormatException e) { - System.out.println("보너스 볼은 숫자로만 입력해야 합니다. 다시 입력해 주세요."); + System.out.println("[ERROR] 보너스 볼은 숫자로만 입력해야 합니다. 다시 입력해 주세요."); } catch (IllegalArgumentException e) { - System.out.println(e.getMessage() + " 다시 입력해 주세요."); + System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); } } } @@ -128,4 +90,54 @@ public static void closeScanner(Scanner scanner) { scanner.close(); } } + + private static void validatePurchaseAmount(int price) { + if (price < PRICE_PER_ONE_LOTTO_TICKET) { + throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); + } + if (price % PRICE_PER_ONE_LOTTO_TICKET != 0) { + throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 단위로 입력해야 합니다."); + } + } + + private static void validateManualCount(int manualCount) { + if (manualCount < 0) { + throw new IllegalArgumentException("수동 구매 개수는 0 이상이어야 합니다."); + } + } + + private static String readSingleLottoLine() { + while (true) { + try { + String numbersString = lottoScanner.nextLine(); + validateLottoNumbers(numbersString); + return numbersString; + } catch (NumberFormatException e) { + System.out.println("[ERROR] 로또 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); + } catch (IllegalArgumentException e) { + System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); + } + } + } + + private static void validateLottoNumbers(String numbersString) { + List numbers = Arrays.stream(numbersString.split(",\\s*")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + new Lotto(numbers); + } + + private static void validateBonusBall(String bonusNumberStr) { + if (bonusNumberStr == null || bonusNumberStr.trim().isEmpty()) { + throw new IllegalArgumentException("보너스 볼 번호를 입력해야 합니다."); + } + if (bonusNumberStr.contains(" ") || bonusNumberStr.contains(",")) { + throw new IllegalArgumentException("보너스 볼은 하나의 숫자만 입력해야 합니다."); + } + int bonusNumber = Integer.parseInt(bonusNumberStr); + if (bonusNumber < Lotto.LOTTO_NUMBER_LOWER_BOUND || bonusNumber > Lotto.LOTTO_NUMBER_BOUND) { + throw new IllegalArgumentException("보너스 볼은 " + Lotto.LOTTO_NUMBER_LOWER_BOUND + + "과 " + Lotto.LOTTO_NUMBER_BOUND + " 사이의 숫자여야 합니다."); + } + } } From 86163049fa60d4974633386eea40851f13c02da9 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Wed, 5 Aug 2026 13:57:03 +0900 Subject: [PATCH 49/58] =?UTF-8?q?refactor:=20=EC=83=81=ED=83=9C=EA=B0=80?= =?UTF-8?q?=20=ED=95=84=EC=9A=94=EC=97=86=EB=8A=94=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EB=A5=BC=20=EC=9C=A0=ED=8B=B8=EB=A6=AC=ED=8B=B0?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 3 +-- src/main/java/domain/LottoTicketCount.java | 11 ++++++----- src/test/java/domain/LottoTicketCountTest.java | 14 +++----------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 3ab3df08f..184590407 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -16,8 +16,7 @@ public class Application { public static void main(String[] args) { - LottoTicketCount lottoTicketCount = new LottoTicketCount(); - int totalCount = lottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); + int totalCount = LottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); int manualCount = InputView.inputUserSelectedLottoCount(); List userSelectedNumbersInput = InputView.inputUserSelectedLottoNumbers(manualCount); diff --git a/src/main/java/domain/LottoTicketCount.java b/src/main/java/domain/LottoTicketCount.java index abfba7a87..b0e8cfe9f 100644 --- a/src/main/java/domain/LottoTicketCount.java +++ b/src/main/java/domain/LottoTicketCount.java @@ -2,15 +2,16 @@ public class LottoTicketCount { public static final int PRICE_PER_ONE_LOTTO_TICKET = 1000; - private int lottoTicketCount; - public int convertLottoPriceToTicketCount(int totalLottoPrice) { + private LottoTicketCount() { + } + + public static int convertLottoPriceToTicketCount(int totalLottoPrice) { validatePurchaseAmount(totalLottoPrice); - lottoTicketCount = totalLottoPrice / PRICE_PER_ONE_LOTTO_TICKET; - return lottoTicketCount; + return totalLottoPrice / PRICE_PER_ONE_LOTTO_TICKET; } - private void validatePurchaseAmount(int price) { + private static void validatePurchaseAmount(int price) { if (price < PRICE_PER_ONE_LOTTO_TICKET) { throw new IllegalArgumentException("구입 금액은 " + PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); } diff --git a/src/test/java/domain/LottoTicketCountTest.java b/src/test/java/domain/LottoTicketCountTest.java index 0072888e1..83f9b46f3 100644 --- a/src/test/java/domain/LottoTicketCountTest.java +++ b/src/test/java/domain/LottoTicketCountTest.java @@ -1,6 +1,5 @@ package domain; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.params.ParameterizedTest; @@ -13,13 +12,6 @@ @DisplayName("LottoTicketCount 클래스") class LottoTicketCountTest { - private LottoTicketCount lottoTicketCount; - - @BeforeEach - void setUp() { - lottoTicketCount = new LottoTicketCount(); - } - @Nested @DisplayName("정상적인 금액 입력 시") class ValidAmount { @@ -31,7 +23,7 @@ class ValidAmount { "2000, 2" }) void shouldConvertPriceToTicketCountCorrectly(int price, int expectedCount) { - int actualCount = lottoTicketCount.convertLottoPriceToTicketCount(price); + int actualCount = LottoTicketCount.convertLottoPriceToTicketCount(price); assertThat(actualCount).isEqualTo(expectedCount); } @@ -45,7 +37,7 @@ class InvalidAmount { @ParameterizedTest @ValueSource(ints = {0, 100, 999}) void shouldThrowExceptionForAmountLessThan1000(int price) { - assertThatThrownBy(() -> lottoTicketCount.convertLottoPriceToTicketCount(price)) + assertThatThrownBy(() -> LottoTicketCount.convertLottoPriceToTicketCount(price)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("구입 금액은 " + LottoTicketCount.PRICE_PER_ONE_LOTTO_TICKET + "원 이상이어야 합니다."); } @@ -54,7 +46,7 @@ void shouldThrowExceptionForAmountLessThan1000(int price) { @ParameterizedTest @ValueSource(ints = {1001, 1500, 2999}) void shouldThrowExceptionForAmountNotMultipleOf1000(int price) { - assertThatThrownBy(() -> lottoTicketCount.convertLottoPriceToTicketCount(price)) + assertThatThrownBy(() -> LottoTicketCount.convertLottoPriceToTicketCount(price)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("구입 금액은 " + LottoTicketCount.PRICE_PER_ONE_LOTTO_TICKET + "원 단위로 입력해야 합니다."); } From 423146b5f0fbd9551037ff12bb8e18c1ba56ec53 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Wed, 5 Aug 2026 14:53:16 +0900 Subject: [PATCH 50/58] =?UTF-8?q?refactor:=20Lotto=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=20=EB=82=B4=EB=B6=80=EC=97=90=EC=84=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index c732b80a8..2d10e87f4 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -20,6 +20,12 @@ public Lotto(List userSelectedNumbers) { if (userSelectedNumbers.size() != LOTTO_NUMBER_COUNT) { throw new IllegalArgumentException("로또 번호는" + LOTTO_NUMBER_COUNT + "개여야 합니다."); } + for (Integer number : userSelectedNumbers) { + if (number < LOTTO_NUMBER_LOWER_BOUND || number > LOTTO_NUMBER_BOUND) { + throw new IllegalArgumentException("로또 번호는 " + LOTTO_NUMBER_LOWER_BOUND + + "부터 " + LOTTO_NUMBER_BOUND + " 사이의 숫자여야 합니다."); + } + } this.randomNumberSet.addAll(userSelectedNumbers); if (this.randomNumberSet.size() != LOTTO_NUMBER_COUNT) { throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); @@ -30,7 +36,7 @@ public TreeSet getRandomNumberSet() { return this.randomNumberSet; } - private void setLottoNumber(){ + private void setLottoNumber() { while (randomNumberSet.size() < LOTTO_NUMBER_COUNT) { randomNumberSet.add(random.nextInt(LOTTO_NUMBER_LOWER_BOUND, LOTTO_NUMBER_BOUND + 1)); } From 0aca2e05142a2cee2cec4c830d0b122f1517249d Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Wed, 5 Aug 2026 15:09:13 +0900 Subject: [PATCH 51/58] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=EA=B8=88=EC=95=A1=EA=B3=BC=20=EC=8B=A4=EC=A0=9C=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=EB=B0=9C=EA=B8=89=EC=88=98=EB=9F=89=20?= =?UTF-8?q?=EA=B0=84=EC=9D=98=20=EC=83=81=ED=95=9C=20=EB=B3=B4=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 2 +- src/main/java/view/InputView.java | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 184590407..1022f8a48 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -18,7 +18,7 @@ public class Application { public static void main(String[] args) { int totalCount = LottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); - int manualCount = InputView.inputUserSelectedLottoCount(); + int manualCount = InputView.inputUserSelectedLottoCount(totalCount); List userSelectedNumbersInput = InputView.inputUserSelectedLottoNumbers(manualCount); int autoCount = totalCount - manualCount; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 0ec0761cf..bd6dd96b4 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -30,13 +30,13 @@ public static int inputLottoTotalPrice() { } } - public static int inputUserSelectedLottoCount() { + public static int inputUserSelectedLottoCount(int totalCount) { System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요."); while (true) { try { String input = lottoScanner.nextLine(); int manualCount = Integer.parseInt(input); - validateManualCount(manualCount); + validateManualCount(manualCount, totalCount); return manualCount; } catch (NumberFormatException e) { System.out.println("[ERROR] 로또 개수는 숫자로만 입력해야 합니다. 다시 입력해 주세요."); @@ -100,10 +100,13 @@ private static void validatePurchaseAmount(int price) { } } - private static void validateManualCount(int manualCount) { + private static void validateManualCount(int manualCount, int totalCount) { if (manualCount < 0) { throw new IllegalArgumentException("수동 구매 개수는 0 이상이어야 합니다."); } + if (manualCount > totalCount) { + throw new IllegalArgumentException("수동 구매 개수는 전체 구매 개수(" + totalCount + "개)를 초과할 수 없습니다."); + } } private static String readSingleLottoLine() { From d19037c5ea627a4806bf49f7e6f53d474be78473 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Wed, 5 Aug 2026 15:25:06 +0900 Subject: [PATCH 52/58] =?UTF-8?q?refactor:=20=EC=BB=AC=EB=A0=89=EC=85=98?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 2 +- src/main/java/domain/LottoChecker.java | 8 ++++---- src/main/java/domain/LottoTickets.java | 3 +-- src/main/java/view/OutputView.java | 5 +++-- src/test/java/domain/LottoCheckerTest.java | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 1022f8a48..2d26697f5 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -31,7 +31,7 @@ public static void main(String[] args) { OutputView.printLottoNumbers(lottoTickets); - String[] winningNumbers = InputView.inputWinningLottoNumbers().split(",\\s*"); + List winningNumbers = List.of(InputView.inputWinningLottoNumbers().split(",\\s*")); String bonusNumber = InputView.inputBonusBallNumber(); LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index f6043596f..e2112c588 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -1,7 +1,7 @@ package domain; import java.util.ArrayList; -import java.util.Arrays; +import java.util.List; import java.util.stream.Collectors; public class LottoChecker { @@ -11,7 +11,7 @@ public class LottoChecker { private final int bonusNumber; - public LottoChecker(String[] lastWeekWinnerLottoNumbers, LottoTickets lottoTickets, String bonusNumber) { + public LottoChecker(List lastWeekWinnerLottoNumbers, LottoTickets lottoTickets, String bonusNumber) { this.winningLottoNumbers = wrappingToIntegerLottoNumbers(lastWeekWinnerLottoNumbers); this.lottoTickets = lottoTickets; validateBonusNumber(bonusNumber); @@ -34,8 +34,8 @@ public boolean hasBonusNumber(int lottoTicketIndex) { return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); } - private ArrayList wrappingToIntegerLottoNumbers(String[] stringWinnerNumbers) { - return (ArrayList) Arrays.stream(stringWinnerNumbers) + private ArrayList wrappingToIntegerLottoNumbers(List stringWinnerNumbers) { + return (ArrayList) stringWinnerNumbers.stream() .map(Integer::parseInt) .collect(Collectors.toList()); } diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index 3157b9934..968fe87be 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -1,7 +1,6 @@ package domain; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; @@ -11,7 +10,7 @@ public class LottoTickets { public void addUserSelectedLottos(List userSelectedNumbersInput) { for (String numbersString : userSelectedNumbersInput) { - List numbers = Arrays.stream(numbersString.split(",\\s*")) + List numbers = List.of(numbersString.split(",\\s*")).stream() .map(Integer::parseInt) .collect(Collectors.toList()); lottoArrayList.add(new Lotto(numbers)); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e10f79da6..33a8119ee 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,6 +2,7 @@ import domain.LottoTickets; import domain.LottoWinningType; +import java.util.List; import java.util.Map; public final class OutputView { @@ -23,13 +24,13 @@ public static void printMatchCount(Map matchStatistic System.out.println("\n당첨 통계"); System.out.println("---------"); - LottoWinningType[] printOrder = { + List printOrder = List.of( LottoWinningType.FIFTH_PLACE, LottoWinningType.FOURTH_PLACE, LottoWinningType.THIRD_PLACE, LottoWinningType.SECOND_PLACE, LottoWinningType.FIRST_PLACE - }; + ); for (LottoWinningType type : printOrder) { System.out.println(type.getWinningDescription() + matchStatistics.get(type) + "개"); diff --git a/src/test/java/domain/LottoCheckerTest.java b/src/test/java/domain/LottoCheckerTest.java index 3ab65ae3a..5bbc6e862 100644 --- a/src/test/java/domain/LottoCheckerTest.java +++ b/src/test/java/domain/LottoCheckerTest.java @@ -13,12 +13,12 @@ @DisplayName("LottoChecker 클래스") class LottoCheckerTest { - private String[] winningNumbers; + private List winningNumbers; private String bonusNumber; @BeforeEach void setUp() { - winningNumbers = new String[]{"1", "2", "3", "4", "5", "6"}; + winningNumbers = List.of("1", "2", "3", "4", "5", "6"); bonusNumber = "7"; } From fe17ed9d429693879a750187e1f503c9e32d8647 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 9 Aug 2026 15:49:21 +0900 Subject: [PATCH 53/58] =?UTF-8?q?refactor:=20=EC=88=98=EB=8F=99=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20Lotto=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=B1=85=EC=9E=84=EC=9D=84=20View?= =?UTF-8?q?=EC=97=90=EC=84=9C=20Application=EC=9C=BC=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 26 +++++++++++++++-- src/main/java/domain/LottoTickets.java | 10 ++----- src/main/java/view/InputView.java | 34 ++++++---------------- src/test/java/domain/LottoCheckerTest.java | 9 +++++- src/test/java/domain/LottoTicketsTest.java | 21 +++++-------- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 2d26697f5..ac8f782d1 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,6 @@ import static view.InputView.lottoScanner; +import domain.Lotto; import domain.LottoChecker; import domain.LottoResult; import domain.LottoStatistics; @@ -19,14 +20,14 @@ public static void main(String[] args) { int totalCount = LottoTicketCount.convertLottoPriceToTicketCount(InputView.inputLottoTotalPrice()); int manualCount = InputView.inputUserSelectedLottoCount(totalCount); - List userSelectedNumbersInput = InputView.inputUserSelectedLottoNumbers(manualCount); + List userSelectedLottos = inputUserSelectedLottos(manualCount); int autoCount = totalCount - manualCount; OutputView.printLottoCount(manualCount, autoCount); LottoTickets lottoTickets = new LottoTickets(); - lottoTickets.addUserSelectedLottos(userSelectedNumbersInput); + lottoTickets.addUserSelectedLottos(userSelectedLottos); lottoTickets.addAutoLottos(autoCount); OutputView.printLottoNumbers(lottoTickets); @@ -47,4 +48,25 @@ public static void main(String[] args) { InputView.closeScanner(lottoScanner); } + + private static List inputUserSelectedLottos(int manualCount) { + InputView.printUserSelectedLottoNumbersPrompt(); + List userSelectedLottos = new ArrayList<>(); + for (int i = 0; i < manualCount; i++) { + userSelectedLottos.add(readOneUserSelectedLotto()); + } + return userSelectedLottos; + } + + private static Lotto readOneUserSelectedLotto() { + while (true) { + try { + return new Lotto(InputView.readLottoNumbers()); + } catch (NumberFormatException e) { + OutputView.printError("로또 번호는 숫자로만 구성되어야 합니다."); + } catch (IllegalArgumentException e) { + OutputView.printError(e.getMessage()); + } + } + } } diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index 968fe87be..d4787c71d 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -3,18 +3,12 @@ import java.util.ArrayList; import java.util.List; import java.util.TreeSet; -import java.util.stream.Collectors; public class LottoTickets { ArrayList lottoArrayList = new ArrayList<>(); - public void addUserSelectedLottos(List userSelectedNumbersInput) { - for (String numbersString : userSelectedNumbersInput) { - List numbers = List.of(numbersString.split(",\\s*")).stream() - .map(Integer::parseInt) - .collect(Collectors.toList()); - lottoArrayList.add(new Lotto(numbers)); - } + public void addUserSelectedLottos(List userSelectedLottos) { + lottoArrayList.addAll(userSelectedLottos); } public void addAutoLottos(int autoCount) { diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index bd6dd96b4..a841a8189 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,7 +1,6 @@ package view; import domain.Lotto; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; @@ -46,13 +45,13 @@ public static int inputUserSelectedLottoCount(int totalCount) { } } - public static ArrayList inputUserSelectedLottoNumbers(int userSelectedNumbersCount) { + public static void printUserSelectedLottoNumbersPrompt() { System.out.println("\n수동으로 구매할 번호를 입력해 주세요."); - ArrayList userSelectedNumbers = new ArrayList<>(); - for (int i = 0; i < userSelectedNumbersCount; i++) { - userSelectedNumbers.add(readSingleLottoLine()); - } - return userSelectedNumbers; + } + + public static List readLottoNumbers() { + String numbersString = lottoScanner.nextLine(); + return parseLottoNumbers(numbersString); } public static String inputWinningLottoNumbers() { @@ -60,7 +59,7 @@ public static String inputWinningLottoNumbers() { while (true) { try { String winningLottoNumbers = lottoScanner.nextLine(); - validateLottoNumbers(winningLottoNumbers); + new Lotto(parseLottoNumbers(winningLottoNumbers)); return winningLottoNumbers; } catch (NumberFormatException e) { System.out.println("[ERROR] 당첨 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); @@ -109,25 +108,10 @@ private static void validateManualCount(int manualCount, int totalCount) { } } - private static String readSingleLottoLine() { - while (true) { - try { - String numbersString = lottoScanner.nextLine(); - validateLottoNumbers(numbersString); - return numbersString; - } catch (NumberFormatException e) { - System.out.println("[ERROR] 로또 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); - } catch (IllegalArgumentException e) { - System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); - } - } - } - - private static void validateLottoNumbers(String numbersString) { - List numbers = Arrays.stream(numbersString.split(",\\s*")) + private static List parseLottoNumbers(String numbersString) { + return Arrays.stream(numbersString.split(",\\s*")) .map(Integer::parseInt) .collect(Collectors.toList()); - new Lotto(numbers); } private static void validateBonusBall(String bonusNumberStr) { diff --git a/src/test/java/domain/LottoCheckerTest.java b/src/test/java/domain/LottoCheckerTest.java index 5bbc6e862..bf09d8251 100644 --- a/src/test/java/domain/LottoCheckerTest.java +++ b/src/test/java/domain/LottoCheckerTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test; import java.util.List; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -24,7 +25,13 @@ void setUp() { private LottoTickets createLottoTickets(List numberStrings) { LottoTickets lottoTickets = new LottoTickets(); - lottoTickets.addUserSelectedLottos(numberStrings); + List lottos = numberStrings.stream() + .map(numbersString -> List.of(numbersString.split(",\\s*")).stream() + .map(Integer::parseInt) + .collect(Collectors.toList())) + .map(Lotto::new) + .collect(Collectors.toList()); + lottoTickets.addUserSelectedLottos(lottos); return lottoTickets; } diff --git a/src/test/java/domain/LottoTicketsTest.java b/src/test/java/domain/LottoTicketsTest.java index 0aaae8aa8..23415ee9e 100644 --- a/src/test/java/domain/LottoTicketsTest.java +++ b/src/test/java/domain/LottoTicketsTest.java @@ -26,26 +26,19 @@ void setUp() { class AddUserSelectedLottos { @Test - @DisplayName("수동 번호 리스트를 받아 로또를 생성하고 추가한다.") + @DisplayName("이미 생성된 로또 목록을 그대로 추가한다.") void shouldAddUserSelectedLottos() { - List numberStrings = List.of("1, 2, 3, 4, 5, 6", "7, 8, 9, 10, 11, 12"); + List lottos = List.of( + new Lotto(List.of(1, 2, 3, 4, 5, 6)), + new Lotto(List.of(7, 8, 9, 10, 11, 12)) + ); - lottoTickets.addUserSelectedLottos(numberStrings); + lottoTickets.addUserSelectedLottos(lottos); assertThat(lottoTickets.getSize()).isEqualTo(2); assertThat(lottoTickets.getLottoTreeSet(0)).containsExactly(1, 2, 3, 4, 5, 6); assertThat(lottoTickets.getLottoTreeSet(1)).containsExactly(7, 8, 9, 10, 11, 12); } - - @Test - @DisplayName("잘못된 형식의 번호를 받으면 예외를 발생시킨다.") - void shouldThrowExceptionForInvalidNumbers() { - List invalidNumberStrings = List.of("1, 2, 3, 4, 5"); - - assertThatThrownBy(() -> lottoTickets.addUserSelectedLottos(invalidNumberStrings)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("로또 번호는" + Lotto.LOTTO_NUMBER_COUNT + "개여야 합니다."); - } } @Nested @@ -75,7 +68,7 @@ class GetLottoTreeSet { @DisplayName("지정된 인덱스의 로또 번호 Set을 반환한다.") void shouldReturnCorrectLottoSet() { lottoTickets.addAutoLottos(1); - lottoTickets.addUserSelectedLottos(List.of("1, 2, 3, 4, 5, 6")); + lottoTickets.addUserSelectedLottos(List.of(new Lotto(List.of(1, 2, 3, 4, 5, 6)))); TreeSet manualLottoSet = lottoTickets.getLottoTreeSet(1); From d0475baa17f943442f966be3df4ebc94529402db Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 9 Aug 2026 15:49:58 +0900 Subject: [PATCH 54/58] =?UTF-8?q?refactor:=20=EC=9E=AC=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 33a8119ee..20f397be2 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -10,6 +10,10 @@ private OutputView() { } + public static void printError(String message) { + System.out.println("[ERROR] " + message + " 다시 입력해 주세요."); + } + public static void printLottoCount(int userSelectedCount, int autoCount) { System.out.printf("\n수동으로 %d장, 자동으로 %d개를 구매했습니다.\n", userSelectedCount, autoCount); } From 900e7cbb43c6547b8f6990bf6936a30a5642ee1a Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 9 Aug 2026 16:19:12 +0900 Subject: [PATCH 55/58] =?UTF-8?q?refactor:=20=EB=8B=B9=EC=B2=A8=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=8F=84=20Lotto=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=B1=85=EC=9E=84=EC=9D=84=20View=EC=97=90?= =?UTF-8?q?=EC=84=9C=20Application=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 15 ++++++++++----- src/main/java/domain/LottoChecker.java | 12 ++---------- src/main/java/view/InputView.java | 13 +------------ src/test/java/domain/LottoCheckerTest.java | 4 ++-- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index ac8f782d1..eaf8999ca 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -32,10 +32,10 @@ public static void main(String[] args) { OutputView.printLottoNumbers(lottoTickets); - List winningNumbers = List.of(InputView.inputWinningLottoNumbers().split(",\\s*")); + Lotto winningLotto = inputWinningLotto(); String bonusNumber = InputView.inputBonusBallNumber(); - LottoChecker lottoChecker = new LottoChecker(winningNumbers, lottoTickets, bonusNumber); + LottoChecker lottoChecker = new LottoChecker(winningLotto, lottoTickets, bonusNumber); ArrayList checkedTickets = lottoChecker.checkAllTickets(); LottoStatistics lottoStatistics = new LottoStatistics(); @@ -53,17 +53,22 @@ private static List inputUserSelectedLottos(int manualCount) { InputView.printUserSelectedLottoNumbersPrompt(); List userSelectedLottos = new ArrayList<>(); for (int i = 0; i < manualCount; i++) { - userSelectedLottos.add(readOneUserSelectedLotto()); + userSelectedLottos.add(readLottoWithRetry("로또 번호는 숫자로만 구성되어야 합니다.")); } return userSelectedLottos; } - private static Lotto readOneUserSelectedLotto() { + private static Lotto inputWinningLotto() { + InputView.printWinningLottoNumbersPrompt(); + return readLottoWithRetry("당첨 번호는 숫자로만 구성되어야 합니다."); + } + + private static Lotto readLottoWithRetry(String numberFormatErrorMessage) { while (true) { try { return new Lotto(InputView.readLottoNumbers()); } catch (NumberFormatException e) { - OutputView.printError("로또 번호는 숫자로만 구성되어야 합니다."); + OutputView.printError(numberFormatErrorMessage); } catch (IllegalArgumentException e) { OutputView.printError(e.getMessage()); } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index e2112c588..981430d60 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -1,8 +1,6 @@ package domain; import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; public class LottoChecker { @@ -11,8 +9,8 @@ public class LottoChecker { private final int bonusNumber; - public LottoChecker(List lastWeekWinnerLottoNumbers, LottoTickets lottoTickets, String bonusNumber) { - this.winningLottoNumbers = wrappingToIntegerLottoNumbers(lastWeekWinnerLottoNumbers); + public LottoChecker(Lotto winningLotto, LottoTickets lottoTickets, String bonusNumber) { + this.winningLottoNumbers = new ArrayList<>(winningLotto.getRandomNumberSet()); this.lottoTickets = lottoTickets; validateBonusNumber(bonusNumber); this.bonusNumber = Integer.parseInt(bonusNumber); @@ -34,12 +32,6 @@ public boolean hasBonusNumber(int lottoTicketIndex) { return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); } - private ArrayList wrappingToIntegerLottoNumbers(List stringWinnerNumbers) { - return (ArrayList) stringWinnerNumbers.stream() - .map(Integer::parseInt) - .collect(Collectors.toList()); - } - private void validateBonusNumber(String bonusNumber) { try { int number = Integer.parseInt(bonusNumber); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a841a8189..15048900f 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -54,19 +54,8 @@ public static List readLottoNumbers() { return parseLottoNumbers(numbersString); } - public static String inputWinningLottoNumbers() { + public static void printWinningLottoNumbersPrompt() { System.out.println("\n지난 주 당첨번호를 입력해 주세요"); - while (true) { - try { - String winningLottoNumbers = lottoScanner.nextLine(); - new Lotto(parseLottoNumbers(winningLottoNumbers)); - return winningLottoNumbers; - } catch (NumberFormatException e) { - System.out.println("[ERROR] 당첨 번호는 숫자로만 구성되어야 합니다. 다시 입력해 주세요."); - } catch (IllegalArgumentException e) { - System.out.println("[ERROR] " + e.getMessage() + " 다시 입력해 주세요."); - } - } } public static String inputBonusBallNumber() { diff --git a/src/test/java/domain/LottoCheckerTest.java b/src/test/java/domain/LottoCheckerTest.java index bf09d8251..6a996ce1d 100644 --- a/src/test/java/domain/LottoCheckerTest.java +++ b/src/test/java/domain/LottoCheckerTest.java @@ -14,12 +14,12 @@ @DisplayName("LottoChecker 클래스") class LottoCheckerTest { - private List winningNumbers; + private Lotto winningNumbers; private String bonusNumber; @BeforeEach void setUp() { - winningNumbers = List.of("1", "2", "3", "4", "5", "6"); + winningNumbers = new Lotto(List.of(1, 2, 3, 4, 5, 6)); bonusNumber = "7"; } From 86120d734e00ee3ac5abb2b225210939c5b74573 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 9 Aug 2026 16:37:05 +0900 Subject: [PATCH 56/58] =?UTF-8?q?refactor:=20=EC=9D=98=EB=8F=84=EB=A5=BC?= =?UTF-8?q?=20=EB=93=9C=EB=9F=AC=EB=82=B4=EB=8F=84=EB=A1=9D=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Lotto.java | 18 +++++++-------- src/main/java/domain/LottoChecker.java | 8 +++---- src/main/java/domain/LottoResult.java | 2 +- src/main/java/domain/LottoTickets.java | 12 +++++----- src/main/java/domain/LottoWinningType.java | 12 +++++----- src/main/java/view/OutputView.java | 2 +- src/test/java/domain/LottoTest.java | 8 +++---- src/test/java/domain/LottoTicketsTest.java | 12 +++++----- .../java/domain/LottoWinningTypeTest.java | 22 +++++++++---------- 9 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 2d10e87f4..ef9a35811 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -9,11 +9,11 @@ public class Lotto { public static final int LOTTO_NUMBER_BOUND = 45; public static final int LOTTO_NUMBER_COUNT = 6; - TreeSet randomNumberSet = new TreeSet<>(); + TreeSet numbers = new TreeSet<>(); Random random = new Random(); public Lotto() { - setLottoNumber(); + generateRandomNumbers(); } public Lotto(List userSelectedNumbers) { @@ -26,19 +26,19 @@ public Lotto(List userSelectedNumbers) { + "부터 " + LOTTO_NUMBER_BOUND + " 사이의 숫자여야 합니다."); } } - this.randomNumberSet.addAll(userSelectedNumbers); - if (this.randomNumberSet.size() != LOTTO_NUMBER_COUNT) { + this.numbers.addAll(userSelectedNumbers); + if (this.numbers.size() != LOTTO_NUMBER_COUNT) { throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); } } - public TreeSet getRandomNumberSet() { - return this.randomNumberSet; + public TreeSet getNumbers() { + return this.numbers; } - private void setLottoNumber() { - while (randomNumberSet.size() < LOTTO_NUMBER_COUNT) { - randomNumberSet.add(random.nextInt(LOTTO_NUMBER_LOWER_BOUND, LOTTO_NUMBER_BOUND + 1)); + private void generateRandomNumbers() { + while (numbers.size() < LOTTO_NUMBER_COUNT) { + numbers.add(random.nextInt(LOTTO_NUMBER_LOWER_BOUND, LOTTO_NUMBER_BOUND + 1)); } } diff --git a/src/main/java/domain/LottoChecker.java b/src/main/java/domain/LottoChecker.java index 981430d60..0195c9bbc 100644 --- a/src/main/java/domain/LottoChecker.java +++ b/src/main/java/domain/LottoChecker.java @@ -10,7 +10,7 @@ public class LottoChecker { private final int bonusNumber; public LottoChecker(Lotto winningLotto, LottoTickets lottoTickets, String bonusNumber) { - this.winningLottoNumbers = new ArrayList<>(winningLotto.getRandomNumberSet()); + this.winningLottoNumbers = new ArrayList<>(winningLotto.getNumbers()); this.lottoTickets = lottoTickets; validateBonusNumber(bonusNumber); this.bonusNumber = Integer.parseInt(bonusNumber); @@ -23,13 +23,13 @@ public ArrayList checkAllTickets() { int matchCount = calculateMatchCountForTicket(i); boolean matchBonus = hasBonusNumber(i); - winningTypes.add(LottoWinningType.valueOf(matchCount, matchBonus)); + winningTypes.add(LottoWinningType.of(matchCount, matchBonus)); } return winningTypes; } public boolean hasBonusNumber(int lottoTicketIndex) { - return lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(this.bonusNumber); + return lottoTickets.getTicketNumbers(lottoTicketIndex).contains(this.bonusNumber); } private void validateBonusNumber(String bonusNumber) { @@ -53,7 +53,7 @@ private int calculateMatchCountForTicket(int lottoTicketIndex) { } private int getMatchScore(int lottoTicketIndex, int winningNumber) { - if (lottoTickets.getLottoTreeSet(lottoTicketIndex).contains(winningNumber)) { + if (lottoTickets.getTicketNumbers(lottoTicketIndex).contains(winningNumber)) { return 1; } return 0; diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index bd53562b7..d60ed664a 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -27,7 +27,7 @@ private long calculateTotalPrize() { for (Map.Entry entry : stats.entrySet()) { LottoWinningType type = entry.getKey(); int count = entry.getValue(); - totalPrize += (long) type.prizeExpression(count); + totalPrize += (long) type.calculatePrize(count); } return totalPrize; } diff --git a/src/main/java/domain/LottoTickets.java b/src/main/java/domain/LottoTickets.java index d4787c71d..a76f825da 100644 --- a/src/main/java/domain/LottoTickets.java +++ b/src/main/java/domain/LottoTickets.java @@ -5,23 +5,23 @@ import java.util.TreeSet; public class LottoTickets { - ArrayList lottoArrayList = new ArrayList<>(); + ArrayList lottos = new ArrayList<>(); public void addUserSelectedLottos(List userSelectedLottos) { - lottoArrayList.addAll(userSelectedLottos); + lottos.addAll(userSelectedLottos); } public void addAutoLottos(int autoCount) { for (int i = 0; i < autoCount; i++) { - lottoArrayList.add(new Lotto()); + lottos.add(new Lotto()); } } - public TreeSet getLottoTreeSet(int lottoTicketNumber){ - return new TreeSet<>(lottoArrayList.get(lottoTicketNumber).getRandomNumberSet()); + public TreeSet getTicketNumbers(int ticketIndex){ + return new TreeSet<>(lottos.get(ticketIndex).getNumbers()); } public int getSize() { - return lottoArrayList.size(); + return lottos.size(); } } diff --git a/src/main/java/domain/LottoWinningType.java b/src/main/java/domain/LottoWinningType.java index 29016674e..99b09f245 100644 --- a/src/main/java/domain/LottoWinningType.java +++ b/src/main/java/domain/LottoWinningType.java @@ -12,24 +12,24 @@ public enum LottoWinningType { NO_PRIZE("2개 이하 일치 (0원)- ", tickets -> 0d); private String winningDescription; - private Function prizeExpression; + private Function prizeCalculator; - LottoWinningType(String winningDescription, Function prizeExpression) { + LottoWinningType(String winningDescription, Function prizeCalculator) { this.winningDescription = winningDescription; - this.prizeExpression = prizeExpression; + this.prizeCalculator = prizeCalculator; } - public double prizeExpression(double matchingTickets) { - return prizeExpression.apply(matchingTickets); + public double calculatePrize(double winningTicketCount) { + return prizeCalculator.apply(winningTicketCount); } public String getWinningDescription() { return winningDescription; } - public static LottoWinningType valueOf(int matchCount, boolean matchBonus) { + public static LottoWinningType of(int matchCount, boolean matchBonus) { if (matchCount == 6) return FIRST_PLACE; if (matchCount == 5 && matchBonus) return SECOND_PLACE; if (matchCount == 5) return THIRD_PLACE; diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 20f397be2..9db5f493d 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -20,7 +20,7 @@ public static void printLottoCount(int userSelectedCount, int autoCount) { public static void printLottoNumbers(LottoTickets lottoTickets) { for(int i = 0; i< lottoTickets.getSize(); i++) { - System.out.println(lottoTickets.getLottoTreeSet(i)); + System.out.println(lottoTickets.getTicketNumbers(i)); } } diff --git a/src/test/java/domain/LottoTest.java b/src/test/java/domain/LottoTest.java index 79ff3f159..d939857a5 100644 --- a/src/test/java/domain/LottoTest.java +++ b/src/test/java/domain/LottoTest.java @@ -15,7 +15,7 @@ class LottoTest { void createLottoAutomatically() { Lotto lotto = new Lotto(); - assertThat(lotto.getRandomNumberSet()).hasSize(Lotto.LOTTO_NUMBER_COUNT); + assertThat(lotto.getNumbers()).hasSize(Lotto.LOTTO_NUMBER_COUNT); } @DisplayName("자동으로 생성된 로또 번호는 1과 45 사이의 값이다.") @@ -23,7 +23,7 @@ void createLottoAutomatically() { void validateNumberRange() { Lotto lotto = new Lotto(); - assertThat(lotto.getRandomNumberSet()).allMatch(number -> number >= Lotto.LOTTO_NUMBER_LOWER_BOUND && number <= Lotto.LOTTO_NUMBER_BOUND); + assertThat(lotto.getNumbers()).allMatch(number -> number >= Lotto.LOTTO_NUMBER_LOWER_BOUND && number <= Lotto.LOTTO_NUMBER_BOUND); } @DisplayName("수동으로 로또를 생성한다.") @@ -33,8 +33,8 @@ void createLottoManually() { Lotto lotto = new Lotto(userSelectedNumbers); - assertThat(lotto.getRandomNumberSet()).hasSize(Lotto.LOTTO_NUMBER_COUNT); - assertThat(lotto.getRandomNumberSet()).containsAll(userSelectedNumbers); + assertThat(lotto.getNumbers()).hasSize(Lotto.LOTTO_NUMBER_COUNT); + assertThat(lotto.getNumbers()).containsAll(userSelectedNumbers); } @DisplayName("수동으로 로또를 생성할 때 번호가 6개가 아니면 예외가 발생한다.") diff --git a/src/test/java/domain/LottoTicketsTest.java b/src/test/java/domain/LottoTicketsTest.java index 23415ee9e..5db7e6c98 100644 --- a/src/test/java/domain/LottoTicketsTest.java +++ b/src/test/java/domain/LottoTicketsTest.java @@ -36,8 +36,8 @@ void shouldAddUserSelectedLottos() { lottoTickets.addUserSelectedLottos(lottos); assertThat(lottoTickets.getSize()).isEqualTo(2); - assertThat(lottoTickets.getLottoTreeSet(0)).containsExactly(1, 2, 3, 4, 5, 6); - assertThat(lottoTickets.getLottoTreeSet(1)).containsExactly(7, 8, 9, 10, 11, 12); + assertThat(lottoTickets.getTicketNumbers(0)).containsExactly(1, 2, 3, 4, 5, 6); + assertThat(lottoTickets.getTicketNumbers(1)).containsExactly(7, 8, 9, 10, 11, 12); } } @@ -55,14 +55,14 @@ void shouldAddAutoLottos() { assertThat(lottoTickets.getSize()).isEqualTo(3); for (int i = 0; i < autoCount; i++) { - assertThat(lottoTickets.getLottoTreeSet(i)).hasSize(Lotto.LOTTO_NUMBER_COUNT); + assertThat(lottoTickets.getTicketNumbers(i)).hasSize(Lotto.LOTTO_NUMBER_COUNT); } } } @Nested - @DisplayName("getLottoTreeSet 메소드는") - class GetLottoTreeSet { + @DisplayName("getTicketNumbers 메소드는") + class GetTicketNumbers { @Test @DisplayName("지정된 인덱스의 로또 번호 Set을 반환한다.") @@ -70,7 +70,7 @@ void shouldReturnCorrectLottoSet() { lottoTickets.addAutoLottos(1); lottoTickets.addUserSelectedLottos(List.of(new Lotto(List.of(1, 2, 3, 4, 5, 6)))); - TreeSet manualLottoSet = lottoTickets.getLottoTreeSet(1); + TreeSet manualLottoSet = lottoTickets.getTicketNumbers(1); assertThat(manualLottoSet).containsExactly(1, 2, 3, 4, 5, 6); } diff --git a/src/test/java/domain/LottoWinningTypeTest.java b/src/test/java/domain/LottoWinningTypeTest.java index c024fbf5a..e7808f312 100644 --- a/src/test/java/domain/LottoWinningTypeTest.java +++ b/src/test/java/domain/LottoWinningTypeTest.java @@ -12,7 +12,7 @@ class LottoWinningTypeTest { @Nested - @DisplayName("valueOf 메소드는") + @DisplayName("of 메소드는") class ValueOfTest { @DisplayName("일치 개수와 보너스 여부에 따라 정확한 등수를 반환한다.") @@ -28,31 +28,31 @@ class ValueOfTest { "0, false, NO_PRIZE" }) void returnsCorrectWinningType(int matchCount, boolean matchBonus, LottoWinningType expectedType) { - LottoWinningType actualType = LottoWinningType.valueOf(matchCount, matchBonus); + LottoWinningType actualType = LottoWinningType.of(matchCount, matchBonus); assertThat(actualType).isEqualTo(expectedType); } } @Nested - @DisplayName("prizeExpression 메소드는") - class PrizeExpressionTest { + @DisplayName("calculatePrize 메소드는") + class CalculatePrizeTest { @Test @DisplayName("각 등수별 정확한 상금을 계산한다.") void calculatesCorrectPrize() { - assertThat(LottoWinningType.FIRST_PLACE.prizeExpression(1)).isEqualTo(2_000_000_000); - assertThat(LottoWinningType.SECOND_PLACE.prizeExpression(1)).isEqualTo(30_000_000); - assertThat(LottoWinningType.THIRD_PLACE.prizeExpression(1)).isEqualTo(1_500_000); - assertThat(LottoWinningType.FOURTH_PLACE.prizeExpression(1)).isEqualTo(50_000); - assertThat(LottoWinningType.FIFTH_PLACE.prizeExpression(1)).isEqualTo(5_000); - assertThat(LottoWinningType.NO_PRIZE.prizeExpression(1)).isEqualTo(0); + assertThat(LottoWinningType.FIRST_PLACE.calculatePrize(1)).isEqualTo(2_000_000_000); + assertThat(LottoWinningType.SECOND_PLACE.calculatePrize(1)).isEqualTo(30_000_000); + assertThat(LottoWinningType.THIRD_PLACE.calculatePrize(1)).isEqualTo(1_500_000); + assertThat(LottoWinningType.FOURTH_PLACE.calculatePrize(1)).isEqualTo(50_000); + assertThat(LottoWinningType.FIFTH_PLACE.calculatePrize(1)).isEqualTo(5_000); + assertThat(LottoWinningType.NO_PRIZE.calculatePrize(1)).isEqualTo(0); } @Test @DisplayName("여러 티켓 당첨 시 총 상금을 계산한다.") void calculatesCorrectTotalPrizeForMultipleTickets() { - assertThat(LottoWinningType.FIFTH_PLACE.prizeExpression(3)).isEqualTo(15_000); + assertThat(LottoWinningType.FIFTH_PLACE.calculatePrize(3)).isEqualTo(15_000); } } From 1204f8bd129eeef57da7b09a42f5e8308672b075 Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 9 Aug 2026 16:40:22 +0900 Subject: [PATCH 57/58] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20findLottoWinningType=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoWinningType.java | 8 -------- .../java/domain/LottoWinningTypeTest.java | 19 +------------------ 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/src/main/java/domain/LottoWinningType.java b/src/main/java/domain/LottoWinningType.java index 99b09f245..22a366cd0 100644 --- a/src/main/java/domain/LottoWinningType.java +++ b/src/main/java/domain/LottoWinningType.java @@ -1,6 +1,5 @@ package domain; -import java.util.Arrays; import java.util.function.Function; public enum LottoWinningType { @@ -38,11 +37,4 @@ public static LottoWinningType of(int matchCount, boolean matchBonus) { return NO_PRIZE; } - public static LottoWinningType findLottoWinningType(String winningType){ - return Arrays.stream(LottoWinningType.values()) - .filter(lottoWinningTypePrize -> lottoWinningTypePrize.name().equals(winningType)) - .findAny() - .orElse(NO_PRIZE); - } - } diff --git a/src/test/java/domain/LottoWinningTypeTest.java b/src/test/java/domain/LottoWinningTypeTest.java index e7808f312..ea76859c9 100644 --- a/src/test/java/domain/LottoWinningTypeTest.java +++ b/src/test/java/domain/LottoWinningTypeTest.java @@ -13,7 +13,7 @@ class LottoWinningTypeTest { @Nested @DisplayName("of 메소드는") - class ValueOfTest { + class OfTest { @DisplayName("일치 개수와 보너스 여부에 따라 정확한 등수를 반환한다.") @ParameterizedTest @@ -56,21 +56,4 @@ void calculatesCorrectTotalPrizeForMultipleTickets() { } } - @Nested - @DisplayName("findLottoWinningType 메소드는") - class FindLottoWinningTypeTest { - - @Test - @DisplayName("문자열에 해당하는 enum 상수를 찾는다.") - void findsCorrectEnumConstant() { - assertThat(LottoWinningType.findLottoWinningType("FIRST_PLACE")).isEqualTo(LottoWinningType.FIRST_PLACE); - assertThat(LottoWinningType.findLottoWinningType("SECOND_PLACE")).isEqualTo(LottoWinningType.SECOND_PLACE); - } - - @Test - @DisplayName("존재하지 않는 문자열에 대해서는 NO_PRIZE를 반환한다.") - void returnsNoPrizeForNonExistentConstant() { - assertThat(LottoWinningType.findLottoWinningType("INVALID_TYPE")).isEqualTo(LottoWinningType.NO_PRIZE); - } - } } From e25bd75bd8f0488d23eeae81bee4e1dd78924f2e Mon Sep 17 00:00:00 2001 From: juhee0223 Date: Sun, 9 Aug 2026 23:49:26 +0900 Subject: [PATCH 58/58] =?UTF-8?q?refactor:=20enum=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=A7=A4=EC=A7=81=EB=84=98=EB=B2=84=20=EC=97=86=EC=95=A0?= =?UTF-8?q?=EA=B3=A0=20=EC=8B=A4=EC=88=98=EB=A5=BC=20=EB=B0=A9=EC=A7=80?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/LottoResult.java | 2 +- src/main/java/domain/LottoWinningType.java | 61 +++++++++++++--------- src/main/java/view/OutputView.java | 31 +++++++---- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/main/java/domain/LottoResult.java b/src/main/java/domain/LottoResult.java index d60ed664a..76f3fe3bb 100644 --- a/src/main/java/domain/LottoResult.java +++ b/src/main/java/domain/LottoResult.java @@ -27,7 +27,7 @@ private long calculateTotalPrize() { for (Map.Entry entry : stats.entrySet()) { LottoWinningType type = entry.getKey(); int count = entry.getValue(); - totalPrize += (long) type.calculatePrize(count); + totalPrize += type.calculatePrize(count); } return totalPrize; } diff --git a/src/main/java/domain/LottoWinningType.java b/src/main/java/domain/LottoWinningType.java index 22a366cd0..0371132f1 100644 --- a/src/main/java/domain/LottoWinningType.java +++ b/src/main/java/domain/LottoWinningType.java @@ -1,40 +1,49 @@ package domain; -import java.util.function.Function; - public enum LottoWinningType { - FIRST_PLACE("6개 일치 (2000000000원)- ", tickets -> tickets * 2000000000), - SECOND_PLACE("5개 일치, 보너스 볼 일치(30000000원)- ", tickets -> tickets * 30000000), - THIRD_PLACE("5개 일치 (1500000원)- ", tickets -> tickets * 1500000), - FOURTH_PLACE("4개 일치 (50000원)- ", tickets -> tickets * 50000), - FIFTH_PLACE("3개 일치 (5000원)- ", tickets -> tickets * 5000), - NO_PRIZE("2개 이하 일치 (0원)- ", tickets -> 0d); - - private String winningDescription; - private Function prizeCalculator; - + FIRST_PLACE(6, false, 2_000_000_000), + SECOND_PLACE(5, true, 30_000_000), + THIRD_PLACE(5, false, 1_500_000), + FOURTH_PLACE(4, false, 50_000), + FIFTH_PLACE(3, false, 5_000), + NO_PRIZE(0, false, 0); + + private final int matchCount; + private final boolean requiresBonus; + private final int prize; + + LottoWinningType(int matchCount, boolean requiresBonus, int prize) { + this.matchCount = matchCount; + this.requiresBonus = requiresBonus; + this.prize = prize; + } - LottoWinningType(String winningDescription, Function prizeCalculator) { - this.winningDescription = winningDescription; - this.prizeCalculator = prizeCalculator; + public static LottoWinningType of(int matchCount, boolean matchBonus) { + if (matchCount == FIRST_PLACE.matchCount) return FIRST_PLACE; + if (matchCount == SECOND_PLACE.matchCount && matchBonus) return SECOND_PLACE; + if (matchCount == THIRD_PLACE.matchCount) return THIRD_PLACE; + if (matchCount == FOURTH_PLACE.matchCount) return FOURTH_PLACE; + if (matchCount == FIFTH_PLACE.matchCount) return FIFTH_PLACE; + return NO_PRIZE; + } + public long calculatePrize(int winningTicketCount) { + return (long) prize * winningTicketCount; } - public double calculatePrize(double winningTicketCount) { - return prizeCalculator.apply(winningTicketCount); + public boolean isPrizeWinning() { + return prize > 0; } - public String getWinningDescription() { - return winningDescription; + public int getMatchCount() { + return matchCount; } - public static LottoWinningType of(int matchCount, boolean matchBonus) { - if (matchCount == 6) return FIRST_PLACE; - if (matchCount == 5 && matchBonus) return SECOND_PLACE; - if (matchCount == 5) return THIRD_PLACE; - if (matchCount == 4) return FOURTH_PLACE; - if (matchCount == 3) return FIFTH_PLACE; - return NO_PRIZE; + public boolean requiresBonus() { + return requiresBonus; } + public int getPrize() { + return prize; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9db5f493d..d68f9d1e3 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,14 +2,28 @@ import domain.LottoTickets; import domain.LottoWinningType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public final class OutputView { + private static final List WINNING_TYPE_PRINT_ORDER = createWinningTypePrintOrder(); + private OutputView() { } + private static List createWinningTypePrintOrder() { + List printOrder = Arrays.stream(LottoWinningType.values()) + .filter(LottoWinningType::isPrizeWinning) + .collect(Collectors.toCollection(ArrayList::new)); + Collections.reverse(printOrder); + return List.copyOf(printOrder); + } + public static void printError(String message) { System.out.println("[ERROR] " + message + " 다시 입력해 주세요."); } @@ -28,17 +42,16 @@ public static void printMatchCount(Map matchStatistic System.out.println("\n당첨 통계"); System.out.println("---------"); - List printOrder = List.of( - LottoWinningType.FIFTH_PLACE, - LottoWinningType.FOURTH_PLACE, - LottoWinningType.THIRD_PLACE, - LottoWinningType.SECOND_PLACE, - LottoWinningType.FIRST_PLACE - ); + for (LottoWinningType type : WINNING_TYPE_PRINT_ORDER) { + System.out.println(formatWinningStatistic(type, matchStatistics.get(type))); + } + } - for (LottoWinningType type : printOrder) { - System.out.println(type.getWinningDescription() + matchStatistics.get(type) + "개"); + private static String formatWinningStatistic(LottoWinningType type, int winningTicketCount) { + if (type.requiresBonus()) { + return type.getMatchCount() + "개 일치, 보너스 볼 일치(" + type.getPrize() + "원) - " + winningTicketCount + "개"; } + return type.getMatchCount() + "개 일치 (" + type.getPrize() + "원)- " + winningTicketCount + "개"; } public static void printRateOfReturn(double rateOfReturn) {