diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..38d3018 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index e69de29..037cd81 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,65 @@ +# JAVA - LOTTO + +https://github.com/TEAM-ALOM/java-lotto + +## ๐Ÿ—‚๏ธ Package ๊ตฌ์กฐ(MVC) + +### **Model** + +#### LottoUser + +- ์—ญํ•  : (int)`money`, `Lottos`๊ณผ `LottosWinningStatus`๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด + +#### Lotto + +- ์—ญํ•  : ๋กœ๋˜์˜ ์‹ค์งˆ์  ๋ฐ์ดํ„ฐ + +#### Lottos + +- ์—ญํ•  : ๊ตฌ๋งคํ•œ `Lotto`๋“ค์˜ ๋ฌถ์Œ(`List`) ์‹ค์งˆ์  ๋ฐ์ดํ„ฐ + +#### LottoGenerator + +- ์—ญํ•  : `LottoUser.money`์— ๋”ฐ๋ผ `Lotto`๋“ค์„ ์ƒ์„ฑ + +#### LottosWinningChecker + +- ์—ญํ•  : `Lottos`์˜ ๋‹น์ฒจ ๊ณ„์‚ฐ ํ›„ `LottosWinningStatus` ์ƒ์„ฑ + +#### LottosWinningStatus + +- ์—ญํ•  : `WinningNumbers`,`WinningType`๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ `Lottos`์˜ ๋‹น์ณ  ๊ณ„์‚ฐ `LottoWinningChecker` ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์€ ์‹ค์งˆ์  ๋ฐ์ดํ„ฐ + +#### WinningNumbers + +- ์—ญํ•  : ๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ์™€ ๋‹น์ฒจ ๋ฒˆํ˜ธ๋“ค(ํ•˜๋‚˜์˜ ๋กœ๋˜ ๊ฐ์ฒด)์˜ ์‹ค์งˆ์  ๋ฐ์ดํ„ฐ + +#### WinningType + +- ์—ญํ•  : ๋“ฑ์ˆ˜ ๋ณ„ ๋‹น์ฒจ ์กฐ๊ฑด ๋ชฉ๋ก์˜ ์‹ค์งˆ์  ๋ฐ์ดํ„ฐ + +### Controller + +#### LottoSystemController + +- ์—ญํ•  : ๋กœ๋˜ ์‹œ์Šคํ…œ์„ ์‹คํ–‰ + +### **View** + +#### InputView + +- ์—ญํ•  : ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. + +#### OutputView + +- ์—ญํ•  : ์ž…๋ ฅ ๋ฌธ๊ตฌ ๋ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅํ•œ๋‹ค. + +### **Validation** + +#### Validation + +#### ErrorMessage + +- ์—ญํ•  : ์—๋Ÿฌ ๋ฉ”์„ธ์ง€ ๋ชจ์Œ + +## Test diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922..444453b 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,12 @@ package lotto; +import lotto.controller.LottoSystemController; +import lotto.model.domain.LottoUser; + public class Application { public static void main(String[] args) { // TODO: ํ”„๋กœ๊ทธ๋žจ ๊ตฌํ˜„ + LottoSystemController lottoSystemController = new LottoSystemController(new LottoUser()); + lottoSystemController.runLottoSystem(); } -} +} \ No newline at end of file diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java deleted file mode 100644 index 519793d..0000000 --- a/src/main/java/lotto/Lotto.java +++ /dev/null @@ -1,20 +0,0 @@ -package lotto; - -import java.util.List; - -public class Lotto { - private final List numbers; - - public Lotto(List numbers) { - validate(numbers); - this.numbers = numbers; - } - - private void validate(List numbers) { - if (numbers.size() != 6) { - throw new IllegalArgumentException(); - } - } - - // TODO: ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„ -} diff --git a/src/main/java/lotto/controller/LottoSystemController.java b/src/main/java/lotto/controller/LottoSystemController.java new file mode 100644 index 0000000..a5ce41c --- /dev/null +++ b/src/main/java/lotto/controller/LottoSystemController.java @@ -0,0 +1,58 @@ +package lotto.controller; + +import java.util.List; +import lotto.model.domain.LottoUser; +import lotto.model.domain.WinningNumbers; +import lotto.model.service.LottosGenerator; +import lotto.model.service.LottosWinningChecker; +import lotto.view.InputView; +import lotto.view.OutputView; + +public class LottoSystemController { + + private final LottoUser lottoUser; + + public LottoSystemController(LottoUser lottoUser) { + this.lottoUser = lottoUser; + } + + public void runLottoSystem() { + try { + buyLottos(); + + WinningNumbers winningNumbers = inputWinningNumbers(); + + winningResult(winningNumbers); + } catch (IllegalArgumentException e) { + OutputView.displayErrorMessage(e.getMessage()); + } + } + + private void buyLottos() { + OutputView.moneyForPurchaseInputMessage(); + int userMoney = InputView.moneyForPurchaseInput(); + + lottoUser.setMoney(userMoney); + + LottosGenerator.generateLottosAndInput(lottoUser, userMoney); + + OutputView.userLottos(lottoUser.getLottos().getLottoBundle()); + } + + private WinningNumbers inputWinningNumbers() { + OutputView.winningNumbersInputMessage(); + List winningNumbersInput = InputView.winningNumbersInput(); + + OutputView.bonusNumberInputMessage(); + int bonusNumberInput = InputView.bonusNumberInput(); + + return new WinningNumbers( + winningNumbersInput, bonusNumberInput + ); + } + + private void winningResult(WinningNumbers winningNumbers) { + LottosWinningChecker.generateWinningStatusAndInput(lottoUser, winningNumbers); + OutputView.winningStatusMessage(lottoUser.getLottosWinningStatus()); + } +} diff --git a/src/main/java/lotto/model/domain/Lotto.java b/src/main/java/lotto/model/domain/Lotto.java new file mode 100644 index 0000000..9e560dc --- /dev/null +++ b/src/main/java/lotto/model/domain/Lotto.java @@ -0,0 +1,18 @@ +package lotto.model.domain; + +import java.util.List; +import lotto.validation.Validation; + +public class Lotto { + + private final List numbers; + + public Lotto(List numbers) { + Validation.validationLotto(numbers); + this.numbers = numbers; + } + + public List getNumbers() { + return numbers; + } +} diff --git a/src/main/java/lotto/model/domain/LottoUser.java b/src/main/java/lotto/model/domain/LottoUser.java new file mode 100644 index 0000000..720c40e --- /dev/null +++ b/src/main/java/lotto/model/domain/LottoUser.java @@ -0,0 +1,53 @@ +package lotto.model.domain; + +import lotto.validation.Validation; + +public class LottoUser { + private Lottos lottos; + private int money; + private LottosWinningStatus lottosWinningStatus; + + public LottoUser() { + + } + + public LottoUser(int money) { + this.money = money; + } + + public LottoUser(Lottos lottos, int money) { + this.lottos = lottos; + this.money = money; + } + + public LottoUser(Lottos lottos, int money, LottosWinningStatus lottosWinningStatus) { + this.lottos = lottos; + Validation.validationMoney(money); + this.money = money; + this.lottosWinningStatus = lottosWinningStatus; + } + + public Lottos getLottos() { + return lottos; + } + + public int getMoney() { + return money; + } + + public LottosWinningStatus getLottosWinningStatus() { + return lottosWinningStatus; + } + + public void setLottos(Lottos lottos) { + this.lottos = lottos; + } + + public void setLottosWinningStatus(LottosWinningStatus lottosWinningStatus) { + this.lottosWinningStatus = lottosWinningStatus; + } + + public void setMoney(int money) { + this.money = money; + } +} diff --git a/src/main/java/lotto/model/domain/Lottos.java b/src/main/java/lotto/model/domain/Lottos.java new file mode 100644 index 0000000..8b0c18b --- /dev/null +++ b/src/main/java/lotto/model/domain/Lottos.java @@ -0,0 +1,20 @@ +package lotto.model.domain; + +import java.util.List; +import lotto.validation.Validation; + +public class Lottos { + private final int count; + private final List lottoBundle; + + public Lottos(int count, List lottoBundle) { + Validation.validationCount(count); + this.count = count; + Validation.validationLottos(count, lottoBundle); + this.lottoBundle = lottoBundle; + } + + public List getLottoBundle() { + return lottoBundle; + } +} diff --git a/src/main/java/lotto/model/domain/LottosWinningStatus.java b/src/main/java/lotto/model/domain/LottosWinningStatus.java new file mode 100644 index 0000000..a917ff3 --- /dev/null +++ b/src/main/java/lotto/model/domain/LottosWinningStatus.java @@ -0,0 +1,47 @@ +package lotto.model.domain; + +import lotto.validation.Validation; + +public class LottosWinningStatus { + private final int matchesThree; + private final int matchesFour; + private final int matchesFive; + private final int matchesFiveWithBonus; + private final int matchesSix; + private final double profitRatio; + + public LottosWinningStatus(int matchesThree, int matchesFour, int matchesFive, int matchesFiveWithBonus, + int matchesSix, double profitRatio) { + this.matchesThree = matchesThree; + this.matchesFour = matchesFour; + this.matchesFive = matchesFive; + this.matchesFiveWithBonus = matchesFiveWithBonus; + this.matchesSix = matchesSix; + Validation.validationProfitRatio(profitRatio); + this.profitRatio = profitRatio; + } + + public double getProfitRatio() { + return profitRatio; + } + + public int getMatchesThree() { + return matchesThree; + } + + public int getMatchesFour() { + return matchesFour; + } + + public int getMatchesFive() { + return matchesFive; + } + + public int getMatchesFiveWithBonus() { + return matchesFiveWithBonus; + } + + public int getMatchesSix() { + return matchesSix; + } +} diff --git a/src/main/java/lotto/model/domain/WinningNumbers.java b/src/main/java/lotto/model/domain/WinningNumbers.java new file mode 100644 index 0000000..97d5e35 --- /dev/null +++ b/src/main/java/lotto/model/domain/WinningNumbers.java @@ -0,0 +1,23 @@ +package lotto.model.domain; + +import java.util.List; +import lotto.validation.Validation; + +public class WinningNumbers { + private final Lotto winningLotto; + private final int bonusNumber; + + public WinningNumbers(List winningLotto, int bonusNumber) { + this.winningLotto = new Lotto(winningLotto); + Validation.validationBonusNumber(winningLotto, bonusNumber); + this.bonusNumber = bonusNumber; + } + + public Lotto getWinningLotto() { + return winningLotto; + } + + public int getBonusNumber() { + return bonusNumber; + } +} diff --git a/src/main/java/lotto/model/domain/WinningType.java b/src/main/java/lotto/model/domain/WinningType.java new file mode 100644 index 0000000..097a82b --- /dev/null +++ b/src/main/java/lotto/model/domain/WinningType.java @@ -0,0 +1,25 @@ +package lotto.model.domain; + +public enum WinningType { + MATCHES_SIX("6๊ฐœ ์ผ์น˜ (2,000,000,000์›)", 2_000_000_000), + MATCHES_FIVE_WITH_BONUS("5๊ฐœ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ณผ ์ผ์น˜ (30,000,000์›)", 30_000_000), + MATCHES_FIVE("5๊ฐœ ์ผ์น˜ (1,500,000์›)", 1_500_000), + MATCHES_FOUR("4๊ฐœ ์ผ์น˜ (50,000์›)", 50_000), + MATCHES_THREE("3๊ฐœ ์ผ์น˜ (5,000์›)", 5_000); + + private final String message; + private final long profitMoney; + + WinningType(String message, long profitMoney) { + this.message = message; + this.profitMoney = profitMoney; + } + + public String getMessage() { + return message; + } + + public long getProfitMoney() { + return profitMoney; + } +} diff --git a/src/main/java/lotto/model/service/LottosGenerator.java b/src/main/java/lotto/model/service/LottosGenerator.java new file mode 100644 index 0000000..bd90456 --- /dev/null +++ b/src/main/java/lotto/model/service/LottosGenerator.java @@ -0,0 +1,34 @@ +package lotto.model.service; + +import java.util.ArrayList; +import java.util.List; +import lotto.model.domain.Lotto; +import lotto.model.domain.LottoUser; +import lotto.model.domain.Lottos; +import org.kokodak.Randoms; + +public class LottosGenerator { + private static final int MIN_LOTTO_NUMBER = 1; + private static final int MAX_LOTTO_NUMBER = 45; + private static final int LOTTO_COUNT = 6; + + + public static void generateLottosAndInput(LottoUser lottoUser, int userMoney) { + int count = userMoney / 1000; + + lottoUser.setLottos(new Lottos(count, generateLottos(count))); + } + + private static List generateLottos(int count) { + List userLottos = new ArrayList<>(); + for (int i = 0; i < count; i++) { + userLottos.add(generateLotto()); + } + return userLottos; + } + + private static Lotto generateLotto() { + return new Lotto(Randoms.pickUniqueNumbersInRange(MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER, LOTTO_COUNT)); + } + +} diff --git a/src/main/java/lotto/model/service/LottosWinningChecker.java b/src/main/java/lotto/model/service/LottosWinningChecker.java new file mode 100644 index 0000000..f679c81 --- /dev/null +++ b/src/main/java/lotto/model/service/LottosWinningChecker.java @@ -0,0 +1,125 @@ +package lotto.model.service; + +import static lotto.model.domain.WinningType.MATCHES_FIVE; +import static lotto.model.domain.WinningType.MATCHES_FIVE_WITH_BONUS; +import static lotto.model.domain.WinningType.MATCHES_FOUR; +import static lotto.model.domain.WinningType.MATCHES_SIX; +import static lotto.model.domain.WinningType.MATCHES_THREE; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import lotto.model.domain.Lotto; +import lotto.model.domain.LottoUser; +import lotto.model.domain.Lottos; +import lotto.model.domain.LottosWinningStatus; +import lotto.model.domain.WinningNumbers; + +public class LottosWinningChecker { + + public static void generateWinningStatusAndInput(LottoUser lottoUser, + WinningNumbers winningNumbers) { + Lottos lottos = lottoUser.getLottos(); + + AtomicInteger matchesThree = new AtomicInteger(); + AtomicInteger matchesFour = new AtomicInteger(); + AtomicInteger matchesFive = new AtomicInteger(); + AtomicInteger matchesFiveWithBonus = new AtomicInteger(); + AtomicInteger matchesSix = new AtomicInteger(); + + lottos.getLottoBundle().forEach(lotto -> { + int matchesCount = getMatchesCount(lotto.getNumbers(), winningNumbers.getWinningLotto().getNumbers()); + stackByMatchesCount(lotto, matchesCount, matchesThree, matchesFour, matchesFiveWithBonus, matchesFive, + matchesSix, winningNumbers); + } + ); + + lottoUser.setLottosWinningStatus( + getWinningStatus(matchesThree, matchesFour, matchesFive, matchesFiveWithBonus, matchesSix, lottoUser)); +// return getWinningStatus(matchesThree, matchesFour, matchesFive, matchesFiveWithBonus, matchesSix, lottoUser); + +// inputWinningStatusToUser(matchesThree, matchesFour, matchesFive, matchesFiveWithBonus, matchesSix); + } + + private static LottosWinningStatus getWinningStatus(AtomicInteger matchesThree, AtomicInteger matchesFour, + AtomicInteger matchesFive, + AtomicInteger matchesFiveWithBonus, AtomicInteger matchesSix, + LottoUser lottoUser) { + return new LottosWinningStatus( + matchesThree.intValue(), + matchesFour.intValue(), + matchesFive.intValue(), + matchesFiveWithBonus.intValue(), + matchesSix.intValue(), + + calculateProfitRatio(matchesThree, + matchesFour, + matchesFive, + matchesFiveWithBonus, + matchesSix, lottoUser) + ); + } + + private static double calculateProfitRatio(AtomicInteger matchesThree, AtomicInteger matchesFour, + AtomicInteger matchesFive, + AtomicInteger matchesFiveWithBonus, AtomicInteger matchesSix, + LottoUser lottoUser) { + return (double) getTotalProfitMoney(matchesThree, matchesFour, matchesFive, matchesFiveWithBonus, matchesSix) + * 100 + / lottoUser.getMoney(); + } + + private static long getTotalProfitMoney(AtomicInteger matchesThree, AtomicInteger matchesFour, + AtomicInteger matchesFive, + AtomicInteger matchesFiveWithBonus, AtomicInteger matchesSix) { + return matchesThree.intValue() * MATCHES_THREE.getProfitMoney() + + matchesFour.intValue() * MATCHES_FOUR.getProfitMoney() + + matchesFive.intValue() * MATCHES_FIVE.getProfitMoney() + + matchesFiveWithBonus.intValue() * MATCHES_FIVE_WITH_BONUS.getProfitMoney() + + matchesSix.intValue() * MATCHES_SIX.getProfitMoney(); + } + + private static void stackByMatchesCount(Lotto lotto, int matchesCount, AtomicInteger matchesThree, + AtomicInteger matchesFour, AtomicInteger matchesFiveWithBonus, + AtomicInteger matchesFive, AtomicInteger matchesSix, + WinningNumbers winningNumbers) { + switch (matchesCount) { + case 3: + matchesThree.getAndIncrement(); + break; + case 4: + matchesFour.getAndIncrement(); + break; + case 5: + if (isMatchToBonusNumber(lotto, winningNumbers)) { + matchesFiveWithBonus.getAndIncrement(); + break; + } + matchesFive.getAndIncrement(); + break; + case 6: + matchesSix.getAndIncrement(); + break; + } + } + + private static boolean isMatchToBonusNumber(Lotto lotto, WinningNumbers winningNumbers) { + return lotto.getNumbers().contains(winningNumbers.getBonusNumber()); + } + + private static int getMatchesCount(List list1, List list2) { + Set set1 = new HashSet<>(list1); + Set set2 = new HashSet<>(list2); + + set1.retainAll(set2); + + return set1.size(); + } +} + +//3๊ฐœ ์ผ์น˜ (5,000์›) - 1๊ฐœ +//4๊ฐœ ์ผ์น˜ (50,000์›) - 0๊ฐœ +//5๊ฐœ ์ผ์น˜ (1,500,000์›) - 0๊ฐœ +//5๊ฐœ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ณผ ์ผ์น˜ (30,000,000์›) - 0๊ฐœ +//6๊ฐœ ์ผ์น˜ (2,000,000,000์›) - 0๊ฐœ \ No newline at end of file diff --git a/src/main/java/lotto/validation/ErrorMessage.java b/src/main/java/lotto/validation/ErrorMessage.java new file mode 100644 index 0000000..6530c9d --- /dev/null +++ b/src/main/java/lotto/validation/ErrorMessage.java @@ -0,0 +1,34 @@ +package lotto.validation; + +public enum ErrorMessage { + MONEY_FOR_PURCHASE_NOT_NUMBER("๊ตฌ๋งค๊ธˆ์•ก์€ ์ˆซ์ž๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"), + + WINNINGNUMBERS_NOT_START_WITH_COMMA("์‰ผํ‘œ๋กœ ์‹œ์ž‘ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), + WINNINGNUMBERS_NOT_END_WITH_COMMA("์‰ผํ‘œ๋กœ ๋๋‚  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), + WINNINGNUMBERS_NOT_DOUBLE_COMMA("์‰ผํ‘œ ์‚ฌ์ด์— ์ˆซ์ž๋ฅผ ๋„ฃ์–ด์ฃผ์„ธ์š”"), + + LOTTO_SIZE_NOT_SIX("๋กœ๋˜ ๋ฒˆํ˜ธ ๊ฐœ์ˆ˜๋Š” 6๊ฐœ์ž…๋‹ˆ๋‹ค."), + LOTTO_NUMBER_OUT_OF_RANGE("๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 1~45 ์‚ฌ์ด์˜ ์ˆ˜์ž…๋‹ˆ๋‹ค."), + LOTTO_HAS_DUPLICATED_NUMBER("์ค‘๋ณต๋œ ์ˆซ์ž๋Š” ๊ธฐ์ž…ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), + + LOTTOS_COUNT_OUT_OF_RANGE_100("๋กœ๋˜๋Š” 1ํšŒ๋‹น 100๊ฐœ๊นŒ์ง€ ๊ตฌ๋งค๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."), + LOTTOS_SIZE_NOT_MATCH_COUNT("๊ตฌ๋งค ๊ฐ€๊ฒฉ๋งŒํผ ๋กœ๋˜๋ฅผ ๊ตฌ๋งคํ•˜์…”์•ผํ•ฉ๋‹ˆ๋‹ค."), + + BONUS_NUMBER_IS_DUPLICATED("๋‹น์ฒจ๋ฒˆํ˜ธ์™€ ์ค‘๋ณต๋œ ์ˆ˜์ž…๋‹ˆ๋‹ค."), + BONUS_NUMBER_OUT_OF_RANGE("๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋„ ๋กœ๋˜ ๋ฒˆํ˜ธ์™€ ๊ฐ™์ด 1~45 ์‚ฌ์ด์˜ ์ˆ˜์ž…๋‹ˆ๋‹ค."), + + WINNING_STATUS_PROFIT_RATIO_OVER_MAX("์ˆ˜์ต๋ฅ ์€ ์ด๋ก ์ƒ ์ตœ๋Œ€ ์ˆ˜์ต๋ฅ ์„ ๋„˜์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์„ธ์š”"), + + OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS("๋‹น์ฒจ ํ†ต๊ณ„์˜ ๊ฐ’์€ ์Œ์ˆ˜์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + + private final String message; + private static final String START_ERROR = "[ERROR] "; + + ErrorMessage(String message) { + this.message = message; + } + + public String getMessage() { + return START_ERROR + message; + } +} diff --git a/src/main/java/lotto/validation/Validation.java b/src/main/java/lotto/validation/Validation.java new file mode 100644 index 0000000..c0c24b8 --- /dev/null +++ b/src/main/java/lotto/validation/Validation.java @@ -0,0 +1,165 @@ +package lotto.validation; + +import static lotto.validation.ErrorMessage.BONUS_NUMBER_IS_DUPLICATED; +import static lotto.validation.ErrorMessage.BONUS_NUMBER_OUT_OF_RANGE; +import static lotto.validation.ErrorMessage.LOTTOS_COUNT_OUT_OF_RANGE_100; +import static lotto.validation.ErrorMessage.LOTTOS_SIZE_NOT_MATCH_COUNT; +import static lotto.validation.ErrorMessage.LOTTO_HAS_DUPLICATED_NUMBER; +import static lotto.validation.ErrorMessage.LOTTO_NUMBER_OUT_OF_RANGE; +import static lotto.validation.ErrorMessage.LOTTO_SIZE_NOT_SIX; +import static lotto.validation.ErrorMessage.MONEY_FOR_PURCHASE_NOT_NUMBER; +import static lotto.validation.ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS; +import static lotto.validation.ErrorMessage.WINNINGNUMBERS_NOT_DOUBLE_COMMA; +import static lotto.validation.ErrorMessage.WINNINGNUMBERS_NOT_END_WITH_COMMA; +import static lotto.validation.ErrorMessage.WINNINGNUMBERS_NOT_START_WITH_COMMA; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lotto.model.domain.Lotto; +import lotto.model.domain.WinningType; + +public class Validation { + private static final int MIN_LOTTO_NUMBER = 1; + private static final int MAX_LOTTO_NUMBER = 45; + + public static void validationLotto(List numbers) { + checkSizeOnlySix(numbers); + checkNumberOutOfRange(numbers); + checkDuplicatedNumber(numbers); + } + + + public static void validationCount(int count) { + checkCountUnder100(count); + } + + public static void validationProfitRatio(double profitRatio) { + checkMaxProfitRatio(profitRatio); + } + + + public static void validationMoney(int money) { + checkMoneyOutOfRange(money); + checkMoneyDivisibility(money); + } + + public static void validationBonusNumber(List winningLotto, int bonusNumber) { + checkNumberOutOfRange(bonusNumber); + checkDuplicatedBonusNumber(winningLotto, bonusNumber); + } + + + public static void checkPossibleChangeToInt(String moneyForPurchase) { + try { + Integer.parseInt(moneyForPurchase); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(MONEY_FOR_PURCHASE_NOT_NUMBER.getMessage()); + } + } + + public static void checkRightCommaFormat(String winningNumbers) { + if (winningNumbers.startsWith(",")) { + throw new IllegalArgumentException(WINNINGNUMBERS_NOT_START_WITH_COMMA.getMessage()); + } + if (winningNumbers.endsWith(",")) { + throw new IllegalArgumentException(WINNINGNUMBERS_NOT_END_WITH_COMMA.getMessage()); + } + if (winningNumbers.contains(",,")) { + throw new IllegalArgumentException(WINNINGNUMBERS_NOT_DOUBLE_COMMA.getMessage()); + } + } + + + public static void checkStatusValueMinus(int lottosWinningStatusValue) { + if (lottosWinningStatusValue < 0) { + throw new IllegalArgumentException(OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + } + } + + public static void checkStatusValueMinus(double lottosWinningStatusValue) { + if (lottosWinningStatusValue < 0) { + throw new IllegalArgumentException(OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + } + } + + private static void checkDuplicatedBonusNumber(List winningLotto, int bonusNumber) { + if (winningLotto.contains(bonusNumber)) { + throw new IllegalArgumentException(BONUS_NUMBER_IS_DUPLICATED.getMessage()); + } + } + + private static void checkNumberOutOfRange(int bonusNumber) { + if (isNumberOutOfRange(bonusNumber)) { + throw new IllegalArgumentException(BONUS_NUMBER_OUT_OF_RANGE.getMessage()); + } + } + + private static boolean isNumberOutOfRange(int number) { + return number < MIN_LOTTO_NUMBER || number > MAX_LOTTO_NUMBER; + } + + + private static void checkMoneyDivisibility(int money) { + if (money % 1000 != 0) { + throw new IllegalArgumentException(); + } + } + + private static void checkMoneyOutOfRange(int money) { + if (money < 0 || money > 100000) { + throw new IllegalArgumentException(); + } + } + + private static void checkMaxProfitRatio(double profitRatio) { + if (profitRatio > (double) WinningType.MATCHES_SIX.getProfitMoney() * 100 / 1000) { + throw new IllegalArgumentException(ErrorMessage.WINNING_STATUS_PROFIT_RATIO_OVER_MAX.getMessage()); + } + } + + private static void checkCountUnder100(int count) { + if (count > 100) { + throw new IllegalArgumentException(LOTTOS_COUNT_OUT_OF_RANGE_100.getMessage()); + } + } + + public static void validationLottos(int count, List lottos) { + checkLottosSizeSameCount(count, lottos); + } + + private static void checkLottosSizeSameCount(int count, List lottos) { + if (lottos.size() != count) { + throw new IllegalArgumentException(LOTTOS_SIZE_NOT_MATCH_COUNT.getMessage()); + } + } + + private static void checkSizeOnlySix(List numbers) { + if (numbers.size() != 6) { + throw new IllegalArgumentException(LOTTO_SIZE_NOT_SIX.getMessage()); + } + } + + private static void checkNumberOutOfRange(List numbers) { + for (Integer number : numbers) { + if (isNumberOutOfRange(number)) { + throw new IllegalArgumentException(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + } + } + } + + private static void checkDuplicatedNumber(List numbers) { + Set numbersNotDupl = new HashSet<>(); + for (Integer number : numbers) { + checkAndAddNumber(numbersNotDupl, number); + } + } + + private static void checkAndAddNumber(Set numbersNotDupl, Integer number) { + if (numbersNotDupl.contains(number)) { + throw new IllegalArgumentException(LOTTO_HAS_DUPLICATED_NUMBER.getMessage()); + } + numbersNotDupl.add(number); + } + +} diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java new file mode 100644 index 0000000..5c7a12d --- /dev/null +++ b/src/main/java/lotto/view/InputView.java @@ -0,0 +1,37 @@ +package lotto.view; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import lotto.validation.Validation; +import org.kokodak.Console; + +public class InputView { + public static int moneyForPurchaseInput() { + String moneyForPurchase = Console.readLine(); + return changeInputToInt(moneyForPurchase); + } + + public static List winningNumbersInput() { + String winningNumbers = Console.readLine(); + Validation.checkRightCommaFormat(winningNumbers); + return readNumbersFromConsole(winningNumbers); + } + + public static int bonusNumberInput() { + String bonusNumber = Console.readLine(); + return changeInputToInt(bonusNumber); + } + + + private static int changeInputToInt(String moneyForPurchase) { + Validation.checkPossibleChangeToInt(moneyForPurchase); + return Integer.parseInt(moneyForPurchase); + } + + public static List readNumbersFromConsole(String winningNumbers) { + + return Arrays.stream(winningNumbers.split(",")).map(InputView::changeInputToInt) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java new file mode 100644 index 0000000..5394b24 --- /dev/null +++ b/src/main/java/lotto/view/OutputView.java @@ -0,0 +1,66 @@ +package lotto.view; + +import static lotto.view.ViewMessage.BONUS_NUMBER_PROMPT; +import static lotto.view.ViewMessage.LOTTOS_SIZE_PROMPT; +import static lotto.view.ViewMessage.MAIN_WINNING_NUMBERS_PROMPT; +import static lotto.view.ViewMessage.PURCHASE_AMOUNT_PROMPT; +import static lotto.view.ViewMessage.WINNING_STATUS_MAIN; +import static lotto.view.ViewMessage.WINNING_STATUS_START; + +import java.util.List; +import lotto.model.domain.Lotto; +import lotto.model.domain.LottosWinningStatus; +import lotto.validation.Validation; + +public class OutputView { + + public static void moneyForPurchaseInputMessage() { + System.out.println(PURCHASE_AMOUNT_PROMPT.getMessage()); + } + + public static void userLottos(List userLottos) { + StringBuilder stringBuilder = new StringBuilder(); + System.out.printf(LOTTOS_SIZE_PROMPT.getMessage(), userLottos.size()); + for (Lotto userLotto : userLottos) { + stringBuilder.append(userLotto.getNumbers().toString()).append("\n"); + } + System.out.println(stringBuilder); + } + + public static void winningNumbersInputMessage() { + System.out.println(MAIN_WINNING_NUMBERS_PROMPT.getMessage()); + } + + public static void bonusNumberInputMessage() { + System.out.println(BONUS_NUMBER_PROMPT.getMessage()); + } + + public static void winningStatusMessage(LottosWinningStatus lottosWinningStatus) { + validationWinningStatusNumber(lottosWinningStatus); + System.out.println(WINNING_STATUS_START.getMessage()); + System.out.printf(WINNING_STATUS_MAIN.getMessage(), + lottosWinningStatus.getMatchesThree(), + lottosWinningStatus.getMatchesFour(), + lottosWinningStatus.getMatchesFive(), + lottosWinningStatus.getMatchesFiveWithBonus(), + lottosWinningStatus.getMatchesSix(), + lottosWinningStatus.getProfitRatio()); + } + + public static void displayErrorMessage(String errorMessage) { + System.out.println(errorMessage); + } + + private static void validationWinningStatusNumber(LottosWinningStatus lottosWinningStatus) { + Validation.checkStatusValueMinus(lottosWinningStatus.getMatchesThree()); + Validation.checkStatusValueMinus(lottosWinningStatus.getMatchesFour()); + Validation.checkStatusValueMinus(lottosWinningStatus.getMatchesFive()); + Validation.checkStatusValueMinus(lottosWinningStatus.getMatchesFiveWithBonus()); + Validation.checkStatusValueMinus(lottosWinningStatus.getMatchesSix()); + Validation.checkStatusValueMinus(roundToTwoDigits(lottosWinningStatus.getProfitRatio())); + } + + private static double roundToTwoDigits(double profitRatio) { + return profitRatio + 0.05; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/view/ViewMessage.java b/src/main/java/lotto/view/ViewMessage.java new file mode 100644 index 0000000..46a4e77 --- /dev/null +++ b/src/main/java/lotto/view/ViewMessage.java @@ -0,0 +1,33 @@ +package lotto.view; + +import static lotto.model.domain.WinningType.MATCHES_FIVE; +import static lotto.model.domain.WinningType.MATCHES_FIVE_WITH_BONUS; +import static lotto.model.domain.WinningType.MATCHES_FOUR; +import static lotto.model.domain.WinningType.MATCHES_SIX; +import static lotto.model.domain.WinningType.MATCHES_THREE; + +public enum ViewMessage { + PURCHASE_AMOUNT_PROMPT("๊ตฌ์ž…๊ธˆ์•ก์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n"), + MAIN_WINNING_NUMBERS_PROMPT("๋‹น์ฒจ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n"), + BONUS_NUMBER_PROMPT("๋ณด๋„ˆ์Šค ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.\n"), + LOTTOS_SIZE_PROMPT("%d๊ฐœ๋ฅผ ๊ตฌ๋งคํ–ˆ์Šต๋‹ˆ๋‹ค.\n"), + WINNING_STATUS_START("๋‹น์ฒจ ํ†ต๊ณ„\n---"), + WINNING_STATUS_MAIN( + MATCHES_THREE.getMessage() + " - %d๊ฐœ\n" + + MATCHES_FOUR.getMessage() + " - %d๊ฐœ\n" + + MATCHES_FIVE.getMessage() + " - %d๊ฐœ\n" + + MATCHES_FIVE_WITH_BONUS.getMessage() + " - %d๊ฐœ\n" + + MATCHES_SIX.getMessage() + " - %d๊ฐœ\n" + + "์ด ์ˆ˜์ต๋ฅ ์€ %.1f%%์ž…๋‹ˆ๋‹ค." + ); + + private final String message; + + ViewMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/test/java/lotto/ApplicationTest.java b/src/test/java/lotto/ApplicationTest.java index 404cbe1..9c70a0f 100644 --- a/src/test/java/lotto/ApplicationTest.java +++ b/src/test/java/lotto/ApplicationTest.java @@ -32,7 +32,7 @@ class ApplicationTest extends NsTest { "5๊ฐœ ์ผ์น˜, ๋ณด๋„ˆ์Šค ๋ณผ ์ผ์น˜ (30,000,000์›) - 0๊ฐœ", "6๊ฐœ ์ผ์น˜ (2,000,000,000์›) - 0๊ฐœ", "์ด ์ˆ˜์ต๋ฅ ์€ 62.5%์ž…๋‹ˆ๋‹ค." - ); + ); }, List.of(8, 21, 23, 41, 42, 43), List.of(3, 5, 11, 16, 32, 38), @@ -42,7 +42,7 @@ class ApplicationTest extends NsTest { List.of(7, 11, 30, 40, 42, 43), List.of(2, 13, 22, 32, 38, 45), List.of(1, 3, 5, 14, 22, 45) - ); + ); } @Test diff --git a/src/test/java/lotto/LottoTest.java b/src/test/java/lotto/LottoTest.java deleted file mode 100644 index 14ed50f..0000000 --- a/src/test/java/lotto/LottoTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package lotto; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -class LottoTest { - @DisplayName("๋กœ๋˜ ๋ฒˆํ˜ธ์˜ ๊ฐœ์ˆ˜๊ฐ€ 6๊ฐœ๊ฐ€ ๋„˜์–ด๊ฐ€๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") - @Test - void createLottoByOverSize() { - assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7))) - .isInstanceOf(IllegalArgumentException.class); - } - - @DisplayName("๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") - @Test - void createLottoByDuplicatedNumber() { - // TODO: ์ด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž‘์„ฑ - assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) - .isInstanceOf(IllegalArgumentException.class); - } - - // ์•„๋ž˜์— ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๊ฐ€๋Šฅ -} diff --git a/src/test/java/lotto/model/domain/LottoTest.java b/src/test/java/lotto/model/domain/LottoTest.java new file mode 100644 index 0000000..08304f4 --- /dev/null +++ b/src/test/java/lotto/model/domain/LottoTest.java @@ -0,0 +1,56 @@ +package lotto.model.domain; + +import static lotto.validation.ErrorMessage.LOTTO_HAS_DUPLICATED_NUMBER; +import static lotto.validation.ErrorMessage.LOTTO_NUMBER_OUT_OF_RANGE; +import static lotto.validation.ErrorMessage.LOTTO_SIZE_NOT_SIX; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LottoTest { + @DisplayName("๋กœ๋˜ ๋ฒˆํ˜ธ์˜ ๊ฐœ์ˆ˜๊ฐ€ 6๊ฐœ๊ฐ€ ๋„˜์–ด๊ฐ€๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void createLottoByOverSize() { + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_SIZE_NOT_SIX.getMessage()); + } + + @DisplayName("๋กœ๋˜ ๋ฒˆํ˜ธ์— ์ค‘๋ณต๋œ ์ˆซ์ž๊ฐ€ ์žˆ์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void createLottoByDuplicatedNumber() { + // TODO: ์ด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž‘์„ฑ + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_HAS_DUPLICATED_NUMBER.getMessage()); + } + + // ์•„๋ž˜์— ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๊ฐ€๋Šฅ + + @Test + void ๋กœ๋˜๋ฒˆํ˜ธ_์ •์ƒ() { + new Lotto(List.of(1, 2, 3, 4, 5, 6)); + } + + @Test + void ๋กœ๋˜๋ฒˆํ˜ธ_๋น„์ •์ƒ_๊ฐฏ์ˆ˜_5๊ฐœ_์ดํ•˜_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_SIZE_NOT_SIX.getMessage()); + } + + @Test + void ๋กœ๋˜๋ฒˆํ˜ธ_๋น„์ •์ƒ_๋กœ๋˜์ˆ˜_๋ฒ”์œ„๋ฐ–_์ˆซ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 46))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 0))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, -1))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + } +} diff --git a/src/test/java/lotto/model/domain/LottosTest.java b/src/test/java/lotto/model/domain/LottosTest.java new file mode 100644 index 0000000..55fece2 --- /dev/null +++ b/src/test/java/lotto/model/domain/LottosTest.java @@ -0,0 +1,76 @@ +package lotto.model.domain; + +import static lotto.validation.ErrorMessage.LOTTOS_COUNT_OUT_OF_RANGE_100; +import static lotto.validation.ErrorMessage.LOTTOS_SIZE_NOT_MATCH_COUNT; + +import java.util.ArrayList; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class LottosTest { + + private static final int TEST_RIGHT_COUNT = 2; + private static final int TEST_WRONG_COUNT = 101; + private static final List RIGHT_LOTTOS = new ArrayList<>(); + private static final List WRING_SIZE_LOTTOS = new ArrayList<>(); + + @BeforeAll + static void set() { + RIGHT_LOTTOS.add(new Lotto( + List.of(1, 2, 3, 4, 5, 6) + )); + RIGHT_LOTTOS.add(new Lotto( + List.of(6, 7, 8, 9, 10, 11) + )); + + WRING_SIZE_LOTTOS.add(new Lotto( + List.of(1, 2, 3, 4, 5, 6) + )); + WRING_SIZE_LOTTOS.add(new Lotto( + List.of(6, 7, 8, 9, 10, 11) + )); + WRING_SIZE_LOTTOS.add(new Lotto( + List.of(10, 11, 12, 13, 14, 15) + )); + } + + @AfterAll + static void clear() { + RIGHT_LOTTOS.clear(); + WRING_SIZE_LOTTOS.clear(); + } + + @Test + void Lottos์™€_count_์ •์ƒ() { + + new Lottos( + TEST_RIGHT_COUNT, + RIGHT_LOTTOS + ); + } + + @Test + void count_100_์ดˆ๊ณผ_์˜ˆ์™ธ๋ฐœ์ƒ() { + Assertions.assertThatThrownBy(() -> + new Lottos( + TEST_WRONG_COUNT, + RIGHT_LOTTOS + )) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTOS_COUNT_OUT_OF_RANGE_100.getMessage()); + } + + @Test + void count์™€_Lottos_ํฌ๊ธฐ_๋ถˆ์ผ์น˜_์˜ˆ์™ธ๋ฐœ์ƒ() { + Assertions.assertThatThrownBy(() -> + new Lottos( + TEST_RIGHT_COUNT, + WRING_SIZE_LOTTOS + )) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTOS_SIZE_NOT_MATCH_COUNT.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/model/domain/LottosWinningStatusTest.java b/src/test/java/lotto/model/domain/LottosWinningStatusTest.java new file mode 100644 index 0000000..050e84c --- /dev/null +++ b/src/test/java/lotto/model/domain/LottosWinningStatusTest.java @@ -0,0 +1,20 @@ +package lotto.model.domain; + +import static lotto.validation.ErrorMessage.WINNING_STATUS_PROFIT_RATIO_OVER_MAX; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; + +class LottosWinningStatusTest { + + private static final double MAX_PROFIT_RATIO_PLUS_ONE = + (double) (WinningType.MATCHES_SIX.getProfitMoney() + 1) / 1000; + + @Test + void ์ตœ๋Œ€์ˆ˜์ต๋ฅ ์˜_์ดˆ๊ณผ์ˆ˜์ต๋ฅ ์ด๋ฉด_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new LottosWinningStatus( + 1, 1, 1, 1, 1, MAX_PROFIT_RATIO_PLUS_ONE + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(WINNING_STATUS_PROFIT_RATIO_OVER_MAX.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/model/domain/WinningNumbersTest.java b/src/test/java/lotto/model/domain/WinningNumbersTest.java new file mode 100644 index 0000000..8fd61a3 --- /dev/null +++ b/src/test/java/lotto/model/domain/WinningNumbersTest.java @@ -0,0 +1,88 @@ +package lotto.model.domain; + +import static lotto.validation.ErrorMessage.BONUS_NUMBER_IS_DUPLICATED; +import static lotto.validation.ErrorMessage.BONUS_NUMBER_OUT_OF_RANGE; +import static lotto.validation.ErrorMessage.LOTTO_HAS_DUPLICATED_NUMBER; +import static lotto.validation.ErrorMessage.LOTTO_NUMBER_OUT_OF_RANGE; +import static lotto.validation.ErrorMessage.LOTTO_SIZE_NOT_SIX; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class WinningNumbersTest { + private static final List RIGHT_WINNINGNUMBERS = List.of(1, 2, 3, 4, 5, 6); + + @Test + void winningLotto_๋กœ๋˜๋ฒˆํ˜ธ_๊ฐœ์ˆ˜_6๊ฐœ๊ฐ€_์•„๋‹ˆ๋ฉด_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5, 6, 7), 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_SIZE_NOT_SIX.getMessage()); + + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5), 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_SIZE_NOT_SIX.getMessage()); + } + + @Test + void winningLotto_๋กœ๋˜๋ฒˆํ˜ธ_์ค‘๋ณต์ˆซ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5, 5), 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_HAS_DUPLICATED_NUMBER.getMessage()); + } + + @Test + void winningLotto_๋กœ๋˜๋ฒˆํ˜ธ_๋ฒ”์œ„๋ฐ–_์ˆซ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5, 46), 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5, 0), 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5, -1), 10)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + } + + @Test + void bonusNumber_winningLotto์™€_์ค‘๋ณต_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new WinningNumbers(RIGHT_WINNINGNUMBERS, 5)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BONUS_NUMBER_IS_DUPLICATED.getMessage()); + } + + @Test + void bonusNumber_๋กœ๋˜๋ฒˆํ˜ธ_๋ฒ”์œ„๋ฐ–_์ˆซ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> new WinningNumbers(RIGHT_WINNINGNUMBERS, 46)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BONUS_NUMBER_OUT_OF_RANGE.getMessage()); + + assertThatThrownBy(() -> new WinningNumbers(RIGHT_WINNINGNUMBERS, 0)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BONUS_NUMBER_OUT_OF_RANGE.getMessage()); + + assertThatThrownBy(() -> new WinningNumbers(RIGHT_WINNINGNUMBERS, -1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BONUS_NUMBER_OUT_OF_RANGE.getMessage()); + } + + @Test + void winningLotto_bonusNumber_๋ชจ๋‘์ •์ƒ() { + int rightBonusNumber = 10; + WinningNumbers winningNumbers = new WinningNumbers(RIGHT_WINNINGNUMBERS, rightBonusNumber); + + assertThat(winningNumbers.getWinningLotto().getNumbers()).isEqualTo(RIGHT_WINNINGNUMBERS); + assertThat(winningNumbers.getBonusNumber()).isEqualTo(rightBonusNumber); + } + + @Test + void winningLotto_๊ฒ€์ฆ์šฐ์„ _bonusNumber_ํ›„์ˆœ์œ„() { + assertThatThrownBy(() -> new WinningNumbers(List.of(1, 2, 3, 4, 5, 46), -1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_OUT_OF_RANGE.getMessage()); + } + +} \ No newline at end of file diff --git a/src/test/java/lotto/model/service/LottosGeneratorTest.java b/src/test/java/lotto/model/service/LottosGeneratorTest.java new file mode 100644 index 0000000..19fdf2f --- /dev/null +++ b/src/test/java/lotto/model/service/LottosGeneratorTest.java @@ -0,0 +1,24 @@ +package lotto.model.service; + +import lotto.model.domain.LottoUser; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class LottosGeneratorTest { + + private static LottoUser lottoUser; + private static final int USER_MONEY = 3000; + + @BeforeAll + static void setLottoUser() { + lottoUser = new LottoUser(USER_MONEY); + } + + @Test + void Lottos_์ •์ƒ_์ƒ์„ฑํ›„_์œ ์ €์—_์‚ฝ์ž…() { + LottosGenerator.generateLottosAndInput(lottoUser, USER_MONEY); + Assertions.assertThat(lottoUser.getLottos().getLottoBundle().size()) + .isEqualTo(lottoUser.getMoney() / 1000); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/model/service/LottosWinningCheckerTest.java b/src/test/java/lotto/model/service/LottosWinningCheckerTest.java new file mode 100644 index 0000000..4095211 --- /dev/null +++ b/src/test/java/lotto/model/service/LottosWinningCheckerTest.java @@ -0,0 +1,173 @@ +package lotto.model.service; + +import static lotto.model.domain.WinningType.MATCHES_FIVE; +import static lotto.model.domain.WinningType.MATCHES_FIVE_WITH_BONUS; +import static lotto.model.domain.WinningType.MATCHES_FOUR; +import static lotto.model.domain.WinningType.MATCHES_SIX; +import static lotto.model.domain.WinningType.MATCHES_THREE; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import lotto.model.domain.Lotto; +import lotto.model.domain.LottoUser; +import lotto.model.domain.Lottos; +import lotto.model.domain.LottosWinningStatus; +import lotto.model.domain.WinningNumbers; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class LottosWinningCheckerTest { + private static LottoUser lottoUser; + private static final int USER_MONEY = 5000; + + @BeforeAll + static void initData() { + List inputLottos = new ArrayList<>(); + addLotto(inputLottos, List.of(1, 2, 3, 4, 5, 6)); + addLotto(inputLottos, List.of(10, 11, 12, 13, 14, 15)); + addLotto(inputLottos, List.of(35, 36, 37, 38, 39, 40)); + addLotto(inputLottos, List.of(17, 18, 19, 20, 21, 22)); + addLotto(inputLottos, List.of(30, 31, 32, 33, 34, 35)); + lottoUser = new LottoUser( + new Lottos( + 5, + inputLottos + ), + USER_MONEY + ); + } + + private static void addLotto(List inputLottos, List lottoNumbers) { + inputLottos.add( + new Lotto(lottoNumbers) + ); + } + + + /** + * ๊ฐ_๋‹น์ฒจ_ํƒ€์ž…์—_๋งž๋Š”_๊ฐ’_์ •์ƒ๋ˆ„์ _ํ™•์ธ + */ + @Test + void ์ •์ƒ_3๊ฐœ์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(4, 5, 6, 10, 11, 12); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker(inputWinningLottoNumbers, + bonusNumber); + + assertThat(lottosWinningStatus.getMatchesThree()).isEqualTo(2); + } + + + @Test + void ์ •์ƒ_4๊ฐœ์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(4, 5, 10, 11, 12, 13); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getMatchesFour()).isEqualTo(1); + } + + @Test + void ์ •์ƒ_5๊ฐœ์ผ์น˜_๋ณด๋„ˆ์Šค_๋ถˆ์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(5, 10, 11, 12, 13, 14); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getMatchesFive()).isEqualTo(1); + } + + @Test + void ์ •์ƒ_5๊ฐœ์ผ์น˜_๋ณด๋„ˆ์Šค๋„_์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(5, 10, 11, 12, 13, 14); + int bonusNumber = 15; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getMatchesFiveWithBonus()).isEqualTo(1); + } + + @Test + void ์ •์ƒ_6๊ฐœ์ผ์น˜_์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(10, 11, 12, 13, 14, 15); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getMatchesSix()).isEqualTo(1); + } + + /** + * ๊ฐํƒ€์ž…_์ˆ˜์ต๋ฅ _์ •์ƒ๊ณ„์‚ฐ + */ + @Test + void ์ˆ˜์ต๋ฅ _์ •์ƒ_3๊ฐœ์ผ์น˜_๊ณ„์‚ฐ() { + List inputWinningLottoNumbers = List.of(4, 5, 6, 10, 11, 12); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker(inputWinningLottoNumbers, + bonusNumber); + + assertThat(lottosWinningStatus.getProfitRatio()).isEqualTo( + (double) lottosWinningStatus.getMatchesThree() * MATCHES_THREE.getProfitMoney() * 100 / USER_MONEY); + } + + @Test + void ์ˆ˜์ต๋ฅ _์ •์ƒ_4๊ฐœ์ผ์น˜_๊ณ„์‚ฐ() { + List inputWinningLottoNumbers = List.of(1, 2, 3, 4, 41, 42); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getProfitRatio()).isEqualTo( + (double) lottosWinningStatus.getMatchesFour() * MATCHES_FOUR.getProfitMoney() * 100 / USER_MONEY); + } + + @Test + void ์ˆ˜์ต๋ฅ _์ •์ƒ_5๊ฐœ์ผ์น˜_๋ณด๋„ˆ์Šค_๋ถˆ์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(5, 10, 11, 12, 13, 14); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getProfitRatio()).isEqualTo( + (double) lottosWinningStatus.getMatchesFive() * MATCHES_FIVE.getProfitMoney() * 100 / USER_MONEY); + } + + @Test + void ์ˆ˜์ต๋ฅ _์ •์ƒ_5๊ฐœ์ผ์น˜_๋ณด๋„ˆ์Šค๋„_์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(5, 10, 11, 12, 13, 14); + int bonusNumber = 15; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getProfitRatio()).isEqualTo( + (double) lottosWinningStatus.getMatchesFiveWithBonus() * + MATCHES_FIVE_WITH_BONUS.getProfitMoney() * 100 / USER_MONEY); + } + + @Test + void ์ˆ˜์ต๋ฅ _์ •์ƒ_6๊ฐœ์ผ์น˜_์ผ์น˜_ํ™•์ธ() { + List inputWinningLottoNumbers = List.of(10, 11, 12, 13, 14, 15); + int bonusNumber = 45; + LottosWinningStatus lottosWinningStatus = getLottosWinningStatusAfterWinningChecker( + inputWinningLottoNumbers, bonusNumber); + + assertThat(lottosWinningStatus.getProfitRatio()).isEqualTo( + (double) lottosWinningStatus.getMatchesSix() * MATCHES_SIX.getProfitMoney() * 100 / USER_MONEY); + } + + private static LottosWinningStatus getLottosWinningStatusAfterWinningChecker(List inputWinningLottoNumbers, + int bonusNumber) { + WinningNumbers winningNumbers = new WinningNumbers( + inputWinningLottoNumbers, + bonusNumber + ); + LottosWinningChecker.generateWinningStatusAndInput(lottoUser, + winningNumbers); + + return lottoUser.getLottosWinningStatus(); + } + +} \ No newline at end of file diff --git a/src/test/java/lotto/view/InputViewTest.java b/src/test/java/lotto/view/InputViewTest.java new file mode 100644 index 0000000..917d9ee --- /dev/null +++ b/src/test/java/lotto/view/InputViewTest.java @@ -0,0 +1,103 @@ +package lotto.view; + +import static lotto.validation.ErrorMessage.MONEY_FOR_PURCHASE_NOT_NUMBER; +import static lotto.validation.ErrorMessage.WINNINGNUMBERS_NOT_DOUBLE_COMMA; +import static lotto.validation.ErrorMessage.WINNINGNUMBERS_NOT_END_WITH_COMMA; +import static lotto.validation.ErrorMessage.WINNINGNUMBERS_NOT_START_WITH_COMMA; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; + +class InputViewTest { + + @Test + void ๊ตฌ์ž…๊ธˆ์•ก_์ •์ƒ_์ž…๋ ฅ() { + String input = "1000"; + setInput(input); + int money = InputView.moneyForPurchaseInput(); + assertThat(input).isEqualTo(String.valueOf(money)); + } + + @Test + void ๊ตฌ์ž…๊ธˆ์•ก_๋น„์ •์ƒ_์ž…๋ ฅ_๋ฌธ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + String input = "english"; + setInput(input); + assertThatThrownBy(() -> InputView.moneyForPurchaseInput()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(MONEY_FOR_PURCHASE_NOT_NUMBER.getMessage()); + } + + @Test + void ๋‹น์ฒจ๋ฒˆํ˜ธ_์ •์ƒ_์ž…๋ ฅ() { + String input = "1,2,3,4,5,6"; + List rightWinningNumbers = Arrays.asList(1, 2, 3, 4, 5, 6); + setInput(input); + assertThat(rightWinningNumbers).isEqualTo(InputView.winningNumbersInput()); + } + + @Test + void ๋‹น์ฒจ๋ฒˆํ˜ธ_๋น„์ •์ƒ_์ž…๋ ฅ_๋ฌธ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + String input = "1,a,3,4,5,6"; + setInput(input); + assertThatThrownBy(() -> InputView.winningNumbersInput()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(MONEY_FOR_PURCHASE_NOT_NUMBER.getMessage()); + } + + @Test + void ๋‹น์ฒจ๋ฒˆํ˜ธ_๋น„์ •์ƒ_์ž…๋ ฅ_์‰ผํ‘œ์ค‘๋ณต_์˜ˆ์™ธ๋ฐœ์ƒ() { + String input = "1,,3,4,5,6"; + setInput(input); + assertThatThrownBy(() -> InputView.winningNumbersInput()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(WINNINGNUMBERS_NOT_DOUBLE_COMMA.getMessage()); + } + + @Test + void ๋‹น์ฒจ๋ฒˆํ˜ธ_๋น„์ •์ƒ_์ž…๋ ฅ_์ฒ˜์Œ_๋˜๋Š”_๋์—_์‰ผํ‘œ_์˜ˆ์™ธ๋ฐœ์ƒ() { + String input = ",3,4,5,6"; + setInput(input); + assertThatThrownBy(() -> InputView.winningNumbersInput()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(WINNINGNUMBERS_NOT_START_WITH_COMMA.getMessage()); + + input = "3,4,5,6,"; + setInput(input); + assertThatThrownBy(() -> InputView.winningNumbersInput()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(WINNINGNUMBERS_NOT_END_WITH_COMMA.getMessage()); + } + + @Test + void ๋ณด๋„ˆ์Šค๋ฒˆํ˜ธ_์ •์ƒ_์ž…๋ ฅ() { + String input = "3"; + setInput(input); + int money = InputView.bonusNumberInput(); + assertThat(input).isEqualTo(String.valueOf(money)); + } + + @Test + void ๋ณด๋„ˆ์Šค๋ฒˆํ˜ธ_๋น„์ •์ƒ_์ž…๋ ฅ_๋ฌธ์ž_์˜ˆ์™ธ๋ฐœ์ƒ() { + String input = "e"; + setInput(input); + assertThatThrownBy(() -> InputView.bonusNumberInput()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(MONEY_FOR_PURCHASE_NOT_NUMBER.getMessage()); + + } + + private static void setInput(String input) { + OutputStream out = new ByteArrayOutputStream(); + System.setOut(new PrintStream(out)); + InputStream in = new ByteArrayInputStream(input.getBytes()); + System.setIn(in); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/view/OutputViewTest.java b/src/test/java/lotto/view/OutputViewTest.java new file mode 100644 index 0000000..2a0bebc --- /dev/null +++ b/src/test/java/lotto/view/OutputViewTest.java @@ -0,0 +1,107 @@ +package lotto.view; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import lotto.model.domain.LottosWinningStatus; +import lotto.validation.ErrorMessage; +import org.junit.jupiter.api.Test; + +class OutputViewTest { + @Test + void ๋‹น์ฒจํ†ต๊ณ„_์ •์ƒ_์ถœ๋ ฅ_๊ฐฏ์ˆ˜_0์ด์ƒ_์ •์ƒ() { + OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, 1, 1, 1, 300.1222 + ) + ); + } + + @Test + void ๋‹น์ฒจํ†ต๊ณ„_์ •์ƒ_์ถœ๋ ฅ_๊ฐฏ์ˆ˜_์Œ์ˆ˜๋ฉด_์˜ˆ์™ธ๋ฐœ์ƒ() { + assertThatThrownBy(() -> OutputView.winningStatusMessage( + new LottosWinningStatus( + -1, 1, 1, 1, 1, 300.1222 + ) + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + + assertThatThrownBy(() -> OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, -1, 1, 1, 1, 300.1222 + ) + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + + assertThatThrownBy(() -> OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, -1, 1, 1, 300.1222 + ) + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + + assertThatThrownBy(() -> OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, 1, -1, 1, 300.1222 + ) + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + + assertThatThrownBy(() -> OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, 1, 1, -1, 300.1222 + ) + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + + assertThatThrownBy(() -> OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, 1, 1, 1, -300.1222 + ) + )).isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.OUTPUT_VIEW_WINNING_STATUS_NUMBER_MINUS.getMessage()); + + } + + @Test + void ์ˆ˜์ต๋ฅ _๋ฐ˜์˜ฌ๋ฆผ_์ •์ƒ_ํ™•์ธ() { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream originalOut = System.out; + System.setOut(new PrintStream(outputStream)); + + OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, 1, 1, 1, 300.1222 + ) + ); + + String printedOutput = outputStream.toString().trim(); + + System.setOut(originalOut); + + assertThat(printedOutput).contains("300.1%"); + } + + @Test + void ์ˆ˜์ต๋ฅ _๋ฐ˜์˜ฌ๋ฆผ_์ •์ƒ_ํ™•์ธ2() { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream originalOut = System.out; + System.setOut(new PrintStream(outputStream)); + + OutputView.winningStatusMessage( + new LottosWinningStatus( + 1, 1, 1, 1, 1, 300.1722 + ) + ); + + String printedOutput = outputStream.toString().trim(); + + System.setOut(originalOut); + + assertThat(printedOutput).contains("300.2%"); + } + + +} \ No newline at end of file