diff --git a/src/main/java/LottoApplication.java b/src/main/java/LottoApplication.java index 8aa16b7..fd5b91f 100644 --- a/src/main/java/LottoApplication.java +++ b/src/main/java/LottoApplication.java @@ -1,11 +1,15 @@ import domain.lotto.Lotto; import domain.lotto.LottoCollection; +import domain.lotto.LottoNumber; +import domain.lotto.WinningLotto; import domain.money.Money; import domain.provider.LottoSeller; import input.InputView; import output.OutputView; import domain.LottoStatistics; +import java.util.Scanner; + /** * @author delf */ @@ -15,11 +19,14 @@ public static void main(String[] args) { LottoSeller lottoSeller = new LottoSeller(lottoPrice); Money money = InputView.inputMoney(); - LottoCollection myLotto = lottoSeller.sellTo(money); + + int manualCount = InputView.getManualCount(); + + LottoCollection myLotto = lottoSeller.sellTo(money, manualCount); OutputView.printLotto(myLotto); - Lotto winningLotto = InputView.inputWinningLottoNumber(); + WinningLotto winningLotto = InputView.inputWinningLottoNumber(); LottoStatistics lottoStatistics = new LottoStatistics(winningLotto, myLotto, money); OutputView.showWinningStatistics(lottoStatistics); diff --git a/src/main/java/domain/LottoStatistics.java b/src/main/java/domain/LottoStatistics.java index c10deb7..2fe7744 100644 --- a/src/main/java/domain/LottoStatistics.java +++ b/src/main/java/domain/LottoStatistics.java @@ -2,6 +2,7 @@ import domain.lotto.Lotto; import domain.lotto.LottoCollection; +import domain.lotto.WinningLotto; import domain.money.Money; import java.util.Iterator; @@ -14,7 +15,7 @@ public class LottoStatistics implements Iterable { private Map counter; private Money invest; - public LottoStatistics(Lotto winningLotto, LottoCollection lottoCollection, Money money) { + public LottoStatistics(WinningLotto winningLotto, LottoCollection lottoCollection, Money money) { this.counter = getCounter(winningLotto, lottoCollection); this.invest = money; } @@ -25,13 +26,10 @@ public float getRor() { sum += rank.getProfit(counter.get(rank)); } - System.out.println(invest.getAmount()); return (float) sum / invest.getAmount(); } - private final static Rank[] PRINT_ORDER_RANK = {Rank.FIFTH, Rank.FOURTH, Rank.THIRD, /*Rank.SECOND, */Rank.FIRST}; - - private Map getCounter(Lotto winningLotto, LottoCollection lottoCollection) { + private Map getCounter(WinningLotto winningLotto, LottoCollection lottoCollection) { Map counter = Rank.RANK_COUNTER(); for (Lotto lotto : lottoCollection) { counter.merge(winningLotto.match(lotto), 1, Integer::sum); diff --git a/src/main/java/domain/Rank.java b/src/main/java/domain/Rank.java index bac8cac..bc41986 100644 --- a/src/main/java/domain/Rank.java +++ b/src/main/java/domain/Rank.java @@ -25,12 +25,12 @@ public enum Rank { this.winningMoney = winningMoney; } - public static Rank valueOf(int countOfMatch) { + public static Rank valueOf(int countOfMatch, boolean matchBonus) { if (countOfMatch < WINNING_MIN_COUNT) { return MISS; } - if (SECOND.matchCount(countOfMatch)) { + if (SECOND.matchCount(countOfMatch) && matchBonus) { return SECOND; } @@ -61,6 +61,10 @@ public static Map RANK_COUNTER() { @Override public String toString() { - return String.format("%d개 일치 (%,d원)", countOfMatch, winningMoney); + String note = ""; + if (this == Rank.SECOND) { + note = ", 보너스볼 일치"; + } + return String.format("%d개 일치%s (%,d원)", countOfMatch, note, winningMoney); } } diff --git a/src/main/java/domain/lotto/Lotto.java b/src/main/java/domain/lotto/Lotto.java index e48af70..e1a761d 100644 --- a/src/main/java/domain/lotto/Lotto.java +++ b/src/main/java/domain/lotto/Lotto.java @@ -7,30 +7,22 @@ */ public class Lotto { - private static final int PICK_NUM = 6; + public static final int PICK_NUM = 6; private List lotto; public Lotto(List lotto) { + // 중복 체크 if (lotto.size() < PICK_NUM) { throw new IllegalArgumentException(); } this.lotto = lotto; } - public Rank match(Lotto userLotto) { - int matchCount = getMatchCount(userLotto); - return Rank.valueOf(matchCount); + public int getMatchCount(Lotto userLotto) { + return (int) lotto.stream().filter(userLotto::contains).count(); } - private int getMatchCount(Lotto userLotto) { - int count = 0; - for (LottoNumber n : this.lotto) { - count += userLotto.contains(n) ? 1 : 0; - } - return count; - } - - private boolean contains(LottoNumber n) { + public boolean contains(LottoNumber n) { return lotto.contains(n); } @@ -38,5 +30,4 @@ private boolean contains(LottoNumber n) { public String toString() { return lotto.toString(); } - } diff --git a/src/main/java/domain/lotto/LottoCollection.java b/src/main/java/domain/lotto/LottoCollection.java index fb02fed..af4a854 100644 --- a/src/main/java/domain/lotto/LottoCollection.java +++ b/src/main/java/domain/lotto/LottoCollection.java @@ -1,5 +1,7 @@ package domain.lotto; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -9,6 +11,10 @@ public class LottoCollection implements Iterable { private List lottoList; + public LottoCollection() { + lottoList = new ArrayList<>(); + } + public LottoCollection(List lottoList) { if(lottoList.isEmpty()) { throw new IllegalArgumentException(); @@ -16,6 +22,10 @@ public LottoCollection(List lottoList) { this.lottoList = lottoList; } + public void addAll(LottoCollection lottoCollection) { + lottoList.addAll(lottoCollection.getLottoList()); + } + @Override public Iterator iterator() { return lottoList.iterator(); @@ -24,4 +34,8 @@ public Iterator iterator() { public int size() { return lottoList.size(); } + + private List getLottoList() { + return lottoList; + } } diff --git a/src/main/java/domain/lotto/WinningLotto.java b/src/main/java/domain/lotto/WinningLotto.java new file mode 100644 index 0000000..77626b2 --- /dev/null +++ b/src/main/java/domain/lotto/WinningLotto.java @@ -0,0 +1,24 @@ +package domain.lotto; + +import domain.Rank; + +public class WinningLotto { + private Lotto lotto; + private LottoNumber bonusNumber; + + public WinningLotto(Lotto lotto, LottoNumber bonusNumber) { + this.lotto = lotto; + this.bonusNumber = bonusNumber; + } + + public Rank match(Lotto userLotto) { + int matchCount = lotto.getMatchCount(userLotto); + boolean matchBonus = userLotto.contains(bonusNumber); + return Rank.valueOf(matchCount, matchBonus); + } + + @Override + public String toString() { + return String.format("%s + %s", lotto , bonusNumber); + } +} diff --git a/src/main/java/domain/lotto/streragy/LottoAutoGenerateStrategy.java b/src/main/java/domain/lotto/streragy/LottoAutoGenerateStrategy.java new file mode 100644 index 0000000..bcbd776 --- /dev/null +++ b/src/main/java/domain/lotto/streragy/LottoAutoGenerateStrategy.java @@ -0,0 +1,23 @@ +package domain.lotto.streragy; + +import domain.lotto.Lotto; +import domain.lotto.LottoNumber; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * @author delf + */ +public class LottoAutoGenerateStrategy implements LottoGenerateStrategy { + + private static List lottoNumberList = IntStream.rangeClosed(LottoNumber.MIN, LottoNumber.MAX).boxed().collect(Collectors.toList()); + + @Override + public Lotto generateLotto() { + Collections.shuffle(lottoNumberList); + return new Lotto(lottoNumberList.stream().limit(Lotto.PICK_NUM).map(LottoNumber::of).collect(Collectors.toList())); + } +} diff --git a/src/main/java/domain/lotto/streragy/LottoGenerateStrategy.java b/src/main/java/domain/lotto/streragy/LottoGenerateStrategy.java new file mode 100644 index 0000000..3155b6f --- /dev/null +++ b/src/main/java/domain/lotto/streragy/LottoGenerateStrategy.java @@ -0,0 +1,10 @@ +package domain.lotto.streragy; + +import domain.lotto.Lotto; + +/** + * @author delf + */ +public interface LottoGenerateStrategy { + Lotto generateLotto(); +} diff --git a/src/main/java/domain/lotto/streragy/LottoManualGenerateStrategy.java b/src/main/java/domain/lotto/streragy/LottoManualGenerateStrategy.java new file mode 100644 index 0000000..a386ac3 --- /dev/null +++ b/src/main/java/domain/lotto/streragy/LottoManualGenerateStrategy.java @@ -0,0 +1,32 @@ +package domain.lotto.streragy; + +import domain.lotto.Lotto; +import domain.lotto.LottoNumber; +import input.ConsoleInput; +import input.Inputtable; + +import java.util.Arrays; + +import static java.util.stream.Collectors.toList; + +/** + * @author delf + */ +public class LottoManualGenerateStrategy implements LottoGenerateStrategy{ + + private Inputtable inputInterface; + + public LottoManualGenerateStrategy(Inputtable inputInterface) { + this.inputInterface = inputInterface; + } + + @Override + public Lotto generateLotto() { + String inputValue = inputInterface.getStringValue(); + // 중복체크 + return new Lotto(Arrays.stream(inputValue.trim().split(",")) + .map(Integer::parseInt) + .map(LottoNumber::of) + .collect(toList())); + } +} diff --git a/src/main/java/domain/provider/LottoSeller.java b/src/main/java/domain/provider/LottoSeller.java index 0b0a9c8..6455e3e 100644 --- a/src/main/java/domain/provider/LottoSeller.java +++ b/src/main/java/domain/provider/LottoSeller.java @@ -2,7 +2,11 @@ import domain.lotto.Lotto; import domain.lotto.LottoCollection; +import domain.lotto.streragy.LottoAutoGenerateStrategy; +import domain.lotto.streragy.LottoGenerateStrategy; +import domain.lotto.streragy.LottoManualGenerateStrategy; import domain.money.Money; +import input.ConsoleInput; import java.util.ArrayList; import java.util.List; @@ -13,27 +17,34 @@ public class LottoSeller { private Money lotto; - private LottoGenerator lottoGenerator = new LottoGenerator(); // 현재는 고정 public LottoSeller(Money lottoPrice) { this.lotto = lottoPrice; - } - public LottoCollection sellTo(Money money) { + public LottoCollection sellTo(Money money, int manualCount) { int buyLottoSize = getCountOfLotto(money); - return generateLottoCollection(buyLottoSize); + if (manualCount > buyLottoSize) { + throw new IllegalArgumentException(); + } + + LottoCollection lottoCollection = new LottoCollection(); + lottoCollection.addAll(generateLottoCollection(new LottoManualGenerateStrategy(new ConsoleInput()), manualCount)); + lottoCollection.addAll(generateLottoCollection(new LottoAutoGenerateStrategy(), buyLottoSize - manualCount)); + + return lottoCollection; } private int getCountOfLotto(Money money) { return Money.of(money).getAmount() / lotto.getAmount(); } - private LottoCollection generateLottoCollection(/* 로또 생성 전략 ,*/ int size) { + private LottoCollection generateLottoCollection(LottoGenerateStrategy strategy, int size) { List lottoList = new ArrayList<>(); for (int i = 0; i < size; i++) { - lottoList.add(lottoGenerator.generateLotto()); + lottoList.add(strategy.generateLotto()); } + return new LottoCollection(lottoList); } } diff --git a/src/main/java/input/ConsoleInput.java b/src/main/java/input/ConsoleInput.java new file mode 100644 index 0000000..c1db2d7 --- /dev/null +++ b/src/main/java/input/ConsoleInput.java @@ -0,0 +1,16 @@ +package input; + +import java.util.Scanner; + +/** + * @author delf + */ +public class ConsoleInput implements Inputtable { + + private static Scanner scanner = new Scanner(System.in); + + @Override + public String getStringValue() { + return scanner.nextLine(); + } +} diff --git a/src/main/java/input/InputView.java b/src/main/java/input/InputView.java index 535e94d..8f98593 100644 --- a/src/main/java/input/InputView.java +++ b/src/main/java/input/InputView.java @@ -2,6 +2,7 @@ import domain.lotto.Lotto; import domain.lotto.LottoNumber; +import domain.lotto.WinningLotto; import domain.money.Money; import java.util.Arrays; @@ -12,6 +13,7 @@ public class InputView { private static final String buyGuideText = "구입금액을 입력해 주세요."; private static final String winningGuideText = "지난 주 당첨 번호를 입력해 주세요."; + private static final String bonusNumberGuideText = "보너스 볼을 입력해 주세요."; public static Money inputMoney() { return buyMock(1400000); @@ -19,19 +21,31 @@ public static Money inputMoney() { private static Money buyMock(int n) { System.out.println(buyGuideText); - return new Money(n); + return Money.of(n); } - public static Lotto inputWinningLottoNumber() { + public static WinningLotto inputWinningLottoNumber() { return winningLottoMock(); } - private static Lotto winningLottoMock() { + public static int getManualCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + final int count = 3; + System.out.println(count); + return count; // 임시 + } + + private static WinningLotto winningLottoMock() { System.out.println(winningGuideText); Lotto lotto = new Lotto(Arrays.asList(LottoNumber.of(1), LottoNumber.of(2), LottoNumber.of(3), LottoNumber.of(4), LottoNumber.of(5), LottoNumber.of(6))); - System.out.println(lotto); + System.out.println("> 입력함"); - return lotto; - } + System.out.println(bonusNumberGuideText); + WinningLotto winningLotto = new WinningLotto(lotto, LottoNumber.of(7)); + System.out.println("> 입력함"); + System.out.println(" 입력 값: " + winningLotto + "\n"); + + return winningLotto; + } } diff --git a/src/main/java/input/Inputtable.java b/src/main/java/input/Inputtable.java new file mode 100644 index 0000000..0526311 --- /dev/null +++ b/src/main/java/input/Inputtable.java @@ -0,0 +1,8 @@ +package input; + +/** + * @author delf + */ +public interface Inputtable { + String getStringValue(); +} diff --git a/src/main/java/output/OutputView.java b/src/main/java/output/OutputView.java index 4eadbc6..b69a887 100644 --- a/src/main/java/output/OutputView.java +++ b/src/main/java/output/OutputView.java @@ -1,5 +1,6 @@ package output; +import domain.Rank; import domain.lotto.LottoCollection; import domain.LottoStatistics; @@ -14,10 +15,12 @@ public static void printLotto(LottoCollection lottoCollection) { } public static void showWinningStatistics(LottoStatistics lottoStatistics) { + final Rank[] PRINT_ORDER_RANK = {Rank.FIFTH, Rank.FOURTH, Rank.THIRD, Rank.SECOND, Rank.FIRST}; + System.out.println("당첨 통계" + "\n" + "-------------"); - lottoStatistics.forEach(rank -> System.out.println( - String.format("- %s %s개", rank, lottoStatistics.getCount(rank))) - ); + for(Rank rank : PRINT_ORDER_RANK) { + System.out.println(String.format("- %s %s개", rank, lottoStatistics.getCount(rank))); + } System.out.println(String.format("\n총 수익률은 %.2f%%입니다.", lottoStatistics.getRor())); } } diff --git a/src/test/java/domain/lotto/WinningLottoTest.java b/src/test/java/domain/lotto/WinningLottoTest.java new file mode 100644 index 0000000..dfca68b --- /dev/null +++ b/src/test/java/domain/lotto/WinningLottoTest.java @@ -0,0 +1,59 @@ +package domain.lotto; + +import domain.Rank; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; + +class WinningLottoTest { + + private final static WinningLotto WINNING_LOTTO = new WinningLotto( + new Lotto(Arrays.asList(LottoNumber.of(1), LottoNumber.of(2), LottoNumber.of(3), LottoNumber.of(4), LottoNumber.of(5), LottoNumber.of(6))), + LottoNumber.of(7) + ); + + @Test + void noMatch() { + final Lotto userLotto = generateLotto(8, 9, 10, 11, 12, 13, 14); + assertThat(WINNING_LOTTO.match(userLotto)).isEqualTo(Rank.MISS); + } + + @Test + void matchThree() { + final Lotto userLotto = generateLotto(1, 2, 3, 11, 12, 13); + assertThat(WINNING_LOTTO.match(userLotto)).isEqualTo(Rank.FIFTH); + } + + @Test + void matchFour() { + final Lotto userLotto = generateLotto(1, 2, 3, 4, 12, 13); + assertThat(WINNING_LOTTO.match(userLotto)).isEqualTo(Rank.FOURTH); + } + + @Test + void matchFive() { + final Lotto userLotto = generateLotto(1, 2, 3, 4, 5, 13); + assertThat(WINNING_LOTTO.match(userLotto)).isEqualTo(Rank.THIRD); + } + + @Test + void matchSix() { + final Lotto userLotto = generateLotto(1, 2, 3, 4, 5, 6); + assertThat(WINNING_LOTTO.match(userLotto)).isEqualTo(Rank.FIRST); + } + + @Test + void matchFiveAndBonus() { + final Lotto userLotto = generateLotto(1, 2, 3, 4, 5, 7, 14); + assertThat(WINNING_LOTTO.match(userLotto)).isEqualTo(Rank.SECOND); + } + + + private Lotto generateLotto(int... lottoNumbers) { + return new Lotto(Arrays.stream(lottoNumbers).mapToObj(LottoNumber::of).collect(toList())); + } + +}