diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..ada27f7889 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,55 @@ package lotto; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lotto.domain.Lotto; +import lotto.domain.Money; +import lotto.domain.WinNumbers; +import lotto.domain.lottonumbercreator.AutoLottoNumberCreator; +import lotto.domain.lottonumbercreator.LottoNumberCreator; +import lotto.domain.lottorank.LottoRank; +import lotto.domain.lottorank.LottoRanks; +import lotto.view.InputView; + public class Application { + private static final LottoNumberCreator CREATOR = new AutoLottoNumberCreator(); + public static void main(String[] args) { - // TODO: 프로그램 구현 + System.out.println("구입금액을 입력해 주세요."); + + final Money money = new Money(InputView.requestInteger()); + final int lottoCount = money.getLottoCount(); + System.out.println(String.format("\n%d개를 구매했습니다.", lottoCount)); + + final List autoLottos = getAutoLottos(lottoCount); + autoLottos.forEach(System.out::println); + + System.out.println("\n당첨 번호를 입력해 주세요."); + final Lotto winLotto = new Lotto(InputView.requestWinNumbers()); + + System.out.println("\n보너스 번호를 입력해 주세요."); + int bonusBall = InputView.requestInteger(); + + final WinNumbers winNumbers = new WinNumbers(winLotto, bonusBall); + final LottoRanks lottoRanks = getLottoRanks(autoLottos, winNumbers); + + System.out.println("당첨 통계\n---"); + System.out.println(lottoRanks); + System.out.println(String.format("총 수익률은 %.1f%%입니다.", money.getRateOfProfit(lottoRanks.getProfit()))); + } + + private static List getAutoLottos(int lottoCount) { + return Stream.generate(() -> Lotto.from(CREATOR)) + .limit(lottoCount) + .collect(Collectors.toList()); + } + + private static LottoRanks getLottoRanks(List autoLottos, WinNumbers winNumbers) { + final List ranks = autoLottos.stream() + .map(lotto -> LottoRank.calculateRank(winNumbers, lotto)) + .collect(Collectors.toList()); + + return LottoRanks.from(ranks); } } diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 9f8dd83128..8473617e28 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -2,6 +2,7 @@ import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; import lotto.domain.lottonumbercreator.LottoNumberCreator; public class Lotto { @@ -18,6 +19,10 @@ public Lotto(List numbers) { this.numbers = numbers; } + public static Lotto from(LottoNumberCreator creator) { + return new Lotto(creator.create(MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER, LOTTO_NUMBERS_SIZE)); + } + private void validateSize(List numbers) { if (numbers.size() != LOTTO_NUMBERS_SIZE) { throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자의 개수는 %d일 수 없습니다.", numbers.size())); @@ -38,10 +43,6 @@ private void validateNumbersRange(List numbers) { } } - public static Lotto from(LottoNumberCreator creator) { - return new Lotto(creator.create(MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER, LOTTO_NUMBERS_SIZE)); - } - public boolean isPossible(int bonusBall) { final boolean isInRange = bonusBall >= MIN_LOTTO_NUMBER && bonusBall <= MAX_LOTTO_NUMBER; final boolean isNotLottoNumber = !numbers.contains(bonusBall); @@ -54,7 +55,7 @@ public boolean isFirstRank(Lotto lotto) { } public boolean isThirdRank(Lotto lotto) { - return containCount(lotto) == LOTTO_NUMBERS_SIZE - 1 ; + return containCount(lotto) == LOTTO_NUMBERS_SIZE - 1; } public boolean isFourthRank(Lotto lotto) { @@ -78,4 +79,13 @@ private int containCount(Lotto other) { public boolean contain(Integer number) { return this.numbers.contains(number); } + + @Override + public String toString() { + return String.format("[%s]", + this.numbers.stream() + .sorted() + .map(number -> Integer.toString(number)) + .collect(Collectors.joining(", "))); + } } diff --git a/src/main/java/lotto/domain/Money.java b/src/main/java/lotto/domain/Money.java index 5f61e494cb..8d5595f549 100644 --- a/src/main/java/lotto/domain/Money.java +++ b/src/main/java/lotto/domain/Money.java @@ -14,4 +14,12 @@ private void validate(int value) { throw new IllegalArgumentException(String.format("[ERROR] 금액은 %d원일 수 없습니다.", value)); } } + + public int getLottoCount() { + return this.value / MIN_VALUE; + } + + public double getRateOfProfit(int profit) { + return (double) profit * 100 / value; + } } diff --git a/src/main/java/lotto/domain/LottoRank.java b/src/main/java/lotto/domain/lottorank/LottoRank.java similarity index 86% rename from src/main/java/lotto/domain/LottoRank.java rename to src/main/java/lotto/domain/lottorank/LottoRank.java index 8a33bcbfb0..72e7d45d73 100644 --- a/src/main/java/lotto/domain/LottoRank.java +++ b/src/main/java/lotto/domain/lottorank/LottoRank.java @@ -1,6 +1,8 @@ -package lotto.domain; +package lotto.domain.lottorank; import java.util.Arrays; +import lotto.domain.Lotto; +import lotto.domain.WinNumbers; import lotto.domain.rankvalidator.RankValidator; public enum LottoRank { @@ -26,4 +28,8 @@ public static LottoRank calculateRank(WinNumbers winNumbers, Lotto lotto) { .findAny() .orElseThrow(() -> new IllegalArgumentException("[ERROR] 일치하는 등수가 존재하지 않습니다")); } + + public int getPrize() { + return prize; + } } diff --git a/src/main/java/lotto/domain/lottorank/LottoRanks.java b/src/main/java/lotto/domain/lottorank/LottoRanks.java new file mode 100644 index 0000000000..680fe28aad --- /dev/null +++ b/src/main/java/lotto/domain/lottorank/LottoRanks.java @@ -0,0 +1,45 @@ +package lotto.domain.lottorank; + +import static lotto.domain.lottorank.LottoRank.FIFTH; +import static lotto.domain.lottorank.LottoRank.FIRST; +import static lotto.domain.lottorank.LottoRank.FOURTH; +import static lotto.domain.lottorank.LottoRank.SECOND; +import static lotto.domain.lottorank.LottoRank.THIRD; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class LottoRanks { + + private final Map ranks; + + private LottoRanks(Map ranks) { + this.ranks = ranks; + } + + public static LottoRanks from(List ranks) { + EnumMap lottoRankMap = new EnumMap<>(LottoRank.class); + Arrays.stream(LottoRank.values()).forEach(lottoRank -> lottoRankMap.put(lottoRank, 0)); + + ranks.forEach(rank -> lottoRankMap.computeIfPresent(rank, (key, value) -> value + 1)); + return new LottoRanks(lottoRankMap); + } + + public int getProfit() { + return this.ranks.entrySet() + .stream() + .mapToInt(entry -> entry.getKey().getPrize() * entry.getValue()) + .sum(); + } + + @Override + public String toString() { + return String.format("3개 일치 (%,d원) - %d개\n", FIFTH.getPrize(), ranks.get(FIFTH)) + + String.format("4개 일치 (%,d원) - %d개\n", FOURTH.getPrize(), ranks.get(FOURTH)) + + String.format("5개 일치 (%,d원) - %d개\n", THIRD.getPrize(), ranks.get(THIRD)) + + String.format("5개 일치, 보너스 볼 일치 (%,d원) - %d개\n", SECOND.getPrize(), ranks.get(SECOND)) + + String.format("6개 일치 (%,d원) - %d개\n", FIRST.getPrize(), ranks.get(FIRST)); + } +} diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java new file mode 100644 index 0000000000..b3a2b3f43b --- /dev/null +++ b/src/main/java/lotto/view/InputView.java @@ -0,0 +1,31 @@ +package lotto.view; + +import camp.nextstep.edu.missionutils.Console; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class InputView { + private static final String DELIMITER = ","; + + public static int requestInteger() { + final String input = Console.readLine(); + return parseInt(input); + } + + public static List requestWinNumbers() { + final String input = Console.readLine(); + + return Arrays.stream(input.split(DELIMITER)) + .map(InputView::parseInt) + .collect(Collectors.toList()); + } + + private static int parseInt(String value) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("[ERROR] 입력값 %s는 숫자가 아닙니다.", value)); + } + } +} diff --git a/src/test/java/lotto/domain/LottoRankTest.java b/src/test/java/lotto/domain/LottoRankTest.java index 9799473096..6c0a6cdf0c 100644 --- a/src/test/java/lotto/domain/LottoRankTest.java +++ b/src/test/java/lotto/domain/LottoRankTest.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.stream.Stream; +import lotto.domain.lottorank.LottoRank; import org.assertj.core.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments;