From c4fe3ddc8a73ef012a7f46689565742e21e82aeb Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Tue, 25 Nov 2025 22:14:55 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=20=20=EB=91=90=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EB=B9=84=EA=B5=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 기존 방식: LottoGame 중간 객체 사용 LottoGame game = new LottoGame(winning); GameResult gameResult = game.check(purchase); 2. 제안된 방식 (현재 구현) LottoTickets tickets = LottoMachine.generateTickets(purchase); GameResult gameResult = tickets.match(winning); LottoGame 방식의 문제점: - LottoGame.check(purchase) 내부에서 티켓 생성이 일어나면, 랜덤 생성 로직이 포함되어 테스트가 어려움 - 중간 계층이 많아 단위 테스트 작성 시 모킹이 필요해짐 --- src/main/java/lotto/LottoGameApplication.java | 10 ++-- .../java/lotto/domain/game/LottoGame.java | 23 --------- .../java/lotto/domain/game/LottoMachine.java | 10 ++-- .../java/lotto/domain/lotto/LottoTickets.java | 10 ++-- .../java/lotto/domain/lotto/Purchase.java | 17 +++---- src/main/java/lotto/ui/ResultView.java | 6 +-- .../lotto/domain/lotto/LottoTicketsTest.java | 29 ++++++++++++ .../lotto/domain/lotto/WinningTicketTest.java | 47 +++++++++++++++++++ .../lotto/domain/result/PurchaseTest.java | 11 +---- 9 files changed, 99 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/lotto/domain/game/LottoGame.java create mode 100644 src/test/java/lotto/domain/lotto/LottoTicketsTest.java create mode 100644 src/test/java/lotto/domain/lotto/WinningTicketTest.java diff --git a/src/main/java/lotto/LottoGameApplication.java b/src/main/java/lotto/LottoGameApplication.java index 7fc738d13a..894db364e1 100644 --- a/src/main/java/lotto/LottoGameApplication.java +++ b/src/main/java/lotto/LottoGameApplication.java @@ -1,7 +1,7 @@ package lotto; -import lotto.domain.game.LottoGame; import lotto.domain.game.LottoMachine; +import lotto.domain.lotto.LottoTickets; import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; import lotto.domain.lotto.WinningTicket; @@ -16,15 +16,15 @@ public static void main(String[] args) { int purchaseAmount = InputView.inputPurchaseAmount(); Purchase purchase = machine.purchase(new Money(purchaseAmount)); - ResultView.printPurchase(purchase); + LottoTickets tickets = LottoMachine.generateTickets(purchase); // purchase에서 구매할 ticket수를 구해 LottoTicket을 생성해 반환 + ResultView.printPurchase(tickets); String winningLottoNumbers = InputView.inputWinningLottoNumbers(); int bonusNumber = InputView.inputBonusNumber(); WinningTicket winning = new WinningTicket(winningLottoNumbers, bonusNumber); - LottoGame game = new LottoGame(winning); - GameResult gameResult = game.check(purchase); + GameResult result = tickets.match(winning); - ResultView.printResult(gameResult, purchase.getPurchaseAmount()); + ResultView.printResult(result, purchase.getPurchaseAmount()); } } diff --git a/src/main/java/lotto/domain/game/LottoGame.java b/src/main/java/lotto/domain/game/LottoGame.java deleted file mode 100644 index dc9c7909a4..0000000000 --- a/src/main/java/lotto/domain/game/LottoGame.java +++ /dev/null @@ -1,23 +0,0 @@ -package lotto.domain.game; - -import java.util.List; -import lotto.domain.lotto.LottoTicket; -import lotto.domain.lotto.LottoTickets; -import lotto.domain.lotto.Purchase; -import lotto.domain.lotto.WinningTicket; -import lotto.domain.result.GameResult; - -public class LottoGame { - - private final WinningTicket winningTicket; - - public LottoGame(WinningTicket winningTicket) { - this.winningTicket = winningTicket; - } - - public GameResult check(Purchase purchase) { - LottoTickets tickets = purchase.getTickets(); - return tickets.updateRank(winningTicket); - } - -} \ No newline at end of file diff --git a/src/main/java/lotto/domain/game/LottoMachine.java b/src/main/java/lotto/domain/game/LottoMachine.java index 294b4bab33..4fcf259414 100644 --- a/src/main/java/lotto/domain/game/LottoMachine.java +++ b/src/main/java/lotto/domain/game/LottoMachine.java @@ -18,16 +18,16 @@ public LottoMachine(Money lottoTicketPrice) { this.lottoTicketPrice = lottoTicketPrice; } + public static LottoTickets generateTickets(Purchase purchase) { + return new LottoTickets(purchase.getCount()); + } + public Purchase purchase(Money money) { - return new Purchase(lottoTicketPrice, generateTickets(calculate(money))); + return new Purchase(lottoTicketPrice, calculate(money)); } private int calculate(Money money) { return money.divideForCount(lottoTicketPrice); } - LottoTickets generateTickets(int cnt) { - return new LottoTickets(cnt); - } - } \ No newline at end of file diff --git a/src/main/java/lotto/domain/lotto/LottoTickets.java b/src/main/java/lotto/domain/lotto/LottoTickets.java index 050742da1d..d5a616ce7d 100644 --- a/src/main/java/lotto/domain/lotto/LottoTickets.java +++ b/src/main/java/lotto/domain/lotto/LottoTickets.java @@ -24,14 +24,10 @@ private static List generate(int cnt){ return tickets; } - public Money calculate(Money pricePerTicket) { - return pricePerTicket.multiply(tickets.size()); - } - - public GameResult updateRank(WinningTicket winningTicket) { + public GameResult match(WinningTicket winning) { GameResult gameResult = new GameResult(); for(LottoTicket ticket : tickets){ - gameResult.updateRank(winningTicket.match(ticket)); + gameResult.updateRank(winning.match(ticket)); } return gameResult; } @@ -39,7 +35,7 @@ public GameResult updateRank(WinningTicket winningTicket) { @Override public String toString(){ StringBuilder sb = new StringBuilder(); - sb.append(tickets.size()+"개를 구매했습니다."); + sb.append(tickets.size()+"개를 구매했습니다.\n"); for (int i = 0; i < tickets.size(); i++) { sb.append(tickets.get(i) + "\n"); } diff --git a/src/main/java/lotto/domain/lotto/Purchase.java b/src/main/java/lotto/domain/lotto/Purchase.java index 0d6632b362..c126b3b720 100644 --- a/src/main/java/lotto/domain/lotto/Purchase.java +++ b/src/main/java/lotto/domain/lotto/Purchase.java @@ -3,23 +3,18 @@ public class Purchase { private final Money pricePerTicket; - private final LottoTickets tickets; + private final int count; - public Purchase(Money pricePerTicket, LottoTickets tickets) { + public Purchase(Money pricePerTicket, int count) { this.pricePerTicket = pricePerTicket; - this.tickets = tickets; - } - - public LottoTickets getTickets(){ - return this.tickets; + this.count = count; } public Money getPurchaseAmount() { - return tickets.calculate(this.pricePerTicket); + return pricePerTicket.multiply(count); } - @Override - public String toString() { - return tickets.toString(); + public int getCount() { + return this.count; } } \ No newline at end of file diff --git a/src/main/java/lotto/ui/ResultView.java b/src/main/java/lotto/ui/ResultView.java index 8e929ac42d..3c4bdbae71 100644 --- a/src/main/java/lotto/ui/ResultView.java +++ b/src/main/java/lotto/ui/ResultView.java @@ -1,13 +1,13 @@ package lotto.ui; +import lotto.domain.lotto.LottoTickets; import lotto.domain.lotto.Money; -import lotto.domain.lotto.Purchase; import lotto.domain.result.GameResult; public class ResultView { - public static void printPurchase(Purchase purchase) { - System.out.println(purchase); + public static void printPurchase(LottoTickets tickets) { + System.out.println(tickets); } public static void printResult(GameResult gameResult, Money purchaseAmount) { diff --git a/src/test/java/lotto/domain/lotto/LottoTicketsTest.java b/src/test/java/lotto/domain/lotto/LottoTicketsTest.java new file mode 100644 index 0000000000..1734265d29 --- /dev/null +++ b/src/test/java/lotto/domain/lotto/LottoTicketsTest.java @@ -0,0 +1,29 @@ +package lotto.domain.lotto; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Map; +import lotto.domain.game.Rank; +import lotto.domain.result.GameResult; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LottoTicketsTest { + + @Test + @DisplayName("여러 티켓의 당첨 결과가 올바르게 집계된다") + void match_multiple_tickets() { + LottoTickets tickets = new LottoTickets(List.of( + new LottoTicket("1, 2, 3, 10, 11, 12"), + new LottoTicket("1, 2, 3, 20, 21, 22"), + new LottoTicket("1, 2, 3, 30, 31, 32") + )); + WinningTicket winning = new WinningTicket("1, 2, 3, 4, 5, 6", 7); + + GameResult result = tickets.match(winning); + + GameResult expected = new GameResult(Map.of(Rank.FIFTH, 3)); + assertThat(result.toString()).isEqualTo(expected.toString()); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/lotto/WinningTicketTest.java b/src/test/java/lotto/domain/lotto/WinningTicketTest.java new file mode 100644 index 0000000000..b15402617c --- /dev/null +++ b/src/test/java/lotto/domain/lotto/WinningTicketTest.java @@ -0,0 +1,47 @@ +package lotto.domain.lotto; + +import static org.assertj.core.api.Assertions.assertThat; + +import lotto.domain.game.Rank; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class WinningTicketTest { + + private WinningTicket winningTicket; + + @BeforeEach + void setUp() { + winningTicket = new WinningTicket("1, 2, 3, 4, 5, 6", 7); + } + + @Test + @DisplayName("5개 일치 + 보너스 일치 시 2등") + void match_5개_보너스_일치_2등() { + LottoTicket ticket = new LottoTicket("1, 2, 3, 4, 5, 7"); + assertThat(winningTicket.match(ticket)).isEqualTo(Rank.SECOND); + } + + @Test + @DisplayName("5개 일치 + 보너스 불일치 시 3등") + void match_5개_보너스_불일치_3등() { + LottoTicket ticket = new LottoTicket("1, 2, 3, 4, 5, 8"); + assertThat(winningTicket.match(ticket)).isEqualTo(Rank.THIRD); + } + + @ParameterizedTest + @CsvSource({ + "1, 2, 3, 4, 5, 6, FIRST", + "1, 2, 3, 4, 8, 9, FOURTH", + "1, 2, 3, 7, 9, 10, FIFTH", + "1, 2, 8, 9, 10, 11, NONE" + }) + void match_3개_일치_5등(int n1, int n2, int n3, int n4, int n5, int n6, Rank rank) { + LottoTicket ticket = new LottoTicket(n1, n2, n3, n4, n5, n6); + assertThat(winningTicket.match(ticket)).isEqualTo(rank); + } + +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/result/PurchaseTest.java b/src/test/java/lotto/domain/result/PurchaseTest.java index 40b71b269e..c99f874c12 100644 --- a/src/test/java/lotto/domain/result/PurchaseTest.java +++ b/src/test/java/lotto/domain/result/PurchaseTest.java @@ -22,17 +22,8 @@ class PurchaseTest { "2000, 3, 6000" }) void getPurchaseAmount(int pricePerTicket, int ticketCount, int expectedAmount) { - LottoTickets tickets = createTickets(ticketCount); - Purchase purchase = new Purchase(new Money(pricePerTicket), tickets); + Purchase purchase = new Purchase(new Money(pricePerTicket), ticketCount); assertThat(purchase.getPurchaseAmount()).isEqualTo(new Money(expectedAmount)); } - - private LottoTickets createTickets(int count) { - List tickets = new ArrayList<>(); - for (int i = 0; i < count; i++) { - tickets.add(new LottoTicket(1, 2, 3, 4, 5, 6)); - } - return new LottoTickets(tickets); - } } \ No newline at end of file From 37940580ba65046d3a29ca2b2ed1f0cfb73eb0da Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Wed, 26 Nov 2025 18:30:32 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=9A=80=204=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90(=EC=88=98=EB=8F=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/LottoGameApplication.java | 17 +++++--- .../java/lotto/domain/game/LottoMachine.java | 31 +++++++++++--- .../java/lotto/domain/lotto/LottoTickets.java | 21 ++-------- .../java/lotto/domain/lotto/Purchase.java | 30 ++++++++++---- .../lotto/domain/lotto/WinningTicket.java | 4 ++ .../java/lotto/domain/result/GameResult.java | 41 +++++-------------- src/main/java/lotto/ui/InputView.java | 18 +++++++- src/main/java/lotto/ui/ResultView.java | 20 ++++++--- .../lotto/domain/game/LottoMachineTest.java | 16 ++++++-- .../lotto/domain/result/GameResultTest.java | 17 ++++---- .../lotto/domain/result/PurchaseTest.java | 27 +++++++----- 11 files changed, 144 insertions(+), 98 deletions(-) diff --git a/src/main/java/lotto/LottoGameApplication.java b/src/main/java/lotto/LottoGameApplication.java index 894db364e1..a1f636ae39 100644 --- a/src/main/java/lotto/LottoGameApplication.java +++ b/src/main/java/lotto/LottoGameApplication.java @@ -1,5 +1,6 @@ package lotto; +import java.util.List; import lotto.domain.game.LottoMachine; import lotto.domain.lotto.LottoTickets; import lotto.domain.lotto.Money; @@ -15,16 +16,22 @@ public static void main(String[] args) { LottoMachine machine = new LottoMachine(); int purchaseAmount = InputView.inputPurchaseAmount(); - Purchase purchase = machine.purchase(new Money(purchaseAmount)); - LottoTickets tickets = LottoMachine.generateTickets(purchase); // purchase에서 구매할 ticket수를 구해 LottoTicket을 생성해 반환 - ResultView.printPurchase(tickets); + int manualCount = InputView.inputManualLottoCount(); + List manualTickets = InputView.inputManualLottoTickets(manualCount); + + int totalCount = machine.calculateTotalCount(new Money(purchaseAmount)); + + Purchase purchase = machine.createPurchase(manualCount, totalCount); + ResultView.printPurchase(purchase); + + LottoTickets tickets = machine.generateTickets(manualTickets, purchase.getAutoCount()); + ResultView.printTickets(tickets); String winningLottoNumbers = InputView.inputWinningLottoNumbers(); int bonusNumber = InputView.inputBonusNumber(); WinningTicket winning = new WinningTicket(winningLottoNumbers, bonusNumber); GameResult result = tickets.match(winning); - ResultView.printResult(result, purchase.getPurchaseAmount()); } -} +} \ No newline at end of file diff --git a/src/main/java/lotto/domain/game/LottoMachine.java b/src/main/java/lotto/domain/game/LottoMachine.java index 4fcf259414..3f3e775848 100644 --- a/src/main/java/lotto/domain/game/LottoMachine.java +++ b/src/main/java/lotto/domain/game/LottoMachine.java @@ -1,5 +1,8 @@ package lotto.domain.game; +import java.util.ArrayList; +import java.util.List; +import lotto.domain.lotto.LottoTicket; import lotto.domain.lotto.LottoTickets; import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; @@ -18,16 +21,32 @@ public LottoMachine(Money lottoTicketPrice) { this.lottoTicketPrice = lottoTicketPrice; } - public static LottoTickets generateTickets(Purchase purchase) { - return new LottoTickets(purchase.getCount()); + public int calculateTotalCount(Money budget) { + return budget.divideForCount(lottoTicketPrice); } - public Purchase purchase(Money money) { - return new Purchase(lottoTicketPrice, calculate(money)); + public LottoTickets generateTickets(List manualTickets, int autoCount) { + List manual = convert(manualTickets); + List auto = generate(autoCount); + + List allTickets = new ArrayList<>(manual); + allTickets.addAll(auto); + return new LottoTickets(allTickets); + } + + public Purchase createPurchase(int manualCount, int totalCount) { + return new Purchase(manualCount, totalCount, lottoTicketPrice); } - private int calculate(Money money) { - return money.divideForCount(lottoTicketPrice); + private List convert(List tickets) { + return tickets.stream().map(LottoTicket::new).toList(); } + private List generate(int count) { + List tickets = new ArrayList<>(); + for (int i = 0; i < count; i++) { + tickets.add(new LottoTicket(Random.generate())); + } + return tickets; + } } \ No newline at end of file diff --git a/src/main/java/lotto/domain/lotto/LottoTickets.java b/src/main/java/lotto/domain/lotto/LottoTickets.java index d5a616ce7d..4a7afc17b8 100644 --- a/src/main/java/lotto/domain/lotto/LottoTickets.java +++ b/src/main/java/lotto/domain/lotto/LottoTickets.java @@ -1,29 +1,15 @@ package lotto.domain.lotto; -import java.util.ArrayList; import java.util.List; -import lotto.domain.game.Random; import lotto.domain.result.GameResult; public class LottoTickets { private final List tickets; - public LottoTickets(int cnt) { - this(generate(cnt)); - } - public LottoTickets(List tickets){ this.tickets = tickets; } - private static List generate(int cnt){ - List tickets = new ArrayList<>(); - for (int i = 0; i < cnt; i++) { - tickets.add(new LottoTicket(Random.generate())); - } - return tickets; - } - public GameResult match(WinningTicket winning) { GameResult gameResult = new GameResult(); for(LottoTicket ticket : tickets){ @@ -33,11 +19,10 @@ public GameResult match(WinningTicket winning) { } @Override - public String toString(){ + public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(tickets.size()+"개를 구매했습니다.\n"); - for (int i = 0; i < tickets.size(); i++) { - sb.append(tickets.get(i) + "\n"); + for (LottoTicket ticket : tickets) { + sb.append(ticket).append("\n"); } return sb.toString(); } diff --git a/src/main/java/lotto/domain/lotto/Purchase.java b/src/main/java/lotto/domain/lotto/Purchase.java index c126b3b720..7dc7b08513 100644 --- a/src/main/java/lotto/domain/lotto/Purchase.java +++ b/src/main/java/lotto/domain/lotto/Purchase.java @@ -2,19 +2,33 @@ public class Purchase { - private final Money pricePerTicket; - private final int count; + private final int manualCount; + private final int autoCount; + private final Money purchaseAmount; - public Purchase(Money pricePerTicket, int count) { - this.pricePerTicket = pricePerTicket; - this.count = count; + public Purchase(int manualCount, int totalCount, Money pricePerTicket) { + validate(manualCount, totalCount); + this.manualCount = manualCount; + this.autoCount = totalCount - manualCount; + this.purchaseAmount = pricePerTicket.multiply(totalCount); + } + + private static void validate(int manualCount, int totalCount){ + if (manualCount > totalCount) { + throw new IllegalArgumentException("수동 구매 수가 총 구매 가능 수를 초과합니다"); + } } public Money getPurchaseAmount() { - return pricePerTicket.multiply(count); + return purchaseAmount; + } + + public int getAutoCount() { + return autoCount; } - public int getCount() { - return this.count; + @Override + public String toString() { + return "수동으로 " + manualCount + "장, 자동으로 " + autoCount + "개를 구매했습니다."; } } \ No newline at end of file diff --git a/src/main/java/lotto/domain/lotto/WinningTicket.java b/src/main/java/lotto/domain/lotto/WinningTicket.java index 842936d474..b72ef39b1a 100644 --- a/src/main/java/lotto/domain/lotto/WinningTicket.java +++ b/src/main/java/lotto/domain/lotto/WinningTicket.java @@ -11,10 +11,14 @@ public WinningTicket(String numbers, int bonus){ } public WinningTicket(LottoTicket ticket, LottoNumber bonus) { + validate(ticket, bonus); this.ticket = ticket; this.bonus = bonus; } + private static void validate(LottoTicket ticket, LottoNumber bonus){ + if(ticket.contains(bonus))throw new IllegalArgumentException("당첨 번호와 중복됩니다."); + } public Rank match(LottoTicket ticket) { return Rank.valueOf(this.ticket.matchCount(ticket), ticket.contains(this.bonus)); } diff --git a/src/main/java/lotto/domain/result/GameResult.java b/src/main/java/lotto/domain/result/GameResult.java index a9fbeec5fe..c4d3a32707 100644 --- a/src/main/java/lotto/domain/result/GameResult.java +++ b/src/main/java/lotto/domain/result/GameResult.java @@ -1,7 +1,7 @@ package lotto.domain.result; -import java.math.BigDecimal; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -20,44 +20,23 @@ public GameResult(Map ranks) { this.ranks = ranks; } - public void updateRank(Rank rank){ - ranks.put(rank, ranks.getOrDefault(rank, 0) + 1); + public void updateRank(Rank rank) { + ranks.put(rank, ranks.getOrDefault(rank, 0) + 1); } - public String getProfitMessage(Money purchaseAmount) { - int totalPrize = ranks.entrySet().stream() + public Money getTotalPrize() { + int total = ranks.entrySet().stream() .mapToInt(entry -> entry.getKey().getPrize() * entry.getValue()) .sum(); - BigDecimal profit = new Money(totalPrize).divideBy(purchaseAmount); - String explanation = Explanation.getMessage(profit); - return String.format("총 수익률은 %s입니다.(기준이 1이기 때문에 결과적으로 %s라는 의미임)", - profit, explanation); + return new Money(total); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(Arrays.stream(Rank.values()) + return Arrays.stream(Rank.values()) .filter(x -> x != Rank.NONE) - .map( - e -> String.format("%s - %d개", e, ranks.getOrDefault(e, 0)) - ).collect(Collectors.joining("\n"))); - return sb.toString(); - } - - enum Explanation { - PROFIT("이익"), LOSS("손해"); - private final String message; - - Explanation(String message) { - this.message = message; - } - - static String getMessage(BigDecimal value) { - if (value.compareTo(BigDecimal.ONE) >= 0) { - return PROFIT.message; - } - return LOSS.message; - } + .sorted(Comparator.reverseOrder()) + .map(e -> String.format("%s - %d개", e, ranks.getOrDefault(e, 0))) + .collect(Collectors.joining("\n")); } } \ No newline at end of file diff --git a/src/main/java/lotto/ui/InputView.java b/src/main/java/lotto/ui/InputView.java index 84de8918db..d8b2c1f516 100644 --- a/src/main/java/lotto/ui/InputView.java +++ b/src/main/java/lotto/ui/InputView.java @@ -1,5 +1,7 @@ package lotto.ui; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; public class InputView { @@ -21,6 +23,20 @@ public static String inputWinningLottoNumbers() { public static int inputBonusNumber() { System.out.println("보너스 번호를 입력해주세요."); - return scanner.nextInt(); + return Integer.parseInt(scanner.nextLine()); + } + + public static int inputManualLottoCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + return Integer.parseInt(scanner.nextLine()); + } + + public static List inputManualLottoTickets(int manualLottoCount) { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + List tickets = new ArrayList<>(); + for(int i = 0; i < manualLottoCount; i++){ + tickets.add(scanner.nextLine()); + } + return tickets; } } diff --git a/src/main/java/lotto/ui/ResultView.java b/src/main/java/lotto/ui/ResultView.java index 3c4bdbae71..1fc5cc92a0 100644 --- a/src/main/java/lotto/ui/ResultView.java +++ b/src/main/java/lotto/ui/ResultView.java @@ -1,20 +1,30 @@ package lotto.ui; +import java.math.BigDecimal; import lotto.domain.lotto.LottoTickets; import lotto.domain.lotto.Money; +import lotto.domain.lotto.Purchase; import lotto.domain.result.GameResult; public class ResultView { - public static void printPurchase(LottoTickets tickets) { + public static void printPurchase(Purchase purchase) { + System.out.println(purchase); + } + + public static void printTickets(LottoTickets tickets) { System.out.println(tickets); } public static void printResult(GameResult gameResult, Money purchaseAmount) { - System.out.println("\n당첨 통계\n---------"); System.out.println(gameResult); - System.out.println("총 수익률은 " + gameResult.getProfitMessage(purchaseAmount)); - } -} + Money totalPrize = gameResult.getTotalPrize(); + BigDecimal profitRate = totalPrize.divideBy(purchaseAmount); + String explanation = profitRate.compareTo(BigDecimal.ONE) >= 0 ? "이익" : "손해"; + + System.out.printf("총 수익률은 %s입니다.(기준이 1이기 때문에 결과적으로 %s라는 의미임)%n", + profitRate, explanation); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/game/LottoMachineTest.java b/src/test/java/lotto/domain/game/LottoMachineTest.java index f19b0cc226..5669ecee8c 100644 --- a/src/test/java/lotto/domain/game/LottoMachineTest.java +++ b/src/test/java/lotto/domain/game/LottoMachineTest.java @@ -10,10 +10,18 @@ public class LottoMachineTest { @ParameterizedTest - @CsvSource({"10000,10000", "1,0", "2320,2000"}) - void lottoMachinePurchaseNTicketsBasedOnPrice(int pay, int expected) { + @CsvSource({"10000,10", "1000,1", "2320,2"}) + void calculateTotalCountBasedOnBudget(int pay, int expectedCount) { LottoMachine machine = new LottoMachine(); - Purchase tickets = machine.purchase(new Money(pay)); - assertThat(tickets.getPurchaseAmount()).isEqualTo(new Money(expected)); + int totalCount = machine.calculateTotalCount(new Money(pay)); + assertThat(totalCount).isEqualTo(expectedCount); + } + + @ParameterizedTest + @CsvSource({"3, 10, 10000", "0, 10, 10000", "5, 10, 10000"}) + void createPurchaseWithManualAndTotalCount(int manualCount, int totalCount, int expectedAmount) { + LottoMachine machine = new LottoMachine(); + Purchase purchase = machine.createPurchase(manualCount, totalCount); + assertThat(purchase.getPurchaseAmount()).isEqualTo(new Money(expectedAmount)); } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/result/GameResultTest.java b/src/test/java/lotto/domain/result/GameResultTest.java index da4efe3c04..e40acd1a35 100644 --- a/src/test/java/lotto/domain/result/GameResultTest.java +++ b/src/test/java/lotto/domain/result/GameResultTest.java @@ -2,7 +2,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import lotto.domain.game.Rank; @@ -14,21 +13,21 @@ class GameResultTest { @Test - void testCalculateProfitRate() { + void getTotalPrize_first() { Map details = new HashMap<>(); details.put(Rank.FIRST, 1); GameResult result = new GameResult(details); - Money purchaseAmount = new Money(1000); - assertThat(result.getProfitMessage(purchaseAmount)).contains("2000000.00"); + + assertThat(result.getTotalPrize()).isEqualTo(new Money(2_000_000_000)); } @ParameterizedTest - @CsvSource({"50000,50000,이익", "100000,50000,손해"}) - void testExplanation(int purchaseAmount, int totalPrize, String value) { + @CsvSource({"1, 50000", "2, 100000", "3, 150000"}) + void getTotalPrize_fourth(int count, int expectedPrize) { Map details = new HashMap<>(); - details.put(Rank.FOURTH, totalPrize / 50000); + details.put(Rank.FOURTH, count); GameResult result = new GameResult(details); - assertThat(result.getProfitMessage(new Money(purchaseAmount))).contains(value); - } + assertThat(result.getTotalPrize()).isEqualTo(new Money(expectedPrize)); + } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/result/PurchaseTest.java b/src/test/java/lotto/domain/result/PurchaseTest.java index c99f874c12..2d8a0635d6 100644 --- a/src/test/java/lotto/domain/result/PurchaseTest.java +++ b/src/test/java/lotto/domain/result/PurchaseTest.java @@ -2,13 +2,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.ArrayList; -import java.util.List; -import lotto.domain.lotto.LottoTicket; -import lotto.domain.lotto.LottoTickets; import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -16,14 +11,24 @@ class PurchaseTest { @ParameterizedTest @CsvSource({ - "1000, 1, 1000", - "1000, 5, 5000", - "1000, 10, 10000", - "2000, 3, 6000" + "0, 1, 1000, 1000", + "2, 5, 1000, 5000", + "5, 10, 1000, 10000", + "1, 3, 2000, 6000" }) - void getPurchaseAmount(int pricePerTicket, int ticketCount, int expectedAmount) { - Purchase purchase = new Purchase(new Money(pricePerTicket), ticketCount); + void getPurchaseAmount(int manualCount, int totalCount, int pricePerTicket, int expectedAmount) { + Purchase purchase = new Purchase(manualCount, totalCount, new Money(pricePerTicket)); assertThat(purchase.getPurchaseAmount()).isEqualTo(new Money(expectedAmount)); } + @ParameterizedTest + @CsvSource({ + "3, 10, 7", + "0, 10, 10", + "5, 10, 5" + }) + void getAutoCount(int manualCount, int totalCount, int expectedAutoCount) { + Purchase purchase = new Purchase(manualCount, totalCount, new Money(1000)); + assertThat(purchase.getAutoCount()).isEqualTo(expectedAutoCount); + } } \ No newline at end of file From 83657e6b1bafcf0dcb35322d0f591b8ab97cfb08 Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Wed, 26 Nov 2025 18:49:22 +0900 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=9A=80=204=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90(=EC=88=98=EB=8F=99)=20:=20README=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/README.md | 54 ++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/main/java/lotto/README.md b/src/main/java/lotto/README.md index bf8997404e..b49c68679b 100644 --- a/src/main/java/lotto/README.md +++ b/src/main/java/lotto/README.md @@ -1,11 +1,13 @@ # 기능 요구사항 -> 입력한 금액만큼 로또 자동으로 발급해주는 기능 +> 입력한 금액만큼 로또를 수동/자동으로 발급해주는 기능 1. 구입 금액 입력 기능 -2. N개의 로또 구매 기능 (자동) -3. 당첨 번호 입력 기능 (당첨 번호 6개 + 보너스볼 1개) -4. 당첨 통계 조회 기능 +2. 수동 구매 로또 개수 입력 기능 +3. 수동 로또 번호 입력 기능 +4. N개의 로또 구매 기능 (수동 + 자동) +5. 당첨 번호 입력 기능 (당첨 번호 6개 + 보너스볼 1개) +6. 당첨 통계 조회 기능 - 몇 개의 번호가 일치하는지, 몇 개인지 - 보너스볼 일치 여부 (5개 일치 시) - 수익률 @@ -17,25 +19,37 @@ - 무엇인가? : 구매금에 따라 로또를 생성해주는 머신 - 역할 - 로또 발급 개수 계산 - - 랜덤 로또 티켓 생성 + - 수동 로또 티켓 변환 + - 자동 로또 티켓 생성 + - 구매 정보(Purchase) 생성 + +## 로또 티켓들 (LottoTickets) + +- 무엇인가? : 여러 로또 티켓을 관리하는 일급 컬렉션 +- 역할 + - 로또 티켓 목록 보관 + - 당첨 티켓과 비교하여 게임 결과 생성 ## 로또 (LottoTicket) - 무엇인가? : 6개의 고유한 숫자를 담은 로또 티켓 - 역할 - 6개의 숫자 보관 - - 일치 갯수 비교 + - 문자열/숫자 배열로부터 티켓 생성 + - 일치 개수 비교 + - 특정 번호 포함 여부 확인 ## 로또 숫자 (LottoNumber) - 무엇인가? : 로또 내 숫자 - 역할 - 번호 유효성 보장 (1 ~ 45) + - 캐싱을 통한 객체 재사용 - 숫자 객체 비교 ## 금액 (Money) -- 무엇인가? : 금액을 표현하는 일급 컬렉션 +- 무엇인가? : 금액을 표현하는 값 객체 - 역할 - 금액 유효성 보장 (0 이상) - 금액 연산 (덧셈, 곱셈, 나눗셈) @@ -45,9 +59,9 @@ - 무엇인가? : 로또 구매 정보를 담은 객체 - 역할 - - 구매한 로또 티켓 목록 관리 - - 티켓 개수 조회 + - 수동/자동 구매 개수 관리 - 총 구매 금액 계산 + - 수동 구매 수 유효성 검증 ## 당첨 티켓 (WinningTicket) @@ -55,15 +69,7 @@ - 역할 - 당첨 번호 6개 보관 - 보너스볼 보관 - - 구매 티켓의 보너스볼 포함 여부 확인 - -## 로또 게임 (LottoGame) - -- 무엇인가? : 당첨 번호와 구매한 티켓들을 비교하여 결과를 생성하는 객체 -- 역할 - - 당첨 번호 보관 - - 구매한 티켓들의 당첨 결과 계산 - - 게임 결과 생성 + - 구매 티켓과 비교하여 등수(Rank) 반환 ## 당첨 등수 (Rank) @@ -75,12 +81,14 @@ ## 로또 게임 결과 (GameResult) -- 무엇인가? : 전체 로또 구매 결과 (당첨 통계, 수익률)를 나타내는 객체 +- 무엇인가? : 전체 로또 구매 결과 (당첨 통계)를 나타내는 객체 - 역할 - 등수별 당첨 통계 관리 - - 수익률 계산 (당첨 금액 / 구입 금액) - - 손익 판정 (기준: 1.0) - - + - 총 당첨 금액 계산 +## 랜덤 번호 생성기 (Random) +- 무엇인가? : 로또 번호를 랜덤으로 생성하는 유틸리티 +- 역할 + - 1~45 범위에서 중복 없이 6개 번호 생성 + - 정렬된 LottoNumber 리스트 반환 From a5266dbc6eb71a4fd4d0e490a8ab2dccb5443639 Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Wed, 26 Nov 2025 21:22:34 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=9A=80=204=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90(=EC=88=98=EB=8F=99)=20:=20=EC=83=81=EA=B8=88?= =?UTF-8?q?=20=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=20Rank=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=EC=97=90=20=EC=BA=A1=EC=8A=90=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/game/Rank.java | 4 ++-- src/main/java/lotto/domain/result/GameResult.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/lotto/domain/game/Rank.java b/src/main/java/lotto/domain/game/Rank.java index ba091122a1..bc92b553a6 100644 --- a/src/main/java/lotto/domain/game/Rank.java +++ b/src/main/java/lotto/domain/game/Rank.java @@ -32,8 +32,8 @@ public static Rank valueOf(int matched, boolean bonusMatched) { .orElse(NONE); } - public int getPrize() { - return prize; + public int calculatePrize(int count) { + return prize * count; } private static boolean isMatch(Rank rank, int matched, diff --git a/src/main/java/lotto/domain/result/GameResult.java b/src/main/java/lotto/domain/result/GameResult.java index c4d3a32707..866560b42a 100644 --- a/src/main/java/lotto/domain/result/GameResult.java +++ b/src/main/java/lotto/domain/result/GameResult.java @@ -26,7 +26,7 @@ public void updateRank(Rank rank) { public Money getTotalPrize() { int total = ranks.entrySet().stream() - .mapToInt(entry -> entry.getKey().getPrize() * entry.getValue()) + .mapToInt(entry -> entry.getKey().calculatePrize(entry.getValue())) .sum(); return new Money(total); } From f23ea01a89835c23b30d79739c845de2dc6a5d9b Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Wed, 26 Nov 2025 22:25:07 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=9A=80=204=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90(=EC=88=98=EB=8F=99)=20:=20Money=20=EC=99=80?= =?UTF-8?q?=20Purchase=EC=9D=98=20=EC=B1=85=EC=9E=84=EA=B3=BC=20=EC=97=AD?= =?UTF-8?q?=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/LottoGameApplication.java | 6 ++--- .../java/lotto/domain/game/LottoMachine.java | 8 ++---- src/main/java/lotto/domain/lotto/Money.java | 12 ++++++--- .../java/lotto/domain/lotto/Purchase.java | 25 +++++++++++++------ src/main/java/lotto/ui/ResultView.java | 2 +- .../lotto/domain/game/LottoMachineTest.java | 16 ++++++------ .../java/lotto/domain/lotto/MoneyTest.java | 4 +-- .../lotto/domain/result/PurchaseTest.java | 24 +++++++++--------- 8 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/main/java/lotto/LottoGameApplication.java b/src/main/java/lotto/LottoGameApplication.java index a1f636ae39..f493fae1f3 100644 --- a/src/main/java/lotto/LottoGameApplication.java +++ b/src/main/java/lotto/LottoGameApplication.java @@ -19,9 +19,7 @@ public static void main(String[] args) { int manualCount = InputView.inputManualLottoCount(); List manualTickets = InputView.inputManualLottoTickets(manualCount); - int totalCount = machine.calculateTotalCount(new Money(purchaseAmount)); - - Purchase purchase = machine.createPurchase(manualCount, totalCount); + Purchase purchase = machine.createPurchase(new Money(purchaseAmount), manualCount); ResultView.printPurchase(purchase); LottoTickets tickets = machine.generateTickets(manualTickets, purchase.getAutoCount()); @@ -32,6 +30,6 @@ public static void main(String[] args) { WinningTicket winning = new WinningTicket(winningLottoNumbers, bonusNumber); GameResult result = tickets.match(winning); - ResultView.printResult(result, purchase.getPurchaseAmount()); + ResultView.printResult(result, purchase.getSpentAmount()); } } \ No newline at end of file diff --git a/src/main/java/lotto/domain/game/LottoMachine.java b/src/main/java/lotto/domain/game/LottoMachine.java index 3f3e775848..e44844544c 100644 --- a/src/main/java/lotto/domain/game/LottoMachine.java +++ b/src/main/java/lotto/domain/game/LottoMachine.java @@ -21,8 +21,8 @@ public LottoMachine(Money lottoTicketPrice) { this.lottoTicketPrice = lottoTicketPrice; } - public int calculateTotalCount(Money budget) { - return budget.divideForCount(lottoTicketPrice); + public Purchase createPurchase(Money budget, int manualCount) { + return new Purchase(budget, lottoTicketPrice, manualCount); } public LottoTickets generateTickets(List manualTickets, int autoCount) { @@ -34,10 +34,6 @@ public LottoTickets generateTickets(List manualTickets, int autoCount) { return new LottoTickets(allTickets); } - public Purchase createPurchase(int manualCount, int totalCount) { - return new Purchase(manualCount, totalCount, lottoTicketPrice); - } - private List convert(List tickets) { return tickets.stream().map(LottoTicket::new).toList(); } diff --git a/src/main/java/lotto/domain/lotto/Money.java b/src/main/java/lotto/domain/lotto/Money.java index 32b97582fc..f16228f30c 100644 --- a/src/main/java/lotto/domain/lotto/Money.java +++ b/src/main/java/lotto/domain/lotto/Money.java @@ -31,14 +31,18 @@ public Money multiply(int multiplier) { return new Money(this.amount.multiply(BigDecimal.valueOf(multiplier))); } - public BigDecimal divideBy(Money divisor) { + public BigDecimal calculateRatio(Money divisor) { validateDivisor(divisor); return this.amount.divide(divisor.amount, 2, RoundingMode.HALF_UP); } - public int divideForCount(Money divisor) { - validateDivisor(divisor); - return this.amount.divide(divisor.amount, 0, RoundingMode.DOWN).intValue(); + public int countUnits(Money unit) { + validateDivisor(unit); + return this.amount.divide(unit.amount, 0, RoundingMode.DOWN).intValue(); + } + + public boolean isLessThan(Money other) { + return this.amount.compareTo(other.amount) < 0; } private void validateDivisor(Money divisor) { diff --git a/src/main/java/lotto/domain/lotto/Purchase.java b/src/main/java/lotto/domain/lotto/Purchase.java index 7dc7b08513..db7f3e3f88 100644 --- a/src/main/java/lotto/domain/lotto/Purchase.java +++ b/src/main/java/lotto/domain/lotto/Purchase.java @@ -2,27 +2,38 @@ public class Purchase { + private final Money budget; + private final Money ticketPrice; private final int manualCount; private final int autoCount; - private final Money purchaseAmount; - public Purchase(int manualCount, int totalCount, Money pricePerTicket) { - validate(manualCount, totalCount); + public Purchase(Money budget, Money ticketPrice, int manualCount) { + validateBudget(budget, ticketPrice); + int totalCount = budget.countUnits(ticketPrice); + validateManualCount(manualCount, totalCount); + this.budget = budget; + this.ticketPrice = ticketPrice; this.manualCount = manualCount; this.autoCount = totalCount - manualCount; - this.purchaseAmount = pricePerTicket.multiply(totalCount); } - private static void validate(int manualCount, int totalCount){ + private static void validateBudget(Money budget, Money ticketPrice) { + if (budget.isLessThan(ticketPrice)) { + throw new IllegalArgumentException("예산이 티켓 가격보다 적습니다"); + } + } + + private static void validateManualCount(int manualCount, int totalCount) { if (manualCount > totalCount) { throw new IllegalArgumentException("수동 구매 수가 총 구매 가능 수를 초과합니다"); } } - public Money getPurchaseAmount() { - return purchaseAmount; + public Money getSpentAmount() { + return ticketPrice.multiply(manualCount + autoCount); } + public int getAutoCount() { return autoCount; } diff --git a/src/main/java/lotto/ui/ResultView.java b/src/main/java/lotto/ui/ResultView.java index 1fc5cc92a0..633b29dde8 100644 --- a/src/main/java/lotto/ui/ResultView.java +++ b/src/main/java/lotto/ui/ResultView.java @@ -21,7 +21,7 @@ public static void printResult(GameResult gameResult, Money purchaseAmount) { System.out.println(gameResult); Money totalPrize = gameResult.getTotalPrize(); - BigDecimal profitRate = totalPrize.divideBy(purchaseAmount); + BigDecimal profitRate = totalPrize.calculateRatio(purchaseAmount); String explanation = profitRate.compareTo(BigDecimal.ONE) >= 0 ? "이익" : "손해"; System.out.printf("총 수익률은 %s입니다.(기준이 1이기 때문에 결과적으로 %s라는 의미임)%n", diff --git a/src/test/java/lotto/domain/game/LottoMachineTest.java b/src/test/java/lotto/domain/game/LottoMachineTest.java index 5669ecee8c..d9cce11167 100644 --- a/src/test/java/lotto/domain/game/LottoMachineTest.java +++ b/src/test/java/lotto/domain/game/LottoMachineTest.java @@ -10,18 +10,18 @@ public class LottoMachineTest { @ParameterizedTest - @CsvSource({"10000,10", "1000,1", "2320,2"}) - void calculateTotalCountBasedOnBudget(int pay, int expectedCount) { + @CsvSource({"10000, 3, 7", "1000, 0, 1", "10000, 5, 5"}) + void createPurchaseWithBudgetAndManualCount(int budget, int manualCount, int expectedAutoCount) { LottoMachine machine = new LottoMachine(); - int totalCount = machine.calculateTotalCount(new Money(pay)); - assertThat(totalCount).isEqualTo(expectedCount); + Purchase purchase = machine.createPurchase(new Money(budget), manualCount); + assertThat(purchase.getAutoCount()).isEqualTo(expectedAutoCount); } @ParameterizedTest - @CsvSource({"3, 10, 10000", "0, 10, 10000", "5, 10, 10000"}) - void createPurchaseWithManualAndTotalCount(int manualCount, int totalCount, int expectedAmount) { + @CsvSource({"10000, 3, 10000", "5000, 2, 5000", "2320, 0, 2000"}) + void createPurchaseCalculatesSpentAmount(int budget, int manualCount, int expectedSpent) { LottoMachine machine = new LottoMachine(); - Purchase purchase = machine.createPurchase(manualCount, totalCount); - assertThat(purchase.getPurchaseAmount()).isEqualTo(new Money(expectedAmount)); + Purchase purchase = machine.createPurchase(new Money(budget), manualCount); + assertThat(purchase.getSpentAmount()).isEqualTo(new Money(expectedSpent)); } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/lotto/MoneyTest.java b/src/test/java/lotto/domain/lotto/MoneyTest.java index e6c8cef1fa..45ec58542e 100644 --- a/src/test/java/lotto/domain/lotto/MoneyTest.java +++ b/src/test/java/lotto/domain/lotto/MoneyTest.java @@ -13,9 +13,9 @@ void negativeAmountThrowsException() { } @Test - void divideByZeroThrowsException() { + void calculateRatioByZeroThrowsException() { Money money = new Money(1000); - assertThatThrownBy(() -> money.divideBy(new Money(0))) + assertThatThrownBy(() -> money.calculateRatio(new Money(0))) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("몫은 0보다 커야 합니다"); } diff --git a/src/test/java/lotto/domain/result/PurchaseTest.java b/src/test/java/lotto/domain/result/PurchaseTest.java index 2d8a0635d6..332444f969 100644 --- a/src/test/java/lotto/domain/result/PurchaseTest.java +++ b/src/test/java/lotto/domain/result/PurchaseTest.java @@ -11,24 +11,24 @@ class PurchaseTest { @ParameterizedTest @CsvSource({ - "0, 1, 1000, 1000", - "2, 5, 1000, 5000", - "5, 10, 1000, 10000", - "1, 3, 2000, 6000" + "1000, 1000, 0, 1000", + "5000, 1000, 2, 5000", + "10000, 1000, 5, 10000", + "6000, 2000, 1, 6000" }) - void getPurchaseAmount(int manualCount, int totalCount, int pricePerTicket, int expectedAmount) { - Purchase purchase = new Purchase(manualCount, totalCount, new Money(pricePerTicket)); - assertThat(purchase.getPurchaseAmount()).isEqualTo(new Money(expectedAmount)); + void getSpentAmount(int budget, int pricePerTicket, int manualCount, int expectedAmount) { + Purchase purchase = new Purchase(new Money(budget), new Money(pricePerTicket), manualCount); + assertThat(purchase.getSpentAmount()).isEqualTo(new Money(expectedAmount)); } @ParameterizedTest @CsvSource({ - "3, 10, 7", - "0, 10, 10", - "5, 10, 5" + "10000, 1000, 3, 7", + "10000, 1000, 0, 10", + "10000, 1000, 5, 5" }) - void getAutoCount(int manualCount, int totalCount, int expectedAutoCount) { - Purchase purchase = new Purchase(manualCount, totalCount, new Money(1000)); + void getAutoCount(int budget, int pricePerTicket, int manualCount, int expectedAutoCount) { + Purchase purchase = new Purchase(new Money(budget), new Money(pricePerTicket), manualCount); assertThat(purchase.getAutoCount()).isEqualTo(expectedAutoCount); } } \ No newline at end of file From 65d166c3fafaac8b9b269b38a57f220fa84e20b9 Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Thu, 27 Nov 2025 20:36:20 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=9A=80=204=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90(=EC=88=98=EB=8F=99)=20:=20Purchase=EC=9D=98?= =?UTF-8?q?=20=EC=B1=85=EC=9E=84=EA=B3=BC=20=EC=97=AD=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Money 클래스 삭제, Purchase가 금액 관련 로직 직접 담당 - Purchase: int 타입으로 단순화 (ticketPrice, manualCount, autoCount) - 수익률 계산(calculateProfitRate)을 Purchase가 담당 - LottoMachine, GameResult, ResultView에서 Money 의존성 제거 --- src/main/java/lotto/LottoGameApplication.java | 5 +- .../java/lotto/domain/game/LottoMachine.java | 9 ++- src/main/java/lotto/domain/lotto/Money.java | 72 ------------------- .../java/lotto/domain/lotto/Purchase.java | 39 +++++++--- .../java/lotto/domain/result/GameResult.java | 6 +- src/main/java/lotto/ui/ResultView.java | 7 +- .../lotto/domain/game/LottoMachineTest.java | 7 +- .../java/lotto/domain/lotto/MoneyTest.java | 22 ------ .../lotto/domain/result/GameResultTest.java | 5 +- .../lotto/domain/result/PurchaseTest.java | 19 +++-- 10 files changed, 61 insertions(+), 130 deletions(-) delete mode 100644 src/main/java/lotto/domain/lotto/Money.java delete mode 100644 src/test/java/lotto/domain/lotto/MoneyTest.java diff --git a/src/main/java/lotto/LottoGameApplication.java b/src/main/java/lotto/LottoGameApplication.java index f493fae1f3..a3c223c332 100644 --- a/src/main/java/lotto/LottoGameApplication.java +++ b/src/main/java/lotto/LottoGameApplication.java @@ -3,7 +3,6 @@ import java.util.List; import lotto.domain.game.LottoMachine; import lotto.domain.lotto.LottoTickets; -import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; import lotto.domain.lotto.WinningTicket; import lotto.domain.result.GameResult; @@ -19,7 +18,7 @@ public static void main(String[] args) { int manualCount = InputView.inputManualLottoCount(); List manualTickets = InputView.inputManualLottoTickets(manualCount); - Purchase purchase = machine.createPurchase(new Money(purchaseAmount), manualCount); + Purchase purchase = machine.createPurchase(purchaseAmount, manualCount); ResultView.printPurchase(purchase); LottoTickets tickets = machine.generateTickets(manualTickets, purchase.getAutoCount()); @@ -30,6 +29,6 @@ public static void main(String[] args) { WinningTicket winning = new WinningTicket(winningLottoNumbers, bonusNumber); GameResult result = tickets.match(winning); - ResultView.printResult(result, purchase.getSpentAmount()); + ResultView.printResult(result, purchase); } } \ No newline at end of file diff --git a/src/main/java/lotto/domain/game/LottoMachine.java b/src/main/java/lotto/domain/game/LottoMachine.java index e44844544c..c103e1cfa4 100644 --- a/src/main/java/lotto/domain/game/LottoMachine.java +++ b/src/main/java/lotto/domain/game/LottoMachine.java @@ -4,24 +4,23 @@ import java.util.List; import lotto.domain.lotto.LottoTicket; import lotto.domain.lotto.LottoTickets; -import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; public class LottoMachine { - private static final Money DEFAULT_LOTTO_TICKET_PRICE = new Money(1_000); + private static final int DEFAULT_LOTTO_TICKET_PRICE = 1_000; - private final Money lottoTicketPrice; + private final int lottoTicketPrice; public LottoMachine() { this(DEFAULT_LOTTO_TICKET_PRICE); } - public LottoMachine(Money lottoTicketPrice) { + public LottoMachine(int lottoTicketPrice) { this.lottoTicketPrice = lottoTicketPrice; } - public Purchase createPurchase(Money budget, int manualCount) { + public Purchase createPurchase(int budget, int manualCount) { return new Purchase(budget, lottoTicketPrice, manualCount); } diff --git a/src/main/java/lotto/domain/lotto/Money.java b/src/main/java/lotto/domain/lotto/Money.java deleted file mode 100644 index f16228f30c..0000000000 --- a/src/main/java/lotto/domain/lotto/Money.java +++ /dev/null @@ -1,72 +0,0 @@ -package lotto.domain.lotto; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Objects; - -public class Money { - - private final BigDecimal amount; - - public Money(int amount) { - validate(amount); - this.amount = new BigDecimal(amount); - } - - private Money(BigDecimal amount) { - this.amount = amount; - } - - private void validate(int amount) { - if (amount < 0) { - throw new IllegalArgumentException("금액은 0이상이어야 합니다"); - } - } - - public Money add(Money money) { - return new Money(this.amount.add(money.amount)); - } - - public Money multiply(int multiplier) { - return new Money(this.amount.multiply(BigDecimal.valueOf(multiplier))); - } - - public BigDecimal calculateRatio(Money divisor) { - validateDivisor(divisor); - return this.amount.divide(divisor.amount, 2, RoundingMode.HALF_UP); - } - - public int countUnits(Money unit) { - validateDivisor(unit); - return this.amount.divide(unit.amount, 0, RoundingMode.DOWN).intValue(); - } - - public boolean isLessThan(Money other) { - return this.amount.compareTo(other.amount) < 0; - } - - private void validateDivisor(Money divisor) { - if (divisor.amount.compareTo(BigDecimal.ZERO) <= 0) { - throw new IllegalArgumentException("몫은 0보다 커야 합니다"); - } - } - - @Override - public String toString() { - return this.amount.toString(); - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) { - return false; - } - Money money = (Money) o; - return Objects.equals(amount, money.amount); - } - - @Override - public int hashCode() { - return Objects.hashCode(amount); - } -} diff --git a/src/main/java/lotto/domain/lotto/Purchase.java b/src/main/java/lotto/domain/lotto/Purchase.java index db7f3e3f88..8c99560fab 100644 --- a/src/main/java/lotto/domain/lotto/Purchase.java +++ b/src/main/java/lotto/domain/lotto/Purchase.java @@ -1,24 +1,33 @@ package lotto.domain.lotto; +import java.math.BigDecimal; +import java.math.RoundingMode; + public class Purchase { - private final Money budget; - private final Money ticketPrice; + private final int ticketPrice; private final int manualCount; private final int autoCount; - public Purchase(Money budget, Money ticketPrice, int manualCount) { + public Purchase(int budget, int ticketPrice, int manualCount) { + validatePositive(budget, "예산"); + validatePositive(ticketPrice, "티켓 가격"); validateBudget(budget, ticketPrice); - int totalCount = budget.countUnits(ticketPrice); + int totalCount = budget / ticketPrice; validateManualCount(manualCount, totalCount); - this.budget = budget; this.ticketPrice = ticketPrice; this.manualCount = manualCount; this.autoCount = totalCount - manualCount; } - private static void validateBudget(Money budget, Money ticketPrice) { - if (budget.isLessThan(ticketPrice)) { + private static void validatePositive(int amount, String name) { + if (amount < 0) { + throw new IllegalArgumentException(name + "은 0 이상이어야 합니다"); + } + } + + private static void validateBudget(int budget, int ticketPrice) { + if (budget < ticketPrice) { throw new IllegalArgumentException("예산이 티켓 가격보다 적습니다"); } } @@ -29,10 +38,22 @@ private static void validateManualCount(int manualCount, int totalCount) { } } - public Money getSpentAmount() { - return ticketPrice.multiply(manualCount + autoCount); + public BigDecimal calculateProfitRate(int totalPrize) { + int spent = getSpentAmount(); + if (spent == 0) { + throw new IllegalArgumentException("지출 금액이 0입니다"); + } + return BigDecimal.valueOf(totalPrize) + .divide(BigDecimal.valueOf(spent), 2, RoundingMode.HALF_UP); + } + + public int getSpentAmount() { + return ticketPrice * getTotalCount(); } + public int getTotalCount() { + return manualCount + autoCount; + } public int getAutoCount() { return autoCount; diff --git a/src/main/java/lotto/domain/result/GameResult.java b/src/main/java/lotto/domain/result/GameResult.java index 866560b42a..36debf9af7 100644 --- a/src/main/java/lotto/domain/result/GameResult.java +++ b/src/main/java/lotto/domain/result/GameResult.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.stream.Collectors; import lotto.domain.game.Rank; -import lotto.domain.lotto.Money; public class GameResult { @@ -24,11 +23,10 @@ public void updateRank(Rank rank) { ranks.put(rank, ranks.getOrDefault(rank, 0) + 1); } - public Money getTotalPrize() { - int total = ranks.entrySet().stream() + public int getTotalPrize() { + return ranks.entrySet().stream() .mapToInt(entry -> entry.getKey().calculatePrize(entry.getValue())) .sum(); - return new Money(total); } @Override diff --git a/src/main/java/lotto/ui/ResultView.java b/src/main/java/lotto/ui/ResultView.java index 633b29dde8..472c3596a1 100644 --- a/src/main/java/lotto/ui/ResultView.java +++ b/src/main/java/lotto/ui/ResultView.java @@ -2,7 +2,6 @@ import java.math.BigDecimal; import lotto.domain.lotto.LottoTickets; -import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; import lotto.domain.result.GameResult; @@ -16,12 +15,12 @@ public static void printTickets(LottoTickets tickets) { System.out.println(tickets); } - public static void printResult(GameResult gameResult, Money purchaseAmount) { + public static void printResult(GameResult gameResult, Purchase purchase) { System.out.println("\n당첨 통계\n---------"); System.out.println(gameResult); - Money totalPrize = gameResult.getTotalPrize(); - BigDecimal profitRate = totalPrize.calculateRatio(purchaseAmount); + int totalPrize = gameResult.getTotalPrize(); + BigDecimal profitRate = purchase.calculateProfitRate(totalPrize); String explanation = profitRate.compareTo(BigDecimal.ONE) >= 0 ? "이익" : "손해"; System.out.printf("총 수익률은 %s입니다.(기준이 1이기 때문에 결과적으로 %s라는 의미임)%n", diff --git a/src/test/java/lotto/domain/game/LottoMachineTest.java b/src/test/java/lotto/domain/game/LottoMachineTest.java index d9cce11167..f39e83026c 100644 --- a/src/test/java/lotto/domain/game/LottoMachineTest.java +++ b/src/test/java/lotto/domain/game/LottoMachineTest.java @@ -2,7 +2,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import lotto.domain.lotto.Money; import lotto.domain.lotto.Purchase; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -13,7 +12,7 @@ public class LottoMachineTest { @CsvSource({"10000, 3, 7", "1000, 0, 1", "10000, 5, 5"}) void createPurchaseWithBudgetAndManualCount(int budget, int manualCount, int expectedAutoCount) { LottoMachine machine = new LottoMachine(); - Purchase purchase = machine.createPurchase(new Money(budget), manualCount); + Purchase purchase = machine.createPurchase(budget, manualCount); assertThat(purchase.getAutoCount()).isEqualTo(expectedAutoCount); } @@ -21,7 +20,7 @@ void createPurchaseWithBudgetAndManualCount(int budget, int manualCount, int exp @CsvSource({"10000, 3, 10000", "5000, 2, 5000", "2320, 0, 2000"}) void createPurchaseCalculatesSpentAmount(int budget, int manualCount, int expectedSpent) { LottoMachine machine = new LottoMachine(); - Purchase purchase = machine.createPurchase(new Money(budget), manualCount); - assertThat(purchase.getSpentAmount()).isEqualTo(new Money(expectedSpent)); + Purchase purchase = machine.createPurchase(budget, manualCount); + assertThat(purchase.getSpentAmount()).isEqualTo(expectedSpent); } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/lotto/MoneyTest.java b/src/test/java/lotto/domain/lotto/MoneyTest.java deleted file mode 100644 index 45ec58542e..0000000000 --- a/src/test/java/lotto/domain/lotto/MoneyTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package lotto.domain.lotto; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import org.junit.jupiter.api.Test; - -public class MoneyTest { - @Test - void negativeAmountThrowsException() { - assertThatThrownBy(() -> new Money(-1000)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("금액은 0이상이어야 합니다"); - } - - @Test - void calculateRatioByZeroThrowsException() { - Money money = new Money(1000); - assertThatThrownBy(() -> money.calculateRatio(new Money(0))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("몫은 0보다 커야 합니다"); - } -} diff --git a/src/test/java/lotto/domain/result/GameResultTest.java b/src/test/java/lotto/domain/result/GameResultTest.java index e40acd1a35..1bd95a4399 100644 --- a/src/test/java/lotto/domain/result/GameResultTest.java +++ b/src/test/java/lotto/domain/result/GameResultTest.java @@ -5,7 +5,6 @@ import java.util.HashMap; import java.util.Map; import lotto.domain.game.Rank; -import lotto.domain.lotto.Money; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -18,7 +17,7 @@ void getTotalPrize_first() { details.put(Rank.FIRST, 1); GameResult result = new GameResult(details); - assertThat(result.getTotalPrize()).isEqualTo(new Money(2_000_000_000)); + assertThat(result.getTotalPrize()).isEqualTo(2_000_000_000); } @ParameterizedTest @@ -28,6 +27,6 @@ void getTotalPrize_fourth(int count, int expectedPrize) { details.put(Rank.FOURTH, count); GameResult result = new GameResult(details); - assertThat(result.getTotalPrize()).isEqualTo(new Money(expectedPrize)); + assertThat(result.getTotalPrize()).isEqualTo(expectedPrize); } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/result/PurchaseTest.java b/src/test/java/lotto/domain/result/PurchaseTest.java index 332444f969..f57f021647 100644 --- a/src/test/java/lotto/domain/result/PurchaseTest.java +++ b/src/test/java/lotto/domain/result/PurchaseTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import lotto.domain.lotto.Money; +import java.math.BigDecimal; import lotto.domain.lotto.Purchase; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -17,8 +17,8 @@ class PurchaseTest { "6000, 2000, 1, 6000" }) void getSpentAmount(int budget, int pricePerTicket, int manualCount, int expectedAmount) { - Purchase purchase = new Purchase(new Money(budget), new Money(pricePerTicket), manualCount); - assertThat(purchase.getSpentAmount()).isEqualTo(new Money(expectedAmount)); + Purchase purchase = new Purchase(budget, pricePerTicket, manualCount); + assertThat(purchase.getSpentAmount()).isEqualTo(expectedAmount); } @ParameterizedTest @@ -28,7 +28,18 @@ void getSpentAmount(int budget, int pricePerTicket, int manualCount, int expecte "10000, 1000, 5, 5" }) void getAutoCount(int budget, int pricePerTicket, int manualCount, int expectedAutoCount) { - Purchase purchase = new Purchase(new Money(budget), new Money(pricePerTicket), manualCount); + Purchase purchase = new Purchase(budget, pricePerTicket, manualCount); assertThat(purchase.getAutoCount()).isEqualTo(expectedAutoCount); } + + @ParameterizedTest + @CsvSource({ + "10000, 1000, 0, 50000, 5.00", + "10000, 1000, 5, 5000, 0.50", + "1000, 1000, 0, 2000000000, 2000000.00" + }) + void calculateProfitRate(int budget, int pricePerTicket, int manualCount, int totalPrize, String expectedRate) { + Purchase purchase = new Purchase(budget, pricePerTicket, manualCount); + assertThat(purchase.calculateProfitRate(totalPrize)).isEqualTo(new BigDecimal(expectedRate)); + } } \ No newline at end of file From ec9fad59092aa7a4113dc5e5fbbf4cd4cc95b671 Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Thu, 27 Nov 2025 21:17:45 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=95=EC=82=AC=ED=95=AD=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/README.md | 59 +++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/main/java/lotto/README.md b/src/main/java/lotto/README.md index b49c68679b..6fb270cc62 100644 --- a/src/main/java/lotto/README.md +++ b/src/main/java/lotto/README.md @@ -47,21 +47,37 @@ - 캐싱을 통한 객체 재사용 - 숫자 객체 비교 -## 금액 (Money) - -- 무엇인가? : 금액을 표현하는 값 객체 -- 역할 - - 금액 유효성 보장 (0 이상) - - 금액 연산 (덧셈, 곱셈, 나눗셈) - - BigDecimal을 사용한 정확한 금액 계산 - ## 구매 (Purchase) -- 무엇인가? : 로또 구매 정보를 담은 객체 +- 무엇인가? : 로또 구매 정보와 금액 계산을 담당하는 객체 - 역할 - 수동/자동 구매 개수 관리 - 총 구매 금액 계산 - 수동 구매 수 유효성 검증 + - 수익률 계산 + +### 설계 결정: Money를 Purchase에 통합한 이유 + +기존에는 `Money`(금액 VO)와 `Purchase`(구매 정보)가 분리되어 있었다. + +``` +Money: "나는 금액이야. 더하고, 빼고, 비교할 수 있어" +Purchase: "나는 Money를 갖고 있어. Money에게 물어보고 판단해" +``` + +**문제점:** +- Money가 수동적인 값 객체로만 존재 +- Purchase가 Money에게 물어보고 판단하는 구조 +- "수익률"은 "금액의 비율"이 아니라 "구매의 결과" + +**개선:** +- Purchase가 금액 관련 로직을 직접 담당 (능동적 객체) +- "로또 구매"라는 도메인 맥락에서 수익률 계산이 자연스러움 +- int 타입으로 단순화 (BigDecimal wrapper 불필요) + +``` +Purchase: "나는 로또 구매야. 얼마 썼고, 몇 장 샀는지 알아. 수익률도 계산해줄게" +``` ## 당첨 티켓 (WinningTicket) @@ -78,6 +94,31 @@ - 일치 개수와 보너스볼 여부에 따른 등수 판정 - 등수별 당첨금 관리 - 5개 일치 시 보너스볼로 2등/3등 구분 + - 당첨 개수에 따른 총 상금 계산 + +### 설계 결정: 상금 계산 로직을 Rank 내부에 캡슐화한 이유 + +기존에는 GameResult가 Rank에게 prize를 물어보고 직접 계산했다. + +```java +// 기존: GameResult에서 계산 (Ask) +entry.getKey().getPrize() * entry.getValue() +``` + +**문제점:** +- Rank가 prize 값만 제공하는 수동적 객체 +- "상금 × 개수" 계산 로직이 GameResult에 노출 + +**개선:** +- Rank가 직접 상금을 계산하도록 변경 (Tell, Don't Ask) + +```java +// 개선: Rank에게 계산 요청 (Tell) +entry.getKey().calculatePrize(entry.getValue()) +``` + +- Rank가 자신의 prize를 알고 있으므로, 계산도 Rank가 담당하는 것이 자연스러움 +- GameResult는 "얼마인지 계산해줘"라고 요청만 함 ## 로또 게임 결과 (GameResult) From f73229a76b3890c214508d4cdbd673b83e318df6 Mon Sep 17 00:00:00 2001 From: eunjeong Park Date: Wed, 10 Dec 2025 22:30:11 +0900 Subject: [PATCH 8/8] =?UTF-8?q?GameResult=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/domain/lotto/LottoNumber.java | 6 +++--- .../java/lotto/domain/lotto/LottoTickets.java | 10 +++++----- .../java/lotto/domain/result/GameResult.java | 17 +++++++++-------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/lotto/domain/lotto/LottoNumber.java b/src/main/java/lotto/domain/lotto/LottoNumber.java index a839eac0bb..1d1ccedbf2 100644 --- a/src/main/java/lotto/domain/lotto/LottoNumber.java +++ b/src/main/java/lotto/domain/lotto/LottoNumber.java @@ -5,11 +5,11 @@ import java.util.Objects; public class LottoNumber { - + private static final int MIN = 1, MAX = 45; private static final Map CACHE = new HashMap<>(); static { - for (int i = 1; i <= 45; i++) { + for (int i = MIN; i <= MAX; i++) { CACHE.put(i, new LottoNumber(i)); } } @@ -26,7 +26,7 @@ public static LottoNumber of(int value) { } private static void validate(int value) { - if (value < 1 || value > 45) { + if (value < MIN || value > MAX) { throw new IllegalArgumentException("로또 넘버는 1이상 45이하의 수입니다"); } } diff --git a/src/main/java/lotto/domain/lotto/LottoTickets.java b/src/main/java/lotto/domain/lotto/LottoTickets.java index 4a7afc17b8..812372f9fe 100644 --- a/src/main/java/lotto/domain/lotto/LottoTickets.java +++ b/src/main/java/lotto/domain/lotto/LottoTickets.java @@ -1,6 +1,7 @@ package lotto.domain.lotto; import java.util.List; +import lotto.domain.game.Rank; import lotto.domain.result.GameResult; public class LottoTickets { @@ -11,11 +12,10 @@ public LottoTickets(List tickets){ } public GameResult match(WinningTicket winning) { - GameResult gameResult = new GameResult(); - for(LottoTicket ticket : tickets){ - gameResult.updateRank(winning.match(ticket)); - } - return gameResult; + List rankList = tickets.stream() + .map(winning::match) + .toList(); + return new GameResult(rankList); } @Override diff --git a/src/main/java/lotto/domain/result/GameResult.java b/src/main/java/lotto/domain/result/GameResult.java index 36debf9af7..ca324eb253 100644 --- a/src/main/java/lotto/domain/result/GameResult.java +++ b/src/main/java/lotto/domain/result/GameResult.java @@ -2,8 +2,9 @@ import java.util.Arrays; import java.util.Comparator; -import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; import lotto.domain.game.Rank; @@ -11,16 +12,16 @@ public class GameResult { private final Map ranks; - public GameResult(){ - this(new HashMap<>()); + public GameResult(List rankList) { + this.ranks = rankList.stream() + .collect(Collectors.groupingBy( + Function.identity(), + Collectors.summingInt(e -> 1) + )); } public GameResult(Map ranks) { - this.ranks = ranks; - } - - public void updateRank(Rank rank) { - ranks.put(rank, ranks.getOrDefault(rank, 0) + 1); + this.ranks = Map.copyOf(ranks); } public int getTotalPrize() {