diff --git a/src/main/java/lotto2/controller/LottoController.java b/src/main/java/lotto2/controller/LottoController.java index c9fcef0f6..020ec85ea 100644 --- a/src/main/java/lotto2/controller/LottoController.java +++ b/src/main/java/lotto2/controller/LottoController.java @@ -3,7 +3,7 @@ import lotto2.model.*; import lotto2.model.enums.LottoPrize; import lotto2.model.enums.WinningRank; -import lotto2.model.generator.LottoGeneratorFromWinningNumbers; +import lotto2.model.generator.LottoGeneratorFromUserInput; import lotto2.model.generator.LottoGeneratorRandom; import lotto2.view.InputView; import lotto2.view.OutputView; @@ -20,31 +20,43 @@ public LottoController(InputView inputView, OutputView outputView) { } public void run() { - final MoneyToBuy money = acceptInputMoney(); - final List lottoBucket = generateManyLotto(money); - final Lotto winningNumbers = acceptWinningNumbers(); - final LottoNumber bonusNumber = acceptBonusNumber(); - final Map result = calculateLotto(lottoBucket, winningNumbers, bonusNumber); + final MoneyToBuy moneyToBuy = acceptInputMoney(); + final ManualLottoCount manualLottoCount = acceptManualCount(moneyToBuy); + final List lottoBucket = acceptManyManualLotto(manualLottoCount); + final int automaticLottoCount = getAutomaticLottoCount(moneyToBuy, manualLottoCount); + generateManyAutomaticLotto(automaticLottoCount, lottoBucket); + displayAllLotto(manualLottoCount, automaticLottoCount, lottoBucket); + final WinningLotto winningLotto = acceptWinningNumbers(); + acceptBonusNumber(winningLotto); + final Map result = calculateLotto(lottoBucket, winningLotto); final List winningRankCounts = winningRankCountsAsArray(result); displayStatistics(winningRankCounts); - final double profitRatio = calculateProfitRatio(money, winningRankCounts); + final double profitRatio = calculateProfitRatio(moneyToBuy, winningRankCounts); displayProfitRatio(profitRatio); } private MoneyToBuy acceptInputMoney() { - final MoneyToBuy money = inputView.inputMoney(); - outputView.printNumberOfBoughtLotto(money); - return money; + return inputView.inputMoney(); } - private List generateManyLotto(MoneyToBuy money) { - final List lottoBucket = new ArrayList<>(); - final Round round = new Round(money.getCount()); + private ManualLottoCount acceptManualCount(MoneyToBuy moneyToBuy) { + return inputView.inputManualCount(moneyToBuy); + } + + private List acceptManyManualLotto(ManualLottoCount lottoCount) { + return inputView.inputManyManualLotto(lottoCount); + } + + private int getAutomaticLottoCount(MoneyToBuy moneyToBuy, ManualLottoCount manualLottoCount) { + return moneyToBuy.count() - manualLottoCount.count(); + } + + private List generateManyAutomaticLotto(int count, List lottoBucket) { + final Round round = new Round(count); while (round.hasNext()) { round.goNext(); lottoBucket.add(generateEachLotto()); } - outputView.printListOfLotto(lottoBucket); return lottoBucket; } @@ -52,27 +64,29 @@ private Lotto generateEachLotto() { return LottoGeneratorRandom.generate(); } - private Lotto acceptWinningNumbers() { + private void displayAllLotto(ManualLottoCount manualLottoCount, int automaticLottoCount, List lottoBucket) { + outputView.printListOfLotto(manualLottoCount, automaticLottoCount, lottoBucket); + } + + private WinningLotto acceptWinningNumbers() { final String input = inputView.inputWinningNumbers(); - final LottoGeneratorFromWinningNumbers lottoGenerator = new LottoGeneratorFromWinningNumbers(input); - return lottoGenerator.generate(); + final LottoGeneratorFromUserInput lottoGenerator = new LottoGeneratorFromUserInput(input); + return new WinningLotto(lottoGenerator.generate()); } - private LottoNumber acceptBonusNumber() { - return inputView.inputBonusNumber(); + private WinningLotto acceptBonusNumber(WinningLotto winningLotto) { + final LottoNumber bonusNumber = inputView.inputBonusNumber(); + winningLotto.setBonusNumber(bonusNumber); + return winningLotto; } - private Map calculateLotto( - List lottoBucket, - Lotto winningNumbers, - LottoNumber bonusNumber) { + private Map calculateLotto(List lottoBucket, WinningLotto winningLotto) { final LottoCalculationUtils lottoCalculationUtils = new LottoCalculationUtils(); Map countForEachWinningRank = lottoCalculationUtils.initializeCountMap(); for (Lotto eachLotto : lottoBucket) { - final int matchCount = lottoCalculationUtils.getMatchCount(eachLotto, winningNumbers); - final WinningRank winningRank = lottoCalculationUtils.winningRankForMatchCount( - matchCount, - eachLotto.contains(bonusNumber)); + final int matchCount = eachLotto.getMatchCount(winningLotto.getLotto()); + final WinningRank winningRank = lottoCalculationUtils.winningRankForMatchCount(matchCount, + eachLotto.contains(winningLotto.getBonusNumber())); countForEachWinningRank = lottoCalculationUtils.setCountForEachWinningRank( countForEachWinningRank, winningRank); } @@ -93,12 +107,12 @@ private void displayStatistics(List winningRankCounts) { outputView.printStatistics(winningRankCounts); } - private double calculateProfitRatio(MoneyToBuy money, List winningRankCounts) { + private double calculateProfitRatio(MoneyToBuy moneyToBuy, List winningRankCounts) { int totalPrize = 0; for (final WinningRankCountDto winningRankCount : winningRankCounts) { totalPrize += winningRankCount.getLottoPrize().getPrize() * winningRankCount.getCount(); } - return (double) totalPrize / money.getValue(); + return (double) totalPrize / moneyToBuy.value(); } private void displayProfitRatio(double profitRatio) { diff --git a/src/main/java/lotto2/model/Lotto.java b/src/main/java/lotto2/model/Lotto.java index 2210cc0d7..bbbc7c04f 100644 --- a/src/main/java/lotto2/model/Lotto.java +++ b/src/main/java/lotto2/model/Lotto.java @@ -1,14 +1,24 @@ package lotto2.model; -import java.util.List; +import lotto2.model.constant.LottoConstant; + +import java.util.*; public class Lotto { private final List lottoNumbers; public Lotto(List lottoNumbers) { + checkDuplicateNumberInList(lottoNumbers); this.lottoNumbers = lottoNumbers; } + private void checkDuplicateNumberInList(List winningLottoNumbers) throws IllegalArgumentException { + final Set duplicateCheck = new HashSet<>(winningLottoNumbers); + if (duplicateCheck.size() != LottoConstant.COUNT_OF_NUMBER_IN_LOTTO) { + throw new IllegalArgumentException("최종적으로 당첨 번호는 반드시 6 개가 되어야 합니다."); + } + } + public boolean contains(LottoNumber lottoNumber) { return lottoNumbers.contains(lottoNumber); } @@ -17,8 +27,21 @@ public List lottoNumbers() { return lottoNumbers; } + public int getMatchCount(Lotto other) { + final List otherNumbers = other.lottoNumbers(); + int matchCount = 0; + for (LottoNumber lottoNumber : otherNumbers) { + if (lottoNumbers.contains(lottoNumber)) { + ++matchCount; + } + } + return matchCount; + } + @Override public String toString() { - return lottoNumbers.toString(); + final List listToPrint = new ArrayList<>(lottoNumbers); + Collections.sort(listToPrint, Comparator.comparingInt(LottoNumber::value)); + return listToPrint.toString(); } } diff --git a/src/main/java/lotto2/model/LottoCalculationUtils.java b/src/main/java/lotto2/model/LottoCalculationUtils.java index 88db55568..0cedc2415 100644 --- a/src/main/java/lotto2/model/LottoCalculationUtils.java +++ b/src/main/java/lotto2/model/LottoCalculationUtils.java @@ -3,7 +3,6 @@ import lotto2.model.enums.WinningRank; import java.util.HashMap; -import java.util.List; import java.util.Map; public class LottoCalculationUtils { @@ -17,17 +16,6 @@ public Map initializeCountMap() { return countForEachWinningRank; } - public int getMatchCount(Lotto eachLotto, Lotto winningNumbers) { - final List lottoWinningNumbers = winningNumbers.lottoNumbers(); - int matchCount = 0; - for (LottoNumber currentWinningNumber : lottoWinningNumbers) { - if (eachLotto.contains(currentWinningNumber)) { - ++matchCount; - } - } - return matchCount; - } - public WinningRank winningRankForMatchCount(int matchCount, boolean containsBonusNumber) { if (matchCount == 3) { return WinningRank.FIFTH; @@ -51,6 +39,9 @@ public Map setCountForEachWinningRank( Map countMap, WinningRank winningRank) { final Map countForEachWinningRank = new HashMap<>(countMap); + if (winningRank == WinningRank.NONE) { + return countMap; + } final int count = countForEachWinningRank.get(winningRank); countForEachWinningRank.put(winningRank, count + 1); return countForEachWinningRank; diff --git a/src/main/java/lotto2/model/LottoNumber.java b/src/main/java/lotto2/model/LottoNumber.java index 745b046f3..77fde1c79 100644 --- a/src/main/java/lotto2/model/LottoNumber.java +++ b/src/main/java/lotto2/model/LottoNumber.java @@ -36,6 +36,10 @@ private boolean lottoNumberOutOfRange(int tokenValue) { return tokenValue < LottoConstant.LOTTO_MINIMUM_NUMBER || LottoConstant.LOTTO_MAXIMUM_NUMBER < tokenValue; } + public int value() { + return value; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/src/main/java/lotto2/model/ManualLottoCount.java b/src/main/java/lotto2/model/ManualLottoCount.java new file mode 100644 index 000000000..98a93ea7e --- /dev/null +++ b/src/main/java/lotto2/model/ManualLottoCount.java @@ -0,0 +1,37 @@ +package lotto2.model; + +public class ManualLottoCount { + private final int count; + + public ManualLottoCount(String input, MoneyToBuy moneyToBuy) { + this.count = parseInt(input, moneyToBuy); + } + + private int parseInt(String input, MoneyToBuy moneyToBuy) { + int count; + try { + count = Integer.parseInt(input); + } catch (Exception e) { + throw new NumberFormatException("수동으로 구매할 로또는 숫자를 입력해야 합니다."); + } + if (isNegative(count)) { + throw new IllegalArgumentException("수동으로 구매할 로또는 반드시 0 이상의 정수여야 합니다."); + } + if (isMoreThanTotalCount(moneyToBuy, count)) { + throw new IllegalArgumentException("수동으로 구매할 로또는 입력한 금액으로 구입 가능한 총 개수보다 많을 수 없습니다."); + } + return count; + } + + private boolean isNegative(int count) { + return count < 0; + } + + private boolean isMoreThanTotalCount(MoneyToBuy moneyToBuy, int count) { + return moneyToBuy.count() < count; + } + + public int count() { + return count; + } +} diff --git a/src/main/java/lotto2/model/MoneyToBuy.java b/src/main/java/lotto2/model/MoneyToBuy.java index f4308f1c8..2c6b3cd5e 100644 --- a/src/main/java/lotto2/model/MoneyToBuy.java +++ b/src/main/java/lotto2/model/MoneyToBuy.java @@ -37,11 +37,11 @@ private boolean divisibleWithoutRemainder(int inputMoney) { return inputMoney % PRICE_OF_SINGLE_LOTTO_TICKET == 0; } - public int getValue() { + public int value() { return value; } - public int getCount() { + public int count() { return count; } } diff --git a/src/main/java/lotto2/model/WinningLotto.java b/src/main/java/lotto2/model/WinningLotto.java new file mode 100644 index 000000000..e0110a53e --- /dev/null +++ b/src/main/java/lotto2/model/WinningLotto.java @@ -0,0 +1,22 @@ +package lotto2.model; + +public class WinningLotto { + private final Lotto lotto; + private LottoNumber bonusNumber; + + public WinningLotto(Lotto lotto) { + this.lotto = lotto; + } + + public Lotto getLotto() { + return lotto; + } + + public LottoNumber getBonusNumber() { + return bonusNumber; + } + + public void setBonusNumber(LottoNumber bonusNumber) { + this.bonusNumber = bonusNumber; + } +} diff --git a/src/main/java/lotto2/model/generator/LottoGeneratorFromWinningNumbers.java b/src/main/java/lotto2/model/generator/LottoGeneratorFromUserInput.java similarity index 76% rename from src/main/java/lotto2/model/generator/LottoGeneratorFromWinningNumbers.java rename to src/main/java/lotto2/model/generator/LottoGeneratorFromUserInput.java index 358e7afe8..538648df9 100644 --- a/src/main/java/lotto2/model/generator/LottoGeneratorFromWinningNumbers.java +++ b/src/main/java/lotto2/model/generator/LottoGeneratorFromUserInput.java @@ -6,16 +6,14 @@ import lotto2.model.LottoNumber; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -public class LottoGeneratorFromWinningNumbers { +public class LottoGeneratorFromUserInput { private final String input; private static final String LOTTO_NUMBERS_STRING_DELIMITER_REGEX = ","; - public LottoGeneratorFromWinningNumbers(String input) { + public LottoGeneratorFromUserInput(String input) { this.input = input; } @@ -25,7 +23,6 @@ public Lotto generate() { throw new IllegalArgumentException("당첨 번호는 반드시 6 개를 입력해야 합니다."); } final List winningLottoNumbers = toLottoNumbers(tokens); - checkDuplicateNumberInList(winningLottoNumbers); return new Lotto(winningLottoNumbers); } @@ -60,11 +57,4 @@ private List toLottoNumbers(String[] tokens) { } return lottoNumbersData; } - - private void checkDuplicateNumberInList(List winningLottoNumbers) throws IllegalArgumentException { - final Set duplicateCheck = new HashSet<>(winningLottoNumbers); - if (duplicateCheck.size() != LottoConstant.COUNT_OF_NUMBER_IN_LOTTO) { - throw new IllegalArgumentException("최종적으로 당첨 번호는 반드시 6 개가 되어야 합니다."); - } - } } diff --git a/src/main/java/lotto2/view/InputView.java b/src/main/java/lotto2/view/InputView.java index 91cf214b2..049a112b5 100644 --- a/src/main/java/lotto2/view/InputView.java +++ b/src/main/java/lotto2/view/InputView.java @@ -1,7 +1,11 @@ package lotto2.view; +import lotto2.controller.Round; import lotto2.model.*; +import lotto2.model.generator.LottoGeneratorFromUserInput; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; public class InputView { @@ -12,8 +16,29 @@ public MoneyToBuy inputMoney() { return new MoneyToBuy(input); } + public ManualLottoCount inputManualCount(MoneyToBuy moneyToBuy) { + System.out.print("\n수동으로 구매할 로또 수를 입력해 주세요.\n"); + final Scanner scanner = new Scanner(System.in); + final String input = scanner.nextLine(); + return new ManualLottoCount(input, moneyToBuy); + } + + public List inputManyManualLotto(ManualLottoCount lottoCount) { + System.out.print("\n수동으로 구매할 번호를 입력해 주세요.\n"); + final List lottoBucket = new ArrayList<>(); + final Round round = new Round(lottoCount.count()); + while (round.hasNext()) { + round.goNext(); + final Scanner scanner = new Scanner(System.in); + final String input = scanner.nextLine(); + final LottoGeneratorFromUserInput lottoGenerator = new LottoGeneratorFromUserInput(input); + lottoBucket.add(lottoGenerator.generate()); + } + return lottoBucket; + } + public String inputWinningNumbers() { - System.out.print("지난 주 당첨 번호를 입력해 주세요.\n"); + System.out.print("\n지난 주 당첨 번호를 입력해 주세요.\n"); final Scanner scanner = new Scanner(System.in); return scanner.nextLine(); } diff --git a/src/main/java/lotto2/view/OutputView.java b/src/main/java/lotto2/view/OutputView.java index 2ad6f4bf9..ca3d6f99f 100644 --- a/src/main/java/lotto2/view/OutputView.java +++ b/src/main/java/lotto2/view/OutputView.java @@ -9,15 +9,11 @@ public class OutputView { private static final DecimalFormat decimalFormat = new DecimalFormat("0.00"); - public void printNumberOfBoughtLotto(MoneyToBuy money) { - System.out.printf("%d개를 구매했습니다.\n", money.getCount()); - } - - public void printListOfLotto(List lottoBucket) { + public void printListOfLotto(ManualLottoCount manualLottoCount, int automaticLottoCount, List lottoBucket) { + System.out.printf("\n수동으로 %d장, 자동으로 %d개를 구매했습니다.\n", manualLottoCount.count(), automaticLottoCount); for (Lotto lotto : lottoBucket) { printEachLotto(lotto); } - System.out.println(); } private void printEachLotto(Lotto lotto) {