From 060805236554dc218622b9b14a8aaefb8f3f8bae Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 22:12:02 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20LottoNumber=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoNumber.java | 34 +++++++++++++++++++ .../java/lotto/domain/LottoNumberTest.java | 16 +++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/main/java/lotto/domain/LottoNumber.java create mode 100644 src/test/java/lotto/domain/LottoNumberTest.java diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java new file mode 100644 index 0000000000..4a7aa2ee3f --- /dev/null +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -0,0 +1,34 @@ +package lotto.domain; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class LottoNumber { + 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 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)); + } + } +} diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java new file mode 100644 index 0000000000..3fceafdc5c --- /dev/null +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -0,0 +1,16 @@ +package lotto.domain; + +import org.assertj.core.api.Assertions; +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)); + } +} From 82fd9deada261555d955d9c89080002f48fabb35 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 22:31:32 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20LottoNumber=20=EB=BD=91=EB=8A=94?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoNumber.java | 5 +++++ src/main/java/lotto/domain/picker/Picker.java | 5 +++++ src/test/java/lotto/domain/LottoNumberTest.java | 7 +++++++ 3 files changed, 17 insertions(+) create mode 100644 src/main/java/lotto/domain/picker/Picker.java diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java index 4a7aa2ee3f..3362be40bc 100644 --- a/src/main/java/lotto/domain/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; +import lotto.domain.picker.Picker; public class LottoNumber { private static final int MIN_VALUE = 1; @@ -21,6 +22,10 @@ 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); 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..61f206a138 --- /dev/null +++ b/src/main/java/lotto/domain/picker/Picker.java @@ -0,0 +1,5 @@ +package lotto.domain.picker; + +public interface Picker { + T pick(T minValue, T maxValue); +} diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java index 3fceafdc5c..7df2134966 100644 --- a/src/test/java/lotto/domain/LottoNumberTest.java +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -1,6 +1,7 @@ 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; @@ -13,4 +14,10 @@ class LottoNumberTest { .isInstanceOf(IllegalArgumentException.class) .hasMessage(String.format("[ERROR] 로또 숫자는 %d일 수 없습니다.", value)); } + + @Test + void 로또_숫자를_뽑을_수_있다() { + Assertions.assertThatCode(() -> LottoNumber.pick((min, max) -> 1)) + .doesNotThrowAnyException(); + } } From ad212c5c2bb8b523b91534de526b04e3e5dadef7 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 22:37:38 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20LottoNumber=20=EB=9E=9C=EB=8D=A4?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=BD=91=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoNumber.java | 2 +- src/main/java/lotto/domain/picker/Picker.java | 4 ++-- .../java/lotto/domain/picker/RandomPicker.java | 11 +++++++++++ src/test/java/lotto/domain/LottoNumberTest.java | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/main/java/lotto/domain/picker/RandomPicker.java diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java index 3362be40bc..1ed346cfa5 100644 --- a/src/main/java/lotto/domain/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -22,7 +22,7 @@ private LottoNumber(int value) { this.value = value; } - public static LottoNumber pick(Picker picker) { + public static LottoNumber pick(Picker picker) { return LottoNumber.from(picker.pick(MIN_VALUE, MAX_VALUE)); } diff --git a/src/main/java/lotto/domain/picker/Picker.java b/src/main/java/lotto/domain/picker/Picker.java index 61f206a138..db8502fd85 100644 --- a/src/main/java/lotto/domain/picker/Picker.java +++ b/src/main/java/lotto/domain/picker/Picker.java @@ -1,5 +1,5 @@ package lotto.domain.picker; -public interface Picker { - T pick(T minValue, T maxValue); +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..9f38dd8dfe --- /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(maxValue, maxValue); + } +} diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java index 7df2134966..0bc26033c5 100644 --- a/src/test/java/lotto/domain/LottoNumberTest.java +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -1,5 +1,6 @@ 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; @@ -20,4 +21,18 @@ class LottoNumberTest { 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)); + } } From f08f8b84beacb389c44485280e19dfabd3367fa7 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Mon, 3 Apr 2023 22:20:32 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Lotto.java | 26 +++++++++++ src/main/java/lotto/domain/LottoNumber.java | 18 ++++++++ .../domain/lottocreator/AutoLottoCreator.java | 24 ++++++++++ .../domain/lottocreator/LottoCreator.java | 8 ++++ .../lottocreator/ManualLottoCreator.java | 30 ++++++++++++ .../lotto/domain/picker/RandomPicker.java | 2 +- src/test/java/lotto/domain/LottoTest.java | 46 +++++++++++++++++++ 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 src/main/java/lotto/domain/Lotto.java create mode 100644 src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java create mode 100644 src/main/java/lotto/domain/lottocreator/LottoCreator.java create mode 100644 src/main/java/lotto/domain/lottocreator/ManualLottoCreator.java create mode 100644 src/test/java/lotto/domain/LottoTest.java diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java new file mode 100644 index 0000000000..e59f359860 --- /dev/null +++ b/src/main/java/lotto/domain/Lotto.java @@ -0,0 +1,26 @@ +package lotto.domain; + +import java.util.Set; +import lotto.domain.lottocreator.LottoCreator; + +public class Lotto { + + private static final int LOTTO_SIZE = 6; + + private final Set numbers; + + public Lotto(Set numbers) { + validateLength(numbers); + this.numbers = numbers; + } + + private void validateLength(Set numbers) { + if (numbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자 개수는 %d일 수 없습니다.", numbers.size())); + } + } + + public static Lotto create(LottoCreator creator) { + return new Lotto(creator.create(LOTTO_SIZE)); + } +} diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java index 1ed346cfa5..cce06b8cb5 100644 --- a/src/main/java/lotto/domain/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -1,6 +1,7 @@ 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; @@ -36,4 +37,21 @@ private static void validateRange(int 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); + } } 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..ee68823b51 --- /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/RandomPicker.java b/src/main/java/lotto/domain/picker/RandomPicker.java index 9f38dd8dfe..ac34817e6f 100644 --- a/src/main/java/lotto/domain/picker/RandomPicker.java +++ b/src/main/java/lotto/domain/picker/RandomPicker.java @@ -6,6 +6,6 @@ public class RandomPicker implements Picker { @Override public int pick(int minValue, int maxValue) { - return Randoms.pickNumberInRange(maxValue, maxValue); + return Randoms.pickNumberInRange(minValue, maxValue); } } diff --git a/src/test/java/lotto/domain/LottoTest.java b/src/test/java/lotto/domain/LottoTest.java new file mode 100644 index 0000000000..3f0db8bf82 --- /dev/null +++ b/src/test/java/lotto/domain/LottoTest.java @@ -0,0 +1,46 @@ +package lotto.domain; + +import java.util.List; +import java.util.Set; +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.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class LottoTest { + + public static Stream invalidLotto() { + return Stream.of( + Arguments.of(Set.of(LottoNumber.from(1), LottoNumber.from(2), LottoNumber.from(3), + LottoNumber.from(4), LottoNumber.from(5))), + Arguments.of(Set.of(LottoNumber.from(1), LottoNumber.from(2), LottoNumber.from(3), + LottoNumber.from(4), LottoNumber.from(5), LottoNumber.from(6), LottoNumber.from(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("invalidLotto") + void 로또_숫자가_6개가_아니면_예외를_던진다(Set numbers) { + Assertions.assertThatThrownBy(() -> new Lotto(numbers)) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @MethodSource("LottoCreator") + void 로또_생성기로_로또를_생성할_수_있다(LottoCreator creator) { + Assertions.assertThatCode(() -> Lotto.create(creator)) + .doesNotThrowAnyException(); + } +} From 4ad0cb23de21ceb1a563e2f6ad43212cd0546aee Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Mon, 3 Apr 2023 22:29:39 +0900 Subject: [PATCH 05/12] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=ED=8B=B0?= =?UTF-8?q?=EC=BC=93=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Ticket.java | 22 ++++++++++++++++++++++ src/test/java/lotto/domain/TicketTest.java | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/lotto/domain/Ticket.java create mode 100644 src/test/java/lotto/domain/TicketTest.java diff --git a/src/main/java/lotto/domain/Ticket.java b/src/main/java/lotto/domain/Ticket.java new file mode 100644 index 0000000000..1d64f49470 --- /dev/null +++ b/src/main/java/lotto/domain/Ticket.java @@ -0,0 +1,22 @@ +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); + } +} 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(); + } +} From 9675356cc1f38537a2e0a48078745a1882d73a72 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Mon, 3 Apr 2023 22:55:33 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Money.java | 26 ++++++++++++ src/test/java/lotto/domain/MoneyTest.java | 52 +++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/main/java/lotto/domain/Money.java create mode 100644 src/test/java/lotto/domain/MoneyTest.java diff --git a/src/main/java/lotto/domain/Money.java b/src/main/java/lotto/domain/Money.java new file mode 100644 index 0000000000..7345c15a0c --- /dev/null +++ b/src/main/java/lotto/domain/Money.java @@ -0,0 +1,26 @@ +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; + } +} 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); + } +} From 4851fab0ee0022ba86439acfcd42571fbaca1fae Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Mon, 3 Apr 2023 23:36:31 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20Application=20=ED=9D=90=EB=A6=84?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 36 +++++++++++++++++++- src/main/java/lotto/ui/Input.java | 43 ++++++++++++++++++++++++ src/test/java/lotto/ApplicationTest.java | 24 ------------- 3 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 src/main/java/lotto/ui/Input.java delete mode 100644 src/test/java/lotto/ApplicationTest.java diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..ae3eee7cb3 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,41 @@ package lotto; +import java.util.List; +import java.util.stream.Collectors; +import lotto.domain.Lotto; +import lotto.domain.Money; +import lotto.domain.Ticket; +import lotto.domain.lottocreator.AutoLottoCreator; +import lotto.domain.lottocreator.ManualLottoCreator; +import lotto.domain.picker.RandomPicker; +import lotto.ui.Input; + 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); + + + } + + 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/ui/Input.java b/src/main/java/lotto/ui/Input.java new file mode 100644 index 0000000000..42ba97a5ff --- /dev/null +++ b/src/main/java/lotto/ui/Input.java @@ -0,0 +1,43 @@ +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()); + } + +} 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[]{}); - } -} From 596ebb920ff265bd833dcf389a56d8b6a01bcd5b Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 4 Apr 2023 00:38:15 +0900 Subject: [PATCH 08/12] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EC=99=80=20=EB=AA=87=20=EA=B0=9C=EA=B0=80=20=EA=B0=99?= =?UTF-8?q?=EC=9D=80=EC=A7=80=20=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 6 ++ src/main/java/lotto/domain/Lotto.java | 16 ++++- src/main/java/lotto/domain/WinningLotto.java | 28 ++++++++ src/main/java/lotto/ui/Input.java | 14 ++++ src/test/java/lotto/domain/LottoTest.java | 65 +++++++++++++++---- .../java/lotto/domain/WinningLottoTest.java | 23 +++++++ 6 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 src/main/java/lotto/domain/WinningLotto.java create mode 100644 src/test/java/lotto/domain/WinningLottoTest.java diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index ae3eee7cb3..697cf068f9 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -3,8 +3,10 @@ import java.util.List; import java.util.stream.Collectors; import lotto.domain.Lotto; +import lotto.domain.LottoNumber; 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; @@ -22,6 +24,10 @@ public static void main(String[] args) { final int autoLottoCount = money.remainCount(manualLottoCount); final Ticket autoTicket = Ticket.of(new AutoLottoCreator(new RandomPicker()), autoLottoCount); + final Lotto lotto = Lotto.create(new ManualLottoCreator(Input.getWinningLotto())); + final LottoNumber bonusBall = LottoNumber.from(Input.getBonusBall()); + WinningLotto winningLotto = new WinningLotto(lotto, bonusBall); + } diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index e59f359860..bb451460a3 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -9,18 +9,28 @@ public class Lotto { private final Set numbers; - public Lotto(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 static Lotto create(LottoCreator creator) { - return new Lotto(creator.create(LOTTO_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); } } 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/ui/Input.java b/src/main/java/lotto/ui/Input.java index 42ba97a5ff..690e96f6be 100644 --- a/src/main/java/lotto/ui/Input.java +++ b/src/main/java/lotto/ui/Input.java @@ -40,4 +40,18 @@ public static List> getManualLottos(int manualLottoCount) { .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/test/java/lotto/domain/LottoTest.java b/src/test/java/lotto/domain/LottoTest.java index 3f0db8bf82..cd7f225efe 100644 --- a/src/test/java/lotto/domain/LottoTest.java +++ b/src/test/java/lotto/domain/LottoTest.java @@ -2,25 +2,24 @@ 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(Set.of(LottoNumber.from(1), LottoNumber.from(2), LottoNumber.from(3), - LottoNumber.from(4), LottoNumber.from(5))), - Arguments.of(Set.of(LottoNumber.from(1), LottoNumber.from(2), LottoNumber.from(3), - LottoNumber.from(4), LottoNumber.from(5), LottoNumber.from(6), LottoNumber.from(7)) - )); + 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() { @@ -30,17 +29,59 @@ public static Stream LottoCreator() { ); } + @ParameterizedTest + @MethodSource("LottoCreator") + void 로또_생성기로_로또를_생성할_수_있다(LottoCreator creator) { + Assertions.assertThatCode(() -> Lotto.create(creator)) + .doesNotThrowAnyException(); + } + @ParameterizedTest @MethodSource("invalidLotto") - void 로또_숫자가_6개가_아니면_예외를_던진다(Set numbers) { - Assertions.assertThatThrownBy(() -> new Lotto(numbers)) + 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 - @MethodSource("LottoCreator") - void 로또_생성기로_로또를_생성할_수_있다(LottoCreator creator) { - Assertions.assertThatCode(() -> Lotto.create(creator)) - .doesNotThrowAnyException(); + @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/WinningLottoTest.java b/src/test/java/lotto/domain/WinningLottoTest.java new file mode 100644 index 0000000000..129a27570c --- /dev/null +++ b/src/test/java/lotto/domain/WinningLottoTest.java @@ -0,0 +1,23 @@ +package lotto.domain; + +import java.util.Set; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +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); + } +} From af74f6614b435a7fd9f856992b017494c77c9481 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 4 Apr 2023 00:45:43 +0900 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=93=B1?= =?UTF-8?q?=EC=88=98=20=ED=8C=90=EB=8B=A8=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoRank.java | 41 +++++++++++++++++ src/test/java/lotto/domain/LottoRankTest.java | 44 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/main/java/lotto/domain/LottoRank.java create mode 100644 src/test/java/lotto/domain/LottoRankTest.java diff --git a/src/main/java/lotto/domain/LottoRank.java b/src/main/java/lotto/domain/LottoRank.java new file mode 100644 index 0000000000..a9960aecb0 --- /dev/null +++ b/src/main/java/lotto/domain/LottoRank.java @@ -0,0 +1,41 @@ +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() { + return String.format("%d개 일치%s (%,d원)", this.count, this.bonus ? ", 보너스 볼 일치" : "", this.prize); + } +} 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); + } +} From bbaf05854d8ded61bb8482ef9b0ed31458a513e5 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 4 Apr 2023 01:17:34 +0900 Subject: [PATCH 10/12] =?UTF-8?q?feat:=20Application=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 10 ++++- src/main/java/lotto/domain/Lotto.java | 9 +++++ src/main/java/lotto/domain/LottoNumber.java | 12 +++++- src/main/java/lotto/domain/LottoRank.java | 9 ++++- src/main/java/lotto/domain/LottoRanks.java | 39 +++++++++++++++++++ src/main/java/lotto/domain/Money.java | 4 ++ src/main/java/lotto/domain/Ticket.java | 13 +++++++ .../domain/lottocreator/AutoLottoCreator.java | 2 +- src/main/java/lotto/ui/Output.java | 25 ++++++++++++ .../java/lotto/domain/WinningLottoTest.java | 2 - 10 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 src/main/java/lotto/domain/LottoRanks.java create mode 100644 src/main/java/lotto/ui/Output.java diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 697cf068f9..1adb5b198d 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -4,6 +4,8 @@ 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; @@ -11,6 +13,7 @@ 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) { @@ -20,15 +23,20 @@ public static void main(String[] args) { 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) { diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index bb451460a3..8ae251c589 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,6 +1,7 @@ package lotto.domain; import java.util.Set; +import java.util.stream.Collectors; import lotto.domain.lottocreator.LottoCreator; public class Lotto { @@ -33,4 +34,12 @@ public int calculateSameLottoNumber(Lotto other) { 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 index cce06b8cb5..44912b1967 100644 --- a/src/main/java/lotto/domain/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -6,7 +6,7 @@ import java.util.stream.IntStream; import lotto.domain.picker.Picker; -public class LottoNumber { +public class LottoNumber implements Comparable { private static final int MIN_VALUE = 1; private static final int MAX_VALUE = 45; private static final List VALUES; @@ -54,4 +54,14 @@ public boolean equals(Object o) { 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 index a9960aecb0..11eacad008 100644 --- a/src/main/java/lotto/domain/LottoRank.java +++ b/src/main/java/lotto/domain/LottoRank.java @@ -36,6 +36,13 @@ public int getPrize() { @Override public String toString() { - return String.format("%d개 일치%s (%,d원)", this.count, this.bonus ? ", 보너스 볼 일치" : "", this.prize); + 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..9cdc7c11aa --- /dev/null +++ b/src/main/java/lotto/domain/LottoRanks.java @@ -0,0 +1,39 @@ +package lotto.domain; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +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) { + EnumMap lottoRankMap = new EnumMap<>(LottoRank.class); + Arrays.stream(LottoRank.values()).forEach(rank -> lottoRankMap.put(rank, 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 ranks.entrySet() + .stream() + .filter(entry -> entry.getKey().isNotOtherRank()) + .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 index 7345c15a0c..ebef47a21a 100644 --- a/src/main/java/lotto/domain/Money.java +++ b/src/main/java/lotto/domain/Money.java @@ -23,4 +23,8 @@ public boolean canBuy(int 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 index 1d64f49470..5c0d6f5b42 100644 --- a/src/main/java/lotto/domain/Ticket.java +++ b/src/main/java/lotto/domain/Ticket.java @@ -19,4 +19,17 @@ public static Ticket of(LottoCreator creator, int count) { 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/lottocreator/AutoLottoCreator.java b/src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java index ee68823b51..cdfa796be3 100644 --- a/src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java +++ b/src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java @@ -6,7 +6,7 @@ import lotto.domain.LottoNumber; import lotto.domain.picker.Picker; -public class AutoLottoCreator implements LottoCreator{ +public class AutoLottoCreator implements LottoCreator { private final Picker picker; 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/domain/WinningLottoTest.java b/src/test/java/lotto/domain/WinningLottoTest.java index 129a27570c..336f786b95 100644 --- a/src/test/java/lotto/domain/WinningLottoTest.java +++ b/src/test/java/lotto/domain/WinningLottoTest.java @@ -3,8 +3,6 @@ import java.util.Set; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; class WinningLottoTest { From 3010836454bb4571ec8386ad529921b435737df5 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 4 Apr 2023 03:27:12 +0900 Subject: [PATCH 11/12] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoRanks.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/lotto/domain/LottoRanks.java b/src/main/java/lotto/domain/LottoRanks.java index 9cdc7c11aa..cb36167421 100644 --- a/src/main/java/lotto/domain/LottoRanks.java +++ b/src/main/java/lotto/domain/LottoRanks.java @@ -1,9 +1,10 @@ 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.function.Function; import java.util.stream.Collectors; public class LottoRanks { @@ -14,11 +15,9 @@ private LottoRanks(Map ranks) { } public static LottoRanks from(List ranks) { - EnumMap lottoRankMap = new EnumMap<>(LottoRank.class); - Arrays.stream(LottoRank.values()).forEach(rank -> lottoRankMap.put(rank, 0)); - - ranks.forEach(rank -> lottoRankMap.computeIfPresent(rank, (key, value) -> value + 1)); - return new LottoRanks(lottoRankMap); + return new LottoRanks( + ranks.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(e -> 1))) + ); } public int getProfit() { @@ -30,9 +29,13 @@ public int getProfit() { @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")); } From 030ea7713fb1d51d4ec8b6c4edec43a208c90ee7 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Wed, 5 Apr 2023 02:10:55 +0900 Subject: [PATCH 12/12] =?UTF-8?q?refactor:=20LottoRanks=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoRanks.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/domain/LottoRanks.java b/src/main/java/lotto/domain/LottoRanks.java index cb36167421..391749a2ff 100644 --- a/src/main/java/lotto/domain/LottoRanks.java +++ b/src/main/java/lotto/domain/LottoRanks.java @@ -1,9 +1,11 @@ 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; @@ -16,7 +18,7 @@ private LottoRanks(Map ranks) { public static LottoRanks from(List ranks) { return new LottoRanks( - ranks.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(e -> 1))) + ranks.stream().collect(Collectors.toMap(Function.identity(), rank -> 1, Integer::sum)) ); }