diff --git a/src/main/java/lotto/Main.java b/src/main/java/lotto/Main.java index e973c95cb6..89f084e926 100644 --- a/src/main/java/lotto/Main.java +++ b/src/main/java/lotto/Main.java @@ -1,20 +1,24 @@ package lotto; -import lotto.domain.LottoGame; -import lotto.domain.LottoResult; -import lotto.domain.Money; -import lotto.domain.WinningLotto; +import lotto.domain.*; import lotto.view.InputView; import lotto.view.ResultView; +import java.util.List; + public class Main { public static void main(String[] args) { - long price = InputView.initLottoPrice(); - LottoGame lottoGame = new LottoGame(price); + Money money = new Money(InputView.initLottoPrice()); + int manualCount = InputView.initManualCount(); + List manualList = InputView.initManualList(manualCount); + + LottoPurchase lottoPurchase = new LottoPurchase(money, manualList); + + LottoGame lottoGame = new LottoGame(lottoPurchase); ResultView.printLottos(lottoGame); WinningLotto winningLotto = new WinningLotto(InputView.initWinningLotto(), InputView.initBonusNumber()); LottoResult result = lottoGame.findWinner(winningLotto); - ResultView.printResult(result, new Money(price)); + ResultView.printResult(result, money); } } diff --git a/src/main/java/lotto/domain/AutoLottoGenerator.java b/src/main/java/lotto/domain/AutoLottoGenerator.java new file mode 100644 index 0000000000..e9e582fb0d --- /dev/null +++ b/src/main/java/lotto/domain/AutoLottoGenerator.java @@ -0,0 +1,15 @@ +package lotto.domain; + +public class AutoLottoGenerator implements LottoGenerator { + + private final LottoCount lottoCount; + + public AutoLottoGenerator(LottoCount lottoCount) { + this.lottoCount = lottoCount; + } + + @Override + public Lottos generate() { + return new Lottos(lottoCount.value()); + } +} diff --git a/src/main/java/lotto/domain/CompositeLottoGenerator.java b/src/main/java/lotto/domain/CompositeLottoGenerator.java new file mode 100644 index 0000000000..85cd9e7236 --- /dev/null +++ b/src/main/java/lotto/domain/CompositeLottoGenerator.java @@ -0,0 +1,20 @@ +package lotto.domain; + +import java.util.List; + +public class CompositeLottoGenerator implements LottoGenerator { + + private final List generators; + + public CompositeLottoGenerator(List generators) { + this.generators = generators; + } + + @Override + public Lottos generate() { + return generators.stream() + .map(LottoGenerator::generate) + .reduce(Lottos::merge) + .orElseGet(Lottos::empty); + } +} diff --git a/src/main/java/lotto/domain/LottoCount.java b/src/main/java/lotto/domain/LottoCount.java new file mode 100644 index 0000000000..0218a9c072 --- /dev/null +++ b/src/main/java/lotto/domain/LottoCount.java @@ -0,0 +1,20 @@ +package lotto.domain; + +public class LottoCount { + private final int value; + + public LottoCount(int value) { + validate(value); + this.value = value; + } + + private static void validate(int value) { + if (value < 0) { + throw new IllegalArgumentException(); + } + } + + public int value() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/domain/LottoGame.java b/src/main/java/lotto/domain/LottoGame.java index 6dc73f3325..1de4482afd 100644 --- a/src/main/java/lotto/domain/LottoGame.java +++ b/src/main/java/lotto/domain/LottoGame.java @@ -4,19 +4,13 @@ public class LottoGame { private final Lottos lottos; - private final Money money; - public LottoGame(long amount) { - this(new Money(amount)); + public LottoGame(LottoPurchase purchase) { + this(purchase.purchase()); } - public LottoGame(Money money) { - this(new Lottos(money.buyCount()), money); - } - - public LottoGame(Lottos lottos, Money money) { + public LottoGame(Lottos lottos) { this.lottos = lottos; - this.money = money; } public LottoResult findWinner(WinningLotto winningLotto) { diff --git a/src/main/java/lotto/domain/LottoGenerator.java b/src/main/java/lotto/domain/LottoGenerator.java new file mode 100644 index 0000000000..320451b1d2 --- /dev/null +++ b/src/main/java/lotto/domain/LottoGenerator.java @@ -0,0 +1,5 @@ +package lotto.domain; + +public interface LottoGenerator { + Lottos generate(); +} diff --git a/src/main/java/lotto/domain/LottoPurchase.java b/src/main/java/lotto/domain/LottoPurchase.java new file mode 100644 index 0000000000..0d387a97f5 --- /dev/null +++ b/src/main/java/lotto/domain/LottoPurchase.java @@ -0,0 +1,53 @@ +package lotto.domain; + +import java.util.List; +import java.util.stream.Collectors; + +public class LottoPurchase { + private static final long LOTTO_PRICE = 1_000; + + private final LottoCount count; + private final List manualLottos; + + public LottoPurchase(Money money) { + this(new LottoCount(calculateCount(money))); + } + + public LottoPurchase(LottoCount count) { + this(count, List.of()); + } + + public LottoPurchase(Money money, List manualList) { + this(new LottoCount(calculateCount(money)), convert(manualList)); + } + + public LottoPurchase(LottoCount count, List manualLottos) { + this.count = count; + this.manualLottos = manualLottos; + } + + public Lottos purchase() { + LottoGenerator compositeGenerator = new CompositeLottoGenerator( + List.of(new ManualLottoGenerator(manualLottos), new AutoLottoGenerator(new LottoCount(autoCount())))); + + return compositeGenerator.generate(); + } + + public static List convert(List manualList) { + return manualList.stream() + .map(Lotto::new) + .collect(Collectors.toUnmodifiableList()); + } + + private static int calculateCount(Money money) { + return (int)(money.getMoney() / LOTTO_PRICE); + } + + public int count() { + return count.value(); + } + + public int autoCount() { + return count.value() - manualLottos.size(); + } +} diff --git a/src/main/java/lotto/domain/Lottos.java b/src/main/java/lotto/domain/Lottos.java index 10c4288c57..b6cda0bcbd 100644 --- a/src/main/java/lotto/domain/Lottos.java +++ b/src/main/java/lotto/domain/Lottos.java @@ -1,5 +1,6 @@ package lotto.domain; +import java.util.ArrayList; import java.util.List; public class Lottos { @@ -17,6 +18,20 @@ public List values() { return lottos; } + public static Lottos empty() { + return new Lottos(List.of()); + } + + public Lottos merge(Lottos manualLottos) { + return merge(manualLottos.lottos); + } + + public Lottos merge(List manualLottos) { + List newLottos = new ArrayList<>(this.lottos); + newLottos.addAll(manualLottos); + return new Lottos(newLottos); + } + public LottoResult findResult(WinningLotto winningLotto) { LottoResult result = new LottoResult(); for (Lotto lotto : lottos) { diff --git a/src/main/java/lotto/domain/ManualLottoGenerator.java b/src/main/java/lotto/domain/ManualLottoGenerator.java new file mode 100644 index 0000000000..80fd4740d5 --- /dev/null +++ b/src/main/java/lotto/domain/ManualLottoGenerator.java @@ -0,0 +1,17 @@ +package lotto.domain; + +import java.util.List; + +public class ManualLottoGenerator implements LottoGenerator { + + private final List manualList; + + public ManualLottoGenerator(List manualList) { + this.manualList = manualList; + } + + @Override + public Lottos generate() { + return new Lottos(manualList); + } +} diff --git a/src/main/java/lotto/domain/Money.java b/src/main/java/lotto/domain/Money.java index 2c4cd64c0f..aa2d3d60ef 100644 --- a/src/main/java/lotto/domain/Money.java +++ b/src/main/java/lotto/domain/Money.java @@ -16,10 +16,6 @@ private void validate(long money) { } } - public int buyCount() { - return (int) (money / LOTTO_PRICE); - } - public double getMoney() { return money; } diff --git a/src/main/java/lotto/domain/Rank.java b/src/main/java/lotto/domain/Rank.java index fe414feec7..261f28898e 100644 --- a/src/main/java/lotto/domain/Rank.java +++ b/src/main/java/lotto/domain/Rank.java @@ -26,22 +26,22 @@ public int match() { return match; } - public boolean isMatch(int match) { - return this.match == match; + private boolean isMatch(int matchCount, boolean matchBonus) { + if (this == SECOND) { + return matchCount == 5 && matchBonus; + } + + if (this == THIRD) { + return matchCount == 5 && !matchBonus; + } + + return this.match == matchCount; } public static Rank from(int matchCount, boolean matchBonus) { return Arrays.stream(values()) - .filter(rank -> rank.isMatch(matchCount)) + .filter(rank -> rank.isMatch(matchCount, matchBonus)) .findFirst() - .map(rank -> bonusCheck(rank, matchBonus)) .orElse(NONE); } - - private static Rank bonusCheck(Rank rank, boolean matchBonus) { - if (rank == Rank.THIRD && matchBonus) { - return Rank.SECOND; - } - return rank; - } } diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java index 43359db3ff..fca7479c89 100644 --- a/src/main/java/lotto/view/InputView.java +++ b/src/main/java/lotto/view/InputView.java @@ -1,5 +1,8 @@ package lotto.view; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Scanner; public class InputView { @@ -19,4 +22,20 @@ public static int initBonusNumber() { System.out.println("보너스 볼을 입력해 주세요."); return SCANNER.nextInt(); } + + public static int initManualCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + int count = SCANNER.nextInt(); + SCANNER.nextLine(); + return count; + } + + public static List initManualList(int manualCount) { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + List result = new ArrayList<>(); + for (int i = 0; i < manualCount; i++) { + result.add(SCANNER.nextLine()); + } + return result; + } } diff --git a/src/test/java/lotto/domain/AutoLottoGeneratorTest.java b/src/test/java/lotto/domain/AutoLottoGeneratorTest.java new file mode 100644 index 0000000000..526bcfb2dc --- /dev/null +++ b/src/test/java/lotto/domain/AutoLottoGeneratorTest.java @@ -0,0 +1,16 @@ +package lotto.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class AutoLottoGeneratorTest { + + @Test + void auto_generate_size() { + AutoLottoGenerator auto = new AutoLottoGenerator(new LottoCount(3)); + Lottos generate = auto.generate(); + Assertions.assertThat(generate.size()).isEqualTo(3); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/CompositeLottoGeneratorTest.java b/src/test/java/lotto/domain/CompositeLottoGeneratorTest.java new file mode 100644 index 0000000000..6db80b2839 --- /dev/null +++ b/src/test/java/lotto/domain/CompositeLottoGeneratorTest.java @@ -0,0 +1,27 @@ +package lotto.domain; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class CompositeLottoGeneratorTest { + + @Test + void merge() { + List manualList = List.of( + new Lotto(1, 2, 3, 4, 5, 6) + , new Lotto(2, 3, 4, 5, 6, 7) + ); + LottoGenerator manual = new ManualLottoGenerator(manualList); + LottoGenerator auto = new AutoLottoGenerator(new LottoCount(2)); + + LottoGenerator composite = new CompositeLottoGenerator( + List.of(manual, auto) + ); + + Lottos merge = composite.generate(); + assertThat(merge.size()).isEqualTo(4); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/LottoGameTest.java b/src/test/java/lotto/domain/LottoGameTest.java index d8a018f437..ab77511196 100644 --- a/src/test/java/lotto/domain/LottoGameTest.java +++ b/src/test/java/lotto/domain/LottoGameTest.java @@ -12,6 +12,7 @@ class LottoGameTest { @Test @DisplayName("입력된 금액만큼의 로또가 생성되어야 한다") void generate_lotto() { - assertThat(new LottoGame(14000).lottoCount()).isEqualTo(14); + LottoPurchase lottoPurchase = new LottoPurchase(new LottoCount(14)); + assertThat(new LottoGame(lottoPurchase).lottoCount()).isEqualTo(14); } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/LottoPurchaseTest.java b/src/test/java/lotto/domain/LottoPurchaseTest.java new file mode 100644 index 0000000000..bc0ddc6125 --- /dev/null +++ b/src/test/java/lotto/domain/LottoPurchaseTest.java @@ -0,0 +1,43 @@ +package lotto.domain; + + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LottoPurchaseTest { + + @Test + @DisplayName("정해진 개수로 구매할 수 있다") + void count() { + LottoPurchase purchase = new LottoPurchase(new LottoCount(3)); + + assertThat(purchase.count()).isEqualTo(3); + } + + @Test + @DisplayName("Money로부터 구매 가능한 로또 개수를 계산한다") + void calculate() { + Money money = new Money(5000); + + LottoPurchase purchase = new LottoPurchase(money); + + assertThat(purchase.count()).isEqualTo(5); + } + + @Test + @DisplayName("수동 생성한 리스트의 사이즈를 확인할 수 있다.") + void manualList_size() { + Money money = new Money(5000); + List list = List.of("1,2,3,4,5,6", "2,3,4,5,6,7", "3,4,5,6,7,8"); + + LottoPurchase lottoPurchase = new LottoPurchase(money, list); + Lottos lottos = lottoPurchase.purchase(); + + assertThat(lottos.size()).isEqualTo(5); + assertThat(lottoPurchase.autoCount()).isEqualTo(2); + } +} diff --git a/src/test/java/lotto/domain/ManualLottoGeneratorTest.java b/src/test/java/lotto/domain/ManualLottoGeneratorTest.java new file mode 100644 index 0000000000..a226888db8 --- /dev/null +++ b/src/test/java/lotto/domain/ManualLottoGeneratorTest.java @@ -0,0 +1,22 @@ +package lotto.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +class ManualLottoGeneratorTest { + + @Test + void manual_generate_size() { + List list = List.of( + new Lotto(1, 2, 3, 4, 5, 6), + new Lotto(2, 3, 4, 5, 6, 7) + ); + ManualLottoGenerator manual = new ManualLottoGenerator(list); + Lottos generate = manual.generate(); + assertThat(generate.size()).isEqualTo(2); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/MoneyTest.java b/src/test/java/lotto/domain/MoneyTest.java index c01790abed..e4c954ba7d 100644 --- a/src/test/java/lotto/domain/MoneyTest.java +++ b/src/test/java/lotto/domain/MoneyTest.java @@ -12,10 +12,4 @@ class MoneyTest { void lotto_buy() { assertThatThrownBy(() -> new Money(999)).isInstanceOf(IllegalArgumentException.class); } - - @Test - @DisplayName("1000단위로 로또를 구매할 수 있다") - void lotto_buyCount() { - assertThat(new Money(3500).buyCount()).isEqualTo(3); - } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/WinningLottoTest.java b/src/test/java/lotto/domain/WinningLottoTest.java index 0a8650a5bc..a4b4572dac 100644 --- a/src/test/java/lotto/domain/WinningLottoTest.java +++ b/src/test/java/lotto/domain/WinningLottoTest.java @@ -1,5 +1,6 @@ package lotto.domain; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -8,8 +9,28 @@ class WinningLottoTest { @Test - @DisplayName("보너스 번호는 당첨번호와 달라양한다") + @DisplayName("보너스 번호는 당첨번호와 달라야한다") void bonusNumberCheck_duplicate() { assertThatThrownBy(() -> new WinningLotto(new Lotto(1, 2, 3, 4, 5, 6), 6)).isInstanceOf(IllegalArgumentException.class); } + + @Test + @DisplayName("5개 번호 = 3등") + void match_rank_third() { + WinningLotto winningLotto = new WinningLotto(new Lotto(1, 2, 3, 4, 5, 6), 7); + Lotto userLotto = new Lotto(1, 2, 3, 4, 5, 8); + + Rank rank = winningLotto.match(userLotto); + Assertions.assertThat(rank).isEqualTo(Rank.THIRD); + } + + @Test + @DisplayName("5개 번호 + 보너스 번호 = 2등") + void match_rank_second() { + WinningLotto winningLotto = new WinningLotto(new Lotto(1, 2, 3, 4, 5, 6), 7); + Lotto userLotto = new Lotto(1, 2, 3, 4, 5, 7); + + Rank rank = winningLotto.match(userLotto); + Assertions.assertThat(rank).isEqualTo(Rank.SECOND); + } } \ No newline at end of file