From a19947253dfbf1dcf4cac084c8308cee6dfec63f Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Sat, 25 Mar 2023 02:07:33 +0900 Subject: [PATCH 01/16] =?UTF-8?q?feat:=20Lotto=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=ED=8C=A8=ED=82=A4=EC=A7=80=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}/Lotto.java | 2 +- src/test/java/lotto/{ => domain}/LottoTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename src/main/java/lotto/{ => domain}/Lotto.java (94%) rename src/test/java/lotto/{ => domain}/LottoTest.java (94%) diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/domain/Lotto.java similarity index 94% rename from src/main/java/lotto/Lotto.java rename to src/main/java/lotto/domain/Lotto.java index 519793d1f7..366657953a 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,4 +1,4 @@ -package lotto; +package lotto.domain; import java.util.List; diff --git a/src/test/java/lotto/LottoTest.java b/src/test/java/lotto/domain/LottoTest.java similarity index 94% rename from src/test/java/lotto/LottoTest.java rename to src/test/java/lotto/domain/LottoTest.java index 0f3af0f6c4..1ac857aadd 100644 --- a/src/test/java/lotto/LottoTest.java +++ b/src/test/java/lotto/domain/LottoTest.java @@ -1,5 +1,6 @@ -package lotto; +package lotto.domain; +import lotto.domain.Lotto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 7735f66317fc1e389f49a3daa56d8fc1ee13714d Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Sat, 25 Mar 2023 02:13:20 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat:=20Money=20class=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Money.java | 17 +++++++++++++++++ src/test/java/lotto/domain/MoneyTest.java | 22 ++++++++++++++++++++++ 2 files changed, 39 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..5f61e494cb --- /dev/null +++ b/src/main/java/lotto/domain/Money.java @@ -0,0 +1,17 @@ +package lotto.domain; + +public class Money { + private static final int MIN_VALUE = 1000; + private final int value; + + public Money(int value) { + validate(value); + this.value = value; + } + + private void validate(int value) { + if (value < MIN_VALUE || value % MIN_VALUE != 0) { + throw new IllegalArgumentException(String.format("[ERROR] 금액은 %d원일 수 없습니다.", value)); + } + } +} diff --git a/src/test/java/lotto/domain/MoneyTest.java b/src/test/java/lotto/domain/MoneyTest.java new file mode 100644 index 0000000000..d6b341e81b --- /dev/null +++ b/src/test/java/lotto/domain/MoneyTest.java @@ -0,0 +1,22 @@ +package lotto.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class MoneyTest { + + @ParameterizedTest + @ValueSource(ints = {-1, 0, 999, 1001, 10001}) + void 금액이_1000원_미만이거나_1000으로_나눠지지_않는_경우_예외를_던진다(int value) { + Assertions.assertThatThrownBy(() -> new Money(value)) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @ValueSource(ints = {1000, 12000}) + void 금액이_1000원으로_나눠지는_경우_성공(int value) { + Assertions.assertThatCode(() -> new Money(value)) + .doesNotThrowAnyException(); + } +} From 02d4d329e3fdc1049b6e0b1f557dd81cd7af871c Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Sat, 25 Mar 2023 02:19:02 +0900 Subject: [PATCH 03/16] =?UTF-8?q?feat:=20LottoNumber=20class=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Lotto.java | 6 +-- src/main/java/lotto/domain/LottoNumber.java | 53 +++++++++++++++++++ .../java/lotto/domain/LottoNumberTest.java | 22 ++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) 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/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 366657953a..3e3b9d219d 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -3,14 +3,14 @@ import java.util.List; public class Lotto { - private final List numbers; + private final List numbers; - public Lotto(List numbers) { + public Lotto(List numbers) { validate(numbers); this.numbers = numbers; } - private void validate(List numbers) { + private void validate(List numbers) { if (numbers.size() != 6) { throw new IllegalArgumentException(); } diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java new file mode 100644 index 0000000000..3bb595352f --- /dev/null +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -0,0 +1,53 @@ +package lotto.domain; + +import java.util.List; +import java.util.Objects; +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 NUMBERS; + + static { + NUMBERS = 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 NUMBERS.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); + } +} diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java new file mode 100644 index 0000000000..cfbf1b61c2 --- /dev/null +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -0,0 +1,22 @@ +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 로또_숫자가_1부터_45_사이의_수가_아니면_예외를_던진다(int value) { + Assertions.assertThatThrownBy(() -> LottoNumber.from(value)) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @ValueSource(ints = {1, 45}) + void 로또_숫자가_1부터_45_사이의_수라면_로또_넘버를_생성할_수_있다(int value) { + Assertions.assertThatCode(() -> LottoNumber.from(value)) + .doesNotThrowAnyException(); + } +} From 59107a83e4d699b6b3282015030eb8020d939e22 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Sat, 25 Mar 2023 02:40:35 +0900 Subject: [PATCH 04/16] =?UTF-8?q?feat:=20Lotto=20class=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20=ED=95=84=EB=93=9C=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/Lotto.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 3e3b9d219d..bda8c08798 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,18 +1,24 @@ package lotto.domain; import java.util.List; +import java.util.stream.Collectors; public class Lotto { + private static final int LOTTO_NUMBERS_SIZE = 6; private final List numbers; - public Lotto(List numbers) { + public Lotto(List values) { + final List numbers = values.stream() + .map(LottoNumber::from) + .distinct() + .collect(Collectors.toList()); validate(numbers); this.numbers = numbers; } private void validate(List numbers) { - if (numbers.size() != 6) { - throw new IllegalArgumentException(); + if (numbers.size() != LOTTO_NUMBERS_SIZE) { + throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자의 개수는 %d일 수 없습니다.", numbers.size())); } } From bdeee94769fa4c0c8a201400de5634a762e1c55f Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 28 Mar 2023 12:27:29 +0900 Subject: [PATCH 05/16] =?UTF-8?q?refactor:=20LottoNumber=20class=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Lotto.java | 33 ++++++++---- src/main/java/lotto/domain/LottoNumber.java | 53 ------------------- .../java/lotto/domain/LottoNumberTest.java | 22 -------- src/test/java/lotto/domain/LottoTest.java | 17 ++++-- 4 files changed, 37 insertions(+), 88 deletions(-) delete mode 100644 src/main/java/lotto/domain/LottoNumber.java delete mode 100644 src/test/java/lotto/domain/LottoNumberTest.java diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index bda8c08798..a71f22b693 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,26 +1,39 @@ package lotto.domain; +import java.util.HashSet; import java.util.List; -import java.util.stream.Collectors; public class Lotto { private static final int LOTTO_NUMBERS_SIZE = 6; - private final List numbers; + private static final int MIN_LOTTO_NUMBER = 1; + private static final int MAX_LOTTO_NUMBER = 45; - public Lotto(List values) { - final List numbers = values.stream() - .map(LottoNumber::from) - .distinct() - .collect(Collectors.toList()); - validate(numbers); + private final List numbers; + + public Lotto(List numbers) { + validateSize(numbers); + validateDuplicated(numbers); + validateNumbersRange(numbers); this.numbers = numbers; } - private void validate(List numbers) { + private void validateSize(List numbers) { if (numbers.size() != LOTTO_NUMBERS_SIZE) { throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자의 개수는 %d일 수 없습니다.", numbers.size())); } } - // TODO: 추가 기능 구현 + private void validateDuplicated(List numbers) { + if (numbers.size() != new HashSet<>(numbers).size()) { + throw new IllegalArgumentException("[ERROR] 중복되는 숫자가 존재합니다."); + } + } + + private void validateNumbersRange(List numbers) { + if (numbers.stream().anyMatch(number -> number < MIN_LOTTO_NUMBER || number > MAX_LOTTO_NUMBER)) { + throw new IllegalArgumentException( + String.format("[ERROR] %d ~ %d 범위를 넘어가는 숫자가 존재합니다.", MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER) + ); + } + } } diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java deleted file mode 100644 index 3bb595352f..0000000000 --- a/src/main/java/lotto/domain/LottoNumber.java +++ /dev/null @@ -1,53 +0,0 @@ -package lotto.domain; - -import java.util.List; -import java.util.Objects; -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 NUMBERS; - - static { - NUMBERS = 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 NUMBERS.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); - } -} diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java deleted file mode 100644 index cfbf1b61c2..0000000000 --- a/src/test/java/lotto/domain/LottoNumberTest.java +++ /dev/null @@ -1,22 +0,0 @@ -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 로또_숫자가_1부터_45_사이의_수가_아니면_예외를_던진다(int value) { - Assertions.assertThatThrownBy(() -> LottoNumber.from(value)) - .isInstanceOf(IllegalArgumentException.class); - } - - @ParameterizedTest - @ValueSource(ints = {1, 45}) - void 로또_숫자가_1부터_45_사이의_수라면_로또_넘버를_생성할_수_있다(int value) { - Assertions.assertThatCode(() -> LottoNumber.from(value)) - .doesNotThrowAnyException(); - } -} diff --git a/src/test/java/lotto/domain/LottoTest.java b/src/test/java/lotto/domain/LottoTest.java index 1ac857aadd..839fd7e81b 100644 --- a/src/test/java/lotto/domain/LottoTest.java +++ b/src/test/java/lotto/domain/LottoTest.java @@ -5,6 +5,9 @@ import org.junit.jupiter.api.Test; import java.util.List; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -13,7 +16,8 @@ class LottoTest { @Test void createLottoByOverSize() { assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7))) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 로또 숫자의 개수는 7일 수 없습니다."); } @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.") @@ -21,8 +25,15 @@ void createLottoByOverSize() { void createLottoByDuplicatedNumber() { // TODO: 이 테스트가 통과할 수 있게 구현 코드 작성 assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 중복되는 숫자가 존재합니다."); } - // 아래에 추가 테스트 작성 가능 + @ParameterizedTest + @CsvSource(value = {"0,1,2,3,4,5", "1,2,3,4,5,46"}) + void 로또_번호의_범위를_벗어나는_숫자가_있으면_예외를_던진다(Integer n1, Integer n2, Integer n3, Integer n4, Integer n5, Integer n6) { + assertThatThrownBy(() -> new Lotto(List.of(n1, n2, n3, n4, n5, n6))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 1 ~ 45 범위를 넘어가는 숫자가 존재합니다."); + } } From f0f1e45734f09bb99c9d670075363f7b279cdc2f Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 28 Mar 2023 14:35:27 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat:=20Lotto=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=EC=83=9D=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 | 8 +++++++- .../AutoLottoNumberCreator.java | 11 +++++++++++ .../lottonumbercreator/LottoNumberCreator.java | 7 +++++++ src/test/java/lotto/domain/LottoTest.java | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/main/java/lotto/domain/lottonumbercreator/AutoLottoNumberCreator.java create mode 100644 src/main/java/lotto/domain/lottonumbercreator/LottoNumberCreator.java diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index a71f22b693..2f7fdbff79 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,7 +1,9 @@ package lotto.domain; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import lotto.domain.lottonumbercreator.LottoNumberCreator; public class Lotto { private static final int LOTTO_NUMBERS_SIZE = 6; @@ -14,7 +16,7 @@ public Lotto(List numbers) { validateSize(numbers); validateDuplicated(numbers); validateNumbersRange(numbers); - this.numbers = numbers; + this.numbers = new ArrayList<>(numbers); } private void validateSize(List numbers) { @@ -36,4 +38,8 @@ 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)); + } } diff --git a/src/main/java/lotto/domain/lottonumbercreator/AutoLottoNumberCreator.java b/src/main/java/lotto/domain/lottonumbercreator/AutoLottoNumberCreator.java new file mode 100644 index 0000000000..944e7e18f2 --- /dev/null +++ b/src/main/java/lotto/domain/lottonumbercreator/AutoLottoNumberCreator.java @@ -0,0 +1,11 @@ +package lotto.domain.lottonumbercreator; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; + +public class AutoLottoNumberCreator implements LottoNumberCreator{ + @Override + public List create(int minLottoNumber, int maxLottoNumber, int lottoNumbersSize) { + return Randoms.pickUniqueNumbersInRange(minLottoNumber, maxLottoNumber, lottoNumbersSize); + } +} diff --git a/src/main/java/lotto/domain/lottonumbercreator/LottoNumberCreator.java b/src/main/java/lotto/domain/lottonumbercreator/LottoNumberCreator.java new file mode 100644 index 0000000000..b7e817f865 --- /dev/null +++ b/src/main/java/lotto/domain/lottonumbercreator/LottoNumberCreator.java @@ -0,0 +1,7 @@ +package lotto.domain.lottonumbercreator; + +import java.util.List; + +public interface LottoNumberCreator { + List create(int minLottoNumber, int maxLottoNumber, int lottoNumbersSize); +} diff --git a/src/test/java/lotto/domain/LottoTest.java b/src/test/java/lotto/domain/LottoTest.java index 839fd7e81b..8123ecec6e 100644 --- a/src/test/java/lotto/domain/LottoTest.java +++ b/src/test/java/lotto/domain/LottoTest.java @@ -1,6 +1,7 @@ package lotto.domain; import lotto.domain.Lotto; +import lotto.domain.lottonumbercreator.LottoNumberCreator; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -9,6 +10,7 @@ import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; class LottoTest { @@ -36,4 +38,18 @@ void createLottoByDuplicatedNumber() { .isInstanceOf(IllegalArgumentException.class) .hasMessage("[ERROR] 1 ~ 45 범위를 넘어가는 숫자가 존재합니다."); } + + @Test + void 자동_로또를_생성한다() { + // given + final List numbers = List.of(1, 2, 3, 4, 5, 6); + LottoNumberCreator creator = (min, max, size) -> numbers; + + // when + final Lotto lotto = Lotto.from(creator); + + // then + assertThat(lotto).extracting("numbers") + .isEqualTo(numbers); + } } From ebb73f7f8d7eaef9f7125df73a1fb05c90cf91fa Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 28 Mar 2023 15:17:21 +0900 Subject: [PATCH 07/16] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Lotto.java | 7 ++++++ src/main/java/lotto/domain/WinNumbers.java | 20 +++++++++++++++++ .../java/lotto/domain/WinNumbersTest.java | 22 +++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 src/main/java/lotto/domain/WinNumbers.java create mode 100644 src/test/java/lotto/domain/WinNumbersTest.java diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 2f7fdbff79..89a3c3c3fc 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -42,4 +42,11 @@ 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(Integer bonusBall) { + final boolean isInRange = bonusBall < MIN_LOTTO_NUMBER || bonusBall > MAX_LOTTO_NUMBER; + final boolean isNotLottoNumber = !numbers.contains(bonusBall); + + return isInRange && isNotLottoNumber; + } } diff --git a/src/main/java/lotto/domain/WinNumbers.java b/src/main/java/lotto/domain/WinNumbers.java new file mode 100644 index 0000000000..68807fcb94 --- /dev/null +++ b/src/main/java/lotto/domain/WinNumbers.java @@ -0,0 +1,20 @@ +package lotto.domain; + +public class WinNumbers { + + private final Lotto lotto; + + private final Integer bonusBall; + + public WinNumbers(Lotto lotto, Integer bonusBall) { + validateBonusBall(lotto, bonusBall); + this.lotto = lotto; + this.bonusBall = bonusBall; + } + + private void validateBonusBall(Lotto lotto, Integer bonusBall) { + if (!lotto.isPossible(bonusBall)) { + throw new IllegalArgumentException(String.format("[ERROR] %d는 보너스 볼이 될 수 없습니다.", bonusBall)); + } + } +} diff --git a/src/test/java/lotto/domain/WinNumbersTest.java b/src/test/java/lotto/domain/WinNumbersTest.java new file mode 100644 index 0000000000..10f49b1153 --- /dev/null +++ b/src/test/java/lotto/domain/WinNumbersTest.java @@ -0,0 +1,22 @@ +package lotto.domain; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class WinNumbersTest { + + @Test + void 보너스볼이_로또_넘버와_중복되면_예외를_던진다() { + // given + final Integer bonusBall = 6; + Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, bonusBall)); + + // when & then + Assertions.assertThatThrownBy(() -> new WinNumbers(lotto, bonusBall)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] %d는 보너스 볼이 될 수 없습니다.", bonusBall); + } +} From f18032d9c0986454f656e9a09f393acf17a697da Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 28 Mar 2023 17:01:23 +0900 Subject: [PATCH 08/16] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=20=EB=93=B1=EC=88=98=20=ED=99=95=EC=9D=B8=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/Lotto.java | 37 ++++++++++++++++-- src/main/java/lotto/domain/LottoRank.java | 29 ++++++++++++++ src/main/java/lotto/domain/WinNumbers.java | 30 ++++++++++++-- .../domain/rankvalidator/RankValidator.java | 9 +++++ src/test/java/lotto/domain/LottoRankTest.java | 39 +++++++++++++++++++ 5 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 src/main/java/lotto/domain/LottoRank.java create mode 100644 src/main/java/lotto/domain/rankvalidator/RankValidator.java create mode 100644 src/test/java/lotto/domain/LottoRankTest.java diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 89a3c3c3fc..9f8dd83128 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,6 +1,5 @@ package lotto.domain; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import lotto.domain.lottonumbercreator.LottoNumberCreator; @@ -16,7 +15,7 @@ public Lotto(List numbers) { validateSize(numbers); validateDuplicated(numbers); validateNumbersRange(numbers); - this.numbers = new ArrayList<>(numbers); + this.numbers = numbers; } private void validateSize(List numbers) { @@ -43,10 +42,40 @@ public static Lotto from(LottoNumberCreator creator) { return new Lotto(creator.create(MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER, LOTTO_NUMBERS_SIZE)); } - public boolean isPossible(Integer bonusBall) { - final boolean isInRange = bonusBall < MIN_LOTTO_NUMBER || bonusBall > MAX_LOTTO_NUMBER; + public boolean isPossible(int bonusBall) { + final boolean isInRange = bonusBall >= MIN_LOTTO_NUMBER && bonusBall <= MAX_LOTTO_NUMBER; final boolean isNotLottoNumber = !numbers.contains(bonusBall); return isInRange && isNotLottoNumber; } + + public boolean isFirstRank(Lotto lotto) { + return containCount(lotto) == LOTTO_NUMBERS_SIZE; + } + + public boolean isThirdRank(Lotto lotto) { + return containCount(lotto) == LOTTO_NUMBERS_SIZE - 1 ; + } + + public boolean isFourthRank(Lotto lotto) { + return containCount(lotto) == LOTTO_NUMBERS_SIZE - 2; + } + + public boolean isFifthRank(Lotto lotto) { + return containCount(lotto) == LOTTO_NUMBERS_SIZE - 3; + } + + public boolean isOutOfRank(Lotto lotto) { + return containCount(lotto) < LOTTO_NUMBERS_SIZE - 3; + } + + private int containCount(Lotto other) { + return (int) other.numbers.stream() + .filter(this::contain) + .count(); + } + + public boolean contain(Integer number) { + return this.numbers.contains(number); + } } diff --git a/src/main/java/lotto/domain/LottoRank.java b/src/main/java/lotto/domain/LottoRank.java new file mode 100644 index 0000000000..8a33bcbfb0 --- /dev/null +++ b/src/main/java/lotto/domain/LottoRank.java @@ -0,0 +1,29 @@ +package lotto.domain; + +import java.util.Arrays; +import lotto.domain.rankvalidator.RankValidator; + +public enum LottoRank { + FIRST(2_000_000_000, WinNumbers::isFirstRank), + SECOND(30_000_000, WinNumbers::isSecondRank), + THIRD(1_500_000, WinNumbers::isThirdRank), + FOURTH(50_000, WinNumbers::isFourthRank), + FIFTH(5_000, WinNumbers::isFifthRank), + OTHER(0, WinNumbers::isOutOfRank); + + + private final int prize; + private final RankValidator rankValidator; + + LottoRank(int prize, RankValidator rankValidator) { + this.prize = prize; + this.rankValidator = rankValidator; + } + + public static LottoRank calculateRank(WinNumbers winNumbers, Lotto lotto) { + return Arrays.stream(LottoRank.values()) + .filter(rank -> rank.rankValidator.isRanked(winNumbers, lotto)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("[ERROR] 일치하는 등수가 존재하지 않습니다")); + } +} diff --git a/src/main/java/lotto/domain/WinNumbers.java b/src/main/java/lotto/domain/WinNumbers.java index 68807fcb94..0b2298f879 100644 --- a/src/main/java/lotto/domain/WinNumbers.java +++ b/src/main/java/lotto/domain/WinNumbers.java @@ -4,17 +4,41 @@ public class WinNumbers { private final Lotto lotto; - private final Integer bonusBall; + private final int bonusBall; - public WinNumbers(Lotto lotto, Integer bonusBall) { + public WinNumbers(Lotto lotto, int bonusBall) { validateBonusBall(lotto, bonusBall); this.lotto = lotto; this.bonusBall = bonusBall; } - private void validateBonusBall(Lotto lotto, Integer bonusBall) { + private void validateBonusBall(Lotto lotto, int bonusBall) { if (!lotto.isPossible(bonusBall)) { throw new IllegalArgumentException(String.format("[ERROR] %d는 보너스 볼이 될 수 없습니다.", bonusBall)); } } + + public boolean isFirstRank(Lotto other) { + return this.lotto.isFirstRank(other); + } + + public boolean isSecondRank(Lotto other) { + return this.lotto.isThirdRank(other) && other.contain(this.bonusBall); + } + + public boolean isThirdRank(Lotto other) { + return this.lotto.isThirdRank(other) && !other.contain(this.bonusBall); + } + + public boolean isFourthRank(Lotto other) { + return this.lotto.isFourthRank(other); + } + + public boolean isFifthRank(Lotto other) { + return this.lotto.isFifthRank(other); + } + + public boolean isOutOfRank(Lotto other) { + return this.lotto.isOutOfRank(other); + } } diff --git a/src/main/java/lotto/domain/rankvalidator/RankValidator.java b/src/main/java/lotto/domain/rankvalidator/RankValidator.java new file mode 100644 index 0000000000..7166c3615e --- /dev/null +++ b/src/main/java/lotto/domain/rankvalidator/RankValidator.java @@ -0,0 +1,9 @@ +package lotto.domain.rankvalidator; + +import lotto.domain.Lotto; +import lotto.domain.WinNumbers; + +public interface RankValidator { + + boolean isRanked(WinNumbers winNumbers, Lotto lotto); +} diff --git a/src/test/java/lotto/domain/LottoRankTest.java b/src/test/java/lotto/domain/LottoRankTest.java new file mode 100644 index 0000000000..9799473096 --- /dev/null +++ b/src/test/java/lotto/domain/LottoRankTest.java @@ -0,0 +1,39 @@ +package lotto.domain; + +import java.util.List; +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 winLotto = new Lotto(List.of(1, 2, 3, 4, 5, 6)); + final int bonusBall = 7; + final WinNumbers winNumbers = new WinNumbers(winLotto, bonusBall); + + final Lotto lotto = new Lotto(numbers); + + // when + final LottoRank actual = LottoRank.calculateRank(winNumbers, lotto); + + // then + Assertions.assertThat(actual).isEqualTo(expect); + } +} From 91f6c78806ec0c3fb34094b4aa16d1b141f13ebe Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Tue, 28 Mar 2023 23:49:01 +0900 Subject: [PATCH 09/16] =?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 | 50 ++++++++++++++++++- src/main/java/lotto/domain/Lotto.java | 20 ++++++-- src/main/java/lotto/domain/Money.java | 8 +++ .../domain/{ => lottorank}/LottoRank.java | 8 ++- .../lotto/domain/lottorank/LottoRanks.java | 45 +++++++++++++++++ src/main/java/lotto/view/InputView.java | 31 ++++++++++++ src/test/java/lotto/domain/LottoRankTest.java | 1 + 7 files changed, 156 insertions(+), 7 deletions(-) rename src/main/java/lotto/domain/{ => lottorank}/LottoRank.java (86%) create mode 100644 src/main/java/lotto/domain/lottorank/LottoRanks.java create mode 100644 src/main/java/lotto/view/InputView.java 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; From a308695d3d705901f7118885e09e31cdf2e571f3 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Wed, 29 Mar 2023 00:33:02 +0900 Subject: [PATCH 10/16] =?UTF-8?q?test:=20=EC=98=88=EC=99=B8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/lotto/ApplicationTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/lotto/ApplicationTest.java b/src/test/java/lotto/ApplicationTest.java index a15c7d1f52..546eb4a2b2 100644 --- a/src/test/java/lotto/ApplicationTest.java +++ b/src/test/java/lotto/ApplicationTest.java @@ -8,6 +8,7 @@ import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomUniqueNumbersInRangeTest; import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class ApplicationTest extends NsTest { private static final String ERROR_MESSAGE = "[ERROR]"; @@ -48,10 +49,9 @@ class ApplicationTest extends NsTest { @Test void 예외_테스트() { - assertSimpleTest(() -> { - runException("1000j"); - assertThat(output()).contains(ERROR_MESSAGE); - }); + assertSimpleTest(() -> assertThatThrownBy(() -> runException("1000j")) + .isInstanceOf(IllegalArgumentException.class) + ); } @Override From 83072815c0b7e42c6cb87f11956641a24e9b8f7e Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Wed, 29 Mar 2023 02:19:17 +0900 Subject: [PATCH 11/16] =?UTF-8?q?refactor:=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=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/Application.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index ada27f7889..d1b17173d0 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -22,8 +22,8 @@ public static void main(String[] args) { final int lottoCount = money.getLottoCount(); System.out.println(String.format("\n%d개를 구매했습니다.", lottoCount)); - final List autoLottos = getAutoLottos(lottoCount); - autoLottos.forEach(System.out::println); + final List lottos = getAutoLottos(lottoCount); + lottos.forEach(System.out::println); System.out.println("\n당첨 번호를 입력해 주세요."); final Lotto winLotto = new Lotto(InputView.requestWinNumbers()); @@ -32,7 +32,7 @@ public static void main(String[] args) { int bonusBall = InputView.requestInteger(); final WinNumbers winNumbers = new WinNumbers(winLotto, bonusBall); - final LottoRanks lottoRanks = getLottoRanks(autoLottos, winNumbers); + final LottoRanks lottoRanks = getLottoRanks(lottos, winNumbers); System.out.println("당첨 통계\n---"); System.out.println(lottoRanks); @@ -45,8 +45,8 @@ private static List getAutoLottos(int lottoCount) { .collect(Collectors.toList()); } - private static LottoRanks getLottoRanks(List autoLottos, WinNumbers winNumbers) { - final List ranks = autoLottos.stream() + private static LottoRanks getLottoRanks(List lottos, WinNumbers winNumbers) { + final List ranks = lottos.stream() .map(lotto -> LottoRank.calculateRank(winNumbers, lotto)) .collect(Collectors.toList()); From 1610c8d4fd110b9d202ca32b6ef4a54273dfff77 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 14:42:53 +0900 Subject: [PATCH 12/16] =?UTF-8?q?refactor:=20=EC=9C=A0=ED=8B=B8=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B8=B0=EB=B3=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=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/view/InputView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java index b3a2b3f43b..3421cafc04 100644 --- a/src/main/java/lotto/view/InputView.java +++ b/src/main/java/lotto/view/InputView.java @@ -8,6 +8,10 @@ public class InputView { private static final String DELIMITER = ","; + private InputView() { + throw new UnsupportedOperationException(); + } + public static int requestInteger() { final String input = Console.readLine(); return parseInt(input); From bea1554bcb0b0183c9f8f33ab3488be4f29ccadd Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 14:43:10 +0900 Subject: [PATCH 13/16] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Lotto.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 8473617e28..45609ffe83 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -36,15 +36,19 @@ private void validateDuplicated(List numbers) { } private void validateNumbersRange(List numbers) { - if (numbers.stream().anyMatch(number -> number < MIN_LOTTO_NUMBER || number > MAX_LOTTO_NUMBER)) { + if (!numbers.stream().allMatch(this::isInRange)) { throw new IllegalArgumentException( String.format("[ERROR] %d ~ %d 범위를 넘어가는 숫자가 존재합니다.", MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER) ); } } + private boolean isInRange(int bonusBall) { + return bonusBall >= MIN_LOTTO_NUMBER && bonusBall <= MAX_LOTTO_NUMBER; + } + public boolean isPossible(int bonusBall) { - final boolean isInRange = bonusBall >= MIN_LOTTO_NUMBER && bonusBall <= MAX_LOTTO_NUMBER; + final boolean isInRange = isInRange(bonusBall); final boolean isNotLottoNumber = !numbers.contains(bonusBall); return isInRange && isNotLottoNumber; From 1ab7d50bb908f05b58886bee5ea29b0ffd5536e2 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 15:28:43 +0900 Subject: [PATCH 14/16] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=93=B1=EC=88=98=20=EA=B3=84=EC=82=B0=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=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/Lotto.java | 22 +--------------- src/main/java/lotto/domain/WinNumbers.java | 24 +++--------------- .../lotto/domain/lottorank/LottoRank.java | 25 +++++++++++-------- 3 files changed, 19 insertions(+), 52 deletions(-) diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java index 45609ffe83..46f06c6fa9 100644 --- a/src/main/java/lotto/domain/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -54,27 +54,7 @@ public boolean isPossible(int bonusBall) { return isInRange && isNotLottoNumber; } - public boolean isFirstRank(Lotto lotto) { - return containCount(lotto) == LOTTO_NUMBERS_SIZE; - } - - public boolean isThirdRank(Lotto lotto) { - return containCount(lotto) == LOTTO_NUMBERS_SIZE - 1; - } - - public boolean isFourthRank(Lotto lotto) { - return containCount(lotto) == LOTTO_NUMBERS_SIZE - 2; - } - - public boolean isFifthRank(Lotto lotto) { - return containCount(lotto) == LOTTO_NUMBERS_SIZE - 3; - } - - public boolean isOutOfRank(Lotto lotto) { - return containCount(lotto) < LOTTO_NUMBERS_SIZE - 3; - } - - private int containCount(Lotto other) { + public int calculateSameLottoNumber(Lotto other) { return (int) other.numbers.stream() .filter(this::contain) .count(); diff --git a/src/main/java/lotto/domain/WinNumbers.java b/src/main/java/lotto/domain/WinNumbers.java index 0b2298f879..0eaef90f88 100644 --- a/src/main/java/lotto/domain/WinNumbers.java +++ b/src/main/java/lotto/domain/WinNumbers.java @@ -18,27 +18,11 @@ private void validateBonusBall(Lotto lotto, int bonusBall) { } } - public boolean isFirstRank(Lotto other) { - return this.lotto.isFirstRank(other); + public int calculateSameLottoNumber(Lotto lotto) { + return this.lotto.calculateSameLottoNumber(lotto); } - public boolean isSecondRank(Lotto other) { - return this.lotto.isThirdRank(other) && other.contain(this.bonusBall); - } - - public boolean isThirdRank(Lotto other) { - return this.lotto.isThirdRank(other) && !other.contain(this.bonusBall); - } - - public boolean isFourthRank(Lotto other) { - return this.lotto.isFourthRank(other); - } - - public boolean isFifthRank(Lotto other) { - return this.lotto.isFifthRank(other); - } - - public boolean isOutOfRank(Lotto other) { - return this.lotto.isOutOfRank(other); + public boolean matchBonus(Lotto lotto) { + return lotto.contain(bonusBall); } } diff --git a/src/main/java/lotto/domain/lottorank/LottoRank.java b/src/main/java/lotto/domain/lottorank/LottoRank.java index 72e7d45d73..5e4be5a9f2 100644 --- a/src/main/java/lotto/domain/lottorank/LottoRank.java +++ b/src/main/java/lotto/domain/lottorank/LottoRank.java @@ -6,27 +6,30 @@ import lotto.domain.rankvalidator.RankValidator; public enum LottoRank { - FIRST(2_000_000_000, WinNumbers::isFirstRank), - SECOND(30_000_000, WinNumbers::isSecondRank), - THIRD(1_500_000, WinNumbers::isThirdRank), - FOURTH(50_000, WinNumbers::isFourthRank), - FIFTH(5_000, WinNumbers::isFifthRank), - OTHER(0, WinNumbers::isOutOfRank); + 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 RankValidator rankValidator; + private final int count; + private final boolean bonus; - LottoRank(int prize, RankValidator rankValidator) { + LottoRank(int prize, int count, boolean bonus) { this.prize = prize; - this.rankValidator = rankValidator; + this.count = count; + this.bonus = bonus; } public static LottoRank calculateRank(WinNumbers winNumbers, Lotto lotto) { return Arrays.stream(LottoRank.values()) - .filter(rank -> rank.rankValidator.isRanked(winNumbers, lotto)) + .filter(rank -> rank.count == winNumbers.calculateSameLottoNumber(lotto)) + .filter(rank -> !rank.bonus || winNumbers.matchBonus(lotto)) .findAny() - .orElseThrow(() -> new IllegalArgumentException("[ERROR] 일치하는 등수가 존재하지 않습니다")); + .orElse(LottoRank.OTHER); } public int getPrize() { From 373e46fbe6f06cefd8140cd46cad11a1c0aa2106 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 16:08:19 +0900 Subject: [PATCH 15/16] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=EC=B6=9C=EB=A0=A5=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/domain/lottorank/LottoRank.java | 7 ++++++- .../java/lotto/domain/lottorank/LottoRanks.java | 16 +++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main/java/lotto/domain/lottorank/LottoRank.java b/src/main/java/lotto/domain/lottorank/LottoRank.java index 5e4be5a9f2..13e3efaeb8 100644 --- a/src/main/java/lotto/domain/lottorank/LottoRank.java +++ b/src/main/java/lotto/domain/lottorank/LottoRank.java @@ -3,7 +3,6 @@ import java.util.Arrays; import lotto.domain.Lotto; import lotto.domain.WinNumbers; -import lotto.domain.rankvalidator.RankValidator; public enum LottoRank { FIRST(2_000_000_000, 6, false), @@ -32,7 +31,13 @@ public static LottoRank calculateRank(WinNumbers winNumbers, Lotto lotto) { .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/main/java/lotto/domain/lottorank/LottoRanks.java b/src/main/java/lotto/domain/lottorank/LottoRanks.java index 680fe28aad..c79199b358 100644 --- a/src/main/java/lotto/domain/lottorank/LottoRanks.java +++ b/src/main/java/lotto/domain/lottorank/LottoRanks.java @@ -1,15 +1,10 @@ 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; +import java.util.stream.Collectors; public class LottoRanks { @@ -36,10 +31,9 @@ public int getProfit() { @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)); + return ranks.entrySet() + .stream() + .map(entry -> String.format("%s - %d개", entry.getKey().toString(), entry.getValue())) + .collect(Collectors.joining("\n")); } } From 4cf62264882c4281dffdf3b4d617d17ad2b0f993 Mon Sep 17 00:00:00 2001 From: seong-wooo Date: Thu, 30 Mar 2023 21:59:51 +0900 Subject: [PATCH 16/16] =?UTF-8?q?refctor:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/domain/rankvalidator/RankValidator.java | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/main/java/lotto/domain/rankvalidator/RankValidator.java diff --git a/src/main/java/lotto/domain/rankvalidator/RankValidator.java b/src/main/java/lotto/domain/rankvalidator/RankValidator.java deleted file mode 100644 index 7166c3615e..0000000000 --- a/src/main/java/lotto/domain/rankvalidator/RankValidator.java +++ /dev/null @@ -1,9 +0,0 @@ -package lotto.domain.rankvalidator; - -import lotto.domain.Lotto; -import lotto.domain.WinNumbers; - -public interface RankValidator { - - boolean isRanked(WinNumbers winNumbers, Lotto lotto); -}