diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000..1f2fe1ba --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,8 @@ +import controller.LottoController; + +public class Application { + public static void main(String[] args) { + LottoController lottoController = new LottoController(); + lottoController.run(); + } +} diff --git a/src/main/java/controller/LottoController.java b/src/main/java/controller/LottoController.java new file mode 100644 index 00000000..8b7407a4 --- /dev/null +++ b/src/main/java/controller/LottoController.java @@ -0,0 +1,60 @@ +package controller; + +import java.util.ArrayList; +import java.util.List; + +import domain.Lotto; +import domain.LottoGameResult; +import domain.LottoMachine; +import domain.WinningNumbers; +import view.InputHandler; + +public class LottoController { + private final InputHandler inputHandler = new InputHandler(); + private final LottoMachine lottoMachine = new LottoMachine(); + + public void run() { + int purchaseAmount = inputHandler.getPurchaseAmount(); + + int totalLottos = lottoMachine.calculateNumberOfLottos(purchaseAmount); + + int manualLottoCount = inputHandler.getManualLottoCount(); + + List manualLottoInputs = inputHandler.getManualLottoInputs(manualLottoCount); + List manualLottos = createManualLottos(manualLottoInputs); + + int automaticLottoCount = totalLottos - manualLottoCount; + + List automaticLottos = lottoMachine.generateAutomaticLottos(automaticLottoCount); + + List allLottos = new ArrayList<>(); + allLottos.addAll(manualLottos); + allLottos.addAll(automaticLottos); + + System.out.println("수동으로 " + manualLottoCount + "장, 자동으로 " + automaticLottoCount + "개를 구매했습니다."); + for (Lotto lotto : allLottos) { + System.out.println(lotto); + } + + List winningNumbers = inputHandler.getWinningNumbers(); + int bonusNumber = inputHandler.getBonusNumber(); + WinningNumbers winNums = new WinningNumbers(winningNumbers, bonusNumber); + System.out.println("당첨 번호: " + winNums); + + LottoGameResult gameResult = new LottoGameResult(allLottos, winNums); + gameResult.printWinningStatistics(); + } + + private List createManualLottos(List manualLottoInputs) { + List manualLottos = new ArrayList<>(); + for (String input : manualLottoInputs) { + String[] inputs = input.split("[,\\s]+"); + List numbers = new ArrayList<>(); + for (String number : inputs) { + numbers.add(Integer.parseInt(number)); + } + manualLottos.add(new Lotto(numbers)); + } + return manualLottos; + } +} diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java new file mode 100644 index 00000000..ba15fdde --- /dev/null +++ b/src/main/java/domain/Lotto.java @@ -0,0 +1,31 @@ +package domain; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class Lotto { + private final Set numbers; + + public Lotto(List numbers) { + if (numbers.size() != 6) { + throw new IllegalArgumentException("로또 번호는 정확히 6개여야 합니다."); + } + this.numbers = numbers.stream() + .map(LottoNumber::new) + .collect(Collectors.toSet()); + if (this.numbers.size() != 6) { + throw new IllegalArgumentException("로또 번호는 중복되지 않아야 합니다."); + } + } + + public Set getNumbers() { + return Collections.unmodifiableSet(numbers); + } + + @Override + public String toString() { + return numbers.toString(); + } +} diff --git a/src/main/java/domain/LottoGameResult.java b/src/main/java/domain/LottoGameResult.java new file mode 100644 index 00000000..c8d06d19 --- /dev/null +++ b/src/main/java/domain/LottoGameResult.java @@ -0,0 +1,59 @@ +package domain; + +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class LottoGameResult { + private static final int LOTTO_PRICE = 1000; + + private final List lottos; + private final WinningNumbers winningNumbers; + + public LottoGameResult(List lottos, WinningNumbers winningNumbers) { + this.lottos = lottos; + this.winningNumbers = winningNumbers; + } + + public void printWinningStatistics() { + Map matchCount = new EnumMap<>(WinningRank.class); + for (WinningRank rank : WinningRank.values()) { + matchCount.put(rank, 0); + } + + for (Lotto lotto : lottos) { + WinningRank rank = determineRank(lotto); + matchCount.put(rank, matchCount.get(rank) + 1); + } + printStatistics(matchCount); + } + + private WinningRank determineRank(Lotto lotto) { + int match = winningNumbers.countMatchingNumbers(lotto); + boolean containsBonus = winningNumbers.containsBonusNumber(lotto); + return WinningRank.valueOf(match, containsBonus); + } + + private void printStatistics(Map matchCount) { + System.out.println("당첨 통계"); + System.out.println("---------"); + + for (WinningRank rank : WinningRank.values()) { + if (rank != WinningRank.NONE) { + System.out.println(rank.getMessage() + " - " + matchCount.get(rank) + "개"); + } + } + + double profitRate = calculateProfitRate(matchCount); + System.out.printf("총 수익률은 %.4f입니다.%n", profitRate); + } + + private double calculateProfitRate(Map matchCount) { + int totalPrize = 0; + for (WinningRank rank : WinningRank.values()) { + totalPrize += matchCount.get(rank) * rank.getPrize(); + } + int totalSpent = LOTTO_PRICE * lottos.size(); + return (double) totalPrize / totalSpent; + } +} diff --git a/src/main/java/domain/LottoMachine.java b/src/main/java/domain/LottoMachine.java new file mode 100644 index 00000000..628831dd --- /dev/null +++ b/src/main/java/domain/LottoMachine.java @@ -0,0 +1,34 @@ +package domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class LottoMachine { + private static final int LOTTO_PRICE = 1000; + private static final int LOTTO_NUMBER_COUNT = 6; + + public int calculateNumberOfLottos(int purchaseAmount) { + return purchaseAmount / LOTTO_PRICE; + } + + public List generateAutomaticLottos(int count) { + List lottos = new ArrayList<>(); + for (int i = 0; i < count; i++) { + lottos.add(generateRandomLotto()); + } + return lottos; + } + + private Lotto generateRandomLotto() { + Random random = new Random(); + List numbers = new ArrayList<>(); + while (numbers.size() < LOTTO_NUMBER_COUNT) { + int number = random.nextInt(45) + 1; + if (!numbers.contains(number)) { + numbers.add(number); + } + } + return new Lotto(numbers); + } +} diff --git a/src/main/java/domain/LottoNumber.java b/src/main/java/domain/LottoNumber.java new file mode 100644 index 00000000..f8795cef --- /dev/null +++ b/src/main/java/domain/LottoNumber.java @@ -0,0 +1,34 @@ +package domain; + +public class LottoNumber { + private final int number; + + public LottoNumber(int number) { + if (number < 1 || number > 45) { + throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + this.number = number; + } + + public int getNumber() { + return number; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LottoNumber that = (LottoNumber) o; + return number == that.number; + } + + @Override + public int hashCode() { + return Integer.hashCode(number); + } + + @Override + public String toString() { + return String.valueOf(number); + } +} diff --git a/src/main/java/domain/WinningNumbers.java b/src/main/java/domain/WinningNumbers.java new file mode 100644 index 00000000..e5c64c46 --- /dev/null +++ b/src/main/java/domain/WinningNumbers.java @@ -0,0 +1,33 @@ +package domain; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class WinningNumbers { + private final Set numbers; + private final LottoNumber bonusNumber; + + public WinningNumbers(List numbers, int bonusNumber) { + if (numbers.size() != 6) { + throw new IllegalArgumentException("당첨 번호는 정확히 6개여야 합니다."); + } + this.numbers = numbers.stream() + .map(LottoNumber::new) + .collect(Collectors.toSet()); + if (this.numbers.size() != 6) { + throw new IllegalArgumentException("당첨 번호는 중복되지 않아야 합니다."); + } + this.bonusNumber = new LottoNumber(bonusNumber); + } + + public int countMatchingNumbers(Lotto lotto) { + return (int) lotto.getNumbers().stream() + .filter(numbers::contains) + .count(); + } + + public boolean containsBonusNumber(Lotto lotto) { + return lotto.getNumbers().contains(bonusNumber); + } +} diff --git a/src/main/java/domain/WinningRank.java b/src/main/java/domain/WinningRank.java new file mode 100644 index 00000000..5cd2dbd2 --- /dev/null +++ b/src/main/java/domain/WinningRank.java @@ -0,0 +1,39 @@ +package domain; + +public enum WinningRank { + THREE(3, false, 5000, "3개 일치 (5000원)"), + FOUR(4, false, 50000, "4개 일치 (50000원)"), + FIVE(5, false, 1500000, "5개 일치 (1500000원)"), + FIVE_WITH_BONUS(5, true, 30000000, "5개 일치, 보너스 볼 일치 (30000000원)"), + SIX(6, false, 2000000000, "6개 일치 (2000000000원)"), + NONE(0, false, 0, ""); + + private final int matchCount; + private final boolean requiresBonus; + private final int prize; + private final String message; + + WinningRank(int matchCount, boolean requiresBonus, int prize, String message) { + this.matchCount = matchCount; + this.requiresBonus = requiresBonus; + this.prize = prize; + this.message = message; + } + + public int getPrize() { + return prize; + } + + public String getMessage() { + return message; + } + + public static WinningRank valueOf(int matchCount, boolean bonus) { + for (WinningRank rank : values()) { + if (rank.matchCount == matchCount && rank.requiresBonus == bonus) { + return rank; + } + } + return NONE; + } +} diff --git a/src/main/java/view/InputHandler.java b/src/main/java/view/InputHandler.java new file mode 100644 index 00000000..fd41afb3 --- /dev/null +++ b/src/main/java/view/InputHandler.java @@ -0,0 +1,44 @@ +package view; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class InputHandler { + private final Scanner scanner = new Scanner(System.in); + + public int getPurchaseAmount() { + System.out.println("구입금액을 입력해 주세요."); + return Integer.parseInt(scanner.nextLine()); + } + + public int getManualLottoCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + return Integer.parseInt(scanner.nextLine()); + } + + public List getManualLottoInputs(int manualCount) { + List manualLottoInputs = new ArrayList<>(); + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + for (int i = 0; i < manualCount; i++) { + manualLottoInputs.add(scanner.nextLine()); + } + return manualLottoInputs; + } + + public List getWinningNumbers() { + System.out.println("지난 주 당첨 번호를 입력해 주세요. (예: 1, 2, 3, 4, 5, 6)"); + String input = scanner.nextLine(); + String[] inputs = input.split("[,\\s]+"); + List winningNumbers = new ArrayList<>(); + for (String number : inputs) { + winningNumbers.add(Integer.parseInt(number)); + } + return winningNumbers; + } + + public int getBonusNumber() { + System.out.println("보너스 볼을 입력해 주세요."); + return Integer.parseInt(scanner.nextLine()); + } +}