diff --git a/README.md b/README.md index 32b2a7679a0..6ae266af7a2 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ [x] 로또들을 구매하는 Lottery.buy [x] 로또를 구매하는 buyLottery [x] 당첨 로또 번호를 입력받는 InputView +[x] 보너스 볼을 입력받는 InputView [x] 당첨 통계를 출력하는 OutputView + [x] 맞춘 개수별로 당첨금액 정보를 저장해 놓는 WinPrizes [x] n개 일치하는 로또의 수를 계산해주는 countWinLottery [x] 수익률 계산해주는 calculateRateOfReturn diff --git a/src/main/java/lottery/Main.java b/src/main/java/lottery/Main.java index e47530f1f6f..1c4088ff37f 100644 --- a/src/main/java/lottery/Main.java +++ b/src/main/java/lottery/Main.java @@ -9,6 +9,7 @@ public class Main { private static final PriceInputView priceInputView = new PriceInputView(); private static final NumberOfLotteryOutputView numberOfLotteryOutputView = new NumberOfLotteryOutputView(); private static final WinLotteryInputView winLotteryInputView = new WinLotteryInputView(); + private static final InputView bonusBallInputView = new BonusBallInputView(); private static final LotteryResultOutputView lotteryResultOutputView = new LotteryResultOutputView(); public static void main(String[] args) { @@ -16,7 +17,7 @@ public static void main(String[] args) { LotteryStrategy lotteryStrategy = new RandomLotteryStrategy(); List lotteries = Lotteries.buy(price, lotteryStrategy); numberOfLotteryOutputView.print(lotteries); - Lottery winLottery = winLotteryInputView.receive(); + WinLottery winLottery = new WinLottery(winLotteryInputView.receive(), bonusBallInputView.receive()); LotteryResult lotteryResult = Lotteries.calculateResult(lotteries, winLottery); lotteryResultOutputView.print(lotteryResult); } diff --git a/src/main/java/lottery/domain/BonusBall.java b/src/main/java/lottery/domain/BonusBall.java new file mode 100644 index 00000000000..41f2425a47b --- /dev/null +++ b/src/main/java/lottery/domain/BonusBall.java @@ -0,0 +1,13 @@ +package lottery.domain; + +public class BonusBall { + private final LotteryNumber value; + + public BonusBall(LotteryNumber value) { + this.value = value; + } + + public LotteryNumber value() { + return value; + } +} diff --git a/src/main/java/lottery/domain/Lotteries.java b/src/main/java/lottery/domain/Lotteries.java index 96e63b6ffb6..97bc661c606 100644 --- a/src/main/java/lottery/domain/Lotteries.java +++ b/src/main/java/lottery/domain/Lotteries.java @@ -1,10 +1,17 @@ package lottery.domain; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class Lotteries { + public static final Integer BONUS_BALL_CHANCE_NUMBER = 5; + public static final Integer BONUS_BALL_CHANCE_NUMBER_RANK = 6; + public static final Integer RANK_LENGTH = 8; + public static final List matchNumberToRank = Arrays.asList(0, 1, 2, 3, 4, 5, 7); + public static List buy(Integer price, LotteryStrategy lotteryStrategy) { int number = calculateNumberOfLottery(price); List lotteries = new ArrayList<>(); @@ -18,19 +25,36 @@ private static int calculateNumberOfLottery(Integer price) { return price / LotteryPrice.VALUE; } - public static LotteryResult calculateResult(List lotteries, Lottery winLottery) { + public static LotteryResult calculateResult(List lotteries, WinLottery winLottery) { List numberOfMatchNumbers = lotteries.stream().map((lottery) -> calculateMatchCount(lottery, winLottery)).collect(Collectors.toList()); + List hasBonusBalls = lotteries.stream().map((lottery) -> calculateHasBonusBall(lottery, winLottery)).collect(Collectors.toList()); List winLotteryNumbers = new ArrayList<>(); - for (int i = 0; i <= Lottery.LENGTH; i++) { + for (int i = 0; i < RANK_LENGTH; i++) { winLotteryNumbers.add(0); } - for (int number : numberOfMatchNumbers) { - winLotteryNumbers.set(number, winLotteryNumbers.get(number) + 1); + for (int i = 0; i < numberOfMatchNumbers.size(); i++) { + checkBonusBallAndAdd(hasBonusBalls.get(i), numberOfMatchNumbers.get(i), winLotteryNumbers); } return new LotteryResult(winLotteryNumbers, lotteries.size()); } - private static int calculateMatchCount(Lottery lottery, Lottery winLottery) { + private static void checkBonusBallAndAdd(Boolean hasBonusBall, int number, List winLotteryNumbers) { + if (hasBonusBall && number == BONUS_BALL_CHANCE_NUMBER) { + winLotteryNumbers.set(BONUS_BALL_CHANCE_NUMBER_RANK, winLotteryNumbers.get(BONUS_BALL_CHANCE_NUMBER_RANK) + 1); + return; + } + winLotteryNumbers.set(matchNumberToRank.get(number), winLotteryNumbers.get(matchNumberToRank.get(number)) + 1); + } + + private static Boolean calculateHasBonusBall(Lottery lottery, WinLottery winLottery) { + List lotteryNumbers = lottery.numbers(); + LotteryNumber bonusBallValue = winLottery.bonusBall().value(); + + return lotteryNumbers.contains(bonusBallValue); + } + + + private static int calculateMatchCount(Lottery lottery, WinLottery winLottery) { List lotteryNumbers = lottery.numbers(); List winLotteryNumbers = winLottery.numbers(); diff --git a/src/main/java/lottery/domain/WinLottery.java b/src/main/java/lottery/domain/WinLottery.java new file mode 100644 index 00000000000..171ea5a03ec --- /dev/null +++ b/src/main/java/lottery/domain/WinLottery.java @@ -0,0 +1,21 @@ +package lottery.domain; + +import java.util.List; + +public class WinLottery { + private final Lottery lottery; + private final BonusBall bonusBall; + + public WinLottery(Lottery lottery, BonusBall bonusBall) { + this.lottery = lottery; + this.bonusBall = bonusBall; + } + + public List numbers() { + return lottery.numbers(); + } + + public BonusBall bonusBall() { + return bonusBall; + } +} diff --git a/src/main/java/lottery/domain/WinPrize.java b/src/main/java/lottery/domain/WinPrize.java index e9a2e261f76..a433e250f4f 100644 --- a/src/main/java/lottery/domain/WinPrize.java +++ b/src/main/java/lottery/domain/WinPrize.java @@ -2,9 +2,10 @@ public enum WinPrize { FIRST_PLACE(2000000000), - SECOND_PLACE(1500000), - THIRD_PLACE(50000), - FOURTH_PLACE(5000), + SECOND_PLACE(30000000), + THIRD_PLACE(1500000), + FOURTH_PLACE(50000), + FIFTH_PLACE(5000), LOST(0); diff --git a/src/main/java/lottery/view/BonusBallInputView.java b/src/main/java/lottery/view/BonusBallInputView.java new file mode 100644 index 00000000000..dc65f39db98 --- /dev/null +++ b/src/main/java/lottery/view/BonusBallInputView.java @@ -0,0 +1,16 @@ +package lottery.view; + +import lottery.domain.BonusBall; +import lottery.domain.Lottery; +import lottery.domain.LotteryNumber; + +import java.util.Scanner; + +public class BonusBallInputView implements InputView { + Scanner scanner = new Scanner(System.in); + @Override + public BonusBall receive() { + System.out.println("보너스 볼을 입력해 주세요."); + return new BonusBall(new LotteryNumber(scanner.nextInt())); + } +} diff --git a/src/main/java/lottery/view/LotteryResultOutputView.java b/src/main/java/lottery/view/LotteryResultOutputView.java index 56556522e7f..53ecb3e7285 100644 --- a/src/main/java/lottery/view/LotteryResultOutputView.java +++ b/src/main/java/lottery/view/LotteryResultOutputView.java @@ -1,22 +1,42 @@ package lottery.view; +import jdk.nashorn.api.scripting.ScriptObjectMirror; import lottery.domain.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class LotteryResultOutputView implements OutputView { - private final List winPrizes = Arrays.asList(WinPrize.LOST.value(), WinPrize.LOST.value(), WinPrize.LOST.value(), WinPrize.FOURTH_PLACE.value(), WinPrize.THIRD_PLACE.value(), WinPrize.SECOND_PLACE.value(), WinPrize.FIRST_PLACE.value()); + private final List winPrizes = Arrays.asList(WinPrize.LOST.value(), WinPrize.LOST.value(), WinPrize.LOST.value(), WinPrize.FIFTH_PLACE.value(), WinPrize.FOURTH_PLACE.value(), WinPrize.THIRD_PLACE.value(), WinPrize.SECOND_PLACE.value(), WinPrize.FIRST_PLACE.value()); + private final List rankToMatchNumber; + + public LotteryResultOutputView() { + rankToMatchNumber = new ArrayList<>(); + for (int i = 0; i <= Lotteries.RANK_LENGTH; i++) { + rankToMatchNumber.add(0); + } + for (int i = 0; i < Lotteries.matchNumberToRank.size(); i++) { + rankToMatchNumber.set(Lotteries.matchNumberToRank.get(i), i); + } + } @Override public void print(LotteryResult output) { final int MIN_WIN_NUMBER = 3; List winNumbers = output.winNumbers(); int totalPrize = 0; - for (int i = MIN_WIN_NUMBER; i <= Lottery.LENGTH; i++) { + for (int i = MIN_WIN_NUMBER; i < Lotteries.RANK_LENGTH; i++) { totalPrize += winNumbers.get(i) * winPrizes.get(i); - System.out.printf("%d개 일치 (%d원)- %d개\n", i, winPrizes.get(i), winNumbers.get(i)); + System.out.printf("%s (%d원)- %d개\n", rankToDetail(i), winPrizes.get(i), winNumbers.get(i)); } System.out.printf("총 수익률은 %.2f입니다", (float) totalPrize / (output.numberOfLottery() * LotteryPrice.VALUE)); } + + private String rankToDetail(int i) { + if (i == Lotteries.BONUS_BALL_CHANCE_NUMBER_RANK) { + return String.format("%d개 일치, 보너스 볼 일치", Lotteries.BONUS_BALL_CHANCE_NUMBER); + } + return String.format("%d개 일치", rankToMatchNumber.get(i)); + } } diff --git a/src/test/java/lottery/domain/LotteriesTest.java b/src/test/java/lottery/domain/LotteriesTest.java index 9c44db23a18..639e4a5ac08 100644 --- a/src/test/java/lottery/domain/LotteriesTest.java +++ b/src/test/java/lottery/domain/LotteriesTest.java @@ -1,6 +1,7 @@ package lottery.domain; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -15,6 +16,8 @@ class LotteriesTest { LotteryStrategy defaultLotteryStrategy; List defaultLotteryNumbers; Lottery defaultLottery; + BonusBall defaultBonusBall; + WinLottery defaultWinLottery; List defaultLotteries; @BeforeEach @@ -22,6 +25,8 @@ void setUp() { defaultLotteryStrategy = new TestLotteryStrategy(); defaultLotteryNumbers = Arrays.asList(new LotteryNumber(1), new LotteryNumber(2), new LotteryNumber(3), new LotteryNumber(4), new LotteryNumber(5), new LotteryNumber(6)); defaultLottery = Lottery.createLottery(defaultLotteryNumbers); + defaultBonusBall = new BonusBall(new LotteryNumber(7)); + defaultWinLottery = new WinLottery(defaultLottery, defaultBonusBall); defaultLotteries = new ArrayList<>(); for (int i = 0; i < defaultNumberOfLottery; i++) { defaultLotteries.add(defaultLottery); @@ -29,13 +34,26 @@ void setUp() { } @Test + @DisplayName("로또를 기본로또전략으로 샀을 때 기본로또들 값이랑 같아야한다") void buy() { assertEquals(defaultLotteries, Lotteries.buy(defaultPrice, defaultLotteryStrategy)); } @Test + @DisplayName("기본로또들, 기본승리로또를 바탕으로 계산된 결과는 1등개수가 기본개수와 같고 일치하는 보너스볼이 없어야 한다") void calculateResult() { - LotteryResult lotteryResult = new LotteryResult(Arrays.asList(0, 0, 0, 0, 0, 0, defaultNumberOfLottery), defaultNumberOfLottery); - assertEquals(lotteryResult, Lotteries.calculateResult(defaultLotteries, defaultLottery)); + LotteryResult lotteryResult = new LotteryResult(Arrays.asList(0, 0, 0, 0, 0, 0, 0, defaultNumberOfLottery), defaultNumberOfLottery); + assertEquals(lotteryResult, Lotteries.calculateResult(defaultLotteries, defaultWinLottery)); + + } + + @Test + @DisplayName("보너스볼이 있을 때 2등의 결과는 보너스볼에 따라 달라진다") + void calculateResultWithBonusBall() { + defaultBonusBall = new BonusBall(new LotteryNumber(6)); + List winLotteryNumbersWithBonusBall = Arrays.asList(new LotteryNumber(1), new LotteryNumber(2), new LotteryNumber(3), new LotteryNumber(4), new LotteryNumber(5), new LotteryNumber(7)); + WinLottery winLotteryWithBonusBall = new WinLottery(Lottery.createLottery(winLotteryNumbersWithBonusBall), defaultBonusBall); + LotteryResult lotteryResult = new LotteryResult(Arrays.asList(0, 0, 0, 0, 0, 0, defaultNumberOfLottery, 0), defaultNumberOfLottery); + assertEquals(lotteryResult, Lotteries.calculateResult(defaultLotteries, winLotteryWithBonusBall)); } } diff --git a/src/test/java/lottery/domain/LotteryResultTest.java b/src/test/java/lottery/domain/LotteryResultTest.java index 053ea442bec..faed99ef7f3 100644 --- a/src/test/java/lottery/domain/LotteryResultTest.java +++ b/src/test/java/lottery/domain/LotteryResultTest.java @@ -1,6 +1,7 @@ package lottery.domain; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -12,19 +13,22 @@ class LotteryResultTest { Integer defaultNumberOfLottery = 1; List defaultWinNumbers; LotteryResult defaultLotteryResult; + boolean defaultHasBonusBall = false; @BeforeEach void setUp() { - defaultWinNumbers = Arrays.asList(6, 5, 4, 3, 2, 1); + defaultWinNumbers = Arrays.asList(7, 6, 5, 4, 3, 2, 1); defaultLotteryResult = new LotteryResult(defaultWinNumbers, defaultNumberOfLottery); } @Test + @DisplayName("등수정보, 확인한 로또수 결과가 같으면 논리적으로 같은 객체다") void testEquals() { assertEquals(defaultLotteryResult, new LotteryResult(defaultWinNumbers, defaultNumberOfLottery)); } @Test + @DisplayName("문자열로 변환할 때 등수정보를 보여준다") void testToString() { assertEquals(defaultLotteryResult.toString(), defaultWinNumbers.toString()); }