diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..1adb5b198d 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 lotto.domain.Lotto; +import lotto.domain.LottoNumber; +import lotto.domain.LottoRank; +import lotto.domain.LottoRanks; +import lotto.domain.Money; +import lotto.domain.Ticket; +import lotto.domain.WinningLotto; +import lotto.domain.lottocreator.AutoLottoCreator; +import lotto.domain.lottocreator.ManualLottoCreator; +import lotto.domain.picker.RandomPicker; +import lotto.ui.Input; +import lotto.ui.Output; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + final Money money = new Money(Input.getMoneyValue()); + final int manualLottoCount = Input.getManualLottoCount(); + validateLottoCount(money, manualLottoCount); + + final List> manualLottos = Input.getManualLottos(manualLottoCount); + final Ticket manualTicket = getManualTicket(manualLottos); + final int autoLottoCount = money.remainCount(manualLottoCount); + final Ticket autoTicket = Ticket.of(new AutoLottoCreator(new RandomPicker()), autoLottoCount); + + Output.printTicket(manualLottoCount, manualTicket, autoLottoCount, autoTicket); + + final Lotto lotto = Lotto.create(new ManualLottoCreator(Input.getWinningLotto())); + final LottoNumber bonusBall = LottoNumber.from(Input.getBonusBall()); + WinningLotto winningLotto = new WinningLotto(lotto, bonusBall); + + final List ticketResults = manualTicket.getResults(winningLotto); + ticketResults.addAll(autoTicket.getResults(winningLotto)); + LottoRanks ranks = LottoRanks.from(ticketResults); + + Output.printResult(money, ranks); + } + + private static void validateLottoCount(Money money, int manualLottoCount) { + if (!money.canBuy(manualLottoCount)) { + throw new IllegalArgumentException(String.format("[ERROR] 로또를 %d개 구매할 수 없습니다.", manualLottoCount)); + } + } + + private static Ticket getManualTicket(List> manualLottos) { + return new Ticket( + manualLottos.stream() + .map(lotto -> Lotto.create(new ManualLottoCreator(lotto))) + .collect(Collectors.toList()) + ); } } diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java new file mode 100644 index 0000000000..8ae251c589 --- /dev/null +++ b/src/main/java/lotto/domain/Lotto.java @@ -0,0 +1,45 @@ +package lotto.domain; + +import java.util.Set; +import java.util.stream.Collectors; +import lotto.domain.lottocreator.LottoCreator; + +public class Lotto { + + private static final int LOTTO_SIZE = 6; + + private final Set numbers; + + private Lotto(Set numbers) { + validateLength(numbers); + this.numbers = numbers; + } + + public static Lotto create(LottoCreator creator) { + return new Lotto(creator.create(LOTTO_SIZE)); + } + + private void validateLength(Set numbers) { + if (numbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자 개수는 %d일 수 없습니다.", numbers.size())); + } + } + + public int calculateSameLottoNumber(Lotto other) { + return (int) other.numbers.stream() + .filter(this::contains) + .count(); + } + + public boolean contains(LottoNumber bonusBall) { + return this.numbers.contains(bonusBall); + } + + @Override + public String toString() { + return this.numbers.stream() + .sorted() + .collect(Collectors.toList()) + .toString(); + } +} diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java new file mode 100644 index 0000000000..44912b1967 --- /dev/null +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -0,0 +1,67 @@ +package lotto.domain; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import lotto.domain.picker.Picker; + +public class LottoNumber implements Comparable { + private static final int MIN_VALUE = 1; + private static final int MAX_VALUE = 45; + private static final List VALUES; + + static { + VALUES = IntStream.rangeClosed(MIN_VALUE, MAX_VALUE) + .mapToObj(LottoNumber::new) + .collect(Collectors.toList()); + } + + private final int value; + + private LottoNumber(int value) { + this.value = value; + } + + public static LottoNumber pick(Picker picker) { + return LottoNumber.from(picker.pick(MIN_VALUE, MAX_VALUE)); + } + + public static LottoNumber from(int value) { + validateRange(value); + return VALUES.get(value - 1); + } + + private static void validateRange(int value) { + if (value < MIN_VALUE || value > MAX_VALUE) { + throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자는 %d일 수 없습니다.", value)); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LottoNumber that = (LottoNumber) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + @Override + public int compareTo(LottoNumber o) { + return this.value - o.value; + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/lotto/domain/LottoRank.java b/src/main/java/lotto/domain/LottoRank.java new file mode 100644 index 0000000000..11eacad008 --- /dev/null +++ b/src/main/java/lotto/domain/LottoRank.java @@ -0,0 +1,48 @@ +package lotto.domain; + +import java.util.Arrays; + +public enum LottoRank { + FIRST(2_000_000_000, 6, false), + SECOND(30_000_000, 5, true), + THIRD(1_500_000, 5, false), + FOURTH(50_000, 4, false), + FIFTH(5_000, 3, false), + OTHER(0, 0, false); + + + private final int prize; + private final int count; + private final boolean bonus; + + LottoRank(int prize, int count, boolean bonus) { + this.prize = prize; + this.count = count; + this.bonus = bonus; + } + + public static LottoRank calculateRank(WinningLotto winningLotto, Lotto lotto) { + return Arrays.stream(LottoRank.values()) + .filter(rank -> rank.count == winningLotto.calculateSameLottoNumber(lotto)) + .filter(rank -> !rank.bonus || winningLotto.matchBonus(lotto)) + .findAny() + .orElse(LottoRank.OTHER); + } + + + public int getPrize() { + return prize; + } + + @Override + public String toString() { + if (this.bonus) { + return String.format("%d개 일치, 보너스 볼 일치 (%,d원)", this.count, this.prize); + } + return String.format("%d개 일치 (%,d원)", this.count, this.prize); + } + + public boolean isNotOtherRank() { + return this != OTHER; + } +} diff --git a/src/main/java/lotto/domain/LottoRanks.java b/src/main/java/lotto/domain/LottoRanks.java new file mode 100644 index 0000000000..391749a2ff --- /dev/null +++ b/src/main/java/lotto/domain/LottoRanks.java @@ -0,0 +1,44 @@ +package lotto.domain; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class LottoRanks { + private final Map ranks; + + private LottoRanks(Map ranks) { + this.ranks = ranks; + } + + public static LottoRanks from(List ranks) { + return new LottoRanks( + ranks.stream().collect(Collectors.toMap(Function.identity(), rank -> 1, Integer::sum)) + ); + } + + public int getProfit() { + return this.ranks.entrySet() + .stream() + .mapToInt(entry -> entry.getKey().getPrize() * entry.getValue()) + .sum(); + } + + @Override + public String toString() { + Arrays.stream(LottoRank.values()) + .forEach(rank -> this.ranks.computeIfAbsent(rank, value -> 0)); + + return ranks.entrySet() + .stream() + .filter(entry -> entry.getKey().isNotOtherRank()) + .sorted(Entry.comparingByKey()) + .map(entry -> String.format("%s - %d개", entry.getKey(), entry.getValue())) + .collect(Collectors.joining("\n")); + } +} diff --git a/src/main/java/lotto/domain/Money.java b/src/main/java/lotto/domain/Money.java new file mode 100644 index 0000000000..ebef47a21a --- /dev/null +++ b/src/main/java/lotto/domain/Money.java @@ -0,0 +1,30 @@ +package lotto.domain; + +public class Money { + private static final int LOTTO_AMOUNT = 1000; + + private final int value; + + public Money(int value) { + validate(value); + this.value = value; + } + + private void validate(int value) { + if (value <= 0 || value % LOTTO_AMOUNT != 0) { + throw new IllegalArgumentException(String.format("[ERROR] 금액은 %d일 수 없습니다.", value)); + } + } + + public boolean canBuy(int lottoCount) { + return this.value / LOTTO_AMOUNT >= lottoCount; + } + + public int remainCount(int lottoCount) { + return this.value / LOTTO_AMOUNT - lottoCount; + } + + public double getProfitRate(int profit) { + return (double) profit / this.value; + } +} diff --git a/src/main/java/lotto/domain/Ticket.java b/src/main/java/lotto/domain/Ticket.java new file mode 100644 index 0000000000..5c0d6f5b42 --- /dev/null +++ b/src/main/java/lotto/domain/Ticket.java @@ -0,0 +1,35 @@ +package lotto.domain; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lotto.domain.lottocreator.LottoCreator; + +public class Ticket { + private final List lottos; + + public Ticket(List lottos) { + this.lottos = lottos; + } + + public static Ticket of(LottoCreator creator, int count) { + final List lottos = Stream.generate(() -> Lotto.create(creator)) + .limit(count) + .collect(Collectors.toList()); + + return new Ticket(lottos); + } + + public List getResults(WinningLotto winningLotto) { + return this.lottos.stream() + .map(lotto -> LottoRank.calculateRank(winningLotto, lotto)) + .collect(Collectors.toList()); + } + + @Override + public String toString() { + return this.lottos.stream() + .map(Lotto::toString) + .collect(Collectors.joining("\n")); + } +} diff --git a/src/main/java/lotto/domain/WinningLotto.java b/src/main/java/lotto/domain/WinningLotto.java new file mode 100644 index 0000000000..1e44331b0a --- /dev/null +++ b/src/main/java/lotto/domain/WinningLotto.java @@ -0,0 +1,28 @@ +package lotto.domain; + +public class WinningLotto { + + public final Lotto lotto; + private final LottoNumber bonusBall; + + public WinningLotto(Lotto lotto, LottoNumber bonusBall) { + validateBonusBall(lotto, bonusBall); + + this.lotto = lotto; + this.bonusBall = bonusBall; + } + + private static void validateBonusBall(Lotto winningLotto, LottoNumber bonusBall) { + if (winningLotto.contains(bonusBall)) { + throw new IllegalArgumentException(String.format("[ERROR] 로또에 이미 %s가 존재합니다.", bonusBall)); + } + } + + public int calculateSameLottoNumber(Lotto lotto) { + return this.lotto.calculateSameLottoNumber(lotto); + } + + public boolean matchBonus(Lotto lotto) { + return lotto.contains(this.bonusBall); + } +} diff --git a/src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java b/src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java new file mode 100644 index 0000000000..cdfa796be3 --- /dev/null +++ b/src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java @@ -0,0 +1,24 @@ +package lotto.domain.lottocreator; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lotto.domain.LottoNumber; +import lotto.domain.picker.Picker; + +public class AutoLottoCreator implements LottoCreator { + + private final Picker picker; + + public AutoLottoCreator(Picker picker) { + this.picker = picker; + } + + @Override + public Set create(int lottoSize) { + return Stream.generate(() -> LottoNumber.pick(this.picker)) + .distinct() + .limit(lottoSize) + .collect(Collectors.toSet()); + } +} diff --git a/src/main/java/lotto/domain/lottocreator/LottoCreator.java b/src/main/java/lotto/domain/lottocreator/LottoCreator.java new file mode 100644 index 0000000000..7e632dec12 --- /dev/null +++ b/src/main/java/lotto/domain/lottocreator/LottoCreator.java @@ -0,0 +1,8 @@ +package lotto.domain.lottocreator; + +import java.util.Set; +import lotto.domain.LottoNumber; + +public interface LottoCreator { + Set create(int lottoSize); +} diff --git a/src/main/java/lotto/domain/lottocreator/ManualLottoCreator.java b/src/main/java/lotto/domain/lottocreator/ManualLottoCreator.java new file mode 100644 index 0000000000..39ab907a6c --- /dev/null +++ b/src/main/java/lotto/domain/lottocreator/ManualLottoCreator.java @@ -0,0 +1,30 @@ +package lotto.domain.lottocreator; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import lotto.domain.LottoNumber; + +public class ManualLottoCreator implements LottoCreator { + + private final List numbers; + + public ManualLottoCreator(List numbers) { + this.numbers = numbers; + } + + @Override + public Set create(int lottoSize) { + validateSize(lottoSize); + + return this.numbers.stream() + .map(LottoNumber::from) + .collect(Collectors.toSet()); + } + + private void validateSize(int lottoSize) { + if (this.numbers.size() != lottoSize) { + throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자의 갯수가 %d가 아닙니다.", lottoSize)); + } + } +} diff --git a/src/main/java/lotto/domain/picker/Picker.java b/src/main/java/lotto/domain/picker/Picker.java new file mode 100644 index 0000000000..db8502fd85 --- /dev/null +++ b/src/main/java/lotto/domain/picker/Picker.java @@ -0,0 +1,5 @@ +package lotto.domain.picker; + +public interface Picker { + int pick(int minValue, int maxValue); +} diff --git a/src/main/java/lotto/domain/picker/RandomPicker.java b/src/main/java/lotto/domain/picker/RandomPicker.java new file mode 100644 index 0000000000..ac34817e6f --- /dev/null +++ b/src/main/java/lotto/domain/picker/RandomPicker.java @@ -0,0 +1,11 @@ +package lotto.domain.picker; + +import camp.nextstep.edu.missionutils.Randoms; + +public class RandomPicker implements Picker { + + @Override + public int pick(int minValue, int maxValue) { + return Randoms.pickNumberInRange(minValue, maxValue); + } +} diff --git a/src/main/java/lotto/ui/Input.java b/src/main/java/lotto/ui/Input.java new file mode 100644 index 0000000000..690e96f6be --- /dev/null +++ b/src/main/java/lotto/ui/Input.java @@ -0,0 +1,57 @@ +package lotto.ui; + +import camp.nextstep.edu.missionutils.Console; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class Input { + + private static final String DELIMITER = ", "; + + + private Input() { + throw new UnsupportedOperationException(); + } + + public static int getMoneyValue() { + System.out.println("구입금액을 입력해 주세요."); + final String input = Console.readLine(); + return getAnInt(input); + } + + private static int getAnInt(String input) { + return Integer.parseInt(input); + } + + public static int getManualLottoCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + final String input = Console.readLine(); + return getAnInt(input); + } + + public static List> getManualLottos(int manualLottoCount) { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + + return IntStream.range(0, manualLottoCount) + .mapToObj(i -> Console.readLine()) + .map(lotto -> Arrays.stream(lotto.split(DELIMITER)).map(Input::getAnInt).collect(Collectors.toList())) + .collect(Collectors.toList()); + } + + public static List getWinningLotto() { + System.out.println("지난 주 당첨 번호를 입력해 주세요."); + final String input = Console.readLine(); + + return Arrays.stream(input.split(DELIMITER)) + .map(Input::getAnInt) + .collect(Collectors.toList()); + } + + public static int getBonusBall() { + System.out.println("보너스 볼을 입력해 주세요."); + final String input = Console.readLine(); + return getAnInt(input); + } +} diff --git a/src/main/java/lotto/ui/Output.java b/src/main/java/lotto/ui/Output.java new file mode 100644 index 0000000000..dca4985c9c --- /dev/null +++ b/src/main/java/lotto/ui/Output.java @@ -0,0 +1,25 @@ +package lotto.ui; + +import lotto.domain.LottoRanks; +import lotto.domain.Money; +import lotto.domain.Ticket; + +public class Output { + + private Output() { + throw new UnsupportedOperationException(); + } + + public static void printTicket(int manualLottoCount, Ticket manualTicket, int autoLottoCount, Ticket autoTicket) { + System.out.printf("수동으로 %d장, 자동으로 %d개를 구매했습니다.%n", manualLottoCount, autoLottoCount); + System.out.println(manualTicket); + System.out.println(autoTicket); + } + + public static void printResult(Money money, LottoRanks ranks) { + System.out.println("당첨 통계"); + System.out.println("---------"); + System.out.println(ranks); + System.out.printf("총 수익률은 %.2f입니다.", money.getProfitRate(ranks.getProfit())); + } +} diff --git a/src/test/java/lotto/ApplicationTest.java b/src/test/java/lotto/ApplicationTest.java deleted file mode 100644 index 2f585d0e06..0000000000 --- a/src/test/java/lotto/ApplicationTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package lotto; - -import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; -import static org.assertj.core.api.Assertions.assertThat; - -import camp.nextstep.edu.missionutils.test.NsTest; -import org.junit.jupiter.api.Test; - -class ApplicationTest extends NsTest { - private static final String ERROR_MESSAGE = "[ERROR]"; - - @Test - void 예외_테스트() { - assertSimpleTest(() -> { - runException("1000j"); - assertThat(output()).contains(ERROR_MESSAGE); - }); - } - - @Override - public void runMain() { - Application.main(new String[]{}); - } -} diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java new file mode 100644 index 0000000000..0bc26033c5 --- /dev/null +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -0,0 +1,38 @@ +package lotto.domain; + +import lotto.domain.picker.RandomPicker; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class LottoNumberTest { + + @ParameterizedTest + @ValueSource(ints = {-1, 0, 46}) + void 로또_숫자_생성_시_로또_숫자의_범위에_속하지_않으면_예외를_던진다(int value) { + Assertions.assertThatThrownBy(() -> LottoNumber.from(value)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(String.format("[ERROR] 로또 숫자는 %d일 수 없습니다.", value)); + } + + @Test + void 로또_숫자를_뽑을_수_있다() { + Assertions.assertThatCode(() -> LottoNumber.pick((min, max) -> 1)) + .doesNotThrowAnyException(); + } + + @Test + void 로또_숫자를_랜덤하게_뽑을_수_있다() { + Assertions.assertThatCode(() -> LottoNumber.pick(new RandomPicker())) + .doesNotThrowAnyException(); + } + + @ParameterizedTest + @ValueSource(ints = {-1, 0, 46}) + void 로또_숫자_뽑기_시_로또_숫자의_범위에_속하지_않으면_예외를_던진다(int value) { + Assertions.assertThatThrownBy(() -> LottoNumber.pick((min, max) -> value)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(String.format("[ERROR] 로또 숫자는 %d일 수 없습니다.", value)); + } +} diff --git a/src/test/java/lotto/domain/LottoRankTest.java b/src/test/java/lotto/domain/LottoRankTest.java new file mode 100644 index 0000000000..74e54502d3 --- /dev/null +++ b/src/test/java/lotto/domain/LottoRankTest.java @@ -0,0 +1,44 @@ +package lotto.domain; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class LottoRankTest { + + public static Stream findRank() { + return Stream.of( + Arguments.of(List.of(1, 2, 3, 4, 5, 6), LottoRank.FIRST), + Arguments.of(List.of(1, 2, 3, 4, 5, 7), LottoRank.SECOND), + Arguments.of(List.of(1, 2, 3, 4, 5, 8), LottoRank.THIRD), + Arguments.of(List.of(1, 2, 3, 4, 7, 8), LottoRank.FOURTH), + Arguments.of(List.of(1, 2, 3, 7, 8, 9), LottoRank.FIFTH), + Arguments.of(List.of(1, 2, 7, 8, 9, 10), LottoRank.OTHER) + ); + } + + @ParameterizedTest + @MethodSource("findRank") + void 로또_당첨_등수를_확인한다(List numbers, LottoRank expect) { + // given + final Lotto winningLotto = Lotto.create(count -> IntStream.rangeClosed(1, 6) + .mapToObj(LottoNumber::from) + .collect(Collectors.toSet())); + + final LottoNumber bonusBall = LottoNumber.from(7); + final WinningLotto winNumbers = new WinningLotto(winningLotto, bonusBall); + + final Lotto lotto = Lotto.create(count -> numbers.stream().map(LottoNumber::from).collect(Collectors.toSet())); + + // when + final LottoRank actual = LottoRank.calculateRank(winNumbers, lotto); + + // then + Assertions.assertThat(actual).isEqualTo(expect); + } +} diff --git a/src/test/java/lotto/domain/LottoTest.java b/src/test/java/lotto/domain/LottoTest.java new file mode 100644 index 0000000000..cd7f225efe --- /dev/null +++ b/src/test/java/lotto/domain/LottoTest.java @@ -0,0 +1,87 @@ +package lotto.domain; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import lotto.domain.lottocreator.AutoLottoCreator; +import lotto.domain.lottocreator.LottoCreator; +import lotto.domain.lottocreator.ManualLottoCreator; +import lotto.domain.picker.RandomPicker; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; + +class LottoTest { + + public static Stream invalidLotto() { + return Stream.of(Arguments.of(List.of(1, 2, 3, 4, 5)), Arguments.of(List.of(1, 2, 3, 4, 5, 6, 7))); + } + + public static Stream LottoCreator() { + return Stream.of( + Arguments.of(new AutoLottoCreator(new RandomPicker())), + Arguments.of(new ManualLottoCreator(List.of(1, 2, 3, 4, 5, 6))) + ); + } + + @ParameterizedTest + @MethodSource("LottoCreator") + void 로또_생성기로_로또를_생성할_수_있다(LottoCreator creator) { + Assertions.assertThatCode(() -> Lotto.create(creator)) + .doesNotThrowAnyException(); + } + + @ParameterizedTest + @MethodSource("invalidLotto") + void 로또_숫자가_6개가_아니면_예외를_던진다(List numbers) { + Assertions.assertThatThrownBy(() -> Lotto.create(new ManualLottoCreator(numbers))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 로또_숫자가_존재하는지_확인한다() { + // given + final LottoNumber bonusBall = LottoNumber.from(1); + final Lotto lotto = Lotto.create(count -> IntStream.rangeClosed(1, 6) + .mapToObj(LottoNumber::from) + .collect(Collectors.toSet())); + + // when + final boolean result = lotto.contains(bonusBall); + + // then + Assertions.assertThat(result).isTrue(); + } + + @ParameterizedTest + @CsvSource(value = { + "6,1,2,3,4,5,6", + "5,1,2,3,4,5,7", + "4,1,2,3,4,7,8", + "3,1,2,3,7,8,9", + "2,1,2,7,8,9,10", + "1,1,7,8,9,10,11", + "0,7,8,9,10,11,12" + }) + void 같은_숫자가_몇_개인지_반환한다(int expected, int n1, int n2, int n3, int n4, int n5, int n6) { + // given + final Lotto winningLotto = Lotto.create(count -> IntStream.rangeClosed(1, 6) + .mapToObj(LottoNumber::from) + .collect(Collectors.toSet())); + + final Lotto lotto = Lotto.create( + count -> Set.of(LottoNumber.from(n1), LottoNumber.from(n2), LottoNumber.from(n3), + LottoNumber.from(n4), LottoNumber.from(n5), LottoNumber.from(n6))); + + // when + final int actual = winningLotto.calculateSameLottoNumber(lotto); + + // then + Assertions.assertThat(actual).isEqualTo(expected); + } +} diff --git a/src/test/java/lotto/domain/MoneyTest.java b/src/test/java/lotto/domain/MoneyTest.java new file mode 100644 index 0000000000..e69814dd93 --- /dev/null +++ b/src/test/java/lotto/domain/MoneyTest.java @@ -0,0 +1,52 @@ +package lotto.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class MoneyTest { + + @ParameterizedTest + @ValueSource(ints = {-1, 0, 999, 1001}) + void 금액이_단위에_맞지_않으면_예외를_던진다(int value) { + Assertions.assertThatThrownBy(() -> new Money(value)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 금액으로_주어진_로또_갯수를_구매할_수_있는지_판단한다() { + // given + final Money money = new Money(10000); + + // when + final boolean result = money.canBuy(10); + + // then + Assertions.assertThat(result).isTrue(); + } + + @Test + void 금액으로_주어진_로또_갯수를_구매할_수_없는지_판단한다() { + // given + final Money money = new Money(10000); + + // when + final boolean result = money.canBuy(11); + + // then + Assertions.assertThat(result).isFalse(); + } + + @Test + void 금액으로_주어진_로또_갯수를_구매하고_남은_구매_가능_갯수를_반환한다() { + // given + final Money money = new Money(10000); + + // when + final int result = money.remainCount(10); + + // then + Assertions.assertThat(result).isEqualTo(0); + } +} diff --git a/src/test/java/lotto/domain/TicketTest.java b/src/test/java/lotto/domain/TicketTest.java new file mode 100644 index 0000000000..3e248818a4 --- /dev/null +++ b/src/test/java/lotto/domain/TicketTest.java @@ -0,0 +1,20 @@ +package lotto.domain; + +import lotto.domain.lottocreator.AutoLottoCreator; +import lotto.domain.lottocreator.LottoCreator; +import lotto.domain.picker.RandomPicker; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class TicketTest { + + @Test + void 로또_티켓을_생성할_수_있다() { + // given + final LottoCreator autoLottoCreator = new AutoLottoCreator(new RandomPicker()); + + // when & then + Assertions.assertThatCode(() -> Ticket.of(autoLottoCreator, 5)) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/lotto/domain/WinningLottoTest.java b/src/test/java/lotto/domain/WinningLottoTest.java new file mode 100644 index 0000000000..336f786b95 --- /dev/null +++ b/src/test/java/lotto/domain/WinningLottoTest.java @@ -0,0 +1,21 @@ +package lotto.domain; + +import java.util.Set; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class WinningLottoTest { + + @Test + void 보너스_볼이_이미_로또에_존재하면_예외를_던진다() { + // given + final LottoNumber bonusBall = LottoNumber.from(1); + final Lotto winningLotto = Lotto.create( + lottoCount -> Set.of(bonusBall, LottoNumber.from(2), LottoNumber.from(3), + LottoNumber.from(4), LottoNumber.from(5), LottoNumber.from(6))); + + // when & then + Assertions.assertThatThrownBy(() -> new WinningLotto(winningLotto, bonusBall)) + .isInstanceOf(IllegalArgumentException.class); + } +}