From 16944f105a4e4ae76ee1181d9ffccd2d987d0b08 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:00:23 +0900 Subject: [PATCH 01/46] =?UTF-8?q?docs:=20=EA=B8=B0=EB=B3=B8=20feature=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B5=AC=EC=A1=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/docs/README.md b/docs/README.md index e69de29..19424fa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,66 @@ +## Feature + +- [ ] User는 `1000원` 단위로 로또 N장을 구매한다 + - 구매 후 로또 생성기로부터 N장의 로또를 생성한다 + - `1000원` 단위로 입력하지 않을 경우 `IllegalArgumentException`를 발생시키고 `[Error]`로 시작하는 에러 메시지를 출력 후 `종료`한다 + +- [ ] Machine은 로또 당첨 번호를 생성한다 + - 총 7개의 중복되지 않는 숫자 (기본 6개 + 보너스 1개) + +- [ ] LottoStatistics는 N장의 로또에 대한 당첨 통계를 산출한다 + +
+
+ +## Model + +### `Lotto` + +- 로또 번호 List를 추상화시킨 모델 + - [ ] 로또 번호는 1..45 범위 안에 존재해야 한다 + - [ ] 각 번호들은 중복되지 않아야 한다 + +### `User` + +- `1000원` 단위 N장의 로또를 구매하는 컴포넌트 + +### `Machine` + +- 로또 당첨 번호 6개 + 보너스 번호를 생성하는 컴포넌트 + +### `LottoStatistics` + +- 로또 당첨 내역 및 수익률을 산출하기 위한 통계용 컴포넌트 + +
+
+ +## Utils + +### `ExceptionConstants` + +- 전역 예외 메시지 통합 컴포넌트 + +
+
+ +## View + +### `InputView` + +- 사용자 Input을 받기 위한 컴포넌트 + +### `OutputView` + +- 로또 게임 진행과 관련된 출력 컴포넌트 + +
+
+ +## Controller + +### `GameController` + +- 로또 게임 진행과 관련된 컨트롤러 + +
From 9833710175c7b31fb8659d664b6552c8d5f7c49e Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:11:21 +0900 Subject: [PATCH 02/46] =?UTF-8?q?feat:=20Lotto=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EA=B3=BC=20=EA=B4=80=EB=A0=A8=EB=90=98=20ExceptionConstants=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/utils/ExceptionConstants.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/lotto/utils/ExceptionConstants.java diff --git a/src/main/java/lotto/utils/ExceptionConstants.java b/src/main/java/lotto/utils/ExceptionConstants.java new file mode 100644 index 0000000..824baac --- /dev/null +++ b/src/main/java/lotto/utils/ExceptionConstants.java @@ -0,0 +1,16 @@ +package lotto.utils; + +public interface ExceptionConstants { + enum LottoException { + LOTTO_NUMBER_IS_NOT_IN_RANGE("로또 번호는 1부터 45 사이의 숫자여야 합니다."), + LOTTO_SIZE_IS_NOT_FULFILL("구매한 로또는 총 6개의 번호가 기입되어야 합니다."), + LOTTO_NUMBER_MUST_BE_UNIQUE("중복된 번호는 허용하지 않습니다."), + ; + + public final String message; + + LottoException(final String message) { + this.message = message; + } + } +} From b8b17b41992c30abdb45dffeffa5591bd1bebe99 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:11:56 +0900 Subject: [PATCH 03/46] =?UTF-8?q?feat:=20Lotto=20=EC=83=9D=EC=84=B1=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 - 로또 범위 검증 - 로또 전체 사이즈 검증 - 로또 중복 요소 검증 --- docs/README.md | 4 +-- src/main/java/lotto/Lotto.java | 20 ----------- src/main/java/lotto/model/Lotto.java | 54 ++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/lotto/Lotto.java create mode 100644 src/main/java/lotto/model/Lotto.java diff --git a/docs/README.md b/docs/README.md index 19424fa..754dbab 100644 --- a/docs/README.md +++ b/docs/README.md @@ -17,8 +17,8 @@ ### `Lotto` - 로또 번호 List를 추상화시킨 모델 - - [ ] 로또 번호는 1..45 범위 안에 존재해야 한다 - - [ ] 각 번호들은 중복되지 않아야 한다 + - [X] 로또 번호는 1..45 범위 안에 존재해야 한다 + - [X] 각 번호들은 중복되지 않아야 한다 ### `User` diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java deleted file mode 100644 index 519793d..0000000 --- a/src/main/java/lotto/Lotto.java +++ /dev/null @@ -1,20 +0,0 @@ -package lotto; - -import java.util.List; - -public class Lotto { - private final List numbers; - - public Lotto(List numbers) { - validate(numbers); - this.numbers = numbers; - } - - private void validate(List numbers) { - if (numbers.size() != 6) { - throw new IllegalArgumentException(); - } - } - - // TODO: 추가 기능 구현 -} diff --git a/src/main/java/lotto/model/Lotto.java b/src/main/java/lotto/model/Lotto.java new file mode 100644 index 0000000..08568a7 --- /dev/null +++ b/src/main/java/lotto/model/Lotto.java @@ -0,0 +1,54 @@ +package lotto.model; + +import java.util.Collections; +import java.util.List; + +import static lotto.utils.ExceptionConstants.LottoException.*; + +public class Lotto { + private static final int MIN_VALUE = 1; + private static final int MAX_VALUE = 45; + private static final int LOTTO_SIZE = 6; + + private final List numbers; + + public Lotto(final List numbers) { + validateEachLottoElementIsInRange(numbers); + validateTotalLottoSize(numbers); + validateLottoHasDuplicateElement(numbers); + this.numbers = numbers; + } + + private void validateEachLottoElementIsInRange(final List numbers) { + if (hasOutOfRange(numbers)) { + throw new IllegalArgumentException(LOTTO_NUMBER_IS_NOT_IN_RANGE.message); + } + } + + private boolean hasOutOfRange(final List numbers) { + return numbers.stream() + .anyMatch(number -> number < MIN_VALUE || number > MAX_VALUE); + } + + private void validateTotalLottoSize(final List numbers) { + if (numbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException(LOTTO_SIZE_IS_NOT_FULFILL.message); + } + } + + private void validateLottoHasDuplicateElement(final List numbers) { + if (hasDuplicateNumber(numbers)) { + throw new IllegalArgumentException(LOTTO_NUMBER_MUST_BE_UNIQUE.message); + } + } + + private boolean hasDuplicateNumber(final List baseballs) { + return baseballs.stream() + .distinct() + .count() != LOTTO_SIZE; + } + + public List getNumbers() { + return Collections.unmodifiableList(numbers); + } +} From 132673fa348b9c174a05113d6305aa87c0abc691 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:12:36 +0900 Subject: [PATCH 04/46] =?UTF-8?q?test:=20Lotto=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EA=B3=BC=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/lotto/LottoTest.java | 27 --------- src/test/java/lotto/model/LottoTest.java | 77 ++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 27 deletions(-) delete mode 100644 src/test/java/lotto/LottoTest.java create mode 100644 src/test/java/lotto/model/LottoTest.java diff --git a/src/test/java/lotto/LottoTest.java b/src/test/java/lotto/LottoTest.java deleted file mode 100644 index 0f3af0f..0000000 --- a/src/test/java/lotto/LottoTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package lotto; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -class LottoTest { - @DisplayName("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.") - @Test - void createLottoByOverSize() { - assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7))) - .isInstanceOf(IllegalArgumentException.class); - } - - @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.") - @Test - void createLottoByDuplicatedNumber() { - // TODO: 이 테스트가 통과할 수 있게 구현 코드 작성 - assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) - .isInstanceOf(IllegalArgumentException.class); - } - - // 아래에 추가 테스트 작성 가능 -} diff --git a/src/test/java/lotto/model/LottoTest.java b/src/test/java/lotto/model/LottoTest.java new file mode 100644 index 0000000..b4ff91c --- /dev/null +++ b/src/test/java/lotto/model/LottoTest.java @@ -0,0 +1,77 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +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.MethodSource; + +import java.util.List; +import java.util.stream.Stream; + +import static lotto.utils.ExceptionConstants.LottoException.*; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class LottoTest { + @ParameterizedTest + @MethodSource("invalidRange") + @DisplayName("로또 번호의 범위가 1..45 이외라면 예외가 발생한다") + void throwExceptionByBaseballIsNotInRange(List baseballs) { + assertThatThrownBy(() -> new Lotto(baseballs)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_IS_NOT_IN_RANGE.message); + } + + private static Stream invalidRange() { + return Stream.of( + Arguments.of(List.of(0, 1, 2, 3, 4, 5)), + Arguments.of(List.of(1, 2, 3, 4, 5, 46)) + ); + } + + @ParameterizedTest + @MethodSource("invalidSize") + @DisplayName("로또 번호의 개수가 6개가 아니면 예외가 발생한다") + void throwExceptionByBaseballSizeNotFulfill(List baseballs) { + assertThatThrownBy(() -> new Lotto(baseballs)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_SIZE_IS_NOT_FULFILL.message); + } + + private static Stream invalidSize() { + return Stream.of( + Arguments.of(List.of()), + Arguments.of(List.of(1)), + Arguments.of(List.of(1, 2)), + Arguments.of(List.of(1, 2, 3)), + Arguments.of(List.of(1, 2, 3, 4)), + Arguments.of(List.of(1, 2, 3, 4, 5)) + ); + } + + @ParameterizedTest + @MethodSource("duplicateNumber") + @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다") + void throwExceptionByBaseballIsNotUnique(List baseballs) { + assertThatThrownBy(() -> new Lotto(baseballs)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(LOTTO_NUMBER_MUST_BE_UNIQUE.message); + } + + private static Stream duplicateNumber() { + return Stream.of( + Arguments.of(List.of(1, 1, 2, 3, 4, 5)), + Arguments.of(List.of(1, 1, 1, 2, 3, 4)), + Arguments.of(List.of(1, 1, 1, 1, 2, 3)), + Arguments.of(List.of(1, 1, 1, 1, 1, 2)), + Arguments.of(List.of(1, 1, 1, 1, 1, 1)) + ); + } + + @Test + @DisplayName("Lotto를 생성한다") + void construct() { + assertDoesNotThrow(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6))); + } +} From b5f87e4f0af07420eaaa793e9faff2d0b521be29 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:14:41 +0900 Subject: [PATCH 05/46] =?UTF-8?q?refactor:=20Lotto=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 ++++ src/main/java/lotto/model/Lotto.java | 5 +---- src/main/java/lotto/utils/LottoConstants.java | 7 +++++++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 src/main/java/lotto/utils/LottoConstants.java diff --git a/docs/README.md b/docs/README.md index 754dbab..c58b0a0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -41,6 +41,10 @@ - 전역 예외 메시지 통합 컴포넌트 +### `LottoConstants` + +- Lotto 숫자 범위 & 전체 사이즈 관련 상수 전용 컴포넌트 +

diff --git a/src/main/java/lotto/model/Lotto.java b/src/main/java/lotto/model/Lotto.java index 08568a7..c02f3ac 100644 --- a/src/main/java/lotto/model/Lotto.java +++ b/src/main/java/lotto/model/Lotto.java @@ -4,12 +4,9 @@ import java.util.List; import static lotto.utils.ExceptionConstants.LottoException.*; +import static lotto.utils.LottoConstants.*; public class Lotto { - private static final int MIN_VALUE = 1; - private static final int MAX_VALUE = 45; - private static final int LOTTO_SIZE = 6; - private final List numbers; public Lotto(final List numbers) { diff --git a/src/main/java/lotto/utils/LottoConstants.java b/src/main/java/lotto/utils/LottoConstants.java new file mode 100644 index 0000000..374e16c --- /dev/null +++ b/src/main/java/lotto/utils/LottoConstants.java @@ -0,0 +1,7 @@ +package lotto.utils; + +public interface LottoConstants { + int MIN_VALUE = 1; + int MAX_VALUE = 45; + int LOTTO_SIZE = 6; +} From 048e27ca5ff7a70f5881d3256b70f56a77aa21df Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:33:39 +0900 Subject: [PATCH 06/46] =?UTF-8?q?feat:=201000=EC=9B=90=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=20=EB=A1=9C=EB=98=90=201=EC=9E=A5=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EB=B0=9C=EA=B8=89=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?UserLotto=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=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 --- docs/README.md | 9 +++-- src/main/java/lotto/model/UserLotto.java | 35 ++++++++++++++++++++ src/test/java/lotto/model/UserLottoTest.java | 28 ++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/main/java/lotto/model/UserLotto.java create mode 100644 src/test/java/lotto/model/UserLottoTest.java diff --git a/docs/README.md b/docs/README.md index c58b0a0..671d277 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,9 +20,14 @@ - [X] 로또 번호는 1..45 범위 안에 존재해야 한다 - [X] 각 번호들은 중복되지 않아야 한다 -### `User` +### `UserLotto` -- `1000원` 단위 N장의 로또를 구매하는 컴포넌트 +- `1000원` 단위의 로또 1장을 구매하는 컴포넌트 + +### `UserLottos` + +- `1000원` 단위의 로또 N장을 구매하는 컴포넌트 + - `List` ### `Machine` diff --git a/src/main/java/lotto/model/UserLotto.java b/src/main/java/lotto/model/UserLotto.java new file mode 100644 index 0000000..71bb5ee --- /dev/null +++ b/src/main/java/lotto/model/UserLotto.java @@ -0,0 +1,35 @@ +package lotto.model; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.Collections; +import java.util.List; + +import static lotto.utils.LottoConstants.*; + +public class UserLotto { + private final Lotto lotto; + + private UserLotto() { + this.lotto = new Lotto(generateRandomLottoNumbers()); + } + + public static UserLotto createLottoByAutomatic() { + return new UserLotto(); + } + + private List generateRandomLottoNumbers() { + List numbers = Randoms.pickUniqueNumbersInRange( + MIN_VALUE, + MAX_VALUE, + LOTTO_SIZE + ); + Collections.sort(numbers); + + return numbers; + } + + public List getLottoNumbers() { + return lotto.getNumbers(); + } +} diff --git a/src/test/java/lotto/model/UserLottoTest.java b/src/test/java/lotto/model/UserLottoTest.java new file mode 100644 index 0000000..796a1bb --- /dev/null +++ b/src/test/java/lotto/model/UserLottoTest.java @@ -0,0 +1,28 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static lotto.utils.LottoConstants.LOTTO_SIZE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +class UserLottoTest { + @Test + @DisplayName("UserLotto 생성한다") + void construct() { + // when + final UserLotto userLotto = UserLotto.createLottoByAutomatic(); + + // then + assertAll( + () -> assertThat(userLotto.getLottoNumbers()).hasSize(LOTTO_SIZE), // size + () -> assertThat( + userLotto.getLottoNumbers() + .stream() + .distinct() + .count() + ).isEqualTo(LOTTO_SIZE) // has duplicate + ); + } +} From 3229f0edeb0bbd5efb48d3970c6b5570fe8876c1 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:36:13 +0900 Subject: [PATCH 07/46] =?UTF-8?q?feat:=20=EA=B5=AC=EB=A7=A4=ED=95=9C=20N?= =?UTF-8?q?=EC=9E=A5=20UserLotto=20=EB=B3=B4=EA=B4=80=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20UserLottos=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=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/model/UserLottos.java | 28 +++++++++++++++++++ src/test/java/lotto/model/UserLottosTest.java | 20 +++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/main/java/lotto/model/UserLottos.java create mode 100644 src/test/java/lotto/model/UserLottosTest.java diff --git a/src/main/java/lotto/model/UserLottos.java b/src/main/java/lotto/model/UserLottos.java new file mode 100644 index 0000000..966eb03 --- /dev/null +++ b/src/main/java/lotto/model/UserLottos.java @@ -0,0 +1,28 @@ +package lotto.model; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class UserLottos { + private final List userLottos; + + private UserLottos(final int lottoPurchaseCount) { + this.userLottos = createLottoByPurchaseCount(lottoPurchaseCount); + } + + public static UserLottos issueLottoByPurchaseCount(final int lottoPurchaseCount) { + return new UserLottos(lottoPurchaseCount); + } + + private List createLottoByPurchaseCount(final int lottoPurchaseCount) { + return Stream.generate(UserLotto::createLottoByAutomatic) + .limit(lottoPurchaseCount) + .collect(Collectors.toList()); + } + + public List getUserLottos() { + return Collections.unmodifiableList(userLottos); + } +} diff --git a/src/test/java/lotto/model/UserLottosTest.java b/src/test/java/lotto/model/UserLottosTest.java new file mode 100644 index 0000000..6d3b6c8 --- /dev/null +++ b/src/test/java/lotto/model/UserLottosTest.java @@ -0,0 +1,20 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class UserLottosTest { + @ParameterizedTest + @ValueSource(ints = {5, 10}) + @DisplayName("구매한 개수만큼 UseLotto를 발급받는다") + void construct(int lottoPurchaseCount) { + // when + UserLottos userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); + + // then + assertThat(userLottos.getUserLottos()).hasSize(lottoPurchaseCount); + } +} From 5dae29f2f9ac2b98de174ef2a412c38cf764d888 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 15:46:16 +0900 Subject: [PATCH 08/46] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=20=EB=B2=88=ED=98=B8=20&=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EB=B2=88=ED=98=B8=EB=A5=BC=20=EA=B8=B0=EB=A1=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20LottoWinningMachine=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 16 +++---- .../java/lotto/model/LottoWinningMachine.java | 43 +++++++++++++++++++ .../java/lotto/utils/ExceptionConstants.java | 11 +++++ .../lotto/model/LottoWinningMachineTest.java | 43 +++++++++++++++++++ 4 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 src/main/java/lotto/model/LottoWinningMachine.java create mode 100644 src/test/java/lotto/model/LottoWinningMachineTest.java diff --git a/docs/README.md b/docs/README.md index 671d277..f8ecf5c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,11 @@ ## Feature - [ ] User는 `1000원` 단위로 로또 N장을 구매한다 - - 구매 후 로또 생성기로부터 N장의 로또를 생성한다 - - `1000원` 단위로 입력하지 않을 경우 `IllegalArgumentException`를 발생시키고 `[Error]`로 시작하는 에러 메시지를 출력 후 `종료`한다 + - 구매 후 로또 생성기로부터 N장의 로또를 생성한다 + - `1000원` 단위로 입력하지 않을 경우 `IllegalArgumentException`를 발생시키고 `[Error]`로 시작하는 에러 메시지를 출력 후 `종료`한다 -- [ ] Machine은 로또 당첨 번호를 생성한다 - - 총 7개의 중복되지 않는 숫자 (기본 6개 + 보너스 1개) +- [X] LottoWinningMachine은 로또 당첨 번호를 생성한다 + - 총 7개의 중복되지 않는 숫자 (기본 당첨 번호 6개 + 보너스 번호 1개) - [ ] LottoStatistics는 N장의 로또에 대한 당첨 통계를 산출한다 @@ -17,8 +17,8 @@ ### `Lotto` - 로또 번호 List를 추상화시킨 모델 - - [X] 로또 번호는 1..45 범위 안에 존재해야 한다 - - [X] 각 번호들은 중복되지 않아야 한다 + - [X] 로또 번호는 1..45 범위 안에 존재해야 한다 + - [X] 각 번호들은 중복되지 않아야 한다 ### `UserLotto` @@ -27,9 +27,9 @@ ### `UserLottos` - `1000원` 단위의 로또 N장을 구매하는 컴포넌트 - - `List` + - `List` -### `Machine` +### `LottoWinningMachine` - 로또 당첨 번호 6개 + 보너스 번호를 생성하는 컴포넌트 diff --git a/src/main/java/lotto/model/LottoWinningMachine.java b/src/main/java/lotto/model/LottoWinningMachine.java new file mode 100644 index 0000000..0e3a8ea --- /dev/null +++ b/src/main/java/lotto/model/LottoWinningMachine.java @@ -0,0 +1,43 @@ +package lotto.model; + +import java.util.List; + +import static lotto.utils.ExceptionConstants.LottoMachineException.BONUS_NUMBER_MUST_BE_UNIQUE; + +public class LottoWinningMachine { + private final Lotto winningLottery; + private final int bonusNumber; + + private LottoWinningMachine( + final List winningNumbers, + final int bonusNumber + ) { + validateBonusNumberIsDuplicate(winningNumbers, bonusNumber); + this.winningLottery = new Lotto(winningNumbers); + this.bonusNumber = bonusNumber; + } + + public static LottoWinningMachine drawWinningLottery( + final List winningNumbers, + final int bonusNumber + ) { + return new LottoWinningMachine(winningNumbers, bonusNumber); + } + + private void validateBonusNumberIsDuplicate( + final List winningNumbers, + final int bonusNumber + ) { + if (winningNumbers.contains(bonusNumber)) { + throw new IllegalArgumentException(BONUS_NUMBER_MUST_BE_UNIQUE.message); + } + } + + public List getWinningLotteryNumbers() { + return winningLottery.getNumbers(); + } + + public int getBonusNumber() { + return bonusNumber; + } +} diff --git a/src/main/java/lotto/utils/ExceptionConstants.java b/src/main/java/lotto/utils/ExceptionConstants.java index 824baac..ca4dd36 100644 --- a/src/main/java/lotto/utils/ExceptionConstants.java +++ b/src/main/java/lotto/utils/ExceptionConstants.java @@ -13,4 +13,15 @@ enum LottoException { this.message = message; } } + + enum LottoMachineException { + BONUS_NUMBER_MUST_BE_UNIQUE("보너스 번호는 당첨 번호와 중복되지 않아야 합니다."), + ; + + public final String message; + + LottoMachineException(final String message) { + this.message = message; + } + } } diff --git a/src/test/java/lotto/model/LottoWinningMachineTest.java b/src/test/java/lotto/model/LottoWinningMachineTest.java new file mode 100644 index 0000000..f17cf7e --- /dev/null +++ b/src/test/java/lotto/model/LottoWinningMachineTest.java @@ -0,0 +1,43 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static lotto.utils.ExceptionConstants.LottoMachineException.BONUS_NUMBER_MUST_BE_UNIQUE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +class LottoWinningMachineTest { + @Test + @DisplayName("보너스 번호가 당첨 번호에 중복되면 예외가 발생한다") + void throwExceptionByBonusNumberIsNotUnique() { + // given + final List winningNumbers = List.of(1, 2, 3, 4, 5, 6); + final int bonusNumber = 1; + + // when - then + assertThatThrownBy(() -> LottoWinningMachine.drawWinningLottery(winningNumbers, bonusNumber)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BONUS_NUMBER_MUST_BE_UNIQUE.message); + } + + @Test + @DisplayName("LottoWinningMachine을 생성한다") + void success() { + // given + final List winningNumbers = List.of(1, 2, 3, 4, 5, 6); + final int bonusNumber = 7; + + // when + final LottoWinningMachine lottoWinningMachine = LottoWinningMachine.drawWinningLottery(winningNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(lottoWinningMachine.getWinningLotteryNumbers()).containsExactlyInAnyOrderElementsOf(winningNumbers), + () -> assertThat(lottoWinningMachine.getBonusNumber()).isEqualTo(bonusNumber) + ); + } +} From a64a1f93fcf940205bc08b7b25e16b3c8624f3ca Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 16:11:57 +0900 Subject: [PATCH 09/46] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=9C=EC=9C=84=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=95=EC=9D=84=20=EC=9C=84=ED=95=9C=20WinningRank?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 ++ src/main/java/lotto/model/WinningRank.java | 54 +++++++++++++++++++ .../java/lotto/model/WinningRankTest.java | 38 +++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/main/java/lotto/model/WinningRank.java create mode 100644 src/test/java/lotto/model/WinningRankTest.java diff --git a/docs/README.md b/docs/README.md index f8ecf5c..87ba225 100644 --- a/docs/README.md +++ b/docs/README.md @@ -33,6 +33,10 @@ - 로또 당첨 번호 6개 + 보너스 번호를 생성하는 컴포넌트 +### `WinningRank` + +- 당첨과 관련된 순위를 표현하는 컴포넌트 + ### `LottoStatistics` - 로또 당첨 내역 및 수익률을 산출하기 위한 통계용 컴포넌트 diff --git a/src/main/java/lotto/model/WinningRank.java b/src/main/java/lotto/model/WinningRank.java new file mode 100644 index 0000000..96fa079 --- /dev/null +++ b/src/main/java/lotto/model/WinningRank.java @@ -0,0 +1,54 @@ +package lotto.model; + +import java.util.Arrays; +import java.util.List; + +public enum WinningRank { + FIRST(6, List.of(true, false), 2_000_000_000, "6개 일치"), + SECOND(5, List.of(true), 30_000_000, "5개 일치, 보너스 볼 일치"), + THIRD(5, List.of(false), 1_500_000, "5개 일치"), + FOURTH(4, List.of(true, false), 50_000, "4개 일치"), + FIFTH(3, List.of(true, false), 50_000, "3개 일치"), + NONE(1, List.of(), 0, "NONE..."), + ; + + private final int matchCount; + private final List hasBonus; + private final int reward; + private final String description; + + WinningRank( + final int matchCount, + final List hasBonus, + final int reward, + final String description + ) { + this.matchCount = matchCount; + this.hasBonus = hasBonus; + this.reward = reward; + this.description = description; + } + + public static WinningRank of( + final int matchCount, + final boolean hasBonus + ) { + return Arrays.stream(values()) + .filter(winningRank -> winningRank.matchCount == matchCount) + .filter(winningRank -> winningRank.hasBonus.contains(hasBonus)) + .findFirst() + .orElse(NONE); + } + + public int getMatchCount() { + return matchCount; + } + + public int getReward() { + return reward; + } + + public String getDescription() { + return description; + } +} diff --git a/src/test/java/lotto/model/WinningRankTest.java b/src/test/java/lotto/model/WinningRankTest.java new file mode 100644 index 0000000..391bec2 --- /dev/null +++ b/src/test/java/lotto/model/WinningRankTest.java @@ -0,0 +1,38 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static lotto.model.WinningRank.*; +import static org.assertj.core.api.Assertions.assertThat; + +class WinningRankTest { + @ParameterizedTest + @MethodSource("winningCase") + @DisplayName("로또 번호 당첨 개수 + 보너스 볼 일치 여부에 따른 WinningRank를 배정받는다") + void getWinningRank(int matchCount, boolean hasBonus, WinningRank expect) { + assertThat(WinningRank.of(matchCount, hasBonus)).isEqualTo(expect); + } + + private static Stream winningCase() { + return Stream.of( + Arguments.of(6, true, FIRST), + Arguments.of(6, false, FIRST), + Arguments.of(5, true, SECOND), + Arguments.of(5, false, THIRD), + Arguments.of(4, true, FOURTH), + Arguments.of(4, false, FOURTH), + Arguments.of(3, true, FIFTH), + Arguments.of(3, false, FIFTH), + Arguments.of(2, true, NONE), + Arguments.of(2, false, NONE), + Arguments.of(1, true, NONE), + Arguments.of(1, false, NONE), + Arguments.of(0, false, NONE) + ); + } +} From 34471aaf8d86e512e44de01f91abe19d68e8ec5c Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 16:45:01 +0900 Subject: [PATCH 10/46] =?UTF-8?q?refactor:=20Lotto=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20numbers=20=EC=A0=95=EB=A0=AC=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/model/Lotto.java | 2 ++ src/main/java/lotto/model/UserLotto.java | 6 +----- src/test/java/lotto/model/LottoTest.java | 14 ++++++++++++-- .../java/lotto/model/LottoWinningMachineTest.java | 5 +++-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/java/lotto/model/Lotto.java b/src/main/java/lotto/model/Lotto.java index c02f3ac..f7a19f5 100644 --- a/src/main/java/lotto/model/Lotto.java +++ b/src/main/java/lotto/model/Lotto.java @@ -3,6 +3,7 @@ import java.util.Collections; import java.util.List; +import static java.util.Collections.sort; import static lotto.utils.ExceptionConstants.LottoException.*; import static lotto.utils.LottoConstants.*; @@ -13,6 +14,7 @@ public Lotto(final List numbers) { validateEachLottoElementIsInRange(numbers); validateTotalLottoSize(numbers); validateLottoHasDuplicateElement(numbers); + sort(numbers); this.numbers = numbers; } diff --git a/src/main/java/lotto/model/UserLotto.java b/src/main/java/lotto/model/UserLotto.java index 71bb5ee..d1aafdd 100644 --- a/src/main/java/lotto/model/UserLotto.java +++ b/src/main/java/lotto/model/UserLotto.java @@ -2,7 +2,6 @@ import camp.nextstep.edu.missionutils.Randoms; -import java.util.Collections; import java.util.List; import static lotto.utils.LottoConstants.*; @@ -19,14 +18,11 @@ public static UserLotto createLottoByAutomatic() { } private List generateRandomLottoNumbers() { - List numbers = Randoms.pickUniqueNumbersInRange( + return Randoms.pickUniqueNumbersInRange( MIN_VALUE, MAX_VALUE, LOTTO_SIZE ); - Collections.sort(numbers); - - return numbers; } public List getLottoNumbers() { diff --git a/src/test/java/lotto/model/LottoTest.java b/src/test/java/lotto/model/LottoTest.java index b4ff91c..a6faade 100644 --- a/src/test/java/lotto/model/LottoTest.java +++ b/src/test/java/lotto/model/LottoTest.java @@ -6,12 +6,14 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.util.Arrays; import java.util.List; import java.util.stream.Stream; import static lotto.utils.ExceptionConstants.LottoException.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertAll; class LottoTest { @ParameterizedTest @@ -72,6 +74,14 @@ private static Stream duplicateNumber() { @Test @DisplayName("Lotto를 생성한다") void construct() { - assertDoesNotThrow(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6))); + // when + final Lotto lottoA = new Lotto(Arrays.asList(1, 3, 2, 4, 5, 6)); + final Lotto lottoB = new Lotto(Arrays.asList(44, 1, 10, 23, 18, 6)); + + // then + assertAll( + () -> assertThat(lottoA.getNumbers()).containsExactly(1, 2, 3, 4, 5, 6), + () -> assertThat(lottoB.getNumbers()).containsExactly(1, 6, 10, 18, 23, 44) + ); } } diff --git a/src/test/java/lotto/model/LottoWinningMachineTest.java b/src/test/java/lotto/model/LottoWinningMachineTest.java index f17cf7e..01264b3 100644 --- a/src/test/java/lotto/model/LottoWinningMachineTest.java +++ b/src/test/java/lotto/model/LottoWinningMachineTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Arrays; import java.util.List; import static lotto.utils.ExceptionConstants.LottoMachineException.BONUS_NUMBER_MUST_BE_UNIQUE; @@ -15,7 +16,7 @@ class LottoWinningMachineTest { @DisplayName("보너스 번호가 당첨 번호에 중복되면 예외가 발생한다") void throwExceptionByBonusNumberIsNotUnique() { // given - final List winningNumbers = List.of(1, 2, 3, 4, 5, 6); + final List winningNumbers = Arrays.asList(1, 2, 3, 4, 5, 6); final int bonusNumber = 1; // when - then @@ -28,7 +29,7 @@ void throwExceptionByBonusNumberIsNotUnique() { @DisplayName("LottoWinningMachine을 생성한다") void success() { // given - final List winningNumbers = List.of(1, 2, 3, 4, 5, 6); + final List winningNumbers = Arrays.asList(1, 2, 3, 4, 5, 6); final int bonusNumber = 7; // when From 4b844b0da06def12a375e30fd1552cf5fccd5039 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 17:02:50 +0900 Subject: [PATCH 11/46] =?UTF-8?q?refactor:=20UserLotto=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20random=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B6=84=EB=A6=AC=20(LottoRandom?= =?UTF-8?q?Generator)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LottoStatistics 테스트 시 random에 의한 의존성 제거 --- docs/README.md | 4 ++++ src/main/java/lotto/model/UserLotto.java | 20 ++++--------------- src/main/java/lotto/model/UserLottos.java | 4 +++- .../lotto/utils/LottoRandomGenerator.java | 17 ++++++++++++++++ src/test/java/lotto/model/UserLottoTest.java | 17 +++++++++++----- 5 files changed, 40 insertions(+), 22 deletions(-) create mode 100644 src/main/java/lotto/utils/LottoRandomGenerator.java diff --git a/docs/README.md b/docs/README.md index 87ba225..bf80ae4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -54,6 +54,10 @@ - Lotto 숫자 범위 & 전체 사이즈 관련 상수 전용 컴포넌트 +### `LottoRandomGenerator` + +- 로또 번호 자동 생성기 +

diff --git a/src/main/java/lotto/model/UserLotto.java b/src/main/java/lotto/model/UserLotto.java index d1aafdd..94257c5 100644 --- a/src/main/java/lotto/model/UserLotto.java +++ b/src/main/java/lotto/model/UserLotto.java @@ -1,28 +1,16 @@ package lotto.model; -import camp.nextstep.edu.missionutils.Randoms; - import java.util.List; -import static lotto.utils.LottoConstants.*; - public class UserLotto { private final Lotto lotto; - private UserLotto() { - this.lotto = new Lotto(generateRandomLottoNumbers()); - } - - public static UserLotto createLottoByAutomatic() { - return new UserLotto(); + private UserLotto(final List numbers) { + this.lotto = new Lotto(numbers); } - private List generateRandomLottoNumbers() { - return Randoms.pickUniqueNumbersInRange( - MIN_VALUE, - MAX_VALUE, - LOTTO_SIZE - ); + public static UserLotto createLotto(final List numbers) { + return new UserLotto(numbers); } public List getLottoNumbers() { diff --git a/src/main/java/lotto/model/UserLottos.java b/src/main/java/lotto/model/UserLottos.java index 966eb03..415d746 100644 --- a/src/main/java/lotto/model/UserLottos.java +++ b/src/main/java/lotto/model/UserLottos.java @@ -1,5 +1,7 @@ package lotto.model; +import lotto.utils.LottoRandomGenerator; + import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -17,7 +19,7 @@ public static UserLottos issueLottoByPurchaseCount(final int lottoPurchaseCount) } private List createLottoByPurchaseCount(final int lottoPurchaseCount) { - return Stream.generate(UserLotto::createLottoByAutomatic) + return Stream.generate(() -> UserLotto.createLotto(LottoRandomGenerator.generate())) .limit(lottoPurchaseCount) .collect(Collectors.toList()); } diff --git a/src/main/java/lotto/utils/LottoRandomGenerator.java b/src/main/java/lotto/utils/LottoRandomGenerator.java new file mode 100644 index 0000000..dd7189e --- /dev/null +++ b/src/main/java/lotto/utils/LottoRandomGenerator.java @@ -0,0 +1,17 @@ +package lotto.utils; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.List; + +import static lotto.utils.LottoConstants.*; + +public class LottoRandomGenerator { + public static List generate() { + return Randoms.pickUniqueNumbersInRange( + MIN_VALUE, + MAX_VALUE, + LOTTO_SIZE + ); + } +} diff --git a/src/test/java/lotto/model/UserLottoTest.java b/src/test/java/lotto/model/UserLottoTest.java index 796a1bb..c4f6368 100644 --- a/src/test/java/lotto/model/UserLottoTest.java +++ b/src/test/java/lotto/model/UserLottoTest.java @@ -1,28 +1,35 @@ package lotto.model; +import lotto.utils.LottoRandomGenerator; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.List; + import static lotto.utils.LottoConstants.LOTTO_SIZE; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; class UserLottoTest { @Test - @DisplayName("UserLotto 생성한다") + @DisplayName("UserLotto를 생성한다") void construct() { // when - final UserLotto userLotto = UserLotto.createLottoByAutomatic(); + final List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + final UserLotto userLotto = UserLotto.createLotto(numbers); + final UserLotto userLottoByAuto = UserLotto.createLotto(LottoRandomGenerator.generate()); // then assertAll( - () -> assertThat(userLotto.getLottoNumbers()).hasSize(LOTTO_SIZE), // size + () -> assertThat(userLotto.getLottoNumbers()).containsExactlyElementsOf(numbers), // 수동 생성 + () -> assertThat(userLottoByAuto.getLottoNumbers()).hasSize(LOTTO_SIZE), // 자동 생성 - size validation () -> assertThat( - userLotto.getLottoNumbers() + userLottoByAuto.getLottoNumbers() .stream() .distinct() .count() - ).isEqualTo(LOTTO_SIZE) // has duplicate + ).isEqualTo(LOTTO_SIZE) // 자동 생성 - has duplicate validation ); } } From 89dd6b31261368fa0462326cd62fbe77fd8ea483 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 17:23:53 +0900 Subject: [PATCH 12/46] =?UTF-8?q?feat:=20UserLottos=20=EB=A1=9C=EB=98=90?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20`@VisibleForTesting`=20=EC=A0=84=EC=9A=A9=20?= =?UTF-8?q?=EC=83=9D=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/model/UserLottos.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/lotto/model/UserLottos.java b/src/main/java/lotto/model/UserLottos.java index 415d746..df9e278 100644 --- a/src/main/java/lotto/model/UserLottos.java +++ b/src/main/java/lotto/model/UserLottos.java @@ -1,6 +1,7 @@ package lotto.model; import lotto.utils.LottoRandomGenerator; +import org.assertj.core.util.VisibleForTesting; import java.util.Collections; import java.util.List; @@ -14,6 +15,11 @@ private UserLottos(final int lottoPurchaseCount) { this.userLottos = createLottoByPurchaseCount(lottoPurchaseCount); } + @VisibleForTesting + public UserLottos(final List userLottos) { + this.userLottos = userLottos; + } + public static UserLottos issueLottoByPurchaseCount(final int lottoPurchaseCount) { return new UserLottos(lottoPurchaseCount); } From f559c1a343efd9e57adfb9561404a1ddb6b1c632 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 17:24:49 +0900 Subject: [PATCH 13/46] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=ED=86=B5?= =?UTF-8?q?=EA=B3=84=20=EC=B6=94=EC=B6=9C=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?LottoStatistics=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/model/LottoStatistics.java | 73 ++++++++++++ .../java/lotto/model/LottoStatisticsTest.java | 108 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 src/main/java/lotto/model/LottoStatistics.java create mode 100644 src/test/java/lotto/model/LottoStatisticsTest.java diff --git a/src/main/java/lotto/model/LottoStatistics.java b/src/main/java/lotto/model/LottoStatistics.java new file mode 100644 index 0000000..b9952e1 --- /dev/null +++ b/src/main/java/lotto/model/LottoStatistics.java @@ -0,0 +1,73 @@ +package lotto.model; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class LottoStatistics { + private final LottoWinningMachine lottoWinningMachine; + private final UserLottos userLottos; + private final Map winningResult = new EnumMap<>(WinningRank.class); + + private LottoStatistics( + final LottoWinningMachine lottoWinningMachine, + final UserLottos userLottos + ) { + this.lottoWinningMachine = lottoWinningMachine; + this.userLottos = userLottos; + initWinningResult(); + calculateLotteryWinningResult(); + } + + public static LottoStatistics of( + final LottoWinningMachine lottoWinningMachine, + final UserLottos userLottos + ) { + return new LottoStatistics(lottoWinningMachine, userLottos); + } + + private void initWinningResult() { + for (WinningRank winningRank : WinningRank.values()) { + winningResult.put(winningRank, 0); + } + } + + private void calculateLotteryWinningResult() { + List winningLotteryNumbers = lottoWinningMachine.getWinningLotteryNumbers(); + int bonusNumber = lottoWinningMachine.getBonusNumber(); + + for (UserLotto userLotto : userLottos.getUserLottos()) { + List lottoNumbers = userLotto.getLottoNumbers(); + int matchCount = getLottoMatchCount(lottoNumbers, winningLotteryNumbers); + boolean hasBonus = isBonusNumberExists(lottoNumbers, bonusNumber); + + WinningRank winningRank = WinningRank.of(matchCount, hasBonus); + updateWinningResult(winningRank); + } + } + + private int getLottoMatchCount( + final List lottoNumbers, + final List winningLotteryNumbers + ) { + return (int) lottoNumbers.stream() + .filter(winningLotteryNumbers::contains) + .count(); + } + + private boolean isBonusNumberExists( + final List lottoNumbers, + final int bonusNumber + ) { + return lottoNumbers.contains(bonusNumber); + } + + private void updateWinningResult(final WinningRank winningRank) { + winningResult.put(winningRank, winningResult.get(winningRank) + 1); + } + + public Map getWinningResult() { + return Collections.unmodifiableMap(winningResult); + } +} diff --git a/src/test/java/lotto/model/LottoStatisticsTest.java b/src/test/java/lotto/model/LottoStatisticsTest.java new file mode 100644 index 0000000..2632fe1 --- /dev/null +++ b/src/test/java/lotto/model/LottoStatisticsTest.java @@ -0,0 +1,108 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +class LottoStatisticsTest { + @Test + @DisplayName("구매한 로또 N장에 대한 당첨 통계를 조회한다") + void getWinningResult() { + // given + final LottoWinningMachine lottoWinningMachine = createLottoWinningMachine(); + final UserLottos userLottosCaseA = createUserLottosCaseA(); + final UserLottos userLottosCaseB = createUserLottosCaseB(); + + // when + LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottosCaseA); + LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottosCaseB); + + // then + Map winningResultA = caseA.getWinningResult(); + assertAll( + () -> assertThat(winningResultA.get(WinningRank.FIRST)).isEqualTo(1), + () -> assertThat(winningResultA.get(WinningRank.SECOND)).isEqualTo(1), + () -> assertThat(winningResultA.get(WinningRank.THIRD)).isEqualTo(1), + () -> assertThat(winningResultA.get(WinningRank.FOURTH)).isEqualTo(1), + () -> assertThat(winningResultA.get(WinningRank.FIFTH)).isEqualTo(2), + () -> assertThat(winningResultA.get(WinningRank.NONE)).isEqualTo(5) + ); + + Map winningResultB = caseB.getWinningResult(); + assertAll( + () -> assertThat(winningResultB.get(WinningRank.FIRST)).isEqualTo(0), + () -> assertThat(winningResultB.get(WinningRank.SECOND)).isEqualTo(0), + () -> assertThat(winningResultB.get(WinningRank.THIRD)).isEqualTo(0), + () -> assertThat(winningResultB.get(WinningRank.FOURTH)).isEqualTo(0), + () -> assertThat(winningResultB.get(WinningRank.FIFTH)).isEqualTo(3), + () -> assertThat(winningResultB.get(WinningRank.NONE)).isEqualTo(14) + ); + } + + private LottoWinningMachine createLottoWinningMachine() { + return LottoWinningMachine.drawWinningLottery( + Arrays.asList(1, 9, 10, 12, 22, 37), + 40 + ); + } + + private UserLottos createUserLottosCaseA() { + return new UserLottos( + List.of( + UserLotto.createLotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None + UserLotto.createLotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None + UserLotto.createLotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 + UserLotto.createLotto(Arrays.asList(7, 10, 22, 37, 42, 43)), // 5등 + UserLotto.createLotto(Arrays.asList(1, 10, 22, 37, 38, 45)), // 4등 + UserLotto.createLotto(Arrays.asList(1, 9, 10, 12, 37, 39)), // 3등 + UserLotto.createLotto(Arrays.asList(1, 9, 10, 12, 37, 40)), // 2등 + UserLotto.createLotto(Arrays.asList(1, 9, 10, 12, 22, 37)) // 1등 + ) + ); + + /** + * 구매 금액 = 10_000 + * 당첨 금액 = 2_031_560_000 + * -> 수익률 = 203156% + */ + } + + private UserLottos createUserLottosCaseB() { + return new UserLottos( + List.of( + UserLotto.createLotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None + UserLotto.createLotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None + UserLotto.createLotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None + UserLotto.createLotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None + UserLotto.createLotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 + UserLotto.createLotto(Arrays.asList(7, 10, 22, 37, 42, 43)), // 5등 + UserLotto.createLotto(Arrays.asList(1, 10, 22, 35, 38, 45)) // 5등 + ) + ); + + /** + * 구매 금액 = 17000 + * 당첨 금액 = 15000 + * -> 수익률 = 88.2% + */ + } +} From dfe2bc56744a4be0cda5026c8115c3fc4ffc05fd Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 17:25:46 +0900 Subject: [PATCH 14/46] =?UTF-8?q?refactor:=20final=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/lotto/model/LottoStatisticsTest.java | 8 ++++---- src/test/java/lotto/model/UserLottosTest.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/lotto/model/LottoStatisticsTest.java b/src/test/java/lotto/model/LottoStatisticsTest.java index 2632fe1..a046347 100644 --- a/src/test/java/lotto/model/LottoStatisticsTest.java +++ b/src/test/java/lotto/model/LottoStatisticsTest.java @@ -20,11 +20,11 @@ void getWinningResult() { final UserLottos userLottosCaseB = createUserLottosCaseB(); // when - LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottosCaseA); - LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottosCaseB); + final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottosCaseA); + final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottosCaseB); // then - Map winningResultA = caseA.getWinningResult(); + final Map winningResultA = caseA.getWinningResult(); assertAll( () -> assertThat(winningResultA.get(WinningRank.FIRST)).isEqualTo(1), () -> assertThat(winningResultA.get(WinningRank.SECOND)).isEqualTo(1), @@ -34,7 +34,7 @@ void getWinningResult() { () -> assertThat(winningResultA.get(WinningRank.NONE)).isEqualTo(5) ); - Map winningResultB = caseB.getWinningResult(); + final Map winningResultB = caseB.getWinningResult(); assertAll( () -> assertThat(winningResultB.get(WinningRank.FIRST)).isEqualTo(0), () -> assertThat(winningResultB.get(WinningRank.SECOND)).isEqualTo(0), diff --git a/src/test/java/lotto/model/UserLottosTest.java b/src/test/java/lotto/model/UserLottosTest.java index 6d3b6c8..d08cc98 100644 --- a/src/test/java/lotto/model/UserLottosTest.java +++ b/src/test/java/lotto/model/UserLottosTest.java @@ -12,7 +12,7 @@ class UserLottosTest { @DisplayName("구매한 개수만큼 UseLotto를 발급받는다") void construct(int lottoPurchaseCount) { // when - UserLottos userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); + final UserLottos userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); // then assertThat(userLottos.getUserLottos()).hasSize(lottoPurchaseCount); From 7caf7a52b41057ee4e48be2f52d2d796b00dfb26 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 17:27:59 +0900 Subject: [PATCH 15/46] =?UTF-8?q?refactor:=20=EA=B5=AC=EB=A7=A4=ED=95=9C?= =?UTF-8?q?=20=EB=A1=9C=EB=98=90=20=EA=B0=9C=EC=88=98=EB=A5=BC=20=EC=96=BB?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=9C=20=EB=A9=94=EC=86=8C=EB=93=9C=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/model/UserLottos.java | 4 ++++ src/test/java/lotto/model/UserLottosTest.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/model/UserLottos.java b/src/main/java/lotto/model/UserLottos.java index df9e278..b00911a 100644 --- a/src/main/java/lotto/model/UserLottos.java +++ b/src/main/java/lotto/model/UserLottos.java @@ -33,4 +33,8 @@ private List createLottoByPurchaseCount(final int lottoPurchaseCount) public List getUserLottos() { return Collections.unmodifiableList(userLottos); } + + public int getLottoPurchseCount() { + return userLottos.size(); + } } diff --git a/src/test/java/lotto/model/UserLottosTest.java b/src/test/java/lotto/model/UserLottosTest.java index d08cc98..3bb51f0 100644 --- a/src/test/java/lotto/model/UserLottosTest.java +++ b/src/test/java/lotto/model/UserLottosTest.java @@ -15,6 +15,6 @@ void construct(int lottoPurchaseCount) { final UserLottos userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); // then - assertThat(userLottos.getUserLottos()).hasSize(lottoPurchaseCount); + assertThat(userLottos.getLottoPurchseCount()).isEqualTo(lottoPurchaseCount); } } From 2081329b65e0c681306ebc41600a10b7ab02300d Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 18:07:01 +0900 Subject: [PATCH 16/46] =?UTF-8?q?fix:=205=EB=93=B1=20=EB=8B=B9=EC=B2=A8?= =?UTF-8?q?=EA=B8=88=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/model/WinningRank.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/lotto/model/WinningRank.java b/src/main/java/lotto/model/WinningRank.java index 96fa079..745c6a0 100644 --- a/src/main/java/lotto/model/WinningRank.java +++ b/src/main/java/lotto/model/WinningRank.java @@ -8,7 +8,7 @@ public enum WinningRank { SECOND(5, List.of(true), 30_000_000, "5개 일치, 보너스 볼 일치"), THIRD(5, List.of(false), 1_500_000, "5개 일치"), FOURTH(4, List.of(true, false), 50_000, "4개 일치"), - FIFTH(3, List.of(true, false), 50_000, "3개 일치"), + FIFTH(3, List.of(true, false), 5_000, "3개 일치"), NONE(1, List.of(), 0, "NONE..."), ; From 8c5ec97affd055d6c7506a76952a460605ca9e54 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 18:14:18 +0900 Subject: [PATCH 17/46] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=20=EC=88=98=EC=9D=B5=EB=A5=A0=20=EA=B3=84=EC=82=B0=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 --- docs/README.md | 2 +- .../java/lotto/model/LottoStatistics.java | 27 +++++++++++++++++ src/main/java/lotto/model/UserLottos.java | 5 ++++ .../java/lotto/model/LottoStatisticsTest.java | 30 +++++++++++++++---- src/test/java/lotto/model/UserLottosTest.java | 24 ++++++++++++--- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/docs/README.md b/docs/README.md index bf80ae4..9eea093 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,7 +7,7 @@ - [X] LottoWinningMachine은 로또 당첨 번호를 생성한다 - 총 7개의 중복되지 않는 숫자 (기본 당첨 번호 6개 + 보너스 번호 1개) -- [ ] LottoStatistics는 N장의 로또에 대한 당첨 통계를 산출한다 +- [X] LottoStatistics는 N장의 로또에 대한 당첨 통계를 산출한다

diff --git a/src/main/java/lotto/model/LottoStatistics.java b/src/main/java/lotto/model/LottoStatistics.java index b9952e1..ce220e6 100644 --- a/src/main/java/lotto/model/LottoStatistics.java +++ b/src/main/java/lotto/model/LottoStatistics.java @@ -1,5 +1,7 @@ package lotto.model; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Collections; import java.util.EnumMap; import java.util.List; @@ -70,4 +72,29 @@ private void updateWinningResult(final WinningRank winningRank) { public Map getWinningResult() { return Collections.unmodifiableMap(winningResult); } + + public BigDecimal getEarningRate() { + final BigDecimal lottoPurchaseAmount = userLottos.getLottoPurchaseAmount(); + final BigDecimal totalWinningAmount = calculateTotalWinningAmount(); + + return totalWinningAmount + .multiply(BigDecimal.valueOf(100)) // 백분율 + .divide(lottoPurchaseAmount, 1, RoundingMode.HALF_UP); + } + + private BigDecimal calculateTotalWinningAmount() { + BigDecimal amount = BigDecimal.ZERO; + for (WinningRank winningRank : winningResult.keySet()) { + final BigDecimal addPrize = getAddPrize(winningRank); + amount = amount.add(addPrize); + } + return amount; + } + + private BigDecimal getAddPrize(final WinningRank winningRank) { + final int reward = winningRank.getReward(); + final int count = winningResult.get(winningRank); + + return BigDecimal.valueOf((long) reward * count); + } } diff --git a/src/main/java/lotto/model/UserLottos.java b/src/main/java/lotto/model/UserLottos.java index b00911a..9658f73 100644 --- a/src/main/java/lotto/model/UserLottos.java +++ b/src/main/java/lotto/model/UserLottos.java @@ -3,6 +3,7 @@ import lotto.utils.LottoRandomGenerator; import org.assertj.core.util.VisibleForTesting; +import java.math.BigDecimal; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -37,4 +38,8 @@ public List getUserLottos() { public int getLottoPurchseCount() { return userLottos.size(); } + + public BigDecimal getLottoPurchaseAmount() { + return BigDecimal.valueOf(1000).multiply(BigDecimal.valueOf(getLottoPurchseCount())); + } } diff --git a/src/test/java/lotto/model/LottoStatisticsTest.java b/src/test/java/lotto/model/LottoStatisticsTest.java index a046347..8750136 100644 --- a/src/test/java/lotto/model/LottoStatisticsTest.java +++ b/src/test/java/lotto/model/LottoStatisticsTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -45,6 +46,25 @@ void getWinningResult() { ); } + @Test + @DisplayName("구매한 로또 N장에 대한 수익률을 조회한다") + void getEarningRate() { + // given + final LottoWinningMachine lottoWinningMachine = createLottoWinningMachine(); + final UserLottos userLottosCaseA = createUserLottosCaseA(); + final UserLottos userLottosCaseB = createUserLottosCaseB(); + + // when + final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottosCaseA); + final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottosCaseB); + + // then + assertAll( + () -> assertThat(caseA.getEarningRate()).isEqualTo(BigDecimal.valueOf(18468727.3)), + () -> assertThat(caseB.getEarningRate()).isEqualTo(BigDecimal.valueOf(88.2)) + ); + } + private LottoWinningMachine createLottoWinningMachine() { return LottoWinningMachine.drawWinningLottery( Arrays.asList(1, 9, 10, 12, 22, 37), @@ -70,9 +90,9 @@ private UserLottos createUserLottosCaseA() { ); /** - * 구매 금액 = 10_000 + * 구매 금액 = 11_000 * 당첨 금액 = 2_031_560_000 - * -> 수익률 = 203156% + * -> 수익률 = 184,687.27272727272727272727272727... = 18468727.27% = 18468727.3% */ } @@ -94,15 +114,15 @@ private UserLottos createUserLottosCaseB() { UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - UserLotto.createLotto(Arrays.asList(7, 10, 22, 37, 42, 43)), // 5등 - UserLotto.createLotto(Arrays.asList(1, 10, 22, 35, 38, 45)) // 5등 + UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 + UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)) // 5등 ) ); /** * 구매 금액 = 17000 * 당첨 금액 = 15000 - * -> 수익률 = 88.2% + * -> 수익률 = 0.88235294117647058823529411764706... = 88.23% = 88.2% */ } } diff --git a/src/test/java/lotto/model/UserLottosTest.java b/src/test/java/lotto/model/UserLottosTest.java index 3bb51f0..a53f4db 100644 --- a/src/test/java/lotto/model/UserLottosTest.java +++ b/src/test/java/lotto/model/UserLottosTest.java @@ -2,19 +2,35 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.BigDecimal; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; class UserLottosTest { @ParameterizedTest - @ValueSource(ints = {5, 10}) + @MethodSource("issueCase") @DisplayName("구매한 개수만큼 UseLotto를 발급받는다") - void construct(int lottoPurchaseCount) { + void issueLottoByPurchaseCount(int lottoPurchaseCount, BigDecimal purchaseAmount) { // when final UserLottos userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); // then - assertThat(userLottos.getLottoPurchseCount()).isEqualTo(lottoPurchaseCount); + assertAll( + () -> assertThat(userLottos.getLottoPurchseCount()).isEqualTo(lottoPurchaseCount), + () -> assertThat(userLottos.getLottoPurchaseAmount()).isEqualTo(purchaseAmount) + ); + } + + private static Stream issueCase() { + return Stream.of( + Arguments.of(5, BigDecimal.valueOf(5_000)), + Arguments.of(10, BigDecimal.valueOf(10_000)), + Arguments.of(1_000_000, BigDecimal.valueOf(1_000_000_000)) + ); } } From ccc2319fc5c0f3071b5a73490b1cee52803edc8e Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 18:33:44 +0900 Subject: [PATCH 18/46] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20Inp?= =?UTF-8?q?ut=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B8=B0=EB=B3=B8=20Validat?= =?UTF-8?q?or=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/utils/validator/Validator.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/lotto/utils/validator/Validator.java diff --git a/src/main/java/lotto/utils/validator/Validator.java b/src/main/java/lotto/utils/validator/Validator.java new file mode 100644 index 0000000..52d2f6d --- /dev/null +++ b/src/main/java/lotto/utils/validator/Validator.java @@ -0,0 +1,18 @@ +package lotto.utils.validator; + +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; + +public abstract class Validator { + abstract void validate(final String userInput); + + void validateInputHasSpace(final String userInput) { + if (hasSpace(userInput)) { + throw new IllegalArgumentException(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + } + + private static boolean hasSpace(String userInput) { + return userInput.chars() + .anyMatch(Character::isWhitespace); + } +} From debb63e841ee1a6892efe7bc13a97a34da52e323 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 18:34:11 +0900 Subject: [PATCH 19/46] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EC=9E=85=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EA=B2=80=EC=A6=9D=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/utils/ExceptionConstants.java | 13 ++++++ .../LottoPurchaseAmountValidator.java | 29 +++++++++++++ .../LottoPurchaseAmountValidatorTest.java | 43 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java create mode 100644 src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java diff --git a/src/main/java/lotto/utils/ExceptionConstants.java b/src/main/java/lotto/utils/ExceptionConstants.java index ca4dd36..a9c0240 100644 --- a/src/main/java/lotto/utils/ExceptionConstants.java +++ b/src/main/java/lotto/utils/ExceptionConstants.java @@ -24,4 +24,17 @@ enum LottoMachineException { this.message = message; } } + + enum InputException { + INPUT_MUST_NOT_CONTAINS_SPACE("공백없이 입력해주세요."), + INPUT_MUST_BE_NUMERIC("숫자를 입력해주세요."), + PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT("천원 단위로 구입금액을 입력해주세요.") + ; + + public final String message; + + InputException(final String message) { + this.message = message; + } + } } diff --git a/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java b/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java new file mode 100644 index 0000000..c92b631 --- /dev/null +++ b/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java @@ -0,0 +1,29 @@ +package lotto.utils.validator; + +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; +import static lotto.utils.ExceptionConstants.InputException.PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT; + +public class LottoPurchaseAmountValidator extends Validator { + private static final int PURCHASE_UNIT = 1000; + + @Override + public void validate(final String userInput) { + validateInputHasSpace(userInput); + validateInputIsNumeric(userInput); + validateUnitOfAmountIsThousand(userInput); + } + + private void validateInputIsNumeric(String userInput) { + try { + Integer.parseInt(userInput); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException(INPUT_MUST_BE_NUMERIC.message); + } + } + + private void validateUnitOfAmountIsThousand(String userInput) { + if (Integer.parseInt(userInput) % PURCHASE_UNIT != 0) { + throw new IllegalArgumentException(PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT.message); + } + } +} diff --git a/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java b/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java new file mode 100644 index 0000000..4e97f79 --- /dev/null +++ b/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java @@ -0,0 +1,43 @@ +package lotto.utils.validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static lotto.utils.ExceptionConstants.InputException.*; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class LottoPurchaseAmountValidatorTest { + private static final LottoPurchaseAmountValidator LOTTO_PURCHASE_AMOUNT_VALIDATOR + = new LottoPurchaseAmountValidator(); + + @Test + @DisplayName("로또 구입금액에 공백이 존재하면 예외가 발생한다") + void throwExceptionByInputHasSpace() { + assertThatThrownBy(() -> LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate("8000 ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + + @Test + @DisplayName("로또 구입금액이 숫자가 아니면 예외가 발생한다") + void throwExceptionByInputIsNotNumeric() { + assertThatThrownBy(() -> LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate("abcde")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_BE_NUMERIC.message); + } + + @Test + @DisplayName("로또 구입금액이 1000원 단위가 아니면 예외가 발생한다") + void throwExceptionByUnitOfAmountIsNotThousand() { + assertThatThrownBy(() -> LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate("800")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT.message); + } + + @Test + @DisplayName("로또 구입금액 검증에 성공한다") + void success() { + assertDoesNotThrow(() -> LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate("8000")); + } +} From 03da5e18eb96ecf552418635117b072fe414aa35 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 20:12:15 +0900 Subject: [PATCH 20/46] =?UTF-8?q?refactor:=20validateInputIsNumeric=20Vali?= =?UTF-8?q?dator=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/validator/LottoPurchaseAmountValidator.java | 9 --------- src/main/java/lotto/utils/validator/Validator.java | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java b/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java index c92b631..24be8fb 100644 --- a/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java +++ b/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java @@ -1,6 +1,5 @@ package lotto.utils.validator; -import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; import static lotto.utils.ExceptionConstants.InputException.PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT; public class LottoPurchaseAmountValidator extends Validator { @@ -13,14 +12,6 @@ public void validate(final String userInput) { validateUnitOfAmountIsThousand(userInput); } - private void validateInputIsNumeric(String userInput) { - try { - Integer.parseInt(userInput); - } catch (NumberFormatException exception) { - throw new IllegalArgumentException(INPUT_MUST_BE_NUMERIC.message); - } - } - private void validateUnitOfAmountIsThousand(String userInput) { if (Integer.parseInt(userInput) % PURCHASE_UNIT != 0) { throw new IllegalArgumentException(PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT.message); diff --git a/src/main/java/lotto/utils/validator/Validator.java b/src/main/java/lotto/utils/validator/Validator.java index 52d2f6d..0544539 100644 --- a/src/main/java/lotto/utils/validator/Validator.java +++ b/src/main/java/lotto/utils/validator/Validator.java @@ -1,5 +1,6 @@ package lotto.utils.validator; +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; public abstract class Validator { @@ -15,4 +16,12 @@ private static boolean hasSpace(String userInput) { return userInput.chars() .anyMatch(Character::isWhitespace); } + + void validateInputIsNumeric(String userInput) { + try { + Integer.parseInt(userInput); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException(INPUT_MUST_BE_NUMERIC.message); + } + } } From 116f42929ba4155512f9ec85e943aa1421f2e488 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 20:13:51 +0900 Subject: [PATCH 21/46] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../validator/WinningNumberValidator.java | 20 +++++++++++ .../validator/WinningNumberValidatorTest.java | 36 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/main/java/lotto/utils/validator/WinningNumberValidator.java create mode 100644 src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java diff --git a/src/main/java/lotto/utils/validator/WinningNumberValidator.java b/src/main/java/lotto/utils/validator/WinningNumberValidator.java new file mode 100644 index 0000000..4581282 --- /dev/null +++ b/src/main/java/lotto/utils/validator/WinningNumberValidator.java @@ -0,0 +1,20 @@ +package lotto.utils.validator; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class WinningNumberValidator extends Validator { + private static final String COMMA = ","; + + @Override + public void validate(final String userInput) { + validateInputHasSpace(userInput); + inputSplitByComma(userInput).forEach(this::validateInputIsNumeric); + } + + private List inputSplitByComma(final String userInput) { + return Arrays.stream(userInput.split(COMMA)) + .collect(Collectors.toList()); + } +} diff --git a/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java b/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java new file mode 100644 index 0000000..02fefb6 --- /dev/null +++ b/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java @@ -0,0 +1,36 @@ +package lotto.utils.validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class WinningNumberValidatorTest { + private static final WinningNumberValidator WINNING_NUMBER_VALIDATOR + = new WinningNumberValidator(); + + @Test + @DisplayName("당첨번호에 공백이 존재하면 예외가 발생한다") + void throwExceptionByInputHasSpace() { + assertThatThrownBy(() -> WINNING_NUMBER_VALIDATOR.validate("1,2,3,4, 5, 6, ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + + @Test + @DisplayName("당첨번호의 각 번호들이 숫자가 아니면 예외가 발생한다") + void throwExceptionByInputIsNotNumeric() { + assertThatThrownBy(() -> WINNING_NUMBER_VALIDATOR.validate("1,2,3,a,4,5,b,6")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_BE_NUMERIC.message); + } + + @Test + @DisplayName("당첨번호 검증에 성공한다") + void success() { + assertDoesNotThrow(() -> WINNING_NUMBER_VALIDATOR.validate("1,2,3,4,5,6")); + } +} From 62780ab016d2a5a5f328d31bc635a1e286d9b726 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 20:20:14 +0900 Subject: [PATCH 22/46] =?UTF-8?q?refactor:=20=EB=8B=B9=EC=B2=A8=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EA=B2=80=EC=A6=9D=20=EA=B0=84=20Exception=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/utils/ExceptionConstants.java | 3 ++- .../utils/validator/WinningNumberValidator.java | 12 +++++++++++- .../utils/validator/WinningNumberValidatorTest.java | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/lotto/utils/ExceptionConstants.java b/src/main/java/lotto/utils/ExceptionConstants.java index a9c0240..554aef4 100644 --- a/src/main/java/lotto/utils/ExceptionConstants.java +++ b/src/main/java/lotto/utils/ExceptionConstants.java @@ -28,7 +28,8 @@ enum LottoMachineException { enum InputException { INPUT_MUST_NOT_CONTAINS_SPACE("공백없이 입력해주세요."), INPUT_MUST_BE_NUMERIC("숫자를 입력해주세요."), - PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT("천원 단위로 구입금액을 입력해주세요.") + PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT("천원 단위로 구입금액을 입력해주세요."), + WINNING_NUMBER_MUST_BE_SPLIT_BY_COMMA("당첨번호는 콤마(,)로 구분해서 공백없이 입력해주세요."), ; public final String message; diff --git a/src/main/java/lotto/utils/validator/WinningNumberValidator.java b/src/main/java/lotto/utils/validator/WinningNumberValidator.java index 4581282..045a25e 100644 --- a/src/main/java/lotto/utils/validator/WinningNumberValidator.java +++ b/src/main/java/lotto/utils/validator/WinningNumberValidator.java @@ -4,17 +4,27 @@ import java.util.List; import java.util.stream.Collectors; +import static lotto.utils.ExceptionConstants.InputException.WINNING_NUMBER_MUST_BE_SPLIT_BY_COMMA; + public class WinningNumberValidator extends Validator { private static final String COMMA = ","; @Override public void validate(final String userInput) { validateInputHasSpace(userInput); - inputSplitByComma(userInput).forEach(this::validateInputIsNumeric); + inputSplitByComma(userInput).forEach(this::validateInputElementIsNumeric); } private List inputSplitByComma(final String userInput) { return Arrays.stream(userInput.split(COMMA)) .collect(Collectors.toList()); } + + void validateInputElementIsNumeric(String userInput) { + try { + Integer.parseInt(userInput); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException(WINNING_NUMBER_MUST_BE_SPLIT_BY_COMMA.message); + } + } } diff --git a/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java b/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java index 02fefb6..8e91451 100644 --- a/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java +++ b/src/test/java/lotto/utils/validator/WinningNumberValidatorTest.java @@ -3,8 +3,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; +import static lotto.utils.ExceptionConstants.InputException.WINNING_NUMBER_MUST_BE_SPLIT_BY_COMMA; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -25,7 +25,7 @@ void throwExceptionByInputHasSpace() { void throwExceptionByInputIsNotNumeric() { assertThatThrownBy(() -> WINNING_NUMBER_VALIDATOR.validate("1,2,3,a,4,5,b,6")) .isInstanceOf(IllegalArgumentException.class) - .hasMessage(INPUT_MUST_BE_NUMERIC.message); + .hasMessage(WINNING_NUMBER_MUST_BE_SPLIT_BY_COMMA.message); } @Test From f6aeb7dbdc7be1b176a26a60dcbf2fd7e8b38386 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 20:20:27 +0900 Subject: [PATCH 23/46] =?UTF-8?q?feat:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EA=B2=80=EC=A6=9D=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/validator/BonusNumberValidator.java | 9 +++++ .../validator/BonusNumberValidatorTest.java | 36 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/java/lotto/utils/validator/BonusNumberValidator.java create mode 100644 src/test/java/lotto/utils/validator/BonusNumberValidatorTest.java diff --git a/src/main/java/lotto/utils/validator/BonusNumberValidator.java b/src/main/java/lotto/utils/validator/BonusNumberValidator.java new file mode 100644 index 0000000..c860a97 --- /dev/null +++ b/src/main/java/lotto/utils/validator/BonusNumberValidator.java @@ -0,0 +1,9 @@ +package lotto.utils.validator; + +public class BonusNumberValidator extends Validator { + @Override + public void validate(final String userInput) { + validateInputHasSpace(userInput); + validateInputIsNumeric(userInput); + } +} diff --git a/src/test/java/lotto/utils/validator/BonusNumberValidatorTest.java b/src/test/java/lotto/utils/validator/BonusNumberValidatorTest.java new file mode 100644 index 0000000..9189cbe --- /dev/null +++ b/src/test/java/lotto/utils/validator/BonusNumberValidatorTest.java @@ -0,0 +1,36 @@ +package lotto.utils.validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_BE_NUMERIC; +import static lotto.utils.ExceptionConstants.InputException.INPUT_MUST_NOT_CONTAINS_SPACE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class BonusNumberValidatorTest { + private static final BonusNumberValidator BONUS_NUMBER_VALIDATOR + = new BonusNumberValidator(); + + @Test + @DisplayName("보너스 번호에 공백이 존재하면 예외가 발생한다") + void throwExceptionByInputHasSpace() { + assertThatThrownBy(() -> BONUS_NUMBER_VALIDATOR.validate("7 ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_NOT_CONTAINS_SPACE.message); + } + + @Test + @DisplayName("보너스 번호가 숫자가 아니면 예외가 발생한다") + void throwExceptionByInputIsNotNumeric() { + assertThatThrownBy(() -> BONUS_NUMBER_VALIDATOR.validate("a")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(INPUT_MUST_BE_NUMERIC.message); + } + + @Test + @DisplayName("보너스 번호 검증에 성공한다") + void success() { + assertDoesNotThrow(() -> BONUS_NUMBER_VALIDATOR.validate("7")); + } +} From 52e8417051ede6f0be676555ab249a4d59f53e84 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 20:20:48 +0900 Subject: [PATCH 24/46] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20InputView=20?= =?UTF-8?q?=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/view/InputView.java | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/lotto/view/InputView.java diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java new file mode 100644 index 0000000..9238098 --- /dev/null +++ b/src/main/java/lotto/view/InputView.java @@ -0,0 +1,53 @@ +package lotto.view; + +import camp.nextstep.edu.missionutils.Console; +import lotto.utils.validator.BonusNumberValidator; +import lotto.utils.validator.LottoPurchaseAmountValidator; +import lotto.utils.validator.WinningNumberValidator; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class InputView { + private static final String COMMA = ","; + private static final LottoPurchaseAmountValidator LOTTO_PURCHASE_AMOUNT_VALIDATOR + = new LottoPurchaseAmountValidator(); + private static final WinningNumberValidator WINNING_NUMBER_VALIDATOR + = new WinningNumberValidator(); + private static final BonusNumberValidator BONUS_NUMBER_VALIDATOR + = new BonusNumberValidator(); + + public static int readLottoPurchaseAmount() { + System.out.println("구입금액을 입력해 주세요."); + + final String userInput = Console.readLine(); + LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate(userInput); + + return Integer.parseInt(userInput); + } + + public static List readWiningNumbers() { + System.out.println("당첨 번호를 입력해 주세요."); + + final String userInput = Console.readLine(); + WINNING_NUMBER_VALIDATOR.validate(userInput); + + return convertUserInputToIntegerList(userInput); + } + + private static List convertUserInputToIntegerList(final String userInput) { + return Arrays.stream(userInput.split(COMMA)) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } + + public static int readBonusNumber() { + System.out.println("보너스 번호를 입력해 주세요."); + + final String userInput = Console.readLine(); + BONUS_NUMBER_VALIDATOR.validate(userInput); + + return Integer.parseInt(userInput); + } +} From 44009388353d5bf72261a9af08f0aa94d4da9bb5 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:06:08 +0900 Subject: [PATCH 25/46] =?UTF-8?q?refactor:=20=EB=AF=B8=EB=8B=B9=EC=B2=A8?= =?UTF-8?q?=EC=9E=90=20matchCount=200=EC=9C=BC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/model/WinningRank.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/lotto/model/WinningRank.java b/src/main/java/lotto/model/WinningRank.java index 745c6a0..c3f5c68 100644 --- a/src/main/java/lotto/model/WinningRank.java +++ b/src/main/java/lotto/model/WinningRank.java @@ -9,7 +9,7 @@ public enum WinningRank { THIRD(5, List.of(false), 1_500_000, "5개 일치"), FOURTH(4, List.of(true, false), 50_000, "4개 일치"), FIFTH(3, List.of(true, false), 5_000, "3개 일치"), - NONE(1, List.of(), 0, "NONE..."), + NONE(0, List.of(), 0, "NONE..."), ; private final int matchCount; From af698570e3790e74d645f67c3dfb02660f6417ca Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:06:22 +0900 Subject: [PATCH 26/46] =?UTF-8?q?feat:=20UserLotto=20toString()=20?= =?UTF-8?q?=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/model/UserLotto.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/lotto/model/UserLotto.java b/src/main/java/lotto/model/UserLotto.java index 94257c5..4d0c3c9 100644 --- a/src/main/java/lotto/model/UserLotto.java +++ b/src/main/java/lotto/model/UserLotto.java @@ -16,4 +16,9 @@ public static UserLotto createLotto(final List numbers) { public List getLottoNumbers() { return lotto.getNumbers(); } + + @Override + public String toString() { + return lotto.getNumbers().toString(); + } } From 1be1d24babb3c16737b2db6a2aa9b7941b9f29db Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:06:46 +0900 Subject: [PATCH 27/46] =?UTF-8?q?feat:=20=EC=88=9C=EC=9C=84=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=8B=B9=EC=B2=A8=20=EA=B0=9C=EC=88=98=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=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/model/LottoStatistics.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/lotto/model/LottoStatistics.java b/src/main/java/lotto/model/LottoStatistics.java index ce220e6..e1aa743 100644 --- a/src/main/java/lotto/model/LottoStatistics.java +++ b/src/main/java/lotto/model/LottoStatistics.java @@ -73,6 +73,10 @@ public Map getWinningResult() { return Collections.unmodifiableMap(winningResult); } + public int getWinningCountByRank(final WinningRank winningRank) { + return winningResult.getOrDefault(winningRank, 0); + } + public BigDecimal getEarningRate() { final BigDecimal lottoPurchaseAmount = userLottos.getLottoPurchaseAmount(); final BigDecimal totalWinningAmount = calculateTotalWinningAmount(); From c96e0e671fe80844fe67314c7850fe06f4ac6dd3 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:07:16 +0900 Subject: [PATCH 28/46] =?UTF-8?q?fix:=20UserLottos=20generate()=EC=8B=9C?= =?UTF-8?q?=20unmodifiable=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20wrapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/utils/LottoRandomGenerator.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/lotto/utils/LottoRandomGenerator.java b/src/main/java/lotto/utils/LottoRandomGenerator.java index dd7189e..dda9cdc 100644 --- a/src/main/java/lotto/utils/LottoRandomGenerator.java +++ b/src/main/java/lotto/utils/LottoRandomGenerator.java @@ -2,16 +2,19 @@ import camp.nextstep.edu.missionutils.Randoms; +import java.util.ArrayList; import java.util.List; import static lotto.utils.LottoConstants.*; public class LottoRandomGenerator { public static List generate() { - return Randoms.pickUniqueNumbersInRange( - MIN_VALUE, - MAX_VALUE, - LOTTO_SIZE + return new ArrayList<>( + Randoms.pickUniqueNumbersInRange( + MIN_VALUE, + MAX_VALUE, + LOTTO_SIZE + ) ); } } From a9838c3222f1940ec2df67e4b821c732a1b1c7fb Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:07:37 +0900 Subject: [PATCH 29/46] =?UTF-8?q?refactor:=20=EA=B5=AC=EC=9E=85=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20->=20=EA=B8=88=EC=95=A1=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EB=A1=9C=EB=98=90=20=EA=B0=9C=EC=88=98=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/view/InputView.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java index 9238098..0566fb5 100644 --- a/src/main/java/lotto/view/InputView.java +++ b/src/main/java/lotto/view/InputView.java @@ -10,6 +10,7 @@ import java.util.stream.Collectors; public class InputView { + private static final int PURCHASE_UNIT = 1000; private static final String COMMA = ","; private static final LottoPurchaseAmountValidator LOTTO_PURCHASE_AMOUNT_VALIDATOR = new LottoPurchaseAmountValidator(); @@ -18,13 +19,13 @@ public class InputView { private static final BonusNumberValidator BONUS_NUMBER_VALIDATOR = new BonusNumberValidator(); - public static int readLottoPurchaseAmount() { + public static int readLottoPurchaseCount() { System.out.println("구입금액을 입력해 주세요."); final String userInput = Console.readLine(); LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate(userInput); - return Integer.parseInt(userInput); + return Integer.parseInt(userInput) / PURCHASE_UNIT; } public static List readWiningNumbers() { From 21bd2dcd7a31e331c259e0785d47165e1371460f Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:07:52 +0900 Subject: [PATCH 30/46] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=20=EC=8B=9C=20=EC=BD=98=EC=86=94=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20OutputView=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/view/OutputView.java | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/lotto/view/OutputView.java diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java new file mode 100644 index 0000000..58abb1a --- /dev/null +++ b/src/main/java/lotto/view/OutputView.java @@ -0,0 +1,70 @@ +package lotto.view; + +import lotto.model.LottoStatistics; +import lotto.model.UserLotto; +import lotto.model.WinningRank; + +import java.text.DecimalFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class OutputView { + private static final String ENTER = "\n"; + private static final String ERROR_MESSAGE_FORMAT = "[ERROR] %s"; + private static final String WINNNG_FORMAT = "%s (%s원) - %d개"; + private static final String REWARD_FORMAT = "#,###"; + private static final String EARNING_FORMAT = "총 수익률은 %s%%입니다."; + + public static void printPurchaseInformation(final List userLottos) { + System.out.printf("%d개를 구매했습니다." + ENTER, userLottos.size()); + userLottos.forEach(System.out::println); + } + + public static void printWinningStatistics(final LottoStatistics lottoStatistics) { + StringBuilder result = new StringBuilder("당첨 통계" + ENTER + "---" + ENTER); + addWinningStatistics(lottoStatistics, result); + addEarningRate(lottoStatistics, result); + System.out.println(result); + } + + private static void addWinningStatistics( + final LottoStatistics lottoStatistics, + final StringBuilder result + ) { + List filteredWinningRank = getFilteredWinningRank(); + for (WinningRank winningRank : filteredWinningRank) { + result.append( + String.format( + WINNNG_FORMAT, + winningRank.getDescription(), + refineReward(winningRank.getReward()), + lottoStatistics.getWinningCountByRank(winningRank) + ) + ).append(ENTER); + } + } + + private static Object refineReward(final int reward) { + return new DecimalFormat(REWARD_FORMAT).format(reward); + } + + private static List getFilteredWinningRank() { + return Arrays.stream(WinningRank.values()) + .filter(winningRank -> winningRank != WinningRank.NONE) + .sorted(Collections.reverseOrder()) // Enum Position DESC + .collect(Collectors.toList()); + } + + private static void addEarningRate( + final LottoStatistics lottoStatistics, + final StringBuilder result + ) { + result.append(String.format(EARNING_FORMAT, lottoStatistics.getEarningRate())); + } + + public static void printErrorMessage(final String message) { + System.out.printf(ERROR_MESSAGE_FORMAT, message); + } +} From fdfaf4477026ec12d56d4f43192b615d67f2cbf2 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:08:39 +0900 Subject: [PATCH 31/46] =?UTF-8?q?feat:=20=EC=BD=98=EC=86=94=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EB=9E=A8=20=EC=A7=84=ED=96=89=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20GameController=20=EA=B5=AC=ED=98=84,=20App?= =?UTF-8?q?lication=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 4 +- .../java/lotto/controller/GameController.java | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/main/java/lotto/controller/GameController.java diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922..8fb5a65 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,9 @@ package lotto; +import lotto.controller.GameController; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + new GameController().run(); } } diff --git a/src/main/java/lotto/controller/GameController.java b/src/main/java/lotto/controller/GameController.java new file mode 100644 index 0000000..faa4a37 --- /dev/null +++ b/src/main/java/lotto/controller/GameController.java @@ -0,0 +1,41 @@ +package lotto.controller; + +import lotto.model.LottoStatistics; +import lotto.model.LottoWinningMachine; +import lotto.model.UserLottos; +import lotto.view.InputView; +import lotto.view.OutputView; + +import java.util.List; + +public class GameController { + private static UserLottos userLottos; + private static LottoWinningMachine lottoWinningMachine; + + public void run() { + try { + buyLotto(); + initLottoWinningMachine(); + displayLottoResult(); + } catch (IllegalArgumentException e) { + OutputView.printErrorMessage(e.getMessage()); + } + } + + private void buyLotto() { + final int lottoPurchaseCount = InputView.readLottoPurchaseCount(); + userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); + OutputView.printPurchaseInformation(userLottos.getUserLottos()); + } + + private void initLottoWinningMachine() { + final List winingNumbers = InputView.readWiningNumbers(); + final int bonusNumber = InputView.readBonusNumber(); + lottoWinningMachine = LottoWinningMachine.drawWinningLottery(winingNumbers, bonusNumber); + } + + private void displayLottoResult() { + final LottoStatistics lottoStatistics = LottoStatistics.of(lottoWinningMachine, userLottos); + OutputView.printWinningStatistics(lottoStatistics); + } +} From 54f6ff5f99f47b865afb03356e0597282ad9c876 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:11:19 +0900 Subject: [PATCH 32/46] docs: check clear feature --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 9eea093..a497cc0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ ## Feature -- [ ] User는 `1000원` 단위로 로또 N장을 구매한다 +- [X] User는 `1000원` 단위로 로또 N장을 구매한다 - 구매 후 로또 생성기로부터 N장의 로또를 생성한다 - `1000원` 단위로 입력하지 않을 경우 `IllegalArgumentException`를 발생시키고 `[Error]`로 시작하는 에러 메시지를 출력 후 `종료`한다 From 488b96c31f861c8b98348a3b82e6202d9ec3cf8b Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sat, 15 Jul 2023 21:12:59 +0900 Subject: [PATCH 33/46] =?UTF-8?q?docs:=20validator=20=EB=AC=B8=EC=84=9C=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 --- docs/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/README.md b/docs/README.md index a497cc0..ead5cc2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -58,6 +58,13 @@ - 로또 번호 자동 생성기 +### `Validator` + +- 사용자 Input에 대한 기본 검증 컴포넌트 + - `LottoPurchaseAmountValidator` -> 로또 구입금액 검증 컴포넌트 + - `WinningNumberValidator` -> 로또 당첨번호 검증 컴포넌트 + - `BonusNumberValidator` -> 보너스 번호 검증 컴포넌트 +

From fd0ce650e8f84e2570dd013c7e34a8bca67512a8 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 16 Jul 2023 00:48:27 +0900 Subject: [PATCH 34/46] =?UTF-8?q?refactor:=20Lotto/UserLotto/UserLottos=20?= =?UTF-8?q?=EA=B3=84=EC=B8=B5=EC=97=90=EC=84=9C=20UserLotto=20Wrapping=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 - Lotto -> UserLottos(UserLotto)로 중간 매핑 계층 제거 --- .../java/lotto/controller/GameController.java | 10 +-- src/main/java/lotto/model/Lotto.java | 5 ++ .../java/lotto/model/LottoStatistics.java | 16 ++-- src/main/java/lotto/model/UserLotto.java | 41 +++++++--- src/main/java/lotto/model/UserLottos.java | 45 ----------- src/main/java/lotto/model/WinningRank.java | 4 - src/main/java/lotto/view/OutputView.java | 4 +- .../java/lotto/model/LottoStatisticsTest.java | 80 +++++++++---------- src/test/java/lotto/model/UserLottoTest.java | 39 ++++----- src/test/java/lotto/model/UserLottosTest.java | 36 --------- 10 files changed, 111 insertions(+), 169 deletions(-) delete mode 100644 src/main/java/lotto/model/UserLottos.java delete mode 100644 src/test/java/lotto/model/UserLottosTest.java diff --git a/src/main/java/lotto/controller/GameController.java b/src/main/java/lotto/controller/GameController.java index faa4a37..e250062 100644 --- a/src/main/java/lotto/controller/GameController.java +++ b/src/main/java/lotto/controller/GameController.java @@ -2,14 +2,14 @@ import lotto.model.LottoStatistics; import lotto.model.LottoWinningMachine; -import lotto.model.UserLottos; +import lotto.model.UserLotto; import lotto.view.InputView; import lotto.view.OutputView; import java.util.List; public class GameController { - private static UserLottos userLottos; + private static UserLotto userLotto; private static LottoWinningMachine lottoWinningMachine; public void run() { @@ -24,8 +24,8 @@ public void run() { private void buyLotto() { final int lottoPurchaseCount = InputView.readLottoPurchaseCount(); - userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); - OutputView.printPurchaseInformation(userLottos.getUserLottos()); + userLotto = UserLotto.issueLottoByPurchaseCount(lottoPurchaseCount); + OutputView.printPurchaseInformation(userLotto.getUserLottos()); } private void initLottoWinningMachine() { @@ -35,7 +35,7 @@ private void initLottoWinningMachine() { } private void displayLottoResult() { - final LottoStatistics lottoStatistics = LottoStatistics.of(lottoWinningMachine, userLottos); + final LottoStatistics lottoStatistics = LottoStatistics.of(lottoWinningMachine, userLotto); OutputView.printWinningStatistics(lottoStatistics); } } diff --git a/src/main/java/lotto/model/Lotto.java b/src/main/java/lotto/model/Lotto.java index f7a19f5..9bcfbbe 100644 --- a/src/main/java/lotto/model/Lotto.java +++ b/src/main/java/lotto/model/Lotto.java @@ -50,4 +50,9 @@ private boolean hasDuplicateNumber(final List baseballs) { public List getNumbers() { return Collections.unmodifiableList(numbers); } + + @Override + public String toString() { + return numbers.toString(); + } } diff --git a/src/main/java/lotto/model/LottoStatistics.java b/src/main/java/lotto/model/LottoStatistics.java index e1aa743..ee1f520 100644 --- a/src/main/java/lotto/model/LottoStatistics.java +++ b/src/main/java/lotto/model/LottoStatistics.java @@ -9,24 +9,24 @@ public class LottoStatistics { private final LottoWinningMachine lottoWinningMachine; - private final UserLottos userLottos; + private final UserLotto userLotto; private final Map winningResult = new EnumMap<>(WinningRank.class); private LottoStatistics( final LottoWinningMachine lottoWinningMachine, - final UserLottos userLottos + final UserLotto userLotto ) { this.lottoWinningMachine = lottoWinningMachine; - this.userLottos = userLottos; + this.userLotto = userLotto; initWinningResult(); calculateLotteryWinningResult(); } public static LottoStatistics of( final LottoWinningMachine lottoWinningMachine, - final UserLottos userLottos + final UserLotto userLotto ) { - return new LottoStatistics(lottoWinningMachine, userLottos); + return new LottoStatistics(lottoWinningMachine, userLotto); } private void initWinningResult() { @@ -39,8 +39,8 @@ private void calculateLotteryWinningResult() { List winningLotteryNumbers = lottoWinningMachine.getWinningLotteryNumbers(); int bonusNumber = lottoWinningMachine.getBonusNumber(); - for (UserLotto userLotto : userLottos.getUserLottos()) { - List lottoNumbers = userLotto.getLottoNumbers(); + for (Lotto lotto : userLotto.getUserLottos()) { + List lottoNumbers = lotto.getNumbers(); int matchCount = getLottoMatchCount(lottoNumbers, winningLotteryNumbers); boolean hasBonus = isBonusNumberExists(lottoNumbers, bonusNumber); @@ -78,7 +78,7 @@ public int getWinningCountByRank(final WinningRank winningRank) { } public BigDecimal getEarningRate() { - final BigDecimal lottoPurchaseAmount = userLottos.getLottoPurchaseAmount(); + final BigDecimal lottoPurchaseAmount = userLotto.getLottoPurchaseAmount(); final BigDecimal totalWinningAmount = calculateTotalWinningAmount(); return totalWinningAmount diff --git a/src/main/java/lotto/model/UserLotto.java b/src/main/java/lotto/model/UserLotto.java index 4d0c3c9..7c37c98 100644 --- a/src/main/java/lotto/model/UserLotto.java +++ b/src/main/java/lotto/model/UserLotto.java @@ -1,24 +1,45 @@ package lotto.model; +import lotto.utils.LottoRandomGenerator; +import org.assertj.core.util.VisibleForTesting; + +import java.math.BigDecimal; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class UserLotto { - private final Lotto lotto; + private final List userLottos; + + private UserLotto(final int lottoPurchaseCount) { + this.userLottos = createLottoByPurchaseCount(lottoPurchaseCount); + } + + @VisibleForTesting + public UserLotto(final List userLottos) { + this.userLottos = userLottos; + } + + public static UserLotto issueLottoByPurchaseCount(final int lottoPurchaseCount) { + return new UserLotto(lottoPurchaseCount); + } - private UserLotto(final List numbers) { - this.lotto = new Lotto(numbers); + private List createLottoByPurchaseCount(final int lottoPurchaseCount) { + return Stream.generate(() -> new Lotto(LottoRandomGenerator.generate())) + .limit(lottoPurchaseCount) + .collect(Collectors.toList()); } - public static UserLotto createLotto(final List numbers) { - return new UserLotto(numbers); + public List getUserLottos() { + return Collections.unmodifiableList(userLottos); } - public List getLottoNumbers() { - return lotto.getNumbers(); + public int getLottoPurchseCount() { + return userLottos.size(); } - @Override - public String toString() { - return lotto.getNumbers().toString(); + public BigDecimal getLottoPurchaseAmount() { + return BigDecimal.valueOf(1000).multiply(BigDecimal.valueOf(getLottoPurchseCount())); } } diff --git a/src/main/java/lotto/model/UserLottos.java b/src/main/java/lotto/model/UserLottos.java deleted file mode 100644 index 9658f73..0000000 --- a/src/main/java/lotto/model/UserLottos.java +++ /dev/null @@ -1,45 +0,0 @@ -package lotto.model; - -import lotto.utils.LottoRandomGenerator; -import org.assertj.core.util.VisibleForTesting; - -import java.math.BigDecimal; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class UserLottos { - private final List userLottos; - - private UserLottos(final int lottoPurchaseCount) { - this.userLottos = createLottoByPurchaseCount(lottoPurchaseCount); - } - - @VisibleForTesting - public UserLottos(final List userLottos) { - this.userLottos = userLottos; - } - - public static UserLottos issueLottoByPurchaseCount(final int lottoPurchaseCount) { - return new UserLottos(lottoPurchaseCount); - } - - private List createLottoByPurchaseCount(final int lottoPurchaseCount) { - return Stream.generate(() -> UserLotto.createLotto(LottoRandomGenerator.generate())) - .limit(lottoPurchaseCount) - .collect(Collectors.toList()); - } - - public List getUserLottos() { - return Collections.unmodifiableList(userLottos); - } - - public int getLottoPurchseCount() { - return userLottos.size(); - } - - public BigDecimal getLottoPurchaseAmount() { - return BigDecimal.valueOf(1000).multiply(BigDecimal.valueOf(getLottoPurchseCount())); - } -} diff --git a/src/main/java/lotto/model/WinningRank.java b/src/main/java/lotto/model/WinningRank.java index c3f5c68..c2c2ebc 100644 --- a/src/main/java/lotto/model/WinningRank.java +++ b/src/main/java/lotto/model/WinningRank.java @@ -40,10 +40,6 @@ public static WinningRank of( .orElse(NONE); } - public int getMatchCount() { - return matchCount; - } - public int getReward() { return reward; } diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java index 58abb1a..ed713c6 100644 --- a/src/main/java/lotto/view/OutputView.java +++ b/src/main/java/lotto/view/OutputView.java @@ -1,7 +1,7 @@ package lotto.view; +import lotto.model.Lotto; import lotto.model.LottoStatistics; -import lotto.model.UserLotto; import lotto.model.WinningRank; import java.text.DecimalFormat; @@ -17,7 +17,7 @@ public class OutputView { private static final String REWARD_FORMAT = "#,###"; private static final String EARNING_FORMAT = "총 수익률은 %s%%입니다."; - public static void printPurchaseInformation(final List userLottos) { + public static void printPurchaseInformation(final List userLottos) { System.out.printf("%d개를 구매했습니다." + ENTER, userLottos.size()); userLottos.forEach(System.out::println); } diff --git a/src/test/java/lotto/model/LottoStatisticsTest.java b/src/test/java/lotto/model/LottoStatisticsTest.java index 8750136..a3f6ea1 100644 --- a/src/test/java/lotto/model/LottoStatisticsTest.java +++ b/src/test/java/lotto/model/LottoStatisticsTest.java @@ -17,12 +17,12 @@ class LottoStatisticsTest { void getWinningResult() { // given final LottoWinningMachine lottoWinningMachine = createLottoWinningMachine(); - final UserLottos userLottosCaseA = createUserLottosCaseA(); - final UserLottos userLottosCaseB = createUserLottosCaseB(); + final UserLotto userLottoCaseA = createUserLottosCaseA(); + final UserLotto userLottoCaseB = createUserLottosCaseB(); // when - final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottosCaseA); - final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottosCaseB); + final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottoCaseA); + final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottoCaseB); // then final Map winningResultA = caseA.getWinningResult(); @@ -51,12 +51,12 @@ void getWinningResult() { void getEarningRate() { // given final LottoWinningMachine lottoWinningMachine = createLottoWinningMachine(); - final UserLottos userLottosCaseA = createUserLottosCaseA(); - final UserLottos userLottosCaseB = createUserLottosCaseB(); + final UserLotto userLottoCaseA = createUserLottosCaseA(); + final UserLotto userLottoCaseB = createUserLottosCaseB(); // when - final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottosCaseA); - final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottosCaseB); + final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottoCaseA); + final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottoCaseB); // then assertAll( @@ -72,20 +72,20 @@ private LottoWinningMachine createLottoWinningMachine() { ); } - private UserLottos createUserLottosCaseA() { - return new UserLottos( + private UserLotto createUserLottosCaseA() { + return new UserLotto( List.of( - UserLotto.createLotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None - UserLotto.createLotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None - UserLotto.createLotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None - UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - UserLotto.createLotto(Arrays.asList(7, 10, 22, 37, 42, 43)), // 5등 - UserLotto.createLotto(Arrays.asList(1, 10, 22, 37, 38, 45)), // 4등 - UserLotto.createLotto(Arrays.asList(1, 9, 10, 12, 37, 39)), // 3등 - UserLotto.createLotto(Arrays.asList(1, 9, 10, 12, 37, 40)), // 2등 - UserLotto.createLotto(Arrays.asList(1, 9, 10, 12, 22, 37)) // 1등 + new Lotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None + new Lotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None + new Lotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 + new Lotto(Arrays.asList(7, 10, 22, 37, 42, 43)), // 5등 + new Lotto(Arrays.asList(1, 10, 22, 37, 38, 45)), // 4등 + new Lotto(Arrays.asList(1, 9, 10, 12, 37, 39)), // 3등 + new Lotto(Arrays.asList(1, 9, 10, 12, 37, 40)), // 2등 + new Lotto(Arrays.asList(1, 9, 10, 12, 22, 37)) // 1등 ) ); @@ -96,26 +96,26 @@ private UserLottos createUserLottosCaseA() { */ } - private UserLottos createUserLottosCaseB() { - return new UserLottos( + private UserLotto createUserLottosCaseB() { + return new UserLotto( List.of( - UserLotto.createLotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None - UserLotto.createLotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None - UserLotto.createLotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None - UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None - UserLotto.createLotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None - UserLotto.createLotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None - UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - UserLotto.createLotto(Arrays.asList(1, 9, 11, 22, 41, 42)) // 5등 + new Lotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None + new Lotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None + new Lotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None + new Lotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None + new Lotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None + new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 + new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 + new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)) // 5등 ) ); diff --git a/src/test/java/lotto/model/UserLottoTest.java b/src/test/java/lotto/model/UserLottoTest.java index c4f6368..0700527 100644 --- a/src/test/java/lotto/model/UserLottoTest.java +++ b/src/test/java/lotto/model/UserLottoTest.java @@ -1,35 +1,36 @@ package lotto.model; -import lotto.utils.LottoRandomGenerator; import org.junit.jupiter.api.DisplayName; -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.MethodSource; -import java.util.Arrays; -import java.util.List; +import java.math.BigDecimal; +import java.util.stream.Stream; -import static lotto.utils.LottoConstants.LOTTO_SIZE; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; class UserLottoTest { - @Test - @DisplayName("UserLotto를 생성한다") - void construct() { + @ParameterizedTest + @MethodSource("issueCase") + @DisplayName("구매한 개수만큼 UseLotto를 발급받는다") + void issueLottoByPurchaseCount(int lottoPurchaseCount, BigDecimal purchaseAmount) { // when - final List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); - final UserLotto userLotto = UserLotto.createLotto(numbers); - final UserLotto userLottoByAuto = UserLotto.createLotto(LottoRandomGenerator.generate()); + final UserLotto userLotto = UserLotto.issueLottoByPurchaseCount(lottoPurchaseCount); // then assertAll( - () -> assertThat(userLotto.getLottoNumbers()).containsExactlyElementsOf(numbers), // 수동 생성 - () -> assertThat(userLottoByAuto.getLottoNumbers()).hasSize(LOTTO_SIZE), // 자동 생성 - size validation - () -> assertThat( - userLottoByAuto.getLottoNumbers() - .stream() - .distinct() - .count() - ).isEqualTo(LOTTO_SIZE) // 자동 생성 - has duplicate validation + () -> assertThat(userLotto.getLottoPurchseCount()).isEqualTo(lottoPurchaseCount), + () -> assertThat(userLotto.getLottoPurchaseAmount()).isEqualTo(purchaseAmount) + ); + } + + private static Stream issueCase() { + return Stream.of( + Arguments.of(5, BigDecimal.valueOf(5_000)), + Arguments.of(10, BigDecimal.valueOf(10_000)), + Arguments.of(1_000_000, BigDecimal.valueOf(1_000_000_000)) ); } } diff --git a/src/test/java/lotto/model/UserLottosTest.java b/src/test/java/lotto/model/UserLottosTest.java deleted file mode 100644 index a53f4db..0000000 --- a/src/test/java/lotto/model/UserLottosTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package lotto.model; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.math.BigDecimal; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; - -class UserLottosTest { - @ParameterizedTest - @MethodSource("issueCase") - @DisplayName("구매한 개수만큼 UseLotto를 발급받는다") - void issueLottoByPurchaseCount(int lottoPurchaseCount, BigDecimal purchaseAmount) { - // when - final UserLottos userLottos = UserLottos.issueLottoByPurchaseCount(lottoPurchaseCount); - - // then - assertAll( - () -> assertThat(userLottos.getLottoPurchseCount()).isEqualTo(lottoPurchaseCount), - () -> assertThat(userLottos.getLottoPurchaseAmount()).isEqualTo(purchaseAmount) - ); - } - - private static Stream issueCase() { - return Stream.of( - Arguments.of(5, BigDecimal.valueOf(5_000)), - Arguments.of(10, BigDecimal.valueOf(10_000)), - Arguments.of(1_000_000, BigDecimal.valueOf(1_000_000_000)) - ); - } -} From ff34b25a2cf259e463f049bcec2c1515590a7328 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Sun, 16 Jul 2023 00:49:38 +0900 Subject: [PATCH 35/46] =?UTF-8?q?docs:=20docs=20Model=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/README.md b/docs/README.md index ead5cc2..37b1f55 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,12 +22,8 @@ ### `UserLotto` -- `1000원` 단위의 로또 1장을 구매하는 컴포넌트 - -### `UserLottos` - - `1000원` 단위의 로또 N장을 구매하는 컴포넌트 - - `List` + - `List` ### `LottoWinningMachine` From 944fc21400b4c13e4548bd487ded888f02f93b1f Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 12:59:17 +0900 Subject: [PATCH 36/46] typo: getLottoPurchseCount -> getLottoPurchaseCount --- src/main/java/lotto/model/UserLotto.java | 4 ++-- src/test/java/lotto/model/UserLottoTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/lotto/model/UserLotto.java b/src/main/java/lotto/model/UserLotto.java index 7c37c98..ca016e6 100644 --- a/src/main/java/lotto/model/UserLotto.java +++ b/src/main/java/lotto/model/UserLotto.java @@ -35,11 +35,11 @@ public List getUserLottos() { return Collections.unmodifiableList(userLottos); } - public int getLottoPurchseCount() { + public int getLottoPurchaseCount() { return userLottos.size(); } public BigDecimal getLottoPurchaseAmount() { - return BigDecimal.valueOf(1000).multiply(BigDecimal.valueOf(getLottoPurchseCount())); + return BigDecimal.valueOf(1000).multiply(BigDecimal.valueOf(getLottoPurchaseCount())); } } diff --git a/src/test/java/lotto/model/UserLottoTest.java b/src/test/java/lotto/model/UserLottoTest.java index 0700527..0c45ab2 100644 --- a/src/test/java/lotto/model/UserLottoTest.java +++ b/src/test/java/lotto/model/UserLottoTest.java @@ -21,7 +21,7 @@ void issueLottoByPurchaseCount(int lottoPurchaseCount, BigDecimal purchaseAmount // then assertAll( - () -> assertThat(userLotto.getLottoPurchseCount()).isEqualTo(lottoPurchaseCount), + () -> assertThat(userLotto.getLottoPurchaseCount()).isEqualTo(lottoPurchaseCount), () -> assertThat(userLotto.getLottoPurchaseAmount()).isEqualTo(purchaseAmount) ); } From 8bdd18279c4532577f3df88ae2328bc2a2824e68 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 13:00:58 +0900 Subject: [PATCH 37/46] typo: WINNNG_FORMAT -> WINNING_FORMAT --- src/main/java/lotto/view/OutputView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java index ed713c6..d886647 100644 --- a/src/main/java/lotto/view/OutputView.java +++ b/src/main/java/lotto/view/OutputView.java @@ -13,7 +13,7 @@ public class OutputView { private static final String ENTER = "\n"; private static final String ERROR_MESSAGE_FORMAT = "[ERROR] %s"; - private static final String WINNNG_FORMAT = "%s (%s원) - %d개"; + private static final String WINNING_FORMAT = "%s (%s원) - %d개"; private static final String REWARD_FORMAT = "#,###"; private static final String EARNING_FORMAT = "총 수익률은 %s%%입니다."; @@ -37,7 +37,7 @@ private static void addWinningStatistics( for (WinningRank winningRank : filteredWinningRank) { result.append( String.format( - WINNNG_FORMAT, + WINNING_FORMAT, winningRank.getDescription(), refineReward(winningRank.getReward()), lottoStatistics.getWinningCountByRank(winningRank) From 8fb3ec96d09a54f4d817b6b15f57ed0b5e49d5ca Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 13:01:36 +0900 Subject: [PATCH 38/46] =?UTF-8?q?refactor:=20=EB=A9=94=EC=86=8C=EB=93=9C?= =?UTF-8?q?=20=EC=88=9C=EC=84=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/view/OutputView.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java index d886647..495016f 100644 --- a/src/main/java/lotto/view/OutputView.java +++ b/src/main/java/lotto/view/OutputView.java @@ -46,10 +46,6 @@ private static void addWinningStatistics( } } - private static Object refineReward(final int reward) { - return new DecimalFormat(REWARD_FORMAT).format(reward); - } - private static List getFilteredWinningRank() { return Arrays.stream(WinningRank.values()) .filter(winningRank -> winningRank != WinningRank.NONE) @@ -57,6 +53,10 @@ private static List getFilteredWinningRank() { .collect(Collectors.toList()); } + private static Object refineReward(final int reward) { + return new DecimalFormat(REWARD_FORMAT).format(reward); + } + private static void addEarningRate( final LottoStatistics lottoStatistics, final StringBuilder result From 8668b156b0495742027ab171b408869f3a30d0e4 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 13:02:24 +0900 Subject: [PATCH 39/46] =?UTF-8?q?refactor:=20`refineReward`=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4=20=ED=83=80=EC=9E=85=20Object=20->=20String?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/view/OutputView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/lotto/view/OutputView.java b/src/main/java/lotto/view/OutputView.java index 495016f..7c8bbdb 100644 --- a/src/main/java/lotto/view/OutputView.java +++ b/src/main/java/lotto/view/OutputView.java @@ -53,7 +53,7 @@ private static List getFilteredWinningRank() { .collect(Collectors.toList()); } - private static Object refineReward(final int reward) { + private static String refineReward(final int reward) { return new DecimalFormat(REWARD_FORMAT).format(reward); } From 3c8a799f81d1ffcfad5f8b5ce0960089c8edbbe1 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 13:18:31 +0900 Subject: [PATCH 40/46] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EA=B5=AC=EC=9E=85=EA=B8=88=EC=95=A1=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20`=EC=9D=8C=EC=88=98=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4`=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/utils/ExceptionConstants.java | 1 + .../validator/LottoPurchaseAmountValidator.java | 14 +++++++++++++- src/main/java/lotto/utils/validator/Validator.java | 6 +++--- .../utils/validator/WinningNumberValidator.java | 5 +++-- .../LottoPurchaseAmountValidatorTest.java | 8 ++++++++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/main/java/lotto/utils/ExceptionConstants.java b/src/main/java/lotto/utils/ExceptionConstants.java index 554aef4..4b3c01a 100644 --- a/src/main/java/lotto/utils/ExceptionConstants.java +++ b/src/main/java/lotto/utils/ExceptionConstants.java @@ -28,6 +28,7 @@ enum LottoMachineException { enum InputException { INPUT_MUST_NOT_CONTAINS_SPACE("공백없이 입력해주세요."), INPUT_MUST_BE_NUMERIC("숫자를 입력해주세요."), + PURCHASE_AMOUNT_MUST_BE_POSITIVE("구입 금액은 음수가 될 수 없습니다."), PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT("천원 단위로 구입금액을 입력해주세요."), WINNING_NUMBER_MUST_BE_SPLIT_BY_COMMA("당첨번호는 콤마(,)로 구분해서 공백없이 입력해주세요."), ; diff --git a/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java b/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java index 24be8fb..061f837 100644 --- a/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java +++ b/src/main/java/lotto/utils/validator/LottoPurchaseAmountValidator.java @@ -1,5 +1,6 @@ package lotto.utils.validator; +import static lotto.utils.ExceptionConstants.InputException.PURCHASE_AMOUNT_MUST_BE_POSITIVE; import static lotto.utils.ExceptionConstants.InputException.PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT; public class LottoPurchaseAmountValidator extends Validator { @@ -9,10 +10,21 @@ public class LottoPurchaseAmountValidator extends Validator { public void validate(final String userInput) { validateInputHasSpace(userInput); validateInputIsNumeric(userInput); + validatePurchaseAmountIsPositive(userInput); validateUnitOfAmountIsThousand(userInput); } - private void validateUnitOfAmountIsThousand(String userInput) { + private void validatePurchaseAmountIsPositive(final String userInput) { + if (isUserInputNegative(userInput)) { + throw new IllegalArgumentException(PURCHASE_AMOUNT_MUST_BE_POSITIVE.message); + } + } + + private boolean isUserInputNegative(final String userInput) { + return Integer.parseInt(userInput) < 0; + } + + private void validateUnitOfAmountIsThousand(final String userInput) { if (Integer.parseInt(userInput) % PURCHASE_UNIT != 0) { throw new IllegalArgumentException(PURCHASE_AMOUNT_MUST_BE_THOUSAND_UNIT.message); } diff --git a/src/main/java/lotto/utils/validator/Validator.java b/src/main/java/lotto/utils/validator/Validator.java index 0544539..3170014 100644 --- a/src/main/java/lotto/utils/validator/Validator.java +++ b/src/main/java/lotto/utils/validator/Validator.java @@ -6,18 +6,18 @@ public abstract class Validator { abstract void validate(final String userInput); - void validateInputHasSpace(final String userInput) { + public void validateInputHasSpace(final String userInput) { if (hasSpace(userInput)) { throw new IllegalArgumentException(INPUT_MUST_NOT_CONTAINS_SPACE.message); } } - private static boolean hasSpace(String userInput) { + private boolean hasSpace(final String userInput) { return userInput.chars() .anyMatch(Character::isWhitespace); } - void validateInputIsNumeric(String userInput) { + public void validateInputIsNumeric(final String userInput) { try { Integer.parseInt(userInput); } catch (NumberFormatException exception) { diff --git a/src/main/java/lotto/utils/validator/WinningNumberValidator.java b/src/main/java/lotto/utils/validator/WinningNumberValidator.java index 045a25e..fd0b65c 100644 --- a/src/main/java/lotto/utils/validator/WinningNumberValidator.java +++ b/src/main/java/lotto/utils/validator/WinningNumberValidator.java @@ -12,7 +12,8 @@ public class WinningNumberValidator extends Validator { @Override public void validate(final String userInput) { validateInputHasSpace(userInput); - inputSplitByComma(userInput).forEach(this::validateInputElementIsNumeric); + inputSplitByComma(userInput) + .forEach(this::validateInputElementIsNumeric); } private List inputSplitByComma(final String userInput) { @@ -20,7 +21,7 @@ private List inputSplitByComma(final String userInput) { .collect(Collectors.toList()); } - void validateInputElementIsNumeric(String userInput) { + private void validateInputElementIsNumeric(final String userInput) { try { Integer.parseInt(userInput); } catch (NumberFormatException exception) { diff --git a/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java b/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java index 4e97f79..5a538da 100644 --- a/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java +++ b/src/test/java/lotto/utils/validator/LottoPurchaseAmountValidatorTest.java @@ -27,6 +27,14 @@ void throwExceptionByInputIsNotNumeric() { .hasMessage(INPUT_MUST_BE_NUMERIC.message); } + @Test + @DisplayName("로또 구입금액이 음수면 예외가 발생한다") + void throwExceptionByPurchaseAmountIsNegative() { + assertThatThrownBy(() -> LOTTO_PURCHASE_AMOUNT_VALIDATOR.validate("-8000")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(PURCHASE_AMOUNT_MUST_BE_POSITIVE.message); + } + @Test @DisplayName("로또 구입금액이 1000원 단위가 아니면 예외가 발생한다") void throwExceptionByUnitOfAmountIsNotThousand() { From 2702a95d6e12835494d0dd15f8a4adba47d4a5a1 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 13:25:45 +0900 Subject: [PATCH 41/46] =?UTF-8?q?refactor:=20=EB=8B=B9=EC=B2=A8=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B2=88=ED=98=B8=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20`BonusNumber=20=EB=AA=A8=EB=8D=B8`=20?= =?UTF-8?q?=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/model/BonusNumber.java | 28 ++++++++++++ .../java/lotto/model/LottoWinningMachine.java | 6 +-- .../java/lotto/utils/ExceptionConstants.java | 1 + .../java/lotto/model/BonusNumberTest.java | 45 +++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/main/java/lotto/model/BonusNumber.java create mode 100644 src/test/java/lotto/model/BonusNumberTest.java diff --git a/src/main/java/lotto/model/BonusNumber.java b/src/main/java/lotto/model/BonusNumber.java new file mode 100644 index 0000000..e0cf256 --- /dev/null +++ b/src/main/java/lotto/model/BonusNumber.java @@ -0,0 +1,28 @@ +package lotto.model; + +import static lotto.utils.ExceptionConstants.LottoMachineException.BONUS_NUMBER_IS_NOT_IN_RANGE; +import static lotto.utils.LottoConstants.MAX_VALUE; +import static lotto.utils.LottoConstants.MIN_VALUE; + +public class BonusNumber { + private final int value; + + public BonusNumber(final int value) { + validateBonusNumberIsInRange(value); + this.value = value; + } + + private void validateBonusNumberIsInRange(final int value) { + if (isOutOfRange(value)) { + throw new IllegalArgumentException(BONUS_NUMBER_IS_NOT_IN_RANGE.message); + } + } + + private boolean isOutOfRange(final int value) { + return value < MIN_VALUE || value > MAX_VALUE; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/lotto/model/LottoWinningMachine.java b/src/main/java/lotto/model/LottoWinningMachine.java index 0e3a8ea..5d32380 100644 --- a/src/main/java/lotto/model/LottoWinningMachine.java +++ b/src/main/java/lotto/model/LottoWinningMachine.java @@ -6,7 +6,7 @@ public class LottoWinningMachine { private final Lotto winningLottery; - private final int bonusNumber; + private final BonusNumber bonusNumber; private LottoWinningMachine( final List winningNumbers, @@ -14,7 +14,7 @@ private LottoWinningMachine( ) { validateBonusNumberIsDuplicate(winningNumbers, bonusNumber); this.winningLottery = new Lotto(winningNumbers); - this.bonusNumber = bonusNumber; + this.bonusNumber = new BonusNumber(bonusNumber); } public static LottoWinningMachine drawWinningLottery( @@ -38,6 +38,6 @@ public List getWinningLotteryNumbers() { } public int getBonusNumber() { - return bonusNumber; + return bonusNumber.getValue(); } } diff --git a/src/main/java/lotto/utils/ExceptionConstants.java b/src/main/java/lotto/utils/ExceptionConstants.java index 4b3c01a..339c422 100644 --- a/src/main/java/lotto/utils/ExceptionConstants.java +++ b/src/main/java/lotto/utils/ExceptionConstants.java @@ -15,6 +15,7 @@ enum LottoException { } enum LottoMachineException { + BONUS_NUMBER_IS_NOT_IN_RANGE("보너스 번호는 1부터 45 사이의 숫자여야 합니다."), BONUS_NUMBER_MUST_BE_UNIQUE("보너스 번호는 당첨 번호와 중복되지 않아야 합니다."), ; diff --git a/src/test/java/lotto/model/BonusNumberTest.java b/src/test/java/lotto/model/BonusNumberTest.java new file mode 100644 index 0000000..4b0c873 --- /dev/null +++ b/src/test/java/lotto/model/BonusNumberTest.java @@ -0,0 +1,45 @@ +package lotto.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static lotto.utils.ExceptionConstants.LottoMachineException.BONUS_NUMBER_IS_NOT_IN_RANGE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class BonusNumberTest { + @ParameterizedTest + @MethodSource("invalidRange") + @DisplayName("보너스 번호의 범위가 1..45 이외라면 예외가 발생한다") + void throwExceptionByBonusNumberIsNotInRange(int value) { + assertThatThrownBy(() -> new BonusNumber(value)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(BONUS_NUMBER_IS_NOT_IN_RANGE.message); + } + + private static Stream invalidRange() { + return Stream.of( + Arguments.of(0), + Arguments.of(46) + ); + } + + @ParameterizedTest + @MethodSource("validRange") + @DisplayName("BonusNumber를 생성한다") + void success(int value) { + assertDoesNotThrow(() -> new BonusNumber(value)); + } + + private static Stream validRange() { + return Stream.of( + Arguments.of(1), + Arguments.of(10), + Arguments.of(45) + ); + } +} From e9e86be4d586f3ca72e63ae34b0f98022858d7de Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Mon, 17 Jul 2023 13:25:53 +0900 Subject: [PATCH 42/46] =?UTF-8?q?docs:=20`BonusNumber`=20docs=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 --- docs/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/README.md b/docs/README.md index 37b1f55..b7e5778 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,6 +29,10 @@ - 로또 당첨 번호 6개 + 보너스 번호를 생성하는 컴포넌트 +### `BonusNumber` + +- `보너스 번호`에 대한 컴포넌트 + ### `WinningRank` - 당첨과 관련된 순위를 표현하는 컴포넌트 From 857450549dfab2d7f8dda08bab6f6041fce7c385 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Wed, 19 Jul 2023 11:30:44 +0900 Subject: [PATCH 43/46] typo: baseballs -> numbers --- src/main/java/lotto/model/Lotto.java | 4 ++-- src/test/java/lotto/model/LottoTest.java | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/lotto/model/Lotto.java b/src/main/java/lotto/model/Lotto.java index 9bcfbbe..63c26b0 100644 --- a/src/main/java/lotto/model/Lotto.java +++ b/src/main/java/lotto/model/Lotto.java @@ -41,8 +41,8 @@ private void validateLottoHasDuplicateElement(final List numbers) { } } - private boolean hasDuplicateNumber(final List baseballs) { - return baseballs.stream() + private boolean hasDuplicateNumber(final List number) { + return number.stream() .distinct() .count() != LOTTO_SIZE; } diff --git a/src/test/java/lotto/model/LottoTest.java b/src/test/java/lotto/model/LottoTest.java index a6faade..407eff2 100644 --- a/src/test/java/lotto/model/LottoTest.java +++ b/src/test/java/lotto/model/LottoTest.java @@ -19,8 +19,8 @@ class LottoTest { @ParameterizedTest @MethodSource("invalidRange") @DisplayName("로또 번호의 범위가 1..45 이외라면 예외가 발생한다") - void throwExceptionByBaseballIsNotInRange(List baseballs) { - assertThatThrownBy(() -> new Lotto(baseballs)) + void throwExceptionByLottoNumberIsNotInRange(List numbers) { + assertThatThrownBy(() -> new Lotto(numbers)) .isInstanceOf(IllegalArgumentException.class) .hasMessage(LOTTO_NUMBER_IS_NOT_IN_RANGE.message); } @@ -35,8 +35,8 @@ private static Stream invalidRange() { @ParameterizedTest @MethodSource("invalidSize") @DisplayName("로또 번호의 개수가 6개가 아니면 예외가 발생한다") - void throwExceptionByBaseballSizeNotFulfill(List baseballs) { - assertThatThrownBy(() -> new Lotto(baseballs)) + void throwExceptionByLottoSizeNotFulfill(List numbers) { + assertThatThrownBy(() -> new Lotto(numbers)) .isInstanceOf(IllegalArgumentException.class) .hasMessage(LOTTO_SIZE_IS_NOT_FULFILL.message); } @@ -55,8 +55,8 @@ private static Stream invalidSize() { @ParameterizedTest @MethodSource("duplicateNumber") @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다") - void throwExceptionByBaseballIsNotUnique(List baseballs) { - assertThatThrownBy(() -> new Lotto(baseballs)) + void throwExceptionByLottoNumberIsNotUnique(List numbers) { + assertThatThrownBy(() -> new Lotto(numbers)) .isInstanceOf(IllegalArgumentException.class) .hasMessage(LOTTO_NUMBER_MUST_BE_UNIQUE.message); } From ff2a951ef1b761bf062d41009678572d3f5f43d4 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Wed, 19 Jul 2023 11:45:28 +0900 Subject: [PATCH 44/46] typo: LottoStatistics of -> checkLotteryResult --- src/main/java/lotto/controller/GameController.java | 2 +- src/main/java/lotto/model/LottoStatistics.java | 2 +- src/test/java/lotto/model/LottoStatisticsTest.java | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/lotto/controller/GameController.java b/src/main/java/lotto/controller/GameController.java index e250062..fdbd937 100644 --- a/src/main/java/lotto/controller/GameController.java +++ b/src/main/java/lotto/controller/GameController.java @@ -35,7 +35,7 @@ private void initLottoWinningMachine() { } private void displayLottoResult() { - final LottoStatistics lottoStatistics = LottoStatistics.of(lottoWinningMachine, userLotto); + final LottoStatistics lottoStatistics = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLotto); OutputView.printWinningStatistics(lottoStatistics); } } diff --git a/src/main/java/lotto/model/LottoStatistics.java b/src/main/java/lotto/model/LottoStatistics.java index ee1f520..1ed9a59 100644 --- a/src/main/java/lotto/model/LottoStatistics.java +++ b/src/main/java/lotto/model/LottoStatistics.java @@ -22,7 +22,7 @@ private LottoStatistics( calculateLotteryWinningResult(); } - public static LottoStatistics of( + public static LottoStatistics checkLotteryResult( final LottoWinningMachine lottoWinningMachine, final UserLotto userLotto ) { diff --git a/src/test/java/lotto/model/LottoStatisticsTest.java b/src/test/java/lotto/model/LottoStatisticsTest.java index a3f6ea1..382fcfc 100644 --- a/src/test/java/lotto/model/LottoStatisticsTest.java +++ b/src/test/java/lotto/model/LottoStatisticsTest.java @@ -21,8 +21,8 @@ void getWinningResult() { final UserLotto userLottoCaseB = createUserLottosCaseB(); // when - final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottoCaseA); - final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottoCaseB); + final LottoStatistics caseA = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseA); + final LottoStatistics caseB = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseB); // then final Map winningResultA = caseA.getWinningResult(); @@ -55,8 +55,8 @@ void getEarningRate() { final UserLotto userLottoCaseB = createUserLottosCaseB(); // when - final LottoStatistics caseA = LottoStatistics.of(lottoWinningMachine, userLottoCaseA); - final LottoStatistics caseB = LottoStatistics.of(lottoWinningMachine, userLottoCaseB); + final LottoStatistics caseA = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseA); + final LottoStatistics caseB = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseB); // then assertAll( From a40cb93df5b40df4dd074269a3a1dda324e242f7 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Wed, 19 Jul 2023 12:32:53 +0900 Subject: [PATCH 45/46] =?UTF-8?q?fix:=20matchCount=206=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20bonusNumber=20=EC=BC=80=EC=9D=B4=EC=8A=A4?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/model/WinningRank.java | 4 ++-- src/test/java/lotto/model/WinningRankTest.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/lotto/model/WinningRank.java b/src/main/java/lotto/model/WinningRank.java index c2c2ebc..1773381 100644 --- a/src/main/java/lotto/model/WinningRank.java +++ b/src/main/java/lotto/model/WinningRank.java @@ -4,12 +4,12 @@ import java.util.List; public enum WinningRank { - FIRST(6, List.of(true, false), 2_000_000_000, "6개 일치"), + FIRST(6, List.of(false), 2_000_000_000, "6개 일치"), SECOND(5, List.of(true), 30_000_000, "5개 일치, 보너스 볼 일치"), THIRD(5, List.of(false), 1_500_000, "5개 일치"), FOURTH(4, List.of(true, false), 50_000, "4개 일치"), FIFTH(3, List.of(true, false), 5_000, "3개 일치"), - NONE(0, List.of(), 0, "NONE..."), + NONE(0, List.of(false), 0, "NONE..."), ; private final int matchCount; diff --git a/src/test/java/lotto/model/WinningRankTest.java b/src/test/java/lotto/model/WinningRankTest.java index 391bec2..aa7346d 100644 --- a/src/test/java/lotto/model/WinningRankTest.java +++ b/src/test/java/lotto/model/WinningRankTest.java @@ -20,7 +20,6 @@ void getWinningRank(int matchCount, boolean hasBonus, WinningRank expect) { private static Stream winningCase() { return Stream.of( - Arguments.of(6, true, FIRST), Arguments.of(6, false, FIRST), Arguments.of(5, true, SECOND), Arguments.of(5, false, THIRD), From 05f3b148722a3adf05972423ef9825c80d4c9986 Mon Sep 17 00:00:00 2001 From: SeoJiWon Date: Wed, 19 Jul 2023 12:33:15 +0900 Subject: [PATCH 46/46] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=8B=B9=EC=B2=A8=20=ED=86=B5=EA=B3=84=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=B4=EC=A0=84=20Calculation=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/model/LottoStatisticsTest.java | 107 ++++++++++++------ 1 file changed, 72 insertions(+), 35 deletions(-) diff --git a/src/test/java/lotto/model/LottoStatisticsTest.java b/src/test/java/lotto/model/LottoStatisticsTest.java index 382fcfc..996cb7a 100644 --- a/src/test/java/lotto/model/LottoStatisticsTest.java +++ b/src/test/java/lotto/model/LottoStatisticsTest.java @@ -19,10 +19,12 @@ void getWinningResult() { final LottoWinningMachine lottoWinningMachine = createLottoWinningMachine(); final UserLotto userLottoCaseA = createUserLottosCaseA(); final UserLotto userLottoCaseB = createUserLottosCaseB(); + final UserLotto userLottoCaseC = createUserLottosCaseB(); // when final LottoStatistics caseA = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseA); final LottoStatistics caseB = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseB); + final LottoStatistics caseC = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseC); // then final Map winningResultA = caseA.getWinningResult(); @@ -30,7 +32,7 @@ void getWinningResult() { () -> assertThat(winningResultA.get(WinningRank.FIRST)).isEqualTo(1), () -> assertThat(winningResultA.get(WinningRank.SECOND)).isEqualTo(1), () -> assertThat(winningResultA.get(WinningRank.THIRD)).isEqualTo(1), - () -> assertThat(winningResultA.get(WinningRank.FOURTH)).isEqualTo(1), + () -> assertThat(winningResultA.get(WinningRank.FOURTH)).isEqualTo(2), () -> assertThat(winningResultA.get(WinningRank.FIFTH)).isEqualTo(2), () -> assertThat(winningResultA.get(WinningRank.NONE)).isEqualTo(5) ); @@ -44,6 +46,16 @@ void getWinningResult() { () -> assertThat(winningResultB.get(WinningRank.FIFTH)).isEqualTo(3), () -> assertThat(winningResultB.get(WinningRank.NONE)).isEqualTo(14) ); + + final Map winningResultC = caseC.getWinningResult(); + assertAll( + () -> assertThat(winningResultC.get(WinningRank.FIRST)).isEqualTo(0), + () -> assertThat(winningResultC.get(WinningRank.SECOND)).isEqualTo(0), + () -> assertThat(winningResultC.get(WinningRank.THIRD)).isEqualTo(0), + () -> assertThat(winningResultC.get(WinningRank.FOURTH)).isEqualTo(0), + () -> assertThat(winningResultC.get(WinningRank.FIFTH)).isEqualTo(3), + () -> assertThat(winningResultC.get(WinningRank.NONE)).isEqualTo(14) + ); } @Test @@ -53,76 +65,101 @@ void getEarningRate() { final LottoWinningMachine lottoWinningMachine = createLottoWinningMachine(); final UserLotto userLottoCaseA = createUserLottosCaseA(); final UserLotto userLottoCaseB = createUserLottosCaseB(); + final UserLotto userLottoCaseC = createUserLottosCaseC(); // when final LottoStatistics caseA = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseA); final LottoStatistics caseB = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseB); + final LottoStatistics caseC = LottoStatistics.checkLotteryResult(lottoWinningMachine, userLottoCaseC); // then assertAll( - () -> assertThat(caseA.getEarningRate()).isEqualTo(BigDecimal.valueOf(18468727.3)), - () -> assertThat(caseB.getEarningRate()).isEqualTo(BigDecimal.valueOf(88.2)) + () -> assertThat(caseA.getEarningRate()).isEqualTo(BigDecimal.valueOf(16930083.3)), + () -> assertThat(caseB.getEarningRate()).isEqualTo(BigDecimal.valueOf(88.2)), + () -> assertThat(caseC.getEarningRate()).isEqualTo(BigDecimal.valueOf(62.5)) ); } private LottoWinningMachine createLottoWinningMachine() { return LottoWinningMachine.drawWinningLottery( - Arrays.asList(1, 9, 10, 12, 22, 37), - 40 + Arrays.asList(1, 2, 3, 4, 5, 6), + 7 ); } private UserLotto createUserLottosCaseA() { return new UserLotto( List.of( - new Lotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None - new Lotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None - new Lotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None - new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - new Lotto(Arrays.asList(7, 10, 22, 37, 42, 43)), // 5등 - new Lotto(Arrays.asList(1, 10, 22, 37, 38, 45)), // 4등 - new Lotto(Arrays.asList(1, 9, 10, 12, 37, 39)), // 3등 - new Lotto(Arrays.asList(1, 9, 10, 12, 37, 40)), // 2등 - new Lotto(Arrays.asList(1, 9, 10, 12, 22, 37)) // 1등 + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(1, 2, 3, 11, 12, 13)), // 5등 (당첨 3개) + new Lotto(Arrays.asList(1, 2, 3, 7, 12, 13)), // 5등 (당첨 3개 + 보너스 1개) + new Lotto(Arrays.asList(1, 2, 3, 4, 12, 13)), // 4등 (당첨 4개) + new Lotto(Arrays.asList(1, 2, 3, 4, 7, 13)), // 4등 (당첨 4개 + 보너스 1개) + new Lotto(Arrays.asList(1, 2, 3, 4, 5, 13)), // 3등 (당첨 5개) + new Lotto(Arrays.asList(1, 2, 3, 4, 5, 7)), // 2등 (당첨 5개 + 보너스 1개) + new Lotto(Arrays.asList(1, 2, 3, 4, 5, 6)) // 1등 (당첨 6개) ) ); /** - * 구매 금액 = 11_000 - * 당첨 금액 = 2_031_560_000 - * -> 수익률 = 184,687.27272727272727272727272727... = 18468727.27% = 18468727.3% + * 구매 금액 = 12_000 + * 당첨 금액 = 2,031,610,000 + * -> 수익률 = 169,300.83333333333333333333333333... = 16930083.33% = 16930083.3% */ } private UserLotto createUserLottosCaseB() { + return new UserLotto( + List.of( + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(8, 9, 10, 11, 12, 13)), // None + new Lotto(Arrays.asList(1, 2, 3, 11, 12, 13)), // 5등 (당첨 3개) + new Lotto(Arrays.asList(1, 2, 3, 11, 12, 13)), // 5등 (당첨 3개) + new Lotto(Arrays.asList(1, 2, 3, 7, 12, 13)) // 5등 (당첨 3개 + 보너스 1개) + ) + ); + + /** + * 구매 금액 = 17000 + * 당첨 금액 = 15000 + * -> 수익률 = 0.88235294117647058823529411764706... = 88.23% = 88.2% + */ + } + + private UserLotto createUserLottosCaseC() { return new UserLotto( List.of( new Lotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None new Lotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None new Lotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None + new Lotto(Arrays.asList(1, 8, 11, 31, 41, 42)), // None new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(8, 21, 23, 41, 42, 43)), // None - new Lotto(Arrays.asList(3, 5, 11, 16, 32, 38)), // None - new Lotto(Arrays.asList(7, 11, 16, 35, 36, 44)), // None - new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(13, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(12, 14, 16, 38, 42, 45)), // None - new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)), // 5등 - new Lotto(Arrays.asList(1, 9, 11, 22, 41, 42)) // 5등 + new Lotto(Arrays.asList(7, 11, 30, 40, 42, 43)), // None + new Lotto(Arrays.asList(2, 13, 22, 32, 38, 45)), // None + new Lotto(Arrays.asList(1, 3, 5, 14, 22, 45)) // 5등 (당첨 3개) ) ); /** - * 구매 금액 = 17000 - * 당첨 금액 = 15000 - * -> 수익률 = 0.88235294117647058823529411764706... = 88.23% = 88.2% + * 구매 금액 = 8000 + * 당첨 금액 = 5000 + * -> 수익률 = 0.625 = 62.5% */ } }