diff --git a/settings.gradle b/settings.gradle index 1daa39f3..555efb54 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,10 @@ -rootProject.name = 'java-lotto' +pluginManagement { + plugins { + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} +rootProject.name = 'java-lotto' diff --git a/src/README.md b/src/README.md index 983bf126..abdbc253 100644 --- a/src/README.md +++ b/src/README.md @@ -1,51 +1,5 @@ # 로또 미션 -## 클래스 구성 - -### controller - -- **RaceLotto** - 로또 게임 전체 실행 흐름 관리 (금액 입력 → 로또 번호 생성 → 당첨 번호 입력 → 통계 출력) -- **RaceLottoMethod** - 구입 금액 검증·로또 번호 생성·당첨 번호 입력·통계 산출 등 비즈니스 로직 수행 - -### inputView (View) - -- **InputView** - 구입 금액과 지난 주 당첨 번호 입력 받기 -- **OutputView** - 금액 안내, 구매 수량, 로또 번호, 당첨 통계 출력 -- **Price** - 구입 금액을 값 객체로 포장 (0원 이상 검증, 로또 구매 개수 계산) - -### model (Domain) - -- **LottoNumber** - 1~45 사이 번호 하나를 원시값 포장 (범위 검증) -- **LottoNumbers** - LottoNumber 6개를 모은 일급 컬렉션 (6개 검증, 정렬, 불변 리스트) -- **LottoNumbersRepository** - 여러 장의 LottoNumbers를 저장·조회하는 저장소 (읽기 전용 리스트 반환) - -### util (Utility / Strategy) - -- **LottoNumberGenerator (interface)** - 로또 번호 생성 전략 인터페이스 -- **RandomLottoNumberGenerator (implementation)** - 1~45 번호를 섞어 6개를 랜덤으로 생성하는 기본 구현체 - -### Main - -- **Main** - 프로그램 엔트리 포인트 - -### test (JUnit5 단위 테스트) - -- **PriceTest** — 값 객체 생성·예외·로또 개수 계산 테스트 -- **LottoNumberTest** — 원시값 포장(범위 검증) 테스트 -- **LottoNumbersTest** — 일급 컬렉션 생성·예외·불변 리스트·정렬 기능 테스트 -- **LottoNumbersRepositoryTest** — 저장소 추가·조회·불변 리스트 테스트 -- **RandomLottoNumberGeneratorTest** — 랜덤 생성기가 6개 번호를 반환하는지 테스트 ## 기능 요구사항 @@ -56,3 +10,11 @@ - 모든 원시 값과 문자열을 포장한다. - 일급 컬렉션을 쓴다. +## 추가 기능 요구사항 + +- 2등을 위한 보너스볼을 추첨한다. +- 당첨 통계에 2등을 추가한다. +- 2등 당첨 조건은 당첨 번호 5개 + 보너스 볼이다 +- 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다. +- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다. + diff --git a/src/main/java/Main.java b/src/main/java/Main.java index c1fccc42..cbccb4a7 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,24 +1,31 @@ -import controller.AutoLottoController; -import inputView.Price; -import model.LottoNumbers; -import model.LottoNumbersRepository; + +import controller.LottoController; +import model.PurchaseAmount; +import model.LottoNumber; +import model.LottoTicket; +import model.LottoTicketBundle; public class Main { public static void main(String[] args) { - AutoLottoController controller = new AutoLottoController(); + LottoController controller = new LottoController(); // 1. 구입 금액 입력 - Price money = controller.showPrice(); + PurchaseAmount purchaseAmount = controller.askPurchaseAmount(); - // 2. 로또 번호 생성 - LottoNumbersRepository allLotteries = controller.showLottoNumbers(money.howManyLottos()); + // 2. 수동 및 자동 로또 번호 생성 + LottoTicketBundle allTickets = controller.buyTickets(purchaseAmount.calculateLottoCount()); // 3. 당첨 번호 입력 - LottoNumbers lastLotto = controller.readLastLotto(); + LottoTicket winningNumbers = controller.askWinningNumbers(); + + // 4. 보너스 볼 입력 + LottoNumber bonusBall = controller.askBonusBall(); - // 4. 통계 출력 - controller.showLotteryStatistics(allLotteries.readLottoNumbersRepository() - , lastLotto.getNumbers() - , money.getValue()); + // 5. 통계 출력 + controller.showStatistics(allTickets.readLottoNumbersRepository(), + winningNumbers.getNumbers(), + purchaseAmount.getValue(), + bonusBall + ); } } diff --git a/src/main/java/controller/LottoController.java b/src/main/java/controller/LottoController.java new file mode 100644 index 00000000..72f0bdeb --- /dev/null +++ b/src/main/java/controller/LottoController.java @@ -0,0 +1,100 @@ +package controller; + +import view.InputView; +import view.OutputView; +import model.PurchaseAmount; +import model.LottoNumber; +import model.LottoTicket; +import model.LottoService; +import model.LottoTicketBundle; +import model.MatchResult; + + +import java.util.List; +import java.util.Map; + +public class LottoController { + private final LottoService lottoService = new LottoService(); + private final OutputView outView = new OutputView(); + private final InputView inputView = new InputView(); + + private PurchaseAmount readPrice() { + outView.printInputPrice(); + while (true) { + PurchaseAmount purchaseAmount = readPriceException(); + if (purchaseAmount != null) return purchaseAmount; + } + } + + private PurchaseAmount readPriceException() { + try { + return new PurchaseAmount(Integer.parseInt(inputView.inputPrice())); + } catch (NumberFormatException input) { + outView.printInvalidNumber(); + } catch (IllegalArgumentException input) { + outView.printInvalidPrice(); + } + return null; + } + + public PurchaseAmount askPurchaseAmount() { + PurchaseAmount purchaseAmount = readPrice(); + outView.printPriceValue(purchaseAmount.getValue()); + outView.printBlankLine(); + return purchaseAmount; + } + + public LottoTicketBundle buyTickets(int ticketCount) { + int manualCount = requestManualTicketCount(); + int autoCount = calculateAutoCount(ticketCount, manualCount); + + LottoTicketBundle tickets = generateTickets(manualCount, autoCount); + displayTickets(manualCount, autoCount, tickets); + + return tickets; + } + + private int requestManualTicketCount() { + outView.printManualTicketCount(); + return Integer.parseInt(inputView.inputManualCount()); + } + + private int calculateAutoCount(int totalTickets, int manualCount) { + return totalTickets - manualCount; + } + + private LottoTicketBundle generateTickets(int manualCount, int autoCount) { + outView.printManualLottoNumbersPrompt(); + List manualInputs = inputView.inputManualLottos(manualCount); + + LottoTicketBundle manualTickets = lottoService.createManualLottos(manualInputs); + LottoTicketBundle autoTickets = lottoService.createLottos(autoCount); + + return lottoService.mergeAutoAndManualLottos(manualTickets, autoTickets); + } + + private void displayTickets(int manualCount, int autoCount, LottoTicketBundle tickets) { + outView.printBuyCount(manualCount, autoCount); + outView.printLottos(tickets.readLottoNumbersRepository()); + } + + public LottoTicket askWinningNumbers() { + outView.printInputWinningNumbers(); + LottoTicket winningLotto = lottoService.createInputLotto(inputView.inputWinningNumbers()); + outView.printBlankLine(); + return winningLotto; + } + + public LottoNumber askBonusBall() { + outView.printBonusBall(); + LottoNumber bonusNumber = new LottoNumber(Integer.parseInt(inputView.inputBonusBall())); + outView.printBlankLine(); + return bonusNumber; + } + + public void showStatistics(List allTickets, List winningNumbers, int purchaseAmount, LottoNumber bonusBall) { + Map matchCounts = lottoService.countMatchResults(allTickets, winningNumbers, bonusBall); + String profitRate = lottoService.calculateProfitRate(matchCounts, purchaseAmount); + outView.printLotteryStatistics(matchCounts, profitRate); + } +} diff --git a/src/main/java/model/FixedLottoNumberGenerator.java b/src/main/java/model/FixedLottoNumberGenerator.java index 31182625..6c9c79d2 100644 --- a/src/main/java/model/FixedLottoNumberGenerator.java +++ b/src/main/java/model/FixedLottoNumberGenerator.java @@ -15,7 +15,7 @@ public FixedLottoNumberGenerator(List numbers) { } @Override - public LottoNumbers generate() { - return new LottoNumbers(fixedNumbers); + public LottoTicket generate() { + return new LottoTicket(fixedNumbers); } } diff --git a/src/main/java/model/LottoNumberGenerator.java b/src/main/java/model/LottoNumberGenerator.java index c387ede4..e16ac363 100644 --- a/src/main/java/model/LottoNumberGenerator.java +++ b/src/main/java/model/LottoNumberGenerator.java @@ -1,5 +1,5 @@ package model; public interface LottoNumberGenerator { - LottoNumbers generate(); + LottoTicket generate(); } diff --git a/src/main/java/model/LottoService.java b/src/main/java/model/LottoService.java new file mode 100644 index 00000000..8915cee0 --- /dev/null +++ b/src/main/java/model/LottoService.java @@ -0,0 +1,110 @@ +package model; + + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class LottoService { + private final LottoNumberGenerator generator; + + public LottoService() { + this(new RandomLottoNumberGenerator()); + } + + public LottoService(LottoNumberGenerator generator) { + this.generator = generator; + } + + public LottoTicket createOneLotto() { + return generator.generate(); + } + + public LottoTicketBundle createLottos(int count) { + LottoTicketBundle repository = new LottoTicketBundle(); + for (int i = 0; i < count; i++) { + repository.addLottoNumbers(createOneLotto().sortNumbers()); + } + return repository; + } + + public LottoTicket createInputLotto(String inputNumber) { + List numbers = parseInputToNumbers(inputNumber); + return new LottoTicket(numbers); + } + + private List parseInputToNumbers(String inputNumber) { + String[] rawNumbers = inputNumber.split(","); + List numbers = new ArrayList<>(); + for (String raw : rawNumbers) { + numbers.add(new LottoNumber(Integer.parseInt(raw.trim()))); + } + return numbers; + } + + public LottoTicketBundle createManualLottos(List inputs) { + LottoTicketBundle repository = new LottoTicketBundle(); + for (String input : inputs) { + repository.addLottoNumbers(createInputLotto(input)); + } + return repository; + } + + public LottoTicketBundle mergeAutoAndManualLottos(LottoTicketBundle manual, LottoTicketBundle auto) { + LottoTicketBundle repository = new LottoTicketBundle(); + for (LottoTicket lotto : manual.readLottoNumbersRepository()) { + repository.addLottoNumbers(lotto); + } + + for (LottoTicket lotto : auto.readLottoNumbersRepository()) { + repository.addLottoNumbers(lotto); + } + return repository; + } + + public Map countMatchResults( + List allLotteries, + List winningLotto, + LottoNumber bonusBall + ) { + Map matchCounts = initializeMatchCounts(); + for (LottoTicket lotto : allLotteries) { + int count = matchLottoNumber(lotto.getNumbers(), winningLotto); + boolean bonusMatch = matchBonus(lotto.getNumbers(), bonusBall, count); + MatchResult result = MatchResult.fromCount(count, bonusMatch); + matchCounts.put(result, matchCounts.get(result) + 1); + } + return matchCounts; + } + + private Map initializeMatchCounts() { + Map counts = new EnumMap<>(MatchResult.class); + for (MatchResult result : MatchResult.values()) { + counts.put(result, 0); + } + return counts; + } + + private int matchLottoNumber(List lotto, List winningLotto) { + return (int) lotto.stream() + .filter(winningLotto::contains) + .count(); + } + + private boolean matchBonus(List lotto, LottoNumber bonusBall, int count) { + if (count == 5) { + return lotto.contains(bonusBall); + } + return false; + } + + public String calculateProfitRate(Map matchCounts, int money) { + double profitRate = 0; + for (MatchResult result : matchCounts.keySet()) { + profitRate += matchCounts.get(result) * result.getReward(); + } + profitRate = profitRate / (double) money; + return String.format("%.2f", profitRate); + } +} diff --git a/src/main/java/model/LottoTicket.java b/src/main/java/model/LottoTicket.java new file mode 100644 index 00000000..0c740255 --- /dev/null +++ b/src/main/java/model/LottoTicket.java @@ -0,0 +1,29 @@ +package model; + +import java.util.*; + +public class LottoTicket { + private final List numbers; + + public LottoTicket(List numbers) { + validateSize(numbers); + this.numbers = List.copyOf(numbers); + } + + private void validateSize(List numbers) { + if (numbers.size() != 6) { + throw new IllegalArgumentException("로또 번호가 6개가 아닙니다"); + } + } + + public LottoTicket sortNumbers() { + List sortNumber = new ArrayList<>(numbers); + Collections.sort(sortNumber, Comparator.comparingInt(LottoNumber::getNumber)); + return new LottoTicket(sortNumber); + } + + public List getNumbers() { + return numbers; + } + +} diff --git a/src/main/java/model/LottoTicketBundle.java b/src/main/java/model/LottoTicketBundle.java new file mode 100644 index 00000000..c7dba79b --- /dev/null +++ b/src/main/java/model/LottoTicketBundle.java @@ -0,0 +1,19 @@ +package model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class LottoTicketBundle { + private final List repository = new ArrayList<>(); + + public void addLottoNumbers(LottoTicket lottoTicket) { + repository.add(lottoTicket); + } + + public List readLottoNumbersRepository() { + return Collections.unmodifiableList(repository); + } + +} diff --git a/src/main/java/model/MatchResult.java b/src/main/java/model/MatchResult.java index 14ba13fd..570cee1b 100644 --- a/src/main/java/model/MatchResult.java +++ b/src/main/java/model/MatchResult.java @@ -1,40 +1,36 @@ package model; + +import java.util.Arrays; + public enum MatchResult { - ZERO(0, "0개 일치", 0), - ONE(1, "1개 일치", 0), - TWO(2, "2개 일치", 0), - THREE(3, "3개 일치", 5000), - FOUR(4, "4개 일치", 50000), - FIVE(5, "5개 일치", 150000), - SIX(6, "6개 일치", 2000000000); + ZERO(0, 0), + THREE(3, 5000), + FOUR(4, 50000), + FIVE(5, 1500000), + FIVE_BONUS(5, 30000000), + SIX(6, 2000000000); private final int count; - private final String description; private final int reward; - MatchResult(int count, String description, int reward) { + MatchResult(int count, int reward) { this.count = count; - this.description = description; this.reward = reward; } - - public int getCount() { - return count; - } - - public String getDescription() { - return description; - } - + public int getReward() { return reward; } - public static MatchResult fromCount(int count) { - for (MatchResult result : values()) { - if (result.count == count) return result; + public static MatchResult fromCount(int count, boolean bonusMatch) { + if (count == 5 && bonusMatch) { + return FIVE_BONUS; } - return ZERO; + + return Arrays.stream(values()) + .filter(result -> result.count == count && result != FIVE_BONUS) + .findFirst() + .orElse(ZERO); } } diff --git a/src/main/java/model/PurchaseAmount.java b/src/main/java/model/PurchaseAmount.java new file mode 100644 index 00000000..33cd24ca --- /dev/null +++ b/src/main/java/model/PurchaseAmount.java @@ -0,0 +1,39 @@ +package model; + +import java.util.Objects; + +public class PurchaseAmount { + private final int value; + + public PurchaseAmount(int value) { + validateNegative(value); + this.value = value; + } + + private static void validateNegative(int value) { + if (value < 0) { + throw new IllegalArgumentException("구입 금액은 0원 이상입니다."); + } + } + + public int getValue() { + return value; + } + + public int calculateLottoCount() { + return value / 1000; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof PurchaseAmount)) return false; + PurchaseAmount money = (PurchaseAmount) o; + return value == money.value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} diff --git a/src/main/java/model/RandomLottoNumberGenerator.java b/src/main/java/model/RandomLottoNumberGenerator.java index 2e6d23fa..4e11ece6 100644 --- a/src/main/java/model/RandomLottoNumberGenerator.java +++ b/src/main/java/model/RandomLottoNumberGenerator.java @@ -7,10 +7,10 @@ public class RandomLottoNumberGenerator implements LottoNumberGenerator { @Override - public LottoNumbers generate() { + public LottoTicket generate() { List numbers = createLottoNumbers(); Collections.shuffle(numbers); - return new LottoNumbers(numbers.subList(0, 6)); + return new LottoTicket(numbers.subList(0, 6)); } public List createLottoNumbers() { diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000..5919c61c --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,33 @@ +package view; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class InputView { + private static final Scanner scanner = new Scanner(System.in); + + public String inputPrice() { + return scanner.nextLine(); + } + + public String inputManualCount() { + return scanner.nextLine(); + } + + public List inputManualLottos(int count) { + List inputs = new ArrayList<>(); + for (int i = 0; i < count; i++) { + inputs.add(scanner.nextLine()); + } + return inputs; + } + + public String inputBonusBall() { + return scanner.nextLine(); + } + + public String inputWinningNumbers() { + return scanner.nextLine(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000..ed7174e1 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,66 @@ +package view; + +import model.LottoTicket; +import model.MatchResult; + +import java.util.List; +import java.util.Map; + +public class OutputView { + public void printInputPrice() { + System.out.print("구입 금액을 입력해 주세요: "); + } + + public void printInvalidNumber() { + System.out.println("숫자만 입력해 주세요"); + } + + public void printInvalidPrice() { + System.out.println("0원 이상을 입력해 주세요"); + } + + public void printPriceValue(int price) { + System.out.println(price); + } + + public void printBuyCount(int manualCount, int autoCount) { + System.out.println("수동으로 " + manualCount + "장, 자동으로 " + autoCount + "개를 구매했습니다."); + } + + public void printInputWinningNumbers() { + System.out.println("지난 주 당첨 번호를 입력해 주세요."); + } + + public void printLottos(List Lottos) { + for (LottoTicket lotto : Lottos) { + System.out.println(lotto.getNumbers()); + } + } + + public void printManualTicketCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + } + + public void printManualLottoNumbersPrompt() { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + } + + public void printBonusBall() { + System.out.println("보너스 볼을 입력해 주세요."); + } + + public void printBlankLine(){ + System.out.println(); + } + + public void printLotteryStatistics(Map matchCounts, String profitRate) { + System.out.println("당첨 통계"); + System.out.println("---------"); + System.out.println("3개 일치 (5000원)- " + matchCounts.get(MatchResult.THREE) + "개"); + System.out.println("4개 일치 (50000원)- " + matchCounts.get(MatchResult.FOUR) + "개"); + System.out.println("5개 일치 (150000원)- " + matchCounts.get(MatchResult.FIVE) + "개"); + System.out.println("5개 일치, 보너스 볼 일치(30000000원)- " + matchCounts.get(MatchResult.FIVE_BONUS) + "개"); + System.out.println("6개 일치 (2000000000원)- " + matchCounts.get(MatchResult.SIX) + "개"); + System.out.println("총 수익률은 " + profitRate + "입니다."); + } +} diff --git a/src/test/java/model/FixedLottoNumberGeneratorTest.java b/src/test/java/model/FixedLottoNumberGeneratorTest.java index 60b7121b..f1bc89dd 100644 --- a/src/test/java/model/FixedLottoNumberGeneratorTest.java +++ b/src/test/java/model/FixedLottoNumberGeneratorTest.java @@ -15,11 +15,29 @@ class FixedLottoNumberGeneratorTest { FixedLottoNumberGenerator generator = new FixedLottoNumberGenerator(input); // When - LottoNumbers lotto = generator.generate(); + LottoTicket lotto = generator.generate(); // Then - // LottoNumbers.getNumbers()는 LottoNumber 객체들이라서 - // 그대로 toString()해서 비교하면 간단해짐 assertEquals(input.toString(), lotto.getNumbers().toString()); } + + @Test + void 숫자가_6개가_아니면_예외가_발생한다() { + // Given + List input = List.of(1, 2, 3, 4, 5); + + // When & Then + assertThrows(IllegalArgumentException.class, + () -> new FixedLottoNumberGenerator(input)); + } + + @Test + void 숫자가_1에서_45범위를_벗어나면_예외가_발생한다() { + // Given + List input = List.of(1, 2, 3, 4, 5, 46); + + // When & Then + assertThrows(IllegalArgumentException.class, + () -> new FixedLottoNumberGenerator(input)); + } } diff --git a/src/test/java/model/LottoFixture.java b/src/test/java/model/LottoFixture.java new file mode 100644 index 00000000..5efb9b24 --- /dev/null +++ b/src/test/java/model/LottoFixture.java @@ -0,0 +1,32 @@ +package model; + +import java.util.List; + +public class LottoFixture { + + // 기본 1~6 로또 + public static LottoTicket 기본로또() { + return new LottoTicket(List.of( + new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), + new LottoNumber(4), new LottoNumber(5), new LottoNumber(6) + )); + } + + // 보너스볼(7) 포함된 로또 + public static LottoTicket 보너스7포함로또() { + return new LottoTicket(List.of( + new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), + new LottoNumber(4), new LottoNumber(5), new LottoNumber(7) + )); + } + + // 4개 일치 로또 (1~4 일치) + public static LottoTicket 네개일치로또() { + return new LottoTicket(List.of( + new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), + new LottoNumber(4), new LottoNumber(7), new LottoNumber(8) + )); + } +} + + diff --git a/src/test/java/model/LottoServiceTest.java b/src/test/java/model/LottoServiceTest.java new file mode 100644 index 00000000..540808e7 --- /dev/null +++ b/src/test/java/model/LottoServiceTest.java @@ -0,0 +1,106 @@ +package model; + +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static model.LottoFixture.기본로또; +import static model.LottoFixture.네개일치로또; +import static model.LottoFixture.보너스7포함로또; +import static org.junit.jupiter.api.Assertions.*; + +class LottoServiceTest { + private final LottoService business = new LottoService(); + + @Test + void 고정된로또가_생성된다() { + // Given + LottoService business = + new LottoService(new FixedLottoNumberGenerator(List.of(1, 2, 3, 4, 5, 6))); + + // When + LottoTicket lotto = business.createOneLotto(); + + // Then + assertEquals(기본로또(), lotto); + } + + @Test + void 요청한_개수만큼_로또가_생성된다() { + // Given + int count = 3; + + // When + LottoTicketBundle re = business.createLottos(count); + + // Then + assertEquals(count, re.readLottoNumbersRepository().size()); + assertTrue(re.readLottoNumbersRepository() + .stream().allMatch(n -> n.getNumbers().size() == 6)); + } + + @Test + void 지난주_로또가_생성된다() { + // Given + String input = "1, 2,3, 4 ,5,6"; + + // When + LottoTicket last = business.createInputLotto(input); + + // Then + assertEquals(6, last.getNumbers().size()); + assertEquals(기본로또(), last); + } + + @Test + void countMatchResults_4개일치면_FOUR가_1로_집계된다() { + // Given + LottoTicket mine = 기본로또(); + LottoTicket last = 네개일치로또(); + LottoNumber bonus = new LottoNumber(9); + + // When + Map result = + business.countMatchResults(List.of(mine), last.getNumbers(), bonus); + + // Then + assertEquals(1, result.get(MatchResult.FOUR)); + } + + @Test + void calculateProfitRrate_3개일치_한장_구입1000원은_5배다() { + // Given + Map matchCounts = Map.of( + MatchResult.THREE, 1, + MatchResult.ZERO, 0, + MatchResult.FOUR, 0, + MatchResult.FIVE, 0, + MatchResult.FIVE_BONUS, 0, + MatchResult.SIX, 0 + ); + LottoNumber bonus = new LottoNumber(7); + int money = 1000; + + // When + String rate = business.calculateProfitRate(matchCounts, money); + + // Then + assertEquals("5.00", rate); + } + + @Test + void 보너스볼까지_맞추면_FIVE_BONUS로_집계된다() { + // Given + LottoTicket mine = 보너스7포함로또(); + LottoTicket winning = 기본로또(); + LottoNumber bonus = new LottoNumber(7); + + // When + Map result = + business.countMatchResults(List.of(mine), winning.getNumbers(), bonus); + + // Then + assertEquals(1, result.get(MatchResult.FIVE_BONUS)); + } +} diff --git a/src/test/java/model/LottoTicketBundleTest.java b/src/test/java/model/LottoTicketBundleTest.java new file mode 100644 index 00000000..bc989b10 --- /dev/null +++ b/src/test/java/model/LottoTicketBundleTest.java @@ -0,0 +1,22 @@ +package model; + +import org.junit.jupiter.api.Test; + +import static model.LottoFixture.기본로또; +import static org.junit.jupiter.api.Assertions.*; + +class LottoTicketBundleTest { + + @Test + void 저장소에_로또번호를_추가하면_읽을때_사이즈가_증가한다() { + // given + LottoTicketBundle repository = new LottoTicketBundle(); + LottoTicket lottoTicket = 기본로또(); + + // when + repository.addLottoNumbers(lottoTicket); + + // then + assertEquals(1, repository.readLottoNumbersRepository().size()); + } +} diff --git a/src/test/java/model/LottoTicketTest.java b/src/test/java/model/LottoTicketTest.java new file mode 100644 index 00000000..de41e73f --- /dev/null +++ b/src/test/java/model/LottoTicketTest.java @@ -0,0 +1,46 @@ +package model; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + + +import static model.LottoFixture.기본로또; +import static org.junit.jupiter.api.Assertions.*; + +class LottoTicketTest { + + @Test + void 로또번호가_6개면_정상적으로_생성된다() { + List numbers = Arrays.asList( + new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), + new LottoNumber(4), new LottoNumber(5), new LottoNumber(6)); + + LottoTicket lottoTicket = new LottoTicket(numbers); + + assertEquals(6, lottoTicket.getNumbers().size()); + } + + @Test + void 로또번호가_6개가_아니면_예외가_발생한다() { + List numbers = Arrays.asList( + new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), + new LottoNumber(4)); + + assertThrows(IllegalArgumentException.class, + () -> new LottoTicket(numbers)); + } + + @Test + void sortNumbers는_번호를_오름차순으로_정렬한다() { + List numbers = Arrays.asList( + new LottoNumber(6), new LottoNumber(3), new LottoNumber(5), + new LottoNumber(1), new LottoNumber(4), new LottoNumber(2) + ); + + LottoTicket sorted = new LottoTicket(numbers).sortNumbers(); + + assertEquals(기본로또(), sorted); + } +} diff --git a/src/test/java/model/PurchaseAmountTest.java b/src/test/java/model/PurchaseAmountTest.java new file mode 100644 index 00000000..46e0b3da --- /dev/null +++ b/src/test/java/model/PurchaseAmountTest.java @@ -0,0 +1,41 @@ +package model; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class PurchaseAmountTest { + + @Test + void 올바른_금액이면_로또개수계산() { + // given + PurchaseAmount purchaseAmount = new PurchaseAmount(2000); + + // when + int count = purchaseAmount.calculateLottoCount(); + + // then + assertEquals(2, count); + } + + @Test + void _0원_미만이면_예외가_발생한다() { + // given + int invalidMoney = -2000; + + // when & then + assertThrows(IllegalArgumentException.class, () -> new PurchaseAmount(invalidMoney)); + } + + @Test + void 같은금액이면_동일객체() { + // given + PurchaseAmount purchaseAmount1 = new PurchaseAmount(6000); + PurchaseAmount purchaseAmount2 = new PurchaseAmount(6000); + + // when & then + assertEquals(purchaseAmount1, purchaseAmount2); + assertEquals(purchaseAmount1.hashCode(), purchaseAmount2.hashCode()); + } +}