From 5363326c7cb1766c8389b662a3a807e89ac7c15e Mon Sep 17 00:00:00 2001 From: "jieun4510@sju.ac.kr" Date: Wed, 1 May 2024 20:47:37 +0900 Subject: [PATCH 01/37] =?UTF-8?q?Docs:=20readme=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..bd8dc4c2 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +## Lotto +- 크기가 6인 int List : numbers + - 1 ~ 45 사이의 숫자 + - 중복되지 않아야 함 + +[ ] 로또 금액을 입력 받아야 함 + [ ] 1000원 단위로 입력 + [ ] 최소 1000원 이상 +[ ] 로또 번호는 랜덤으로 설정 + [ ] 숫자들끼리 중복되지 않도록 + [ ] 1 ~ 45 사이 +[ ] 출력 시 숫자들이 오름차순으로 정렬 From 2f27c66c150cc83e9e85751952c7cf8b283cce1c Mon Sep 17 00:00:00 2001 From: "jieun4510@sju.ac.kr" Date: Wed, 1 May 2024 20:58:38 +0900 Subject: [PATCH 02/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/LottoNumber.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/LottoNumber.java diff --git a/README.md b/README.md index bd8dc4c2..558a02f4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Lotto - 크기가 6인 int List : numbers - - 1 ~ 45 사이의 숫자 + - [x] 1 ~ 45 사이의 숫자 - 중복되지 않아야 함 [ ] 로또 금액을 입력 받아야 함 diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java new file mode 100644 index 00000000..cbb542d0 --- /dev/null +++ b/src/main/java/LottoNumber.java @@ -0,0 +1,18 @@ +public class LottoNumber { + + public static final int MIN_VALUE = 0; + public static final int MAX_VALUE = 45; + + private final int number; + + public LottoNumber(int number) { + validateRange(number); + this.number = number; + } + + private void validateRange(int number) { + if (number < MIN_VALUE || number > MAX_VALUE) { + throw new IllegalArgumentException(); + } + } +} From ffec0c5138f43de44eb045ec831c38ee6199bd78 Mon Sep 17 00:00:00 2001 From: "jieun4510@sju.ac.kr" Date: Wed, 1 May 2024 21:13:42 +0900 Subject: [PATCH 03/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++------ src/main/java/Lotto.java | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/main/java/Lotto.java diff --git a/README.md b/README.md index 558a02f4..e4346601 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ ## Lotto + - 크기가 6인 int List : numbers - - [x] 1 ~ 45 사이의 숫자 - - 중복되지 않아야 함 + - [x] 1 ~ 45 사이의 숫자 + - [x] 중복되지 않아야 함 + - [x] 크기가 6이어야 함 [ ] 로또 금액을 입력 받아야 함 - [ ] 1000원 단위로 입력 - [ ] 최소 1000원 이상 +[ ] 1000원 단위로 입력 +[ ] 최소 1000원 이상 [ ] 로또 번호는 랜덤으로 설정 - [ ] 숫자들끼리 중복되지 않도록 - [ ] 1 ~ 45 사이 +[ ] 숫자들끼리 중복되지 않도록 +[ ] 1 ~ 45 사이 [ ] 출력 시 숫자들이 오름차순으로 정렬 diff --git a/src/main/java/Lotto.java b/src/main/java/Lotto.java new file mode 100644 index 00000000..7dd3e695 --- /dev/null +++ b/src/main/java/Lotto.java @@ -0,0 +1,32 @@ +import java.util.List; + +public class Lotto { + + public static final int LOTTO_SIZE = 6; + + private final List numbers; + + public Lotto(List numbers) { + validate(numbers); + this.numbers = numbers; + } + + private void validate(List numbers) { + validateSize(numbers); + validateDuplication(numbers); + } + + private void validateSize(List numbers) { + if (numbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException(); + } + } + + private void validateDuplication(List numbers) { + long duplicatedSize = numbers.stream().distinct().count(); + if (numbers.size() != duplicatedSize) { + throw new IllegalArgumentException(); + } + } + +} From 36e7a0d59c0de97a69a4e181fe5259512651fccd Mon Sep 17 00:00:00 2001 From: "jieun4510@sju.ac.kr" Date: Wed, 1 May 2024 21:20:50 +0900 Subject: [PATCH 04/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +++++++------- src/main/java/LottoPrice.java | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 src/main/java/LottoPrice.java diff --git a/README.md b/README.md index e4346601..3761c131 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ - [x] 중복되지 않아야 함 - [x] 크기가 6이어야 함 -[ ] 로또 금액을 입력 받아야 함 -[ ] 1000원 단위로 입력 -[ ] 최소 1000원 이상 -[ ] 로또 번호는 랜덤으로 설정 -[ ] 숫자들끼리 중복되지 않도록 -[ ] 1 ~ 45 사이 -[ ] 출력 시 숫자들이 오름차순으로 정렬 +- [ ] 로또 금액을 입력 받아야 함 +- [x] 1000원 단위로 입력 +- [x] 최소 1000원 이상 +- [ ] 로또 번호는 랜덤으로 설정 +- [ ] 숫자들끼리 중복되지 않도록 +- [ ] 1 ~ 45 사이 +- [ ] 출력 시 숫자들이 오름차순으로 정렬 diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java new file mode 100644 index 00000000..2f81a3b6 --- /dev/null +++ b/src/main/java/LottoPrice.java @@ -0,0 +1,30 @@ +public class LottoPrice { + + public static final int MIN_PRICE = 0; + public static final int PRICE_UNIT = 1_000; + + private final int price; + + public LottoPrice(int price) { + validate(price); + this.price = price; + } + + private void validate(int price) { + validateRange(price); + validateUnit(price); + } + + + private void validateRange(int price) { + if (price < MIN_PRICE) { + throw new IllegalArgumentException(); + } + } + + private void validateUnit(int price) { + if (price % PRICE_UNIT != 0) { + throw new IllegalArgumentException(); + } + } +} From 178bc0ea0ee6c77ac10cc1275ac9f8be35ee3a11 Mon Sep 17 00:00:00 2001 From: "jieun4510@sju.ac.kr" Date: Wed, 1 May 2024 21:26:17 +0900 Subject: [PATCH 05/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/InputView.java | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/main/java/InputView.java diff --git a/README.md b/README.md index 3761c131..ae143eb1 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ - [x] 중복되지 않아야 함 - [x] 크기가 6이어야 함 -- [ ] 로또 금액을 입력 받아야 함 +- [x] 로또 금액을 입력 받아야 함 - [x] 1000원 단위로 입력 - [x] 최소 1000원 이상 - [ ] 로또 번호는 랜덤으로 설정 diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java new file mode 100644 index 00000000..779c0ee4 --- /dev/null +++ b/src/main/java/InputView.java @@ -0,0 +1,11 @@ +import java.util.Scanner; + +public class InputView { + + public static final Scanner SCANNER = new Scanner(System.in); + + public int inputLottoPrice() { + System.out.println("구입금액을 입력해 주세요."); + return SCANNER.nextInt(); + } +} From 6d2244cc2c1cb68faadd3bc8356e92abdcb4820b Mon Sep 17 00:00:00 2001 From: "jieun4510@sju.ac.kr" Date: Wed, 1 May 2024 21:38:21 +0900 Subject: [PATCH 06/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=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 --- README.md | 6 +++--- src/main/java/RandomLottoGenerator.java | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/main/java/RandomLottoGenerator.java diff --git a/README.md b/README.md index ae143eb1..81cd3f16 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - [x] 로또 금액을 입력 받아야 함 - [x] 1000원 단위로 입력 - [x] 최소 1000원 이상 -- [ ] 로또 번호는 랜덤으로 설정 -- [ ] 숫자들끼리 중복되지 않도록 -- [ ] 1 ~ 45 사이 +- [x] 로또 번호는 랜덤으로 설정 +- [x] 숫자들끼리 중복되지 않도록 +- [x] 1 ~ 45 사이 - [ ] 출력 시 숫자들이 오름차순으로 정렬 diff --git a/src/main/java/RandomLottoGenerator.java b/src/main/java/RandomLottoGenerator.java new file mode 100644 index 00000000..cd18fcbf --- /dev/null +++ b/src/main/java/RandomLottoGenerator.java @@ -0,0 +1,23 @@ +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; + +public class RandomLottoGenerator { + + + public static final Random RANDOM = new Random(); + + public Lotto generateLotto() { + Set numbers = new HashSet<>(); + while (numbers.size() < 6) { + int randomNumber = RANDOM.nextInt(1, 45); + numbers.add(randomNumber); + } + + List lottoNumbers = numbers.stream() + .map(LottoNumber::new) + .toList(); + return new Lotto(lottoNumbers); + } +} From 2e22419c20c6ba0abc03909e97a3a578ff4201ff Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:10:06 +0900 Subject: [PATCH 07/37] =?UTF-8?q?fix:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B2=94=EC=9C=84=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/LottoNumber.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java index cbb542d0..4d0abbee 100644 --- a/src/main/java/LottoNumber.java +++ b/src/main/java/LottoNumber.java @@ -1,6 +1,6 @@ public class LottoNumber { - public static final int MIN_VALUE = 0; + public static final int MIN_VALUE = 1; public static final int MAX_VALUE = 45; private final int number; From ea1f13332e1d55f1c909dc42335b61d823da8508 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:14:07 +0900 Subject: [PATCH 08/37] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=A7=81=20?= =?UTF-8?q?=EB=84=98=EB=B2=84=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/RandomLottoGenerator.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/RandomLottoGenerator.java b/src/main/java/RandomLottoGenerator.java index cd18fcbf..ac70863f 100644 --- a/src/main/java/RandomLottoGenerator.java +++ b/src/main/java/RandomLottoGenerator.java @@ -5,13 +5,12 @@ public class RandomLottoGenerator { - public static final Random RANDOM = new Random(); public Lotto generateLotto() { Set numbers = new HashSet<>(); - while (numbers.size() < 6) { - int randomNumber = RANDOM.nextInt(1, 45); + while (numbers.size() < Lotto.LOTTO_SIZE) { + int randomNumber = RANDOM.nextInt(LottoNumber.MIN_VALUE, LottoNumber.MAX_VALUE); numbers.add(randomNumber); } From 02117a53e063caaa69db17a87055f56f47486ebb Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:23:39 +0900 Subject: [PATCH 09/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EA=B4=80=EB=A6=AC=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/LottoGame.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/LottoGame.java diff --git a/src/main/java/LottoGame.java b/src/main/java/LottoGame.java new file mode 100644 index 00000000..1e6d5295 --- /dev/null +++ b/src/main/java/LottoGame.java @@ -0,0 +1,12 @@ +public class LottoGame { + + private final InputView inputView; + + public LottoGame(InputView inputView) { + this.inputView = inputView; + } + + public void run() { + LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); + } +} From e5270006ade1dfa074d341d65c15771ab52005d9 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:24:01 +0900 Subject: [PATCH 10/37] =?UTF-8?q?fix:=20=EB=A1=9C=EB=98=90=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C,=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20=EC=9E=85=EB=A0=A5=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/InputView.java | 4 ++-- src/main/java/LottoPrice.java | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java index 779c0ee4..58f2b4c1 100644 --- a/src/main/java/InputView.java +++ b/src/main/java/InputView.java @@ -4,8 +4,8 @@ public class InputView { public static final Scanner SCANNER = new Scanner(System.in); - public int inputLottoPrice() { + public String readLottoPrice() { System.out.println("구입금액을 입력해 주세요."); - return SCANNER.nextInt(); + return SCANNER.nextLine(); } } diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java index 2f81a3b6..cfce44e7 100644 --- a/src/main/java/LottoPrice.java +++ b/src/main/java/LottoPrice.java @@ -15,7 +15,6 @@ private void validate(int price) { validateUnit(price); } - private void validateRange(int price) { if (price < MIN_PRICE) { throw new IllegalArgumentException(); @@ -27,4 +26,12 @@ private void validateUnit(int price) { throw new IllegalArgumentException(); } } + + public static LottoPrice valueOf(String price) { + try { + return new LottoPrice(Integer.parseInt(price)); + } catch (NumberFormatException numberFormatException) { + throw new IllegalArgumentException(); + } + } } From 8dc66387c8297b9063077bb0e51b41db7ecad997 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:28:34 +0900 Subject: [PATCH 11/37] =?UTF-8?q?test:=20=EB=A1=9C=EB=98=90=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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/LottoPrice.java | 6 ++-- src/test/java/LottoPriceTest.java | 49 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/test/java/LottoPriceTest.java diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java index cfce44e7..6eb45114 100644 --- a/src/main/java/LottoPrice.java +++ b/src/main/java/LottoPrice.java @@ -17,13 +17,13 @@ private void validate(int price) { private void validateRange(int price) { if (price < MIN_PRICE) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("로또 금액은 0원 보다 작을 수 없습니다."); } } private void validateUnit(int price) { if (price % PRICE_UNIT != 0) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("로또 금액은 1000원 단위여야 합니다."); } } @@ -31,7 +31,7 @@ public static LottoPrice valueOf(String price) { try { return new LottoPrice(Integer.parseInt(price)); } catch (NumberFormatException numberFormatException) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("로또 금액은 숫자여야 합니다."); } } } diff --git a/src/test/java/LottoPriceTest.java b/src/test/java/LottoPriceTest.java new file mode 100644 index 00000000..26ffc7f6 --- /dev/null +++ b/src/test/java/LottoPriceTest.java @@ -0,0 +1,49 @@ +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class LottoPriceTest { + + @ParameterizedTest + @ValueSource(ints = {0, 1000, 2000, 3000, 4000, 5000}) + void 로또_금액은_0원_혹은_1000원_단위이어야_한다(int price) { + // when & then + Assertions.assertThatCode(() -> new LottoPrice(price)).doesNotThrowAnyException(); + } + + @Test + void 로또_금액은_0원_보다_작을_수_없다() { + // given + int price = -1000; + + // when & then + assertThatThrownBy(() -> new LottoPrice(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 금액은 0원 보다 작을 수 없습니다."); + } + + @Test + void 로또_금액은_1000원_단위여야_한다() { + // given + int price = 1234; + + // when & then + assertThatThrownBy(() -> new LottoPrice(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 금액은 1000원 단위여야 합니다."); + } + + @Test + void 로또_금액은_숫자여야_한다() { + // given + String price = "천원"; + + // when & then + assertThatThrownBy(() -> LottoPrice.valueOf(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 금액은 숫자여야 합니다."); + } +} From fe3c459c3b6014becc98b1635f68e807e8ddd147 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:41:06 +0900 Subject: [PATCH 12/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20=EB=A1=9C=EC=A7=81=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/LottoGame.java | 11 +++++++++++ src/main/java/LottoPrice.java | 4 ++++ src/main/java/RandomLottoGenerator.java | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/LottoGame.java b/src/main/java/LottoGame.java index 1e6d5295..5cadf549 100644 --- a/src/main/java/LottoGame.java +++ b/src/main/java/LottoGame.java @@ -1,3 +1,6 @@ +import java.util.List; +import java.util.stream.IntStream; + public class LottoGame { private final InputView inputView; @@ -8,5 +11,13 @@ public LottoGame(InputView inputView) { public void run() { LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); + List lottos = publishLotto(price); + } + + private List publishLotto(LottoPrice price) { + int lottoAmount = price.divideByUnit(); + return IntStream.range(0, lottoAmount) + .mapToObj(i -> RandomLottoGenerator.generateLotto()) + .toList(); } } diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java index 6eb45114..6b14c92b 100644 --- a/src/main/java/LottoPrice.java +++ b/src/main/java/LottoPrice.java @@ -34,4 +34,8 @@ public static LottoPrice valueOf(String price) { throw new IllegalArgumentException("로또 금액은 숫자여야 합니다."); } } + + public int divideByUnit() { + return price / PRICE_UNIT; + } } diff --git a/src/main/java/RandomLottoGenerator.java b/src/main/java/RandomLottoGenerator.java index ac70863f..cda25803 100644 --- a/src/main/java/RandomLottoGenerator.java +++ b/src/main/java/RandomLottoGenerator.java @@ -7,7 +7,7 @@ public class RandomLottoGenerator { public static final Random RANDOM = new Random(); - public Lotto generateLotto() { + public static Lotto generateLotto() { Set numbers = new HashSet<>(); while (numbers.size() < Lotto.LOTTO_SIZE) { int randomNumber = RANDOM.nextInt(LottoNumber.MIN_VALUE, LottoNumber.MAX_VALUE); From e0d1c0abd5c3c169b9dcef9529372264f6334a5a Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 10:56:47 +0900 Subject: [PATCH 13/37] =?UTF-8?q?refactor:=20=EA=B0=92=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20record=EB=A1=9C=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/LottoNumber.java | 9 +++------ src/main/java/LottoPrice.java | 15 ++++++--------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java index 4d0abbee..788a716a 100644 --- a/src/main/java/LottoNumber.java +++ b/src/main/java/LottoNumber.java @@ -1,16 +1,13 @@ -public class LottoNumber { +public record LottoNumber(int number) { public static final int MIN_VALUE = 1; public static final int MAX_VALUE = 45; - private final int number; - - public LottoNumber(int number) { + public LottoNumber { validateRange(number); - this.number = number; } - private void validateRange(int number) { + private static void validateRange(int number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException(); } diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java index 6b14c92b..14f8f229 100644 --- a/src/main/java/LottoPrice.java +++ b/src/main/java/LottoPrice.java @@ -1,27 +1,24 @@ -public class LottoPrice { +public record LottoPrice(int price) { public static final int MIN_PRICE = 0; public static final int PRICE_UNIT = 1_000; - private final int price; - - public LottoPrice(int price) { + public LottoPrice { validate(price); - this.price = price; } - private void validate(int price) { + private static void validate(int price) { validateRange(price); validateUnit(price); } - private void validateRange(int price) { + private static void validateRange(int price) { if (price < MIN_PRICE) { throw new IllegalArgumentException("로또 금액은 0원 보다 작을 수 없습니다."); } } - private void validateUnit(int price) { + private static void validateUnit(int price) { if (price % PRICE_UNIT != 0) { throw new IllegalArgumentException("로또 금액은 1000원 단위여야 합니다."); } @@ -36,6 +33,6 @@ public static LottoPrice valueOf(String price) { } public int divideByUnit() { - return price / PRICE_UNIT; + return price() / PRICE_UNIT; } } From 28637ccc3c2d288473d40eb68bc2da0fb4a03191 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 11:03:30 +0900 Subject: [PATCH 14/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Lotto.java | 3 +++ src/main/java/LottoGame.java | 10 +++++++++- src/main/java/LottoResult.java | 13 +++++++++++++ src/main/java/OutputView.java | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/main/java/LottoResult.java create mode 100644 src/main/java/OutputView.java diff --git a/src/main/java/Lotto.java b/src/main/java/Lotto.java index 7dd3e695..4e28dc11 100644 --- a/src/main/java/Lotto.java +++ b/src/main/java/Lotto.java @@ -29,4 +29,7 @@ private void validateDuplication(List numbers) { } } + public List numbers() { + return List.copyOf(numbers); + } } diff --git a/src/main/java/LottoGame.java b/src/main/java/LottoGame.java index 5cadf549..d68eb920 100644 --- a/src/main/java/LottoGame.java +++ b/src/main/java/LottoGame.java @@ -4,14 +4,17 @@ public class LottoGame { private final InputView inputView; + private final OutputView outputView; - public LottoGame(InputView inputView) { + public LottoGame(InputView inputView, OutputView outputView) { this.inputView = inputView; + this.outputView = outputView; } public void run() { LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); List lottos = publishLotto(price); + printPublishedResult(lottos); } private List publishLotto(LottoPrice price) { @@ -20,4 +23,9 @@ private List publishLotto(LottoPrice price) { .mapToObj(i -> RandomLottoGenerator.generateLotto()) .toList(); } + + private void printPublishedResult(List lottos) { + List results = lottos.stream().map(LottoResult::from).toList(); + outputView.printLotto(results); + } } diff --git a/src/main/java/LottoResult.java b/src/main/java/LottoResult.java new file mode 100644 index 00000000..a2f0cc3e --- /dev/null +++ b/src/main/java/LottoResult.java @@ -0,0 +1,13 @@ +import java.util.List; + +public record LottoResult( + List numbers +) { + + public static LottoResult from(Lotto lottos) { + List numbers = lottos.numbers().stream() + .map(LottoNumber::number) + .toList(); + return new LottoResult(numbers); + } +} diff --git a/src/main/java/OutputView.java b/src/main/java/OutputView.java new file mode 100644 index 00000000..49ad6557 --- /dev/null +++ b/src/main/java/OutputView.java @@ -0,0 +1,16 @@ +import java.util.List; + +public class OutputView { + + public void printLotto(List lottos) { + printLinebreak(); + System.out.println(lottos.size() + "개를 구매했습니다."); + lottos.stream() + .map(LottoResult::numbers) + .forEach(System.out::println); + } + + private void printLinebreak() { + System.out.print(System.lineSeparator()); + } +} From b720de92f1640ef4b6eaa903b3a031e1e04538fa Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 11:09:42 +0900 Subject: [PATCH 15/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EC=98=A4?= =?UTF-8?q?=EB=A6=84=EC=B0=A8=EC=88=9C=20=EC=A0=95=EB=A0=AC=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Lotto.java | 6 +++++- src/main/java/LottoNumber.java | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/Lotto.java b/src/main/java/Lotto.java index 4e28dc11..ba505634 100644 --- a/src/main/java/Lotto.java +++ b/src/main/java/Lotto.java @@ -1,3 +1,5 @@ +import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Lotto { @@ -8,7 +10,9 @@ public class Lotto { public Lotto(List numbers) { validate(numbers); - this.numbers = numbers; + List modifiable = new ArrayList<>(numbers); + Collections.sort(modifiable); + this.numbers = modifiable; } private void validate(List numbers) { diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java index 788a716a..f69ba9cd 100644 --- a/src/main/java/LottoNumber.java +++ b/src/main/java/LottoNumber.java @@ -1,4 +1,4 @@ -public record LottoNumber(int number) { +public record LottoNumber(int number) implements Comparable { public static final int MIN_VALUE = 1; public static final int MAX_VALUE = 45; @@ -12,4 +12,9 @@ private static void validateRange(int number) { throw new IllegalArgumentException(); } } + + @Override + public int compareTo(final LottoNumber other) { + return Integer.compare(number, other.number); + } } From 5e69c08175320a7cb662da8c4d70e7ecf9cf2df9 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 11:11:42 +0900 Subject: [PATCH 16/37] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20static=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/LottoNumber.java | 2 +- src/main/java/LottoPrice.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java index f69ba9cd..354ff8a7 100644 --- a/src/main/java/LottoNumber.java +++ b/src/main/java/LottoNumber.java @@ -7,7 +7,7 @@ public record LottoNumber(int number) implements Comparable { validateRange(number); } - private static void validateRange(int number) { + private void validateRange(int number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException(); } diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java index 14f8f229..e8907f2c 100644 --- a/src/main/java/LottoPrice.java +++ b/src/main/java/LottoPrice.java @@ -7,18 +7,18 @@ public record LottoPrice(int price) { validate(price); } - private static void validate(int price) { + private void validate(int price) { validateRange(price); validateUnit(price); } - private static void validateRange(int price) { + private void validateRange(int price) { if (price < MIN_PRICE) { throw new IllegalArgumentException("로또 금액은 0원 보다 작을 수 없습니다."); } } - private static void validateUnit(int price) { + private void validateUnit(int price) { if (price % PRICE_UNIT != 0) { throw new IllegalArgumentException("로또 금액은 1000원 단위여야 합니다."); } From 77f2eba61f79a2fea8f99f6f63963215fe7e5d70 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 11:15:37 +0900 Subject: [PATCH 17/37] =?UTF-8?q?test:=20=EA=B0=9D=EC=B2=B4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=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.java | 4 +- src/main/java/LottoNumber.java | 2 +- src/test/java/LottoNumberTest.java | 18 +++++++ src/test/java/LottoPriceTest.java | 1 + src/test/java/LottoTest.java | 80 ++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 src/test/java/LottoNumberTest.java create mode 100644 src/test/java/LottoTest.java diff --git a/src/main/java/Lotto.java b/src/main/java/Lotto.java index ba505634..1a409075 100644 --- a/src/main/java/Lotto.java +++ b/src/main/java/Lotto.java @@ -22,14 +22,14 @@ private void validate(List numbers) { private void validateSize(List numbers) { if (numbers.size() != LOTTO_SIZE) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("로또는 6개의 숫자로 이루어져야 합니다."); } } private void validateDuplication(List numbers) { long duplicatedSize = numbers.stream().distinct().count(); if (numbers.size() != duplicatedSize) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("로또는 중복되지 않는 6개의 숫자로 이루어져야 합니다."); } } diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java index 354ff8a7..9026d779 100644 --- a/src/main/java/LottoNumber.java +++ b/src/main/java/LottoNumber.java @@ -9,7 +9,7 @@ public record LottoNumber(int number) implements Comparable { private void validateRange(int number) { if (number < MIN_VALUE || number > MAX_VALUE) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("로또 번호는 1부터 45 사이여야 합니다."); } } diff --git a/src/test/java/LottoNumberTest.java b/src/test/java/LottoNumberTest.java new file mode 100644 index 00000000..8e5f7e06 --- /dev/null +++ b/src/test/java/LottoNumberTest.java @@ -0,0 +1,18 @@ +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; + +@SuppressWarnings("NonAsciiCharacters") +class LottoNumberTest { + + @Test + void 로또_번호는_1부터_45까지_이어야_한다() { + // given + int number = 46; + + // when & then + assertThatThrownBy(() -> new LottoNumber(number)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 번호는 1부터 45 사이여야 합니다."); + } +} diff --git a/src/test/java/LottoPriceTest.java b/src/test/java/LottoPriceTest.java index 26ffc7f6..9a5306b3 100644 --- a/src/test/java/LottoPriceTest.java +++ b/src/test/java/LottoPriceTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +@SuppressWarnings("NonAsciiCharacters") class LottoPriceTest { @ParameterizedTest diff --git a/src/test/java/LottoTest.java b/src/test/java/LottoTest.java new file mode 100644 index 00000000..a8351a9d --- /dev/null +++ b/src/test/java/LottoTest.java @@ -0,0 +1,80 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import org.junit.jupiter.api.Test; + +@SuppressWarnings("NonAsciiCharacters") +class LottoTest { + + @Test + void 로또는_중복되지_않는_6개의_숫자로_이루어져있다() { + // given + var numbers = List.of( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + ); + + // when & then + assertThatCode(() -> new Lotto(numbers)).doesNotThrowAnyException(); + } + + @Test + void 로또는_6개의_숫자로_이루어져야_한다() { + // given + var numbers = List.of( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5) + ); + + // when & then + assertThatThrownBy(() -> new Lotto(numbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또는 6개의 숫자로 이루어져야 합니다."); + } + + @Test + void 로또는_중복되지_않는_6개의_숫자로_이루어져야_한다() { + // given + var numbers = List.of( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(5) + ); + + // when & then + assertThatThrownBy(() -> new Lotto(numbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또는 중복되지 않는 6개의 숫자로 이루어져야 합니다."); + } + + @Test + void 로또의_숫자들은_오름차순으로_정렬되어_있다() { + // given + var numbers = List.of( + new LottoNumber(6), + new LottoNumber(5), + new LottoNumber(4), + new LottoNumber(3), + new LottoNumber(2), + new LottoNumber(1) + ); + + // when + var lotto = new Lotto(numbers); + + // then + assertThat(lotto.numbers()).isSorted(); + } +} From c3d3defb98f5e78a8659c7ff562596e3274aa352 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 11:17:36 +0900 Subject: [PATCH 18/37] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/{ => model}/Lotto.java | 7 ++++--- src/main/java/{ => model}/LottoGame.java | 7 ++++++- src/main/java/{ => model}/LottoNumber.java | 2 ++ src/main/java/{ => model}/LottoPrice.java | 2 ++ src/main/java/{ => model}/RandomLottoGenerator.java | 2 ++ src/main/java/{ => view}/InputView.java | 2 ++ src/main/java/{ => view}/LottoResult.java | 4 ++++ src/main/java/{ => view}/OutputView.java | 2 ++ src/test/java/LottoNumberTest.java | 1 + src/test/java/LottoPriceTest.java | 1 + src/test/java/LottoTest.java | 2 ++ 12 files changed, 29 insertions(+), 5 deletions(-) rename src/main/java/{ => model}/Lotto.java (93%) rename src/main/java/{ => model}/LottoGame.java (87%) rename src/main/java/{ => model}/LottoNumber.java (97%) rename src/main/java/{ => model}/LottoPrice.java (98%) rename src/main/java/{ => model}/RandomLottoGenerator.java (97%) rename src/main/java/{ => view}/InputView.java (94%) rename src/main/java/{ => view}/LottoResult.java (83%) rename src/main/java/{ => view}/OutputView.java (96%) diff --git a/README.md b/README.md index 81cd3f16..7a60e1c6 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,4 @@ - [x] 로또 번호는 랜덤으로 설정 - [x] 숫자들끼리 중복되지 않도록 - [x] 1 ~ 45 사이 -- [ ] 출력 시 숫자들이 오름차순으로 정렬 +- [x] 출력 시 숫자들이 오름차순으로 정렬 diff --git a/src/main/java/Lotto.java b/src/main/java/model/Lotto.java similarity index 93% rename from src/main/java/Lotto.java rename to src/main/java/model/Lotto.java index 1a409075..afcd8b5d 100644 --- a/src/main/java/Lotto.java +++ b/src/main/java/model/Lotto.java @@ -1,13 +1,13 @@ +package model; + import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class Lotto { +public record Lotto(List numbers) { public static final int LOTTO_SIZE = 6; - private final List numbers; - public Lotto(List numbers) { validate(numbers); List modifiable = new ArrayList<>(numbers); @@ -33,6 +33,7 @@ private void validateDuplication(List numbers) { } } + @Override public List numbers() { return List.copyOf(numbers); } diff --git a/src/main/java/LottoGame.java b/src/main/java/model/LottoGame.java similarity index 87% rename from src/main/java/LottoGame.java rename to src/main/java/model/LottoGame.java index d68eb920..ac069885 100644 --- a/src/main/java/LottoGame.java +++ b/src/main/java/model/LottoGame.java @@ -1,10 +1,15 @@ +package model; + import java.util.List; import java.util.stream.IntStream; +import view.InputView; +import view.LottoResult; +import view.OutputView; public class LottoGame { private final InputView inputView; - private final OutputView outputView; + private final OutputView outputView; public LottoGame(InputView inputView, OutputView outputView) { this.inputView = inputView; diff --git a/src/main/java/LottoNumber.java b/src/main/java/model/LottoNumber.java similarity index 97% rename from src/main/java/LottoNumber.java rename to src/main/java/model/LottoNumber.java index 9026d779..6280c01c 100644 --- a/src/main/java/LottoNumber.java +++ b/src/main/java/model/LottoNumber.java @@ -1,3 +1,5 @@ +package model; + public record LottoNumber(int number) implements Comparable { public static final int MIN_VALUE = 1; diff --git a/src/main/java/LottoPrice.java b/src/main/java/model/LottoPrice.java similarity index 98% rename from src/main/java/LottoPrice.java rename to src/main/java/model/LottoPrice.java index e8907f2c..a80b346b 100644 --- a/src/main/java/LottoPrice.java +++ b/src/main/java/model/LottoPrice.java @@ -1,3 +1,5 @@ +package model; + public record LottoPrice(int price) { public static final int MIN_PRICE = 0; diff --git a/src/main/java/RandomLottoGenerator.java b/src/main/java/model/RandomLottoGenerator.java similarity index 97% rename from src/main/java/RandomLottoGenerator.java rename to src/main/java/model/RandomLottoGenerator.java index cda25803..01d311ea 100644 --- a/src/main/java/RandomLottoGenerator.java +++ b/src/main/java/model/RandomLottoGenerator.java @@ -1,3 +1,5 @@ +package model; + import java.util.HashSet; import java.util.List; import java.util.Random; diff --git a/src/main/java/InputView.java b/src/main/java/view/InputView.java similarity index 94% rename from src/main/java/InputView.java rename to src/main/java/view/InputView.java index 58f2b4c1..6ad9c5aa 100644 --- a/src/main/java/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,3 +1,5 @@ +package view; + import java.util.Scanner; public class InputView { diff --git a/src/main/java/LottoResult.java b/src/main/java/view/LottoResult.java similarity index 83% rename from src/main/java/LottoResult.java rename to src/main/java/view/LottoResult.java index a2f0cc3e..fbf4f1ed 100644 --- a/src/main/java/LottoResult.java +++ b/src/main/java/view/LottoResult.java @@ -1,4 +1,8 @@ +package view; + import java.util.List; +import model.Lotto; +import model.LottoNumber; public record LottoResult( List numbers diff --git a/src/main/java/OutputView.java b/src/main/java/view/OutputView.java similarity index 96% rename from src/main/java/OutputView.java rename to src/main/java/view/OutputView.java index 49ad6557..d24d2169 100644 --- a/src/main/java/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,3 +1,5 @@ +package view; + import java.util.List; public class OutputView { diff --git a/src/test/java/LottoNumberTest.java b/src/test/java/LottoNumberTest.java index 8e5f7e06..e8a5052b 100644 --- a/src/test/java/LottoNumberTest.java +++ b/src/test/java/LottoNumberTest.java @@ -1,5 +1,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; +import model.LottoNumber; import org.junit.jupiter.api.Test; @SuppressWarnings("NonAsciiCharacters") diff --git a/src/test/java/LottoPriceTest.java b/src/test/java/LottoPriceTest.java index 9a5306b3..9fab7ab5 100644 --- a/src/test/java/LottoPriceTest.java +++ b/src/test/java/LottoPriceTest.java @@ -1,5 +1,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; +import model.LottoPrice; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/src/test/java/LottoTest.java b/src/test/java/LottoTest.java index a8351a9d..2ee3cff3 100644 --- a/src/test/java/LottoTest.java +++ b/src/test/java/LottoTest.java @@ -3,6 +3,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.List; +import model.Lotto; +import model.LottoNumber; import org.junit.jupiter.api.Test; @SuppressWarnings("NonAsciiCharacters") From 20d6f2f1ec54f9c597d1d3d191f1a4dc84077493 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 11:19:37 +0900 Subject: [PATCH 19/37] =?UTF-8?q?feat:=20=EC=95=A0=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=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/LottoApplication.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/LottoApplication.java diff --git a/src/main/java/LottoApplication.java b/src/main/java/LottoApplication.java new file mode 100644 index 00000000..ec24db46 --- /dev/null +++ b/src/main/java/LottoApplication.java @@ -0,0 +1,13 @@ +import model.LottoGame; +import view.InputView; +import view.OutputView; + +public class LottoApplication { + + public static void main(String[] args) { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + LottoGame lottoGame = new LottoGame(inputView, outputView); + lottoGame.run(); + } +} From db3eb592bbf1882b776bfe25b80b3d668c17420b Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 15:48:00 +0900 Subject: [PATCH 20/37] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/{ => model}/LottoNumberTest.java | 3 ++- src/test/java/{ => model}/LottoPriceTest.java | 3 ++- src/test/java/{ => model}/LottoTest.java | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) rename src/test/java/{ => model}/LottoNumberTest.java (95%) rename src/test/java/{ => model}/LottoPriceTest.java (98%) rename src/test/java/{ => model}/LottoTest.java (98%) diff --git a/src/test/java/LottoNumberTest.java b/src/test/java/model/LottoNumberTest.java similarity index 95% rename from src/test/java/LottoNumberTest.java rename to src/test/java/model/LottoNumberTest.java index e8a5052b..c35bf79c 100644 --- a/src/test/java/LottoNumberTest.java +++ b/src/test/java/model/LottoNumberTest.java @@ -1,6 +1,7 @@ +package model; + import static org.assertj.core.api.Assertions.assertThatThrownBy; -import model.LottoNumber; import org.junit.jupiter.api.Test; @SuppressWarnings("NonAsciiCharacters") diff --git a/src/test/java/LottoPriceTest.java b/src/test/java/model/LottoPriceTest.java similarity index 98% rename from src/test/java/LottoPriceTest.java rename to src/test/java/model/LottoPriceTest.java index 9fab7ab5..e0ca87bc 100644 --- a/src/test/java/LottoPriceTest.java +++ b/src/test/java/model/LottoPriceTest.java @@ -1,6 +1,7 @@ +package model; + import static org.assertj.core.api.Assertions.assertThatThrownBy; -import model.LottoPrice; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/src/test/java/LottoTest.java b/src/test/java/model/LottoTest.java similarity index 98% rename from src/test/java/LottoTest.java rename to src/test/java/model/LottoTest.java index 2ee3cff3..6ea5f4a8 100644 --- a/src/test/java/LottoTest.java +++ b/src/test/java/model/LottoTest.java @@ -1,10 +1,10 @@ +package model; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.List; -import model.Lotto; -import model.LottoNumber; import org.junit.jupiter.api.Test; @SuppressWarnings("NonAsciiCharacters") From fad8541316644757d900e8b65d64066d54a7f2d4 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 15:51:27 +0900 Subject: [PATCH 21/37] =?UTF-8?q?docs:=202=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 7a60e1c6..e841f32d 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,9 @@ - [x] 숫자들끼리 중복되지 않도록 - [x] 1 ~ 45 사이 - [x] 출력 시 숫자들이 오름차순으로 정렬 + +- 당첨 번호를 입력 받는다 +- 당첨 결과를 계산한다. + - 일치한 개수에 따라 순위와 당첨금이 결정된다. + - 수익률을 계산한다 +- 당첨 통계를 출력한다. From ed40d837182404a0a97fbe602d91550ce63747f5 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 16:04:06 +0900 Subject: [PATCH 22/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EC=88=9C=EC=9C=84=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Rank.java | 28 +++++++++++++++++++++++++ src/test/java/model/RankTest.java | 34 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/main/java/model/Rank.java create mode 100644 src/test/java/model/RankTest.java diff --git a/src/main/java/model/Rank.java b/src/main/java/model/Rank.java new file mode 100644 index 00000000..b10d8346 --- /dev/null +++ b/src/main/java/model/Rank.java @@ -0,0 +1,28 @@ +package model; + +import java.util.Arrays; + +public enum Rank { + + NONE(0, 0), + FIFTH_PRIZE(3, 5_000), + FOURTH_PRIZE(4, 50_000), + THIRD_PRIZE(5, 1_500_000), + FIRST_PRIZE(6, 2_000_000_000), + ; + + private final int matchCount; + private final int prize; + + Rank(int matchCount, int prize) { + this.matchCount = matchCount; + this.prize = prize; + } + + public static Rank of(int matchCount) { + return Arrays.stream(Rank.values()) + .filter(rank -> rank.matchCount == matchCount) + .findFirst() + .orElse(NONE); + } +} diff --git a/src/test/java/model/RankTest.java b/src/test/java/model/RankTest.java new file mode 100644 index 00000000..285b9c4d --- /dev/null +++ b/src/test/java/model/RankTest.java @@ -0,0 +1,34 @@ +package model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@SuppressWarnings("NonAsciiCharacters") +class RankTest { + + @ParameterizedTest + @MethodSource("matchCountWithRank") + void 당첨_숫자의_개수에_따라_순위가_결정된다(int matchCount, Rank rank) { + // when + Rank actual = Rank.of(matchCount); + + // then + assertThat(actual).isEqualTo(rank); + } + + static Stream matchCountWithRank() { + return Stream.of( + Arguments.of(6, Rank.FIRST_PRIZE), + Arguments.of(5, Rank.THIRD_PRIZE), + Arguments.of(4, Rank.FOURTH_PRIZE), + Arguments.of(3, Rank.FIFTH_PRIZE), + Arguments.of(2, Rank.NONE), + Arguments.of(1, Rank.NONE), + Arguments.of(1, Rank.NONE) + ); + } +} From 4e861b4ed11de395757c512ad0d4c8b8d27fbb69 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 16:14:04 +0900 Subject: [PATCH 23/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=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 --- README.md | 4 +- src/main/java/model/Lotto.java | 14 ++++ src/test/java/model/LottoTest.java | 123 ++++++++++++++--------------- 3 files changed, 75 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index e841f32d..1387225f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ - [x] 출력 시 숫자들이 오름차순으로 정렬 - 당첨 번호를 입력 받는다 -- 당첨 결과를 계산한다. - - 일치한 개수에 따라 순위와 당첨금이 결정된다. +- 당첨 결과를 계산한다. + - [x] 일치한 개수에 따라 순위와 당첨금이 결정된다. - 수익률을 계산한다 - 당첨 통계를 출력한다. diff --git a/src/main/java/model/Lotto.java b/src/main/java/model/Lotto.java index afcd8b5d..45c2b482 100644 --- a/src/main/java/model/Lotto.java +++ b/src/main/java/model/Lotto.java @@ -33,6 +33,20 @@ private void validateDuplication(List numbers) { } } + public static Lotto from(List numbers) { + List lottoNumbers = numbers.stream() + .map(LottoNumber::new) + .toList(); + return new Lotto(lottoNumbers); + } + + public Rank matchRank(Lotto other) { + int matchCount = (int) numbers.stream() + .filter(other.numbers()::contains) + .count(); + return Rank.of(matchCount); + } + @Override public List numbers() { return List.copyOf(numbers); diff --git a/src/test/java/model/LottoTest.java b/src/test/java/model/LottoTest.java index 6ea5f4a8..ea1fd296 100644 --- a/src/test/java/model/LottoTest.java +++ b/src/test/java/model/LottoTest.java @@ -5,78 +5,73 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @SuppressWarnings("NonAsciiCharacters") class LottoTest { - @Test - void 로또는_중복되지_않는_6개의_숫자로_이루어져있다() { - // given - var numbers = List.of( - new LottoNumber(1), - new LottoNumber(2), - new LottoNumber(3), - new LottoNumber(4), - new LottoNumber(5), - new LottoNumber(6) - ); - - // when & then - assertThatCode(() -> new Lotto(numbers)).doesNotThrowAnyException(); - } + @Nested + class 로또_생성_시{ - @Test - void 로또는_6개의_숫자로_이루어져야_한다() { - // given - var numbers = List.of( - new LottoNumber(1), - new LottoNumber(2), - new LottoNumber(3), - new LottoNumber(4), - new LottoNumber(5) - ); - - // when & then - assertThatThrownBy(() -> new Lotto(numbers)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("로또는 6개의 숫자로 이루어져야 합니다."); - } + @Test + void 로또는_중복되지_않는_6개의_숫자로_이루어져있다() { + // given + List numbers = List.of(1, 2, 3, 4, 5, 6); + + // when & then + assertThatCode(() -> Lotto.from(numbers)).doesNotThrowAnyException(); + } + + @Test + void 로또는_6개의_숫자로_이루어져야_한다() { + // given + List numbers = List.of(1, 2, 3, 4, 5); + + // when & then + assertThatThrownBy(() -> Lotto.from(numbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또는 6개의 숫자로 이루어져야 합니다."); + } + + @Test + void 로또는_중복되지_않는_6개의_숫자로_이루어져야_한다() { + // given + List numbers = List.of(1, 2,3,4,5,5); - @Test - void 로또는_중복되지_않는_6개의_숫자로_이루어져야_한다() { - // given - var numbers = List.of( - new LottoNumber(1), - new LottoNumber(2), - new LottoNumber(3), - new LottoNumber(4), - new LottoNumber(5), - new LottoNumber(5) - ); - - // when & then - assertThatThrownBy(() -> new Lotto(numbers)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("로또는 중복되지 않는 6개의 숫자로 이루어져야 합니다."); + // when & then + assertThatThrownBy(() -> Lotto.from(numbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또는 중복되지 않는 6개의 숫자로 이루어져야 합니다."); + } + + @Test + void 로또의_숫자들은_오름차순으로_정렬되어_있다() { + // given + List numbers = List.of(6, 5, 4, 3, 2, 1); + + // when + var lotto = Lotto.from(numbers); + + // then + assertThat(lotto.numbers()).isSorted(); + } } - @Test - void 로또의_숫자들은_오름차순으로_정렬되어_있다() { - // given - var numbers = List.of( - new LottoNumber(6), - new LottoNumber(5), - new LottoNumber(4), - new LottoNumber(3), - new LottoNumber(2), - new LottoNumber(1) - ); - - // when - var lotto = new Lotto(numbers); - - // then - assertThat(lotto.numbers()).isSorted(); + @Nested + class 로또_당첨_계산 { + + @Test + void 당첨_숫자에_따라_순위를_계산한다() { + // given + Lotto lotto = Lotto.from(List.of(1, 2, 3, 4, 5, 6)); + Lotto winningLotto = Lotto.from(List.of(1, 2, 3, 7, 8, 9)); + + // when + Rank rank = lotto.matchRank(winningLotto); + + // then + assertThat(rank).isEqualTo(Rank.FIFTH_PRIZE); + } } } From 314f607c2d00d760b7e3aaaa37dbd1c17caffe19 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Thu, 2 May 2024 16:35:36 +0900 Subject: [PATCH 24/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EC=B6=94=EC=82=B0=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Rank.java | 8 ++--- src/main/java/model/ResultStatistics.java | 24 ++++++++++++++ src/test/java/model/LottoTest.java | 2 +- src/test/java/model/RankTest.java | 8 ++--- src/test/java/model/ResultStatisticsTest.java | 31 +++++++++++++++++++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/main/java/model/ResultStatistics.java create mode 100644 src/test/java/model/ResultStatisticsTest.java diff --git a/src/main/java/model/Rank.java b/src/main/java/model/Rank.java index b10d8346..a7f98afc 100644 --- a/src/main/java/model/Rank.java +++ b/src/main/java/model/Rank.java @@ -5,10 +5,10 @@ public enum Rank { NONE(0, 0), - FIFTH_PRIZE(3, 5_000), - FOURTH_PRIZE(4, 50_000), - THIRD_PRIZE(5, 1_500_000), - FIRST_PRIZE(6, 2_000_000_000), + _5TH_PRIZE(3, 5_000), + _4TH_PRIZE(4, 50_000), + _3RD_PRIZE(5, 1_500_000), + _1ST_PRIZE(6, 2_000_000_000), ; private final int matchCount; diff --git a/src/main/java/model/ResultStatistics.java b/src/main/java/model/ResultStatistics.java new file mode 100644 index 00000000..4bd55119 --- /dev/null +++ b/src/main/java/model/ResultStatistics.java @@ -0,0 +1,24 @@ +package model; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ResultStatistics { + + private final Map ranksByCount; + + private ResultStatistics(Map ranksByCount) { + this.ranksByCount = ranksByCount; + } + + public static ResultStatistics from(List ranks) { + Map ranksByCount = ranks.stream() + .collect(Collectors.toMap(rank -> rank, rank -> 1, Integer::sum)); + return new ResultStatistics(ranksByCount); + } + + public int countOf(Rank rank) { + return ranksByCount.getOrDefault(rank, 0); + } +} diff --git a/src/test/java/model/LottoTest.java b/src/test/java/model/LottoTest.java index ea1fd296..738df731 100644 --- a/src/test/java/model/LottoTest.java +++ b/src/test/java/model/LottoTest.java @@ -71,7 +71,7 @@ class 로또_당첨_계산 { Rank rank = lotto.matchRank(winningLotto); // then - assertThat(rank).isEqualTo(Rank.FIFTH_PRIZE); + assertThat(rank).isEqualTo(Rank._5TH_PRIZE); } } } diff --git a/src/test/java/model/RankTest.java b/src/test/java/model/RankTest.java index 285b9c4d..6fab0d8a 100644 --- a/src/test/java/model/RankTest.java +++ b/src/test/java/model/RankTest.java @@ -22,10 +22,10 @@ class RankTest { static Stream matchCountWithRank() { return Stream.of( - Arguments.of(6, Rank.FIRST_PRIZE), - Arguments.of(5, Rank.THIRD_PRIZE), - Arguments.of(4, Rank.FOURTH_PRIZE), - Arguments.of(3, Rank.FIFTH_PRIZE), + Arguments.of(6, Rank._1ST_PRIZE), + Arguments.of(5, Rank._3RD_PRIZE), + Arguments.of(4, Rank._4TH_PRIZE), + Arguments.of(3, Rank._5TH_PRIZE), Arguments.of(2, Rank.NONE), Arguments.of(1, Rank.NONE), Arguments.of(1, Rank.NONE) diff --git a/src/test/java/model/ResultStatisticsTest.java b/src/test/java/model/ResultStatisticsTest.java new file mode 100644 index 00000000..8563428a --- /dev/null +++ b/src/test/java/model/ResultStatisticsTest.java @@ -0,0 +1,31 @@ +package model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.Test; + +@SuppressWarnings("NonAsciiCharacters") +class ResultStatisticsTest { + + @Test + void 순위_목록을_통해_당첨_결과가_생성된다() { + // given + List ranks = List.of( + Rank._5TH_PRIZE, + Rank._5TH_PRIZE, + Rank.NONE, + Rank.NONE, + Rank._3RD_PRIZE + ); + + // when + var resultStatistics = ResultStatistics.from(ranks); + + // then + assertThat(resultStatistics.countOf(Rank._5TH_PRIZE)).isEqualTo(2); + assertThat(resultStatistics.countOf(Rank.NONE)).isEqualTo(2); + assertThat(resultStatistics.countOf(Rank._3RD_PRIZE)).isEqualTo(1); + } + +} From a0920b46232106acc0d9c6b30bb9cf6c8547000d Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Fri, 3 May 2024 08:54:13 +0900 Subject: [PATCH 25/37] =?UTF-8?q?feat:=20=EC=88=98=EC=9D=B5=EB=A5=A0=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/model/Rank.java | 4 ++++ src/main/java/model/ResultStatistics.java | 13 +++++++++++-- src/test/java/model/ResultStatisticsTest.java | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1387225f..9b90e49b 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,5 @@ - 당첨 번호를 입력 받는다 - 당첨 결과를 계산한다. - [x] 일치한 개수에 따라 순위와 당첨금이 결정된다. - - 수익률을 계산한다 + - [x] 수익률을 계산한다 - 당첨 통계를 출력한다. diff --git a/src/main/java/model/Rank.java b/src/main/java/model/Rank.java index a7f98afc..b9dd640e 100644 --- a/src/main/java/model/Rank.java +++ b/src/main/java/model/Rank.java @@ -25,4 +25,8 @@ public static Rank of(int matchCount) { .findFirst() .orElse(NONE); } + + public int prize() { + return prize; + } } diff --git a/src/main/java/model/ResultStatistics.java b/src/main/java/model/ResultStatistics.java index 4bd55119..82db918a 100644 --- a/src/main/java/model/ResultStatistics.java +++ b/src/main/java/model/ResultStatistics.java @@ -7,18 +7,27 @@ public class ResultStatistics { private final Map ranksByCount; + private final int purchaseAmount; - private ResultStatistics(Map ranksByCount) { + private ResultStatistics(Map ranksByCount, int purchaseAmount) { this.ranksByCount = ranksByCount; + this.purchaseAmount = purchaseAmount; } public static ResultStatistics from(List ranks) { Map ranksByCount = ranks.stream() .collect(Collectors.toMap(rank -> rank, rank -> 1, Integer::sum)); - return new ResultStatistics(ranksByCount); + return new ResultStatistics(ranksByCount, ranks.size() * LottoPrice.PRICE_UNIT); } public int countOf(Rank rank) { return ranksByCount.getOrDefault(rank, 0); } + + public double calculateProfitRate() { + int totalWinningPrize = ranksByCount.entrySet().stream() + .mapToInt(entry -> entry.getKey().prize() * entry.getValue()) + .sum(); + return ((float) (totalWinningPrize * 100) / purchaseAmount) / 100.0; + } } diff --git a/src/test/java/model/ResultStatisticsTest.java b/src/test/java/model/ResultStatisticsTest.java index 8563428a..af99115c 100644 --- a/src/test/java/model/ResultStatisticsTest.java +++ b/src/test/java/model/ResultStatisticsTest.java @@ -28,4 +28,23 @@ class ResultStatisticsTest { assertThat(resultStatistics.countOf(Rank._3RD_PRIZE)).isEqualTo(1); } + + @Test + void 수익률을_계산한다() { + // given + List ranks = List.of( + Rank._5TH_PRIZE, + Rank._5TH_PRIZE, + Rank.NONE, + Rank.NONE, + Rank.NONE + ); + ResultStatistics resultStatistics = ResultStatistics.from(ranks); + + // when + double profitRate = resultStatistics.calculateProfitRate(); + + // then + assertThat(profitRate).isEqualTo(2); + } } From 3d0af7283d66289a0bd1867fd78999dce57b82c0 Mon Sep 17 00:00:00 2001 From: TaeyeonRoyce Date: Fri, 3 May 2024 09:36:45 +0900 Subject: [PATCH 26/37] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B6=94=EC=B2=A8=20=EB=B0=8F=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +-- src/main/java/model/Lotto.java | 14 ++++----- src/main/java/model/LottoGame.java | 29 +++++++++++++++---- src/main/java/model/LottoNumber.java | 10 ++++++- src/main/java/model/LottoPrice.java | 16 +++++----- src/main/java/model/Rank.java | 4 +++ src/main/java/view/InputView.java | 10 +++++++ src/main/java/view/OutputView.java | 27 +++++++++++++++-- .../LottoResponse.java} | 8 ++--- .../view/dto/LottoStatisticsResponse.java | 23 +++++++++++++++ 10 files changed, 116 insertions(+), 29 deletions(-) rename src/main/java/view/{LottoResult.java => dto/LottoResponse.java} (62%) create mode 100644 src/main/java/view/dto/LottoStatisticsResponse.java diff --git a/README.md b/README.md index 9b90e49b..fcd17d8f 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ - [x] 1 ~ 45 사이 - [x] 출력 시 숫자들이 오름차순으로 정렬 -- 당첨 번호를 입력 받는다 +- [x] 당첨 번호를 입력 받는다 - 당첨 결과를 계산한다. - [x] 일치한 개수에 따라 순위와 당첨금이 결정된다. - [x] 수익률을 계산한다 -- 당첨 통계를 출력한다. +- [x] 당첨 통계를 출력한다. diff --git a/src/main/java/model/Lotto.java b/src/main/java/model/Lotto.java index 45c2b482..8a853740 100644 --- a/src/main/java/model/Lotto.java +++ b/src/main/java/model/Lotto.java @@ -15,6 +15,13 @@ public Lotto(List numbers) { this.numbers = modifiable; } + public static Lotto from(List numbers) { + List lottoNumbers = numbers.stream() + .map(LottoNumber::new) + .toList(); + return new Lotto(lottoNumbers); + } + private void validate(List numbers) { validateSize(numbers); validateDuplication(numbers); @@ -33,13 +40,6 @@ private void validateDuplication(List numbers) { } } - public static Lotto from(List numbers) { - List lottoNumbers = numbers.stream() - .map(LottoNumber::new) - .toList(); - return new Lotto(lottoNumbers); - } - public Rank matchRank(Lotto other) { int matchCount = (int) numbers.stream() .filter(other.numbers()::contains) diff --git a/src/main/java/model/LottoGame.java b/src/main/java/model/LottoGame.java index ac069885..568b8351 100644 --- a/src/main/java/model/LottoGame.java +++ b/src/main/java/model/LottoGame.java @@ -3,7 +3,8 @@ import java.util.List; import java.util.stream.IntStream; import view.InputView; -import view.LottoResult; +import view.dto.LottoResponse; +import view.dto.LottoStatisticsResponse; import view.OutputView; public class LottoGame { @@ -17,12 +18,16 @@ public LottoGame(InputView inputView, OutputView outputView) { } public void run() { - LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); - List lottos = publishLotto(price); + List lottos = publishLotto(); printPublishedResult(lottos); + Lotto winningLotto = readWinningLotto(); + ResultStatistics resultStatistics = calculateResultStatistics(lottos, winningLotto); + LottoStatisticsResponse response = LottoStatisticsResponse.from(resultStatistics); + outputView.printResultStatistics(response); } - private List publishLotto(LottoPrice price) { + private List publishLotto() { + LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); int lottoAmount = price.divideByUnit(); return IntStream.range(0, lottoAmount) .mapToObj(i -> RandomLottoGenerator.generateLotto()) @@ -30,7 +35,21 @@ private List publishLotto(LottoPrice price) { } private void printPublishedResult(List lottos) { - List results = lottos.stream().map(LottoResult::from).toList(); + List results = lottos.stream().map(LottoResponse::from).toList(); outputView.printLotto(results); } + + private Lotto readWinningLotto() { + List winningNumbers = inputView.readWinningNumbers().stream() + .map(LottoNumber::valueOf) + .toList(); + return new Lotto(winningNumbers); + } + + private ResultStatistics calculateResultStatistics(List lottos, Lotto winningLotto) { + List ranks = lottos.stream() + .map(lotto -> lotto.matchRank(winningLotto)) + .toList(); + return ResultStatistics.from(ranks); + } } diff --git a/src/main/java/model/LottoNumber.java b/src/main/java/model/LottoNumber.java index 6280c01c..f0826f52 100644 --- a/src/main/java/model/LottoNumber.java +++ b/src/main/java/model/LottoNumber.java @@ -9,6 +9,14 @@ public record LottoNumber(int number) implements Comparable { validateRange(number); } + public static LottoNumber valueOf(String number) { + try { + return new LottoNumber(Integer.parseInt(number)); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException("로또 번호는 숫자여야 합니다."); + } + } + private void validateRange(int number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("로또 번호는 1부터 45 사이여야 합니다."); @@ -16,7 +24,7 @@ private void validateRange(int number) { } @Override - public int compareTo(final LottoNumber other) { + public int compareTo(LottoNumber other) { return Integer.compare(number, other.number); } } diff --git a/src/main/java/model/LottoPrice.java b/src/main/java/model/LottoPrice.java index a80b346b..c3514ccc 100644 --- a/src/main/java/model/LottoPrice.java +++ b/src/main/java/model/LottoPrice.java @@ -9,6 +9,14 @@ public record LottoPrice(int price) { validate(price); } + public static LottoPrice valueOf(String price) { + try { + return new LottoPrice(Integer.parseInt(price)); + } catch (NumberFormatException numberFormatException) { + throw new IllegalArgumentException("로또 금액은 숫자여야 합니다."); + } + } + private void validate(int price) { validateRange(price); validateUnit(price); @@ -26,14 +34,6 @@ private void validateUnit(int price) { } } - public static LottoPrice valueOf(String price) { - try { - return new LottoPrice(Integer.parseInt(price)); - } catch (NumberFormatException numberFormatException) { - throw new IllegalArgumentException("로또 금액은 숫자여야 합니다."); - } - } - public int divideByUnit() { return price() / PRICE_UNIT; } diff --git a/src/main/java/model/Rank.java b/src/main/java/model/Rank.java index b9dd640e..cf622085 100644 --- a/src/main/java/model/Rank.java +++ b/src/main/java/model/Rank.java @@ -26,6 +26,10 @@ public static Rank of(int matchCount) { .orElse(NONE); } + public int matchCount() { + return matchCount; + } + public int prize() { return prize; } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 6ad9c5aa..23755fdb 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,6 +1,8 @@ package view; +import java.util.List; import java.util.Scanner; +import java.util.stream.Stream; public class InputView { @@ -10,4 +12,12 @@ public String readLottoPrice() { System.out.println("구입금액을 입력해 주세요."); return SCANNER.nextLine(); } + + public List readWinningNumbers() { + System.out.println("지난 주 당첨 번호를 입력해 주세요."); + String input = SCANNER.nextLine(); + return Stream.of(input.split(",")) + .filter(it -> !it.isBlank()) + .toList(); + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d24d2169..c7a78ca7 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,18 +1,41 @@ package view; import java.util.List; +import model.Rank; +import view.dto.LottoResponse; +import view.dto.LottoStatisticsResponse; public class OutputView { - public void printLotto(List lottos) { + private static final String MATCH_RESULT_FORMAT = "%d개 일치 (%d원)- %d개"; + private static final String PROFIT_RATE_FORMAT = "총 수익률은 %.2f입니다."; + + public void printLotto(List lottos) { printLinebreak(); System.out.println(lottos.size() + "개를 구매했습니다."); lottos.stream() - .map(LottoResult::numbers) + .map(LottoResponse::numbers) .forEach(System.out::println); } private void printLinebreak() { System.out.print(System.lineSeparator()); } + + public void printResultStatistics(LottoStatisticsResponse response) { + printLinebreak(); + System.out.println("당첨 통계"); + System.out.println("---------"); + response.countOfRank().keySet() + .stream() + .filter(rank -> rank != Rank.NONE) + .sorted() + .forEach(rank -> { + int count = response.countOfRank().get(rank); + System.out.printf(MATCH_RESULT_FORMAT, rank.matchCount(), rank.prize(), count); + printLinebreak(); + }); + + System.out.printf(PROFIT_RATE_FORMAT, response.profitRate()); + } } diff --git a/src/main/java/view/LottoResult.java b/src/main/java/view/dto/LottoResponse.java similarity index 62% rename from src/main/java/view/LottoResult.java rename to src/main/java/view/dto/LottoResponse.java index fbf4f1ed..b9622387 100644 --- a/src/main/java/view/LottoResult.java +++ b/src/main/java/view/dto/LottoResponse.java @@ -1,17 +1,17 @@ -package view; +package view.dto; import java.util.List; import model.Lotto; import model.LottoNumber; -public record LottoResult( +public record LottoResponse( List numbers ) { - public static LottoResult from(Lotto lottos) { + public static LottoResponse from(Lotto lottos) { List numbers = lottos.numbers().stream() .map(LottoNumber::number) .toList(); - return new LottoResult(numbers); + return new LottoResponse(numbers); } } diff --git a/src/main/java/view/dto/LottoStatisticsResponse.java b/src/main/java/view/dto/LottoStatisticsResponse.java new file mode 100644 index 00000000..0a745efa --- /dev/null +++ b/src/main/java/view/dto/LottoStatisticsResponse.java @@ -0,0 +1,23 @@ +package view.dto; + +import java.util.HashMap; +import java.util.Map; +import model.Rank; +import model.ResultStatistics; + +public record LottoStatisticsResponse( + Map countOfRank, + double profitRate +) { + + public static LottoStatisticsResponse from(ResultStatistics resultStatistics) { + Map ranksByCount = new HashMap<>(); + for (Rank rank : Rank.values()) { + ranksByCount.put(rank, resultStatistics.countOf(rank)); + } + return new LottoStatisticsResponse( + ranksByCount, + resultStatistics.calculateProfitRate() + ); + } +} From 9fe9d100f409224a4cc50e04459027626a2d7e78 Mon Sep 17 00:00:00 2001 From: kokodak Date: Sun, 5 May 2024 16:25:46 +0900 Subject: [PATCH 27/37] =?UTF-8?q?fix:=20=EB=8B=B9=EC=B2=A8=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EC=9E=85=EB=A0=A5=20=EC=98=A4=EB=A5=98=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/view/InputView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 23755fdb..97201e26 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -16,7 +16,7 @@ public String readLottoPrice() { public List readWinningNumbers() { System.out.println("지난 주 당첨 번호를 입력해 주세요."); String input = SCANNER.nextLine(); - return Stream.of(input.split(",")) + return Stream.of(input.replace(" ", "").split(",")) .filter(it -> !it.isBlank()) .toList(); } From 98f1349e78d1a33ef4f1d3930691d9d5464d2407 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:33:49 +0900 Subject: [PATCH 28/37] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=8B=B9=EC=B2=A8=20=EB=B9=84=EA=B5=90=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Lotto.java | 11 ++--------- src/test/java/model/LottoTest.java | 21 ++------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/main/java/model/Lotto.java b/src/main/java/model/Lotto.java index 8a853740..4e694b47 100644 --- a/src/main/java/model/Lotto.java +++ b/src/main/java/model/Lotto.java @@ -17,8 +17,8 @@ public Lotto(List numbers) { public static Lotto from(List numbers) { List lottoNumbers = numbers.stream() - .map(LottoNumber::new) - .toList(); + .map(LottoNumber::new) + .toList(); return new Lotto(lottoNumbers); } @@ -40,13 +40,6 @@ private void validateDuplication(List numbers) { } } - public Rank matchRank(Lotto other) { - int matchCount = (int) numbers.stream() - .filter(other.numbers()::contains) - .count(); - return Rank.of(matchCount); - } - @Override public List numbers() { return List.copyOf(numbers); diff --git a/src/test/java/model/LottoTest.java b/src/test/java/model/LottoTest.java index 738df731..6274d05e 100644 --- a/src/test/java/model/LottoTest.java +++ b/src/test/java/model/LottoTest.java @@ -12,7 +12,7 @@ class LottoTest { @Nested - class 로또_생성_시{ + class 로또_생성_시 { @Test void 로또는_중복되지_않는_6개의_숫자로_이루어져있다() { @@ -37,7 +37,7 @@ class 로또_생성_시{ @Test void 로또는_중복되지_않는_6개의_숫자로_이루어져야_한다() { // given - List numbers = List.of(1, 2,3,4,5,5); + List numbers = List.of(1, 2, 3, 4, 5, 5); // when & then assertThatThrownBy(() -> Lotto.from(numbers)) @@ -57,21 +57,4 @@ class 로또_생성_시{ assertThat(lotto.numbers()).isSorted(); } } - - @Nested - class 로또_당첨_계산 { - - @Test - void 당첨_숫자에_따라_순위를_계산한다() { - // given - Lotto lotto = Lotto.from(List.of(1, 2, 3, 4, 5, 6)); - Lotto winningLotto = Lotto.from(List.of(1, 2, 3, 7, 8, 9)); - - // when - Rank rank = lotto.matchRank(winningLotto); - - // then - assertThat(rank).isEqualTo(Rank._5TH_PRIZE); - } - } } From 79d8b5f019115e2ab01ec5521c884b0a2827b14e Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:34:14 +0900 Subject: [PATCH 29/37] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/WinningLotto.java | 36 +++++++++++++++++++++++ src/test/java/model/WinningLottoTest.java | 36 +++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/main/java/model/WinningLotto.java create mode 100644 src/test/java/model/WinningLottoTest.java diff --git a/src/main/java/model/WinningLotto.java b/src/main/java/model/WinningLotto.java new file mode 100644 index 00000000..753b1fc3 --- /dev/null +++ b/src/main/java/model/WinningLotto.java @@ -0,0 +1,36 @@ +package model; + +import static model.Rank._2ND_PRIZE; + +import java.util.List; + +public record WinningLotto(Lotto lotto, LottoNumber bonusNumber) { + + public WinningLotto { + validate(lotto, bonusNumber); + } + + public static WinningLotto from(List numbers, int bonusNumber) { + return new WinningLotto(Lotto.from(numbers), new LottoNumber(bonusNumber)); + } + + private void validate(Lotto lotto, LottoNumber bonusNumber) { + validateDuplication(lotto, bonusNumber); + } + + private void validateDuplication(Lotto lotto, LottoNumber bonusNumber) { + if (lotto.numbers().contains(bonusNumber)) { + throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + } + + public Rank match(Lotto other) { + int matchCount = (int) other.numbers().stream() + .filter(lotto.numbers()::contains) + .count(); + if (matchCount == _2ND_PRIZE.matchCount()) { + return Rank.of(matchCount, other.numbers().contains(bonusNumber)); + } + return Rank.of(matchCount, false); + } +} diff --git a/src/test/java/model/WinningLottoTest.java b/src/test/java/model/WinningLottoTest.java new file mode 100644 index 00000000..e386a669 --- /dev/null +++ b/src/test/java/model/WinningLottoTest.java @@ -0,0 +1,36 @@ +package model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@SuppressWarnings("NonAsciiCharacters") +@DisplayNameGeneration(ReplaceUnderscores.class) +class WinningLottoTest { + + @ParameterizedTest + @MethodSource("lottoAndWinningLotto") + void 당첨_로또와_비교하여_순위를_결정한다(Lotto lotto, WinningLotto winningLotto, Rank expected) { + // given & when + final Rank actual = winningLotto.match(lotto); + + // then + assertThat(actual).isEqualTo(expected); + } + + static Stream lottoAndWinningLotto() { + return Stream.of( + Arguments.of(Lotto.from(List.of(1, 2, 3, 4, 5, 6)), WinningLotto.from(List.of(1, 2, 3, 4, 5, 6), 7), Rank._1ST_PRIZE), + Arguments.of(Lotto.from(List.of(1, 2, 3, 4, 5, 6)), WinningLotto.from(List.of(1, 2, 3, 4, 5, 8), 6), Rank._2ND_PRIZE), + Arguments.of(Lotto.from(List.of(1, 2, 3, 4, 5, 6)), WinningLotto.from(List.of(1, 2, 3, 4, 5, 8), 9), Rank._3RD_PRIZE), + Arguments.of(Lotto.from(List.of(1, 2, 3, 4, 5, 6)), WinningLotto.from(List.of(1, 2, 3, 4, 7, 8), 9), Rank._4TH_PRIZE), + Arguments.of(Lotto.from(List.of(1, 2, 3, 4, 5, 6)), WinningLotto.from(List.of(1, 2, 3, 7, 8, 9), 10), Rank._5TH_PRIZE), + Arguments.of(Lotto.from(List.of(1, 2, 3, 4, 5, 6)), WinningLotto.from(List.of(1, 2, 7, 8, 9, 10), 11), Rank._LAST_PRIZE)); + } +} From 9153d70293dc39155872c07392c90cb3433229ce Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:35:10 +0900 Subject: [PATCH 30/37] =?UTF-8?q?feat:=202=EB=93=B1=EC=83=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/Rank.java | 28 ++++++++++++++++++---------- src/test/java/model/RankTest.java | 21 +++++++++++---------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/main/java/model/Rank.java b/src/main/java/model/Rank.java index cf622085..48ed7f69 100644 --- a/src/main/java/model/Rank.java +++ b/src/main/java/model/Rank.java @@ -4,32 +4,40 @@ public enum Rank { - NONE(0, 0), - _5TH_PRIZE(3, 5_000), - _4TH_PRIZE(4, 50_000), - _3RD_PRIZE(5, 1_500_000), - _1ST_PRIZE(6, 2_000_000_000), + _LAST_PRIZE(0, false, 0), + _5TH_PRIZE(3, false, 5_000), + _4TH_PRIZE(4, false, 50_000), + _3RD_PRIZE(5, false, 1_500_000), + _2ND_PRIZE(5, true, 30_000_000), + _1ST_PRIZE(6, false, 2_000_000_000), ; private final int matchCount; + private final boolean containsBonus; private final int prize; - Rank(int matchCount, int prize) { + Rank(final int matchCount, final boolean containsBonus, final int prize) { this.matchCount = matchCount; + this.containsBonus = containsBonus; this.prize = prize; } - public static Rank of(int matchCount) { + public static Rank of(int matchCount, boolean matchBonus) { return Arrays.stream(Rank.values()) - .filter(rank -> rank.matchCount == matchCount) - .findFirst() - .orElse(NONE); + .filter(rank -> rank.matchCount == matchCount) + .filter(rank -> rank.containsBonus == matchBonus) + .findFirst() + .orElse(_LAST_PRIZE); } public int matchCount() { return matchCount; } + public boolean containsBonus() { + return containsBonus; + } + public int prize() { return prize; } diff --git a/src/test/java/model/RankTest.java b/src/test/java/model/RankTest.java index 6fab0d8a..d91a272e 100644 --- a/src/test/java/model/RankTest.java +++ b/src/test/java/model/RankTest.java @@ -12,9 +12,9 @@ class RankTest { @ParameterizedTest @MethodSource("matchCountWithRank") - void 당첨_숫자의_개수에_따라_순위가_결정된다(int matchCount, Rank rank) { + void 당첨_숫자의_개수와_보너스_볼_여부에_따라_순위가_결정된다(int matchCount, boolean matchBonus, Rank rank) { // when - Rank actual = Rank.of(matchCount); + Rank actual = Rank.of(matchCount, matchBonus); // then assertThat(actual).isEqualTo(rank); @@ -22,13 +22,14 @@ class RankTest { static Stream matchCountWithRank() { return Stream.of( - Arguments.of(6, Rank._1ST_PRIZE), - Arguments.of(5, Rank._3RD_PRIZE), - Arguments.of(4, Rank._4TH_PRIZE), - Arguments.of(3, Rank._5TH_PRIZE), - Arguments.of(2, Rank.NONE), - Arguments.of(1, Rank.NONE), - Arguments.of(1, Rank.NONE) - ); + Arguments.of(6, false, Rank._1ST_PRIZE), + Arguments.of(5, true, Rank._2ND_PRIZE), + Arguments.of(5, false, Rank._3RD_PRIZE), + Arguments.of(4, false, Rank._4TH_PRIZE), + Arguments.of(3, false, Rank._5TH_PRIZE), + Arguments.of(2, false, Rank._LAST_PRIZE), + Arguments.of(1, false, Rank._LAST_PRIZE), + Arguments.of(1, false, Rank._LAST_PRIZE) + ); } } From 5f25494043f08bda82ee86c404de24de38befb11 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:35:38 +0900 Subject: [PATCH 31/37] =?UTF-8?q?feat:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EB=B3=BC=20=EC=9E=85=EB=A0=A5=20=EB=A1=9C=EC=A7=81=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/view/InputView.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 97201e26..dc8e6fe5 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -20,4 +20,9 @@ public List readWinningNumbers() { .filter(it -> !it.isBlank()) .toList(); } + + public int readBonusNumber() { + System.out.println("보너스 볼을 입력해 주세요."); + return Integer.parseInt(SCANNER.nextLine()); + } } From 8255321b36610427b2b656e569d11d55a5505994 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:35:56 +0900 Subject: [PATCH 32/37] =?UTF-8?q?feat:=202=EB=93=B1=EC=83=81=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=ED=98=95=EC=8B=9D=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/view/OutputView.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index c7a78ca7..24297b66 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -8,14 +8,15 @@ public class OutputView { private static final String MATCH_RESULT_FORMAT = "%d개 일치 (%d원)- %d개"; + private static final String MATCH_RESULT_2ND_PRIZE_FORMAT = "%d개 일치, 보너스 볼 일치(%d원)- %d개"; private static final String PROFIT_RATE_FORMAT = "총 수익률은 %.2f입니다."; public void printLotto(List lottos) { printLinebreak(); System.out.println(lottos.size() + "개를 구매했습니다."); lottos.stream() - .map(LottoResponse::numbers) - .forEach(System.out::println); + .map(LottoResponse::numbers) + .forEach(System.out::println); } private void printLinebreak() { @@ -26,12 +27,16 @@ public void printResultStatistics(LottoStatisticsResponse response) { printLinebreak(); System.out.println("당첨 통계"); System.out.println("---------"); - response.countOfRank().keySet() - .stream() - .filter(rank -> rank != Rank.NONE) + response.countOfRank().keySet().stream() + .filter(rank -> rank != Rank._LAST_PRIZE) .sorted() .forEach(rank -> { int count = response.countOfRank().get(rank); + if (rank == Rank._2ND_PRIZE) { + System.out.printf(MATCH_RESULT_2ND_PRIZE_FORMAT, rank.matchCount(), rank.prize(), count); + printLinebreak(); + return; + } System.out.printf(MATCH_RESULT_FORMAT, rank.matchCount(), rank.prize(), count); printLinebreak(); }); From 92a593d64d254d95aa4baafbd6a3790b247ea577 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:36:23 +0900 Subject: [PATCH 33/37] =?UTF-8?q?style:=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/ResultStatistics.java | 6 +++--- src/test/java/model/ResultStatisticsTest.java | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/model/ResultStatistics.java b/src/main/java/model/ResultStatistics.java index 82db918a..bfc3f989 100644 --- a/src/main/java/model/ResultStatistics.java +++ b/src/main/java/model/ResultStatistics.java @@ -16,7 +16,7 @@ private ResultStatistics(Map ranksByCount, int purchaseAmount) { public static ResultStatistics from(List ranks) { Map ranksByCount = ranks.stream() - .collect(Collectors.toMap(rank -> rank, rank -> 1, Integer::sum)); + .collect(Collectors.toMap(rank -> rank, rank -> 1, Integer::sum)); return new ResultStatistics(ranksByCount, ranks.size() * LottoPrice.PRICE_UNIT); } @@ -26,8 +26,8 @@ public int countOf(Rank rank) { public double calculateProfitRate() { int totalWinningPrize = ranksByCount.entrySet().stream() - .mapToInt(entry -> entry.getKey().prize() * entry.getValue()) - .sum(); + .mapToInt(entry -> entry.getKey().prize() * entry.getValue()) + .sum(); return ((float) (totalWinningPrize * 100) / purchaseAmount) / 100.0; } } diff --git a/src/test/java/model/ResultStatisticsTest.java b/src/test/java/model/ResultStatisticsTest.java index af99115c..b8882062 100644 --- a/src/test/java/model/ResultStatisticsTest.java +++ b/src/test/java/model/ResultStatisticsTest.java @@ -14,8 +14,8 @@ class ResultStatisticsTest { List ranks = List.of( Rank._5TH_PRIZE, Rank._5TH_PRIZE, - Rank.NONE, - Rank.NONE, + Rank._LAST_PRIZE, + Rank._LAST_PRIZE, Rank._3RD_PRIZE ); @@ -24,7 +24,7 @@ class ResultStatisticsTest { // then assertThat(resultStatistics.countOf(Rank._5TH_PRIZE)).isEqualTo(2); - assertThat(resultStatistics.countOf(Rank.NONE)).isEqualTo(2); + assertThat(resultStatistics.countOf(Rank._LAST_PRIZE)).isEqualTo(2); assertThat(resultStatistics.countOf(Rank._3RD_PRIZE)).isEqualTo(1); } @@ -35,9 +35,9 @@ class ResultStatisticsTest { List ranks = List.of( Rank._5TH_PRIZE, Rank._5TH_PRIZE, - Rank.NONE, - Rank.NONE, - Rank.NONE + Rank._LAST_PRIZE, + Rank._LAST_PRIZE, + Rank._LAST_PRIZE ); ResultStatistics resultStatistics = ResultStatistics.from(ranks); From 8eff1b4f54e632b9b5a37f332e3c77cf0f2d5c20 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 01:36:49 +0900 Subject: [PATCH 34/37] =?UTF-8?q?feat:=202=EB=93=B1=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B3=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/LottoGame.java | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/model/LottoGame.java b/src/main/java/model/LottoGame.java index 568b8351..de1d7b35 100644 --- a/src/main/java/model/LottoGame.java +++ b/src/main/java/model/LottoGame.java @@ -3,9 +3,9 @@ import java.util.List; import java.util.stream.IntStream; import view.InputView; +import view.OutputView; import view.dto.LottoResponse; import view.dto.LottoStatisticsResponse; -import view.OutputView; public class LottoGame { @@ -20,7 +20,9 @@ public LottoGame(InputView inputView, OutputView outputView) { public void run() { List lottos = publishLotto(); printPublishedResult(lottos); - Lotto winningLotto = readWinningLotto(); + + WinningLotto winningLotto = readWinningLotto(); + ResultStatistics resultStatistics = calculateResultStatistics(lottos, winningLotto); LottoStatisticsResponse response = LottoStatisticsResponse.from(resultStatistics); outputView.printResultStatistics(response); @@ -30,8 +32,8 @@ private List publishLotto() { LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); int lottoAmount = price.divideByUnit(); return IntStream.range(0, lottoAmount) - .mapToObj(i -> RandomLottoGenerator.generateLotto()) - .toList(); + .mapToObj(i -> RandomLottoGenerator.generateLotto()) + .toList(); } private void printPublishedResult(List lottos) { @@ -39,17 +41,18 @@ private void printPublishedResult(List lottos) { outputView.printLotto(results); } - private Lotto readWinningLotto() { + private WinningLotto readWinningLotto() { List winningNumbers = inputView.readWinningNumbers().stream() - .map(LottoNumber::valueOf) - .toList(); - return new Lotto(winningNumbers); + .map(LottoNumber::valueOf) + .toList(); + final LottoNumber bonusNumber = new LottoNumber(inputView.readBonusNumber()); + return new WinningLotto(new Lotto(winningNumbers), bonusNumber); } - private ResultStatistics calculateResultStatistics(List lottos, Lotto winningLotto) { + private ResultStatistics calculateResultStatistics(List lottos, WinningLotto winningLotto) { List ranks = lottos.stream() - .map(lotto -> lotto.matchRank(winningLotto)) - .toList(); + .map(winningLotto::match) + .toList(); return ResultStatistics.from(ranks); } } From 4bafa4570c3bee86fbb449b011eec13efdbf4ba5 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 03:00:30 +0900 Subject: [PATCH 35/37] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index dc8e6fe5..149f194a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -13,12 +13,24 @@ public String readLottoPrice() { return SCANNER.nextLine(); } + public int readManualLottoCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + return Integer.parseInt(SCANNER.nextLine()); + } + + public List readManualLottoNumbers(int count) { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + return Stream.generate(SCANNER::nextLine) + .limit(count) + .toList(); + } + public List readWinningNumbers() { System.out.println("지난 주 당첨 번호를 입력해 주세요."); String input = SCANNER.nextLine(); return Stream.of(input.replace(" ", "").split(",")) - .filter(it -> !it.isBlank()) - .toList(); + .filter(it -> !it.isBlank()) + .toList(); } public int readBonusNumber() { From 018abada41564a6e733cdcacb1693e5b89cfa70f Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 03:00:49 +0900 Subject: [PATCH 36/37] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=20=EA=B5=AC=EB=A7=A4=20=ED=98=84=ED=99=A9=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 24297b66..475b12c1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -7,13 +7,15 @@ public class OutputView { + private static final String LOTTO_PURCHASED_FORMAT = "수동으로 %d장, 자동으로 %d개를 구매했습니다."; private static final String MATCH_RESULT_FORMAT = "%d개 일치 (%d원)- %d개"; private static final String MATCH_RESULT_2ND_PRIZE_FORMAT = "%d개 일치, 보너스 볼 일치(%d원)- %d개"; private static final String PROFIT_RATE_FORMAT = "총 수익률은 %.2f입니다."; - public void printLotto(List lottos) { + public void printLotto(List lottos, int manualLottoCount, int automaticLottoCount) { + printLinebreak(); + System.out.printf(LOTTO_PURCHASED_FORMAT, manualLottoCount, automaticLottoCount); printLinebreak(); - System.out.println(lottos.size() + "개를 구매했습니다."); lottos.stream() .map(LottoResponse::numbers) .forEach(System.out::println); From 660447fe78dc4222483e854c6253fb53d24cc537 Mon Sep 17 00:00:00 2001 From: kokodak Date: Mon, 6 May 2024 03:01:10 +0900 Subject: [PATCH 37/37] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EC=88=98?= =?UTF-8?q?=EB=8F=99=20=EA=B5=AC=EB=A7=A4=20=EB=A1=9C=EC=A7=81=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/model/LottoGame.java | 42 +++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/main/java/model/LottoGame.java b/src/main/java/model/LottoGame.java index de1d7b35..95c59941 100644 --- a/src/main/java/model/LottoGame.java +++ b/src/main/java/model/LottoGame.java @@ -1,7 +1,9 @@ package model; +import java.util.ArrayList; import java.util.List; import java.util.stream.IntStream; +import java.util.stream.Stream; import view.InputView; import view.OutputView; import view.dto.LottoResponse; @@ -18,8 +20,17 @@ public LottoGame(InputView inputView, OutputView outputView) { } public void run() { - List lottos = publishLotto(); - printPublishedResult(lottos); + LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); + int lottoAmount = price.divideByUnit(); + final int manualLottoCount = inputView.readManualLottoCount(); + final int automaticLottoCount = lottoAmount - manualLottoCount; + + if (lottoAmount < manualLottoCount) { + throw new IllegalArgumentException("로또 구매 금액이 부족합니다."); + } + + List lottos = publishLotto(manualLottoCount, automaticLottoCount); + printPublishedResult(lottos, manualLottoCount, automaticLottoCount); WinningLotto winningLotto = readWinningLotto(); @@ -28,17 +39,28 @@ public void run() { outputView.printResultStatistics(response); } - private List publishLotto() { - LottoPrice price = LottoPrice.valueOf(inputView.readLottoPrice()); - int lottoAmount = price.divideByUnit(); - return IntStream.range(0, lottoAmount) - .mapToObj(i -> RandomLottoGenerator.generateLotto()) - .toList(); + private List publishLotto(int manualLottoCount, int automaticLottoCount) { + List lottos = new ArrayList<>(); + + inputView.readManualLottoNumbers(manualLottoCount).stream() + .map(manualLottoNumber -> { + List numbers = Stream.of(manualLottoNumber.replace(" ", "").split(",")) + .map(Integer::parseInt) + .toList(); + return Lotto.from(numbers); + }) + .forEach(lottos::add); + + IntStream.range(0, automaticLottoCount) + .mapToObj(i -> RandomLottoGenerator.generateLotto()) + .forEach(lottos::add); + + return lottos; } - private void printPublishedResult(List lottos) { + private void printPublishedResult(List lottos, int manualLottoCount, int automaticLottoCount) { List results = lottos.stream().map(LottoResponse::from).toList(); - outputView.printLotto(results); + outputView.printLotto(results, manualLottoCount, automaticLottoCount); } private WinningLotto readWinningLotto() {