From af9f84e50709ed0707b1c9188e932465b2651fc9 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 19:35:11 +0900 Subject: [PATCH 01/26] =?UTF-8?q?feat=20:=20LottoApplication=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/LottoApplication.java | 5 +++++ 1 file changed, 5 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 0000000000..9cde742845 --- /dev/null +++ b/src/main/java/LottoApplication.java @@ -0,0 +1,5 @@ +public class LottoApplication { + public static void main(String[] args) { + + } +} From 7cba8fc3615d0fc7abfd99cb7b7a90262ae87154 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 19:49:10 +0900 Subject: [PATCH 02/26] =?UTF-8?q?feat=20:=20=EC=9A=94=EA=B5=AC=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20README.md=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9594b6c872..e3c8831382 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,16 @@ # java-lotto -로또 미션 저장소 +## 비즈니스 요구 사항 +- 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다. +- 로또 1장의 가격은 1000원이다. -# [미션 리드미](https://github.com/talmood/private-mission-README/tree/main/%EB%AF%B8%EC%85%98%203%20-%20%EB%A1%9C%EB%98%90) +## 구현 기능 목록 +- [ ] 구입 금액 사용자 입력을 받는다. +- [ ] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. +- [ ] 구입한 로또의 갯수를 출력한다. +- [ ] 구입한 로또의 목록을 생성한다. +- [ ] 구입한 로또의 목록을 출력한다. +- [ ] 지난 주 당첨 번호를 입력받는다. +- [ ] 보너스 볼을 입력 받는다. +- [ ] 당첨 결과를 판단한다. +- [ ] 당첨 결과를 출력한다. \ No newline at end of file From e87a84d4218bebec5a3284b0c60bbe74b741a1d1 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 19:50:39 +0900 Subject: [PATCH 03/26] =?UTF-8?q?feat=20:=20InputView=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/view/ConsoleInputView.java | 18 ++++++++++++++++++ src/main/java/view/InputView.java | 10 ++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/main/java/view/ConsoleInputView.java create mode 100644 src/main/java/view/InputView.java diff --git a/src/main/java/view/ConsoleInputView.java b/src/main/java/view/ConsoleInputView.java new file mode 100644 index 0000000000..27982be81c --- /dev/null +++ b/src/main/java/view/ConsoleInputView.java @@ -0,0 +1,18 @@ +package view; + +public class ConsoleInputView implements InputView{ + @Override + public void inputPurchaseAmount() { + + } + + @Override + public void inputWinningNumbers() { + + } + + @Override + public void inputBonusNumber() { + + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000000..59498c928b --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,10 @@ +package view; + +public interface InputView { + + void inputPurchaseAmount(); + + void inputWinningNumbers(); + + void inputBonusNumber(); +} From 1ce5340ca79fee9dff104203c77a1a3339b42d5e Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 19:53:11 +0900 Subject: [PATCH 04/26] =?UTF-8?q?feat=20:=20PurchaseInput.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/ConsoleInputView.java | 5 ++++- src/main/java/view/InputView.java | 4 +++- src/main/java/view/dto/PurchaseInput.java | 10 ++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 src/main/java/view/dto/PurchaseInput.java diff --git a/src/main/java/view/ConsoleInputView.java b/src/main/java/view/ConsoleInputView.java index 27982be81c..57dd1d4466 100644 --- a/src/main/java/view/ConsoleInputView.java +++ b/src/main/java/view/ConsoleInputView.java @@ -1,9 +1,12 @@ package view; +import view.dto.PurchaseInput; + public class ConsoleInputView implements InputView{ @Override - public void inputPurchaseAmount() { + public PurchaseInput inputPurchaseAmount() { + return null; } @Override diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 59498c928b..faf0d812ff 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,8 +1,10 @@ package view; +import view.dto.PurchaseInput; + public interface InputView { - void inputPurchaseAmount(); + PurchaseInput inputPurchaseAmount(); void inputWinningNumbers(); diff --git a/src/main/java/view/dto/PurchaseInput.java b/src/main/java/view/dto/PurchaseInput.java new file mode 100644 index 0000000000..fa8c4b987d --- /dev/null +++ b/src/main/java/view/dto/PurchaseInput.java @@ -0,0 +1,10 @@ +package view.dto; + +public class PurchaseInput { + + private final int purchaseAmount; + + public PurchaseInput(int purchaseAmount) { + this.purchaseAmount = purchaseAmount; + } +} From a8479d12ff4b13753aefc68749a8b63ceccab60f Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 19:55:45 +0900 Subject: [PATCH 05/26] =?UTF-8?q?feat=20:=20Console=20=EC=9C=A0=ED=8B=B8?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4=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/util/Console.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/util/Console.java diff --git a/src/main/java/util/Console.java b/src/main/java/util/Console.java new file mode 100644 index 0000000000..27dd27ac1b --- /dev/null +++ b/src/main/java/util/Console.java @@ -0,0 +1,18 @@ +package util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public abstract class Console { + + private static final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); + + public static String readLine() { + try { + return bufferedReader.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} From 22da92c44d59f73e8b89dd968a0f2d145409f860 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 20:14:54 +0900 Subject: [PATCH 06/26] =?UTF-8?q?feat=20:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EA=B5=AC=EC=9E=85=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- src/main/java/LottoApplication.java | 1 + .../java/exception/InvalidInputException.java | 13 ++++++++++++ src/main/java/exception/code/ErrorCode.java | 16 +++++++++++++++ src/main/java/util/StringUtils.java | 12 +++++++++++ src/main/java/view/ConsoleInputView.java | 20 ++++++++++++++++++- 6 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/main/java/exception/InvalidInputException.java create mode 100644 src/main/java/exception/code/ErrorCode.java create mode 100644 src/main/java/util/StringUtils.java diff --git a/README.md b/README.md index e3c8831382..ffa0375402 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ ## 비즈니스 요구 사항 - 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다. - 로또 1장의 가격은 1000원이다. +- 로또는 1개이상 구매해야한다. ## 구현 기능 목록 -- [ ] 구입 금액 사용자 입력을 받는다. +- [x] 구입 금액 사용자 입력을 받는다. - [ ] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. - [ ] 구입한 로또의 갯수를 출력한다. - [ ] 구입한 로또의 목록을 생성한다. diff --git a/src/main/java/LottoApplication.java b/src/main/java/LottoApplication.java index 9cde742845..346f62a540 100644 --- a/src/main/java/LottoApplication.java +++ b/src/main/java/LottoApplication.java @@ -3,3 +3,4 @@ public static void main(String[] args) { } } + diff --git a/src/main/java/exception/InvalidInputException.java b/src/main/java/exception/InvalidInputException.java new file mode 100644 index 0000000000..e5cd2cd6d3 --- /dev/null +++ b/src/main/java/exception/InvalidInputException.java @@ -0,0 +1,13 @@ +package exception; + +import exception.code.ErrorCode; + +public class InvalidInputException extends IllegalArgumentException { + + private final ErrorCode errorCode; + + public InvalidInputException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } +} diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java new file mode 100644 index 0000000000..de10202397 --- /dev/null +++ b/src/main/java/exception/code/ErrorCode.java @@ -0,0 +1,16 @@ +package exception.code; + +public enum ErrorCode { + + ONLY_NUMBER_INPUT("숫자인 입력값만 허용됩니다."); + + private final String message; + + ErrorCode(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/util/StringUtils.java b/src/main/java/util/StringUtils.java new file mode 100644 index 0000000000..920ec64e23 --- /dev/null +++ b/src/main/java/util/StringUtils.java @@ -0,0 +1,12 @@ +package util; + +import java.util.Objects; + +public abstract class StringUtils { + + private static final String NUMERIC_PATTERN = "[+-]?\\d*(\\.\\d+)?"; + + public static boolean isNumeric(String str) { + return Objects.nonNull(str) && str.matches(NUMERIC_PATTERN); + } +} diff --git a/src/main/java/view/ConsoleInputView.java b/src/main/java/view/ConsoleInputView.java index 57dd1d4466..3e29f08a01 100644 --- a/src/main/java/view/ConsoleInputView.java +++ b/src/main/java/view/ConsoleInputView.java @@ -1,12 +1,24 @@ package view; +import exception.InvalidInputException; +import exception.code.ErrorCode; +import util.Console; +import util.StringUtils; import view.dto.PurchaseInput; +import static exception.code.ErrorCode.*; + public class ConsoleInputView implements InputView{ + + private static final String PURCHASE_AMOUNT_NAVIGATION = "구입금액을 입력해 주세요."; + @Override public PurchaseInput inputPurchaseAmount() { + System.out.println(PURCHASE_AMOUNT_NAVIGATION); + String input = Console.readLine(); + this.validateNumber(input); - return null; + return new PurchaseInput(Integer.parseInt(input)); } @Override @@ -18,4 +30,10 @@ public void inputWinningNumbers() { public void inputBonusNumber() { } + + private void validateNumber(String input) { + if(!StringUtils.isNumeric(input)) { + throw new InvalidInputException(ONLY_NUMBER_INPUT); + } + } } From 7f2caba7f3e2ce6fc4ba5be8d09cfac63421cfa7 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 20:17:21 +0900 Subject: [PATCH 07/26] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EC=8B=9C?= =?UTF-8?q?=EB=AE=AC=EB=A0=88=EC=9D=B4=ED=84=B0=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/LottoApplication.java | 4 +++- src/main/java/controller/LottoSimulator.java | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/main/java/controller/LottoSimulator.java diff --git a/src/main/java/LottoApplication.java b/src/main/java/LottoApplication.java index 346f62a540..d272a92208 100644 --- a/src/main/java/LottoApplication.java +++ b/src/main/java/LottoApplication.java @@ -1,6 +1,8 @@ +import controller.LottoSimulator; + public class LottoApplication { public static void main(String[] args) { - + new LottoSimulator().run(); } } diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java new file mode 100644 index 0000000000..6345375512 --- /dev/null +++ b/src/main/java/controller/LottoSimulator.java @@ -0,0 +1,8 @@ +package controller; + +public class LottoSimulator { + + public void run() { + + } +} From 8fdc6c41ec84ea9e38f3b08d6b5fe9f5a64e38d4 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 20:32:07 +0900 Subject: [PATCH 08/26] =?UTF-8?q?feat=20:=20=EA=B5=AC=EC=9E=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=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/controller/LottoSimulator.java | 8 +++++ src/main/java/domain/PurchaseAmount.java | 30 +++++++++++++++++++ .../exception/DomainValidationException.java | 13 ++++++++ src/main/java/exception/code/ErrorCode.java | 3 +- src/main/java/view/dto/PurchaseInput.java | 6 ++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/PurchaseAmount.java create mode 100644 src/main/java/exception/DomainValidationException.java diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 6345375512..a6a0f71534 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -1,8 +1,16 @@ package controller; +import domain.PurchaseAmount; +import view.ConsoleInputView; +import view.InputView; +import view.dto.PurchaseInput; + public class LottoSimulator { public void run() { + InputView inputView = new ConsoleInputView(); + PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); + PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); } } diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java new file mode 100644 index 0000000000..a39ffb59e0 --- /dev/null +++ b/src/main/java/domain/PurchaseAmount.java @@ -0,0 +1,30 @@ +package domain; + +import exception.DomainValidationException; + +import static exception.code.ErrorCode.*; + +public class PurchaseAmount { + + private static final int LOTTO_PRICE = 1000; + + private final int purchaseAmount; + + private final int purchaseCount; + + private PurchaseAmount(int purchaseAmount, int purchaseCount) { + this.validatePurchaseCount(purchaseCount); + this.purchaseAmount = purchaseAmount; + this.purchaseCount = purchaseCount; + } + + public static PurchaseAmount create(int purchaseAmount) { + return new PurchaseAmount(purchaseAmount, purchaseAmount/LOTTO_PRICE); + } + + private void validatePurchaseCount(int purchaseCount) { + if(purchaseCount < 1) { + throw new DomainValidationException(PURCHASE_COUNT_BIGGER_THAN_ZERO); + } + } +} diff --git a/src/main/java/exception/DomainValidationException.java b/src/main/java/exception/DomainValidationException.java new file mode 100644 index 0000000000..a4f96f652c --- /dev/null +++ b/src/main/java/exception/DomainValidationException.java @@ -0,0 +1,13 @@ +package exception; + +import exception.code.ErrorCode; + +public class DomainValidationException extends IllegalArgumentException { + + private final ErrorCode errorCode; + + public DomainValidationException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } +} diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index de10202397..6b77619b5a 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -2,7 +2,8 @@ public enum ErrorCode { - ONLY_NUMBER_INPUT("숫자인 입력값만 허용됩니다."); + ONLY_NUMBER_INPUT("숫자인 입력값만 허용됩니다."), + PURCHASE_COUNT_BIGGER_THAN_ZERO("구입 갯수는 1개이상이어야 합니다."); private final String message; diff --git a/src/main/java/view/dto/PurchaseInput.java b/src/main/java/view/dto/PurchaseInput.java index fa8c4b987d..b23dc6c060 100644 --- a/src/main/java/view/dto/PurchaseInput.java +++ b/src/main/java/view/dto/PurchaseInput.java @@ -1,5 +1,7 @@ package view.dto; +import domain.PurchaseAmount; + public class PurchaseInput { private final int purchaseAmount; @@ -7,4 +9,8 @@ public class PurchaseInput { public PurchaseInput(int purchaseAmount) { this.purchaseAmount = purchaseAmount; } + + public PurchaseAmount toPurchaseAmount() { + return PurchaseAmount.create(purchaseAmount); + } } From 5b6eb3559b7f595680665b13685213c1f77727f7 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 20:33:27 +0900 Subject: [PATCH 09/26] =?UTF-8?q?refactor=20:=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=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/main/java/controller/LottoSimulator.java | 7 ++++--- src/main/java/view/{ => input}/ConsoleInputView.java | 5 ++--- src/main/java/view/{ => input}/InputView.java | 4 ++-- src/main/java/view/{ => input}/dto/PurchaseInput.java | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) rename src/main/java/view/{ => input}/ConsoleInputView.java (91%) rename src/main/java/view/{ => input}/InputView.java (70%) rename src/main/java/view/{ => input}/dto/PurchaseInput.java (92%) diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index a6a0f71534..3cd6752a40 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -1,9 +1,9 @@ package controller; import domain.PurchaseAmount; -import view.ConsoleInputView; -import view.InputView; -import view.dto.PurchaseInput; +import view.input.ConsoleInputView; +import view.input.InputView; +import view.input.dto.PurchaseInput; public class LottoSimulator { @@ -12,5 +12,6 @@ public void run() { PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); + } } diff --git a/src/main/java/view/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java similarity index 91% rename from src/main/java/view/ConsoleInputView.java rename to src/main/java/view/input/ConsoleInputView.java index 3e29f08a01..1a956d0339 100644 --- a/src/main/java/view/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -1,10 +1,9 @@ -package view; +package view.input; import exception.InvalidInputException; -import exception.code.ErrorCode; import util.Console; import util.StringUtils; -import view.dto.PurchaseInput; +import view.input.dto.PurchaseInput; import static exception.code.ErrorCode.*; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/input/InputView.java similarity index 70% rename from src/main/java/view/InputView.java rename to src/main/java/view/input/InputView.java index faf0d812ff..24a1aee575 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/input/InputView.java @@ -1,6 +1,6 @@ -package view; +package view.input; -import view.dto.PurchaseInput; +import view.input.dto.PurchaseInput; public interface InputView { diff --git a/src/main/java/view/dto/PurchaseInput.java b/src/main/java/view/input/dto/PurchaseInput.java similarity index 92% rename from src/main/java/view/dto/PurchaseInput.java rename to src/main/java/view/input/dto/PurchaseInput.java index b23dc6c060..78b1305b64 100644 --- a/src/main/java/view/dto/PurchaseInput.java +++ b/src/main/java/view/input/dto/PurchaseInput.java @@ -1,4 +1,4 @@ -package view.dto; +package view.input.dto; import domain.PurchaseAmount; From d1e16c665023eff14bd492b891e18c756e08d3e9 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 20:39:16 +0900 Subject: [PATCH 10/26] =?UTF-8?q?feat=20:=20=EA=B5=AC=EC=9E=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20Output=EA=B0=9D=EC=B2=B4=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/controller/LottoSimulator.java | 2 ++ src/main/java/domain/PurchaseAmount.java | 5 +++++ src/main/java/view/output/dto/PurchaseOutput.java | 10 ++++++++++ 3 files changed, 17 insertions(+) create mode 100644 src/main/java/view/output/dto/PurchaseOutput.java diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 3cd6752a40..d9e49a97b0 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -4,6 +4,7 @@ import view.input.ConsoleInputView; import view.input.InputView; import view.input.dto.PurchaseInput; +import view.output.dto.PurchaseOutput; public class LottoSimulator { @@ -11,6 +12,7 @@ public void run() { InputView inputView = new ConsoleInputView(); PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); + PurchaseOutput purchaseOutput = purchaseAmount.toPurchaseOutput(); } diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index a39ffb59e0..cd5a725e4f 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -1,6 +1,7 @@ package domain; import exception.DomainValidationException; +import view.output.dto.PurchaseOutput; import static exception.code.ErrorCode.*; @@ -27,4 +28,8 @@ private void validatePurchaseCount(int purchaseCount) { throw new DomainValidationException(PURCHASE_COUNT_BIGGER_THAN_ZERO); } } + + public PurchaseOutput toPurchaseOutput() { + return new PurchaseOutput(this.purchaseCount); + } } diff --git a/src/main/java/view/output/dto/PurchaseOutput.java b/src/main/java/view/output/dto/PurchaseOutput.java new file mode 100644 index 0000000000..85ee8a680a --- /dev/null +++ b/src/main/java/view/output/dto/PurchaseOutput.java @@ -0,0 +1,10 @@ +package view.output.dto; + +public class PurchaseOutput { + + private final int purchaseCount; + + public PurchaseOutput(int purchaseCount) { + this.purchaseCount = purchaseCount; + } +} From 491070d7e33db115060b963199376aff0e106483 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 20:50:22 +0900 Subject: [PATCH 11/26] =?UTF-8?q?feat=20:=20=EA=B5=AC=EC=9E=85=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/java/controller/LottoSimulator.java | 5 ++++ .../java/view/output/ConsoleOutputView.java | 23 +++++++++++++++++++ src/main/java/view/output/OutputView.java | 12 ++++++++++ .../java/view/output/dto/PurchaseOutput.java | 4 ++++ 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/main/java/view/output/ConsoleOutputView.java create mode 100644 src/main/java/view/output/OutputView.java diff --git a/README.md b/README.md index ffa0375402..d7660543d0 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ ## 구현 기능 목록 - [x] 구입 금액 사용자 입력을 받는다. -- [ ] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. -- [ ] 구입한 로또의 갯수를 출력한다. +- [x] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. +- [x] 구입한 로또의 갯수를 출력한다. - [ ] 구입한 로또의 목록을 생성한다. - [ ] 구입한 로또의 목록을 출력한다. - [ ] 지난 주 당첨 번호를 입력받는다. diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index d9e49a97b0..d367947d8c 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -4,15 +4,20 @@ import view.input.ConsoleInputView; import view.input.InputView; import view.input.dto.PurchaseInput; +import view.output.ConsoleOutputView; +import view.output.OutputView; import view.output.dto.PurchaseOutput; public class LottoSimulator { public void run() { InputView inputView = new ConsoleInputView(); + OutputView outputView = new ConsoleOutputView(); + PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); PurchaseOutput purchaseOutput = purchaseAmount.toPurchaseOutput(); + outputView.viewPurchaseAmount(purchaseOutput); } diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java new file mode 100644 index 0000000000..03e50a8e1c --- /dev/null +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -0,0 +1,23 @@ +package view.output; + +import view.output.dto.PurchaseOutput; + +public class ConsoleOutputView implements OutputView{ + + private static final String PURCHASE_COUNT_NAVIGATION = "%d개를 구매했습니다."; + + @Override + public void viewPurchaseAmount(PurchaseOutput purchaseOutput) { + System.out.printf((PURCHASE_COUNT_NAVIGATION) + "%n", purchaseOutput.fetchPurchaseCount()); + } + + @Override + public void viewLotto() { + + } + + @Override + public void viewWinningResult() { + + } +} diff --git a/src/main/java/view/output/OutputView.java b/src/main/java/view/output/OutputView.java new file mode 100644 index 0000000000..bb15dd0f08 --- /dev/null +++ b/src/main/java/view/output/OutputView.java @@ -0,0 +1,12 @@ +package view.output; + +import view.output.dto.PurchaseOutput; + +public interface OutputView { + + void viewPurchaseAmount(PurchaseOutput purchaseOutput); + + void viewLotto(); + + void viewWinningResult(); +} diff --git a/src/main/java/view/output/dto/PurchaseOutput.java b/src/main/java/view/output/dto/PurchaseOutput.java index 85ee8a680a..c1681384c3 100644 --- a/src/main/java/view/output/dto/PurchaseOutput.java +++ b/src/main/java/view/output/dto/PurchaseOutput.java @@ -7,4 +7,8 @@ public class PurchaseOutput { public PurchaseOutput(int purchaseCount) { this.purchaseCount = purchaseCount; } + + public int fetchPurchaseCount() { + return this.purchaseCount; + } } From 15168f2b3b8adb67cff37a7c2cd3b448e1dac95e Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 21:05:57 +0900 Subject: [PATCH 12/26] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=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/controller/LottoSimulator.java | 1 + src/main/java/domain/Lotto.java | 40 +++++++++++++++++++ src/main/java/domain/PurchaseAmount.java | 2 +- .../exception/DomainValidationException.java | 4 +- .../java/exception/InvalidInputException.java | 4 +- src/main/java/exception/code/ErrorCode.java | 15 ++----- .../java/view/input/ConsoleInputView.java | 2 +- 7 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 src/main/java/domain/Lotto.java diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index d367947d8c..4170e0a078 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -20,5 +20,6 @@ public void run() { outputView.viewPurchaseAmount(purchaseOutput); + } } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java new file mode 100644 index 0000000000..cfeaac2764 --- /dev/null +++ b/src/main/java/domain/Lotto.java @@ -0,0 +1,40 @@ +package domain; + +import exception.DomainValidationException; + +import java.util.List; + +import static exception.code.ErrorCode.*; + +public class Lotto { + + private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 0; + private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; + + + private final List lottoNumbers; + + + public Lotto(List lottoNumbers) { + this.validateNumberRange(); + this.lottoNumbers = lottoNumbers; + } + + private void validateNumberRange() { + if(!isAllLottoNumberRange()) { + throw new DomainValidationException( + INVALID_LOTTO_NUMBER_RANGE, + String.format("로또 번호의 범위는 %d부터 %d까지 입니다.", MIN_LOTTO_NUMBER_INCLUSIVE, MAX_LOTTO_NUMBER_INCLUSIVE) + ); + }; + } + + private boolean isAllLottoNumberRange() { + return this.lottoNumbers.stream() + .allMatch(this::isLottoNumberRange); + } + + private boolean isLottoNumberRange(Integer number) { + return number >= MIN_LOTTO_NUMBER_INCLUSIVE && number <= MAX_LOTTO_NUMBER_INCLUSIVE; + } +} diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index cd5a725e4f..2ca8a2c4f8 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -25,7 +25,7 @@ public static PurchaseAmount create(int purchaseAmount) { private void validatePurchaseCount(int purchaseCount) { if(purchaseCount < 1) { - throw new DomainValidationException(PURCHASE_COUNT_BIGGER_THAN_ZERO); + throw new DomainValidationException(PURCHASE_COUNT_BIGGER_THAN_ZERO, "구입 갯수는 1개이상이어야 합니다."); } } diff --git a/src/main/java/exception/DomainValidationException.java b/src/main/java/exception/DomainValidationException.java index a4f96f652c..cc0f270fe5 100644 --- a/src/main/java/exception/DomainValidationException.java +++ b/src/main/java/exception/DomainValidationException.java @@ -6,8 +6,8 @@ public class DomainValidationException extends IllegalArgumentException { private final ErrorCode errorCode; - public DomainValidationException(ErrorCode errorCode) { - super(errorCode.getMessage()); + public DomainValidationException(ErrorCode errorCode, String message) { + super(message); this.errorCode = errorCode; } } diff --git a/src/main/java/exception/InvalidInputException.java b/src/main/java/exception/InvalidInputException.java index e5cd2cd6d3..8056a08d87 100644 --- a/src/main/java/exception/InvalidInputException.java +++ b/src/main/java/exception/InvalidInputException.java @@ -6,8 +6,8 @@ public class InvalidInputException extends IllegalArgumentException { private final ErrorCode errorCode; - public InvalidInputException(ErrorCode errorCode) { - super(errorCode.getMessage()); + public InvalidInputException(ErrorCode errorCode, String message) { + super(message); this.errorCode = errorCode; } } diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index 6b77619b5a..b0d7c195f0 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -2,16 +2,7 @@ public enum ErrorCode { - ONLY_NUMBER_INPUT("숫자인 입력값만 허용됩니다."), - PURCHASE_COUNT_BIGGER_THAN_ZERO("구입 갯수는 1개이상이어야 합니다."); - - private final String message; - - ErrorCode(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } + ONLY_NUMBER_INPUT, + PURCHASE_COUNT_BIGGER_THAN_ZERO, + INVALID_LOTTO_NUMBER_RANGE } diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index 1a956d0339..77785119e2 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -32,7 +32,7 @@ public void inputBonusNumber() { private void validateNumber(String input) { if(!StringUtils.isNumeric(input)) { - throw new InvalidInputException(ONLY_NUMBER_INPUT); + throw new InvalidInputException(ONLY_NUMBER_INPUT, "숫자인 입력값만 허용됩니다."); } } } From f95bdd668e2276aecf6f2df455c024be47d3281d Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 21:40:54 +0900 Subject: [PATCH 13/26] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/controller/LottoSimulator.java | 6 ++++ src/main/java/domain/Lotto.java | 18 ++++++---- src/main/java/domain/Lottos.java | 17 +++++++++ src/main/java/domain/LottosGenerator.java | 38 ++++++++++++++++++++ src/main/java/domain/PurchaseAmount.java | 4 +++ 6 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/main/java/domain/Lottos.java create mode 100644 src/main/java/domain/LottosGenerator.java diff --git a/README.md b/README.md index d7660543d0..6f34156a39 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - [x] 구입 금액 사용자 입력을 받는다. - [x] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. - [x] 구입한 로또의 갯수를 출력한다. -- [ ] 구입한 로또의 목록을 생성한다. +- [x] 구입한 로또의 목록을 생성한다. - [ ] 구입한 로또의 목록을 출력한다. - [ ] 지난 주 당첨 번호를 입력받는다. - [ ] 보너스 볼을 입력 받는다. diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 4170e0a078..23af881142 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -1,5 +1,7 @@ package controller; +import domain.Lottos; +import domain.LottosGenerator; import domain.PurchaseAmount; import view.input.ConsoleInputView; import view.input.InputView; @@ -16,9 +18,13 @@ public void run() { PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); + PurchaseOutput purchaseOutput = purchaseAmount.toPurchaseOutput(); outputView.viewPurchaseAmount(purchaseOutput); + LottosGenerator lottosGenerator = new LottosGenerator(purchaseAmount); + Lottos lottos = lottosGenerator.generate() + } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index cfeaac2764..e1d5230a77 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -8,20 +8,24 @@ public class Lotto { - private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 0; + private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; private final List lottoNumbers; - public Lotto(List lottoNumbers) { - this.validateNumberRange(); + private Lotto(List lottoNumbers) { + this.validateNumberRange(lottoNumbers); this.lottoNumbers = lottoNumbers; } - private void validateNumberRange() { - if(!isAllLottoNumberRange()) { + public static Lotto create(List lottoNumbers) { + return new Lotto(lottoNumbers); + } + + private void validateNumberRange(List lottoNumbers) { + if(!isAllLottoNumberRange(lottoNumbers)) { throw new DomainValidationException( INVALID_LOTTO_NUMBER_RANGE, String.format("로또 번호의 범위는 %d부터 %d까지 입니다.", MIN_LOTTO_NUMBER_INCLUSIVE, MAX_LOTTO_NUMBER_INCLUSIVE) @@ -29,8 +33,8 @@ private void validateNumberRange() { }; } - private boolean isAllLottoNumberRange() { - return this.lottoNumbers.stream() + private boolean isAllLottoNumberRange(List lottoNumbers) { + return lottoNumbers.stream() .allMatch(this::isLottoNumberRange); } diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java new file mode 100644 index 0000000000..b58def948e --- /dev/null +++ b/src/main/java/domain/Lottos.java @@ -0,0 +1,17 @@ +package domain; + +import java.util.List; + +public class Lottos { + + private final List lottos; + + private Lottos(List lottos) { + this.lottos = lottos; + } + + public static Lottos create(List lottos) { + return new Lottos(lottos); + } + +} diff --git a/src/main/java/domain/LottosGenerator.java b/src/main/java/domain/LottosGenerator.java new file mode 100644 index 0000000000..131d7c35bf --- /dev/null +++ b/src/main/java/domain/LottosGenerator.java @@ -0,0 +1,38 @@ +package domain; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class LottosGenerator { + + private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; + private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; + private static final int LOTTO_NUMBERS_SIZE = 6; + + private static final List totalLottoNumbers = + IntStream.range(MIN_LOTTO_NUMBER_INCLUSIVE, MAX_LOTTO_NUMBER_INCLUSIVE) + .boxed() + .collect(Collectors.toList()); + + private final PurchaseAmount purchaseAmount; + + public LottosGenerator(PurchaseAmount purchaseAmount) { + this.purchaseAmount = purchaseAmount; + } + + public Lottos generate() { + List lottos = IntStream.range(0, this.purchaseAmount.fetchPurchaseCount()) + .mapToObj(count -> this.generateLotto()) + .collect(Collectors.toList()); + + return Lottos.create(lottos); + } + + private Lotto generateLotto() { + Collections.shuffle(totalLottoNumbers); + List numbers = List.copyOf(totalLottoNumbers.subList(0, LOTTO_NUMBERS_SIZE)); + return Lotto.create(numbers); + } +} diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index 2ca8a2c4f8..417f0127a6 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -32,4 +32,8 @@ private void validatePurchaseCount(int purchaseCount) { public PurchaseOutput toPurchaseOutput() { return new PurchaseOutput(this.purchaseCount); } + + public int fetchPurchaseCount() { + return this.purchaseCount; + } } From 7e4cefa9333b8a3bd38637b71887bd960e55d4f5 Mon Sep 17 00:00:00 2001 From: kilian Date: Wed, 15 May 2024 21:54:18 +0900 Subject: [PATCH 14/26] =?UTF-8?q?feat=20:=20=EA=B5=AC=EC=9E=85=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1,=20=EA=B5=AC=EC=9E=85=20=EA=B0=AF=EC=88=98=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/controller/LottoSimulator.java | 13 ++++--- src/main/java/domain/LottosGenerator.java | 8 ++--- src/main/java/domain/PurchaseAmount.java | 28 +++++---------- src/main/java/domain/PurchaseCount.java | 34 +++++++++++++++++++ .../java/domain/PurchaseCountCalculator.java | 16 +++++++++ src/main/java/exception/code/ErrorCode.java | 5 +-- 6 files changed, 72 insertions(+), 32 deletions(-) create mode 100644 src/main/java/domain/PurchaseCount.java create mode 100644 src/main/java/domain/PurchaseCountCalculator.java diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 23af881142..c4a09e6831 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -1,8 +1,6 @@ package controller; -import domain.Lottos; -import domain.LottosGenerator; -import domain.PurchaseAmount; +import domain.*; import view.input.ConsoleInputView; import view.input.InputView; import view.input.dto.PurchaseInput; @@ -18,12 +16,13 @@ public void run() { PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); - - PurchaseOutput purchaseOutput = purchaseAmount.toPurchaseOutput(); + PurchaseCountCalculator purchaseCountCalculator = new PurchaseCountCalculator(purchaseAmount); + PurchaseCount purchaseCount = purchaseCountCalculator.calculate(); + PurchaseOutput purchaseOutput = purchaseCount.toPurchaseOutput(); outputView.viewPurchaseAmount(purchaseOutput); - LottosGenerator lottosGenerator = new LottosGenerator(purchaseAmount); - Lottos lottos = lottosGenerator.generate() + LottosGenerator lottosGenerator = new LottosGenerator(purchaseCount); + Lottos lottos = lottosGenerator.generate(); diff --git a/src/main/java/domain/LottosGenerator.java b/src/main/java/domain/LottosGenerator.java index 131d7c35bf..29919ae02d 100644 --- a/src/main/java/domain/LottosGenerator.java +++ b/src/main/java/domain/LottosGenerator.java @@ -16,14 +16,14 @@ public class LottosGenerator { .boxed() .collect(Collectors.toList()); - private final PurchaseAmount purchaseAmount; + private final PurchaseCount purchaseCount; - public LottosGenerator(PurchaseAmount purchaseAmount) { - this.purchaseAmount = purchaseAmount; + public LottosGenerator(PurchaseCount purchaseCount) { + this.purchaseCount = purchaseCount; } public Lottos generate() { - List lottos = IntStream.range(0, this.purchaseAmount.fetchPurchaseCount()) + List lottos = IntStream.range(0, this.purchaseCount.fetchPurchaseCount()) .mapToObj(count -> this.generateLotto()) .collect(Collectors.toList()); diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index 417f0127a6..2f4648b8ef 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -1,39 +1,29 @@ package domain; import exception.DomainValidationException; -import view.output.dto.PurchaseOutput; import static exception.code.ErrorCode.*; public class PurchaseAmount { - private static final int LOTTO_PRICE = 1000; - private final int purchaseAmount; - private final int purchaseCount; - - private PurchaseAmount(int purchaseAmount, int purchaseCount) { - this.validatePurchaseCount(purchaseCount); + private PurchaseAmount(int purchaseAmount) { + this.validateAmount(purchaseAmount); this.purchaseAmount = purchaseAmount; - this.purchaseCount = purchaseCount; } public static PurchaseAmount create(int purchaseAmount) { - return new PurchaseAmount(purchaseAmount, purchaseAmount/LOTTO_PRICE); - } - - private void validatePurchaseCount(int purchaseCount) { - if(purchaseCount < 1) { - throw new DomainValidationException(PURCHASE_COUNT_BIGGER_THAN_ZERO, "구입 갯수는 1개이상이어야 합니다."); - } + return new PurchaseAmount(purchaseAmount); } - public PurchaseOutput toPurchaseOutput() { - return new PurchaseOutput(this.purchaseCount); + public int fetchPurchaseAmount() { + return this.purchaseAmount; } - public int fetchPurchaseCount() { - return this.purchaseCount; + private void validateAmount(int purchaseAmount) { + if(purchaseAmount <= 0) { + throw new DomainValidationException(INVALID_PURCHASE_AMOUNT, "구입 금액은 0보다 커야합니다."); + } } } diff --git a/src/main/java/domain/PurchaseCount.java b/src/main/java/domain/PurchaseCount.java new file mode 100644 index 0000000000..416617e828 --- /dev/null +++ b/src/main/java/domain/PurchaseCount.java @@ -0,0 +1,34 @@ +package domain; + +import exception.DomainValidationException; +import view.output.dto.PurchaseOutput; + +import static exception.code.ErrorCode.INVALID_PURCHASE_COUNT; + +public class PurchaseCount { + + private final int purchaseCount; + + private PurchaseCount(int purchaseCount) { + this.validatePurchaseCount(purchaseCount); + this.purchaseCount = purchaseCount; + } + + public static PurchaseCount create(int purchaseCount) { + return new PurchaseCount(purchaseCount); + } + + private void validatePurchaseCount(int purchaseCount) { + if(purchaseCount < 1) { + throw new DomainValidationException(INVALID_PURCHASE_COUNT, "구입 갯수는 1개이상이어야 합니다."); + } + } + + public PurchaseOutput toPurchaseOutput() { + return new PurchaseOutput(this.purchaseCount); + } + + public int fetchPurchaseCount() { + return this.purchaseCount; + } +} diff --git a/src/main/java/domain/PurchaseCountCalculator.java b/src/main/java/domain/PurchaseCountCalculator.java new file mode 100644 index 0000000000..13de79b983 --- /dev/null +++ b/src/main/java/domain/PurchaseCountCalculator.java @@ -0,0 +1,16 @@ +package domain; + +public class PurchaseCountCalculator { + + private static final int LOTTO_PRICE = 1000; + + private final PurchaseAmount purchaseAmount; + + public PurchaseCountCalculator(PurchaseAmount purchaseAmount) { + this.purchaseAmount = purchaseAmount; + } + + public PurchaseCount calculate() { + return PurchaseCount.create(this.purchaseAmount.fetchPurchaseAmount()/LOTTO_PRICE); + } +} diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index b0d7c195f0..846cc20162 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -3,6 +3,7 @@ public enum ErrorCode { ONLY_NUMBER_INPUT, - PURCHASE_COUNT_BIGGER_THAN_ZERO, - INVALID_LOTTO_NUMBER_RANGE + INVALID_PURCHASE_COUNT, + INVALID_LOTTO_NUMBER_RANGE, + INVALID_PURCHASE_AMOUNT } From 15ef2375d9b8ec09ff30057b744726f81726f277 Mon Sep 17 00:00:00 2001 From: kilian Date: Thu, 16 May 2024 14:43:36 +0900 Subject: [PATCH 15/26] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/controller/LottoSimulator.java | 7 +++++- src/main/java/domain/Lotto.java | 5 +++++ src/main/java/domain/Lottos.java | 7 ++++++ src/main/java/domain/PurchaseCount.java | 4 ---- .../java/view/output/ConsoleOutputView.java | 5 +++-- src/main/java/view/output/OutputView.java | 3 ++- .../java/view/output/dto/LottoOutput.java | 21 ++++++++++++++++++ .../view/output/dto/LottoOutputCreator.java | 22 +++++++++++++++++++ .../java/view/output/dto/LottosOutput.java | 21 ++++++++++++++++++ .../output/dto/PurchaseOutputCreator.java | 10 +++++++++ 11 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 src/main/java/view/output/dto/LottoOutput.java create mode 100644 src/main/java/view/output/dto/LottoOutputCreator.java create mode 100644 src/main/java/view/output/dto/LottosOutput.java create mode 100644 src/main/java/view/output/dto/PurchaseOutputCreator.java diff --git a/README.md b/README.md index 6f34156a39..6ac235f0c1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - [x] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. - [x] 구입한 로또의 갯수를 출력한다. - [x] 구입한 로또의 목록을 생성한다. -- [ ] 구입한 로또의 목록을 출력한다. +- [x] 구입한 로또의 목록을 출력한다. - [ ] 지난 주 당첨 번호를 입력받는다. - [ ] 보너스 볼을 입력 받는다. - [ ] 당첨 결과를 판단한다. diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index c4a09e6831..7366b84faf 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -6,7 +6,10 @@ import view.input.dto.PurchaseInput; import view.output.ConsoleOutputView; import view.output.OutputView; +import view.output.dto.LottoOutputCreator; +import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; +import view.output.dto.PurchaseOutputCreator; public class LottoSimulator { @@ -18,11 +21,13 @@ public void run() { PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); PurchaseCountCalculator purchaseCountCalculator = new PurchaseCountCalculator(purchaseAmount); PurchaseCount purchaseCount = purchaseCountCalculator.calculate(); - PurchaseOutput purchaseOutput = purchaseCount.toPurchaseOutput(); + PurchaseOutput purchaseOutput = PurchaseOutputCreator.create(purchaseCount); outputView.viewPurchaseAmount(purchaseOutput); LottosGenerator lottosGenerator = new LottosGenerator(purchaseCount); Lottos lottos = lottosGenerator.generate(); + LottosOutput lottosOutput = LottoOutputCreator.createLottosOutput(lottos); + outputView.viewLottos(lottosOutput); diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index e1d5230a77..7d71fe4e87 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -1,6 +1,7 @@ package domain; import exception.DomainValidationException; +import view.output.dto.LottoOutput; import java.util.List; @@ -41,4 +42,8 @@ private boolean isAllLottoNumberRange(List lottoNumbers) { private boolean isLottoNumberRange(Integer number) { return number >= MIN_LOTTO_NUMBER_INCLUSIVE && number <= MAX_LOTTO_NUMBER_INCLUSIVE; } + + public List fetchLottoNumberList() { + return List.copyOf(this.lottoNumbers); + } } diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java index b58def948e..1c840a1f48 100644 --- a/src/main/java/domain/Lottos.java +++ b/src/main/java/domain/Lottos.java @@ -1,6 +1,10 @@ package domain; +import view.output.dto.LottoOutput; +import view.output.dto.LottosOutput; + import java.util.List; +import java.util.stream.Collectors; public class Lottos { @@ -14,4 +18,7 @@ public static Lottos create(List lottos) { return new Lottos(lottos); } + public List fetchLottoList() { + return List.copyOf(this.lottos); + } } diff --git a/src/main/java/domain/PurchaseCount.java b/src/main/java/domain/PurchaseCount.java index 416617e828..49e94e2c26 100644 --- a/src/main/java/domain/PurchaseCount.java +++ b/src/main/java/domain/PurchaseCount.java @@ -24,10 +24,6 @@ private void validatePurchaseCount(int purchaseCount) { } } - public PurchaseOutput toPurchaseOutput() { - return new PurchaseOutput(this.purchaseCount); - } - public int fetchPurchaseCount() { return this.purchaseCount; } diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java index 03e50a8e1c..c7c0a6003d 100644 --- a/src/main/java/view/output/ConsoleOutputView.java +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -1,5 +1,6 @@ package view.output; +import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; public class ConsoleOutputView implements OutputView{ @@ -12,8 +13,8 @@ public void viewPurchaseAmount(PurchaseOutput purchaseOutput) { } @Override - public void viewLotto() { - + public void viewLottos(LottosOutput lottosOutput) { + System.out.println(lottosOutput.fetchLottosNumbersStr()); } @Override diff --git a/src/main/java/view/output/OutputView.java b/src/main/java/view/output/OutputView.java index bb15dd0f08..cb2deb3534 100644 --- a/src/main/java/view/output/OutputView.java +++ b/src/main/java/view/output/OutputView.java @@ -1,12 +1,13 @@ package view.output; +import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; public interface OutputView { void viewPurchaseAmount(PurchaseOutput purchaseOutput); - void viewLotto(); + void viewLottos(LottosOutput lottosOutput); void viewWinningResult(); } diff --git a/src/main/java/view/output/dto/LottoOutput.java b/src/main/java/view/output/dto/LottoOutput.java new file mode 100644 index 0000000000..12ff74a18a --- /dev/null +++ b/src/main/java/view/output/dto/LottoOutput.java @@ -0,0 +1,21 @@ +package view.output.dto; + +import java.util.List; +import java.util.stream.Collectors; + +public class LottoOutput { + + private final List lottoNumbers; + + public LottoOutput(List lottoNumbers) { + this.lottoNumbers = lottoNumbers; + } + + public String fetchLottoNumbersStr() { + String lottoNumbersStr = this.lottoNumbers.stream() + .map(Object::toString) + .collect(Collectors.joining(", ")); + + return "[" + lottoNumbersStr + "]"; + } +} diff --git a/src/main/java/view/output/dto/LottoOutputCreator.java b/src/main/java/view/output/dto/LottoOutputCreator.java new file mode 100644 index 0000000000..62a0728ac1 --- /dev/null +++ b/src/main/java/view/output/dto/LottoOutputCreator.java @@ -0,0 +1,22 @@ +package view.output.dto; + +import domain.Lotto; +import domain.Lottos; + +import java.util.List; +import java.util.stream.Collectors; + +public class LottoOutputCreator { + + public static LottosOutput createLottosOutput(Lottos lottos) { + List lottoOutputs = lottos.fetchLottoList().stream() + .map(LottoOutputCreator::createLottoOutput) + .collect(Collectors.toList()); + + return new LottosOutput(lottoOutputs); + } + + public static LottoOutput createLottoOutput(Lotto lotto) { + return new LottoOutput(lotto.fetchLottoNumberList()); + } +} diff --git a/src/main/java/view/output/dto/LottosOutput.java b/src/main/java/view/output/dto/LottosOutput.java new file mode 100644 index 0000000000..b55cbecf94 --- /dev/null +++ b/src/main/java/view/output/dto/LottosOutput.java @@ -0,0 +1,21 @@ +package view.output.dto; + +import domain.Lotto; + +import java.util.List; +import java.util.stream.Collectors; + +public class LottosOutput { + + private final List lottoOutputs; + + public LottosOutput(List lottoOutputs) { + this.lottoOutputs = lottoOutputs; + } + + public String fetchLottosNumbersStr() { + return this.lottoOutputs.stream() + .map(LottoOutput::fetchLottoNumbersStr) + .collect(Collectors.joining("\n")); + } +} diff --git a/src/main/java/view/output/dto/PurchaseOutputCreator.java b/src/main/java/view/output/dto/PurchaseOutputCreator.java new file mode 100644 index 0000000000..ad521970e2 --- /dev/null +++ b/src/main/java/view/output/dto/PurchaseOutputCreator.java @@ -0,0 +1,10 @@ +package view.output.dto; + +import domain.PurchaseCount; + +public abstract class PurchaseOutputCreator { + + public static PurchaseOutput create(PurchaseCount purchaseCount) { + return new PurchaseOutput(purchaseCount.fetchPurchaseCount()); + } +} From 681ac2a8b45bbb3c72ee136412402878bdafb1b7 Mon Sep 17 00:00:00 2001 From: kilian Date: Fri, 17 May 2024 10:23:18 +0900 Subject: [PATCH 16/26] =?UTF-8?q?feat=20:=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20>>=20dto=20=EB=B3=80=ED=99=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 --- README.md | 2 +- src/main/java/controller/LottoSimulator.java | 10 ++------- src/main/java/domain/Lottos.java | 6 +---- src/main/java/domain/LottosGenerator.java | 1 + .../java/view/output/dto/LottoOutput.java | 8 ++++++- .../view/output/dto/LottoOutputCreator.java | 22 ------------------- .../java/view/output/dto/LottosOutput.java | 12 ++++++++-- .../java/view/output/dto/PurchaseOutput.java | 7 ++++++ .../output/dto/PurchaseOutputCreator.java | 10 --------- 9 files changed, 29 insertions(+), 49 deletions(-) delete mode 100644 src/main/java/view/output/dto/LottoOutputCreator.java delete mode 100644 src/main/java/view/output/dto/PurchaseOutputCreator.java diff --git a/README.md b/README.md index 6ac235f0c1..1b17f5c043 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,4 @@ - [ ] 지난 주 당첨 번호를 입력받는다. - [ ] 보너스 볼을 입력 받는다. - [ ] 당첨 결과를 판단한다. -- [ ] 당첨 결과를 출력한다. \ No newline at end of file +- [ ] 당첨 결과를 출력한다.력 \ No newline at end of file diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 7366b84faf..eed03f4003 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -6,10 +6,8 @@ import view.input.dto.PurchaseInput; import view.output.ConsoleOutputView; import view.output.OutputView; -import view.output.dto.LottoOutputCreator; import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; -import view.output.dto.PurchaseOutputCreator; public class LottoSimulator { @@ -21,15 +19,11 @@ public void run() { PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); PurchaseCountCalculator purchaseCountCalculator = new PurchaseCountCalculator(purchaseAmount); PurchaseCount purchaseCount = purchaseCountCalculator.calculate(); - PurchaseOutput purchaseOutput = PurchaseOutputCreator.create(purchaseCount); - outputView.viewPurchaseAmount(purchaseOutput); + outputView.viewPurchaseAmount(PurchaseOutput.from(purchaseCount)); LottosGenerator lottosGenerator = new LottosGenerator(purchaseCount); Lottos lottos = lottosGenerator.generate(); - LottosOutput lottosOutput = LottoOutputCreator.createLottosOutput(lottos); - outputView.viewLottos(lottosOutput); - - + outputView.viewLottos(LottosOutput.from(lottos)); } } diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java index 1c840a1f48..eab0ac76a6 100644 --- a/src/main/java/domain/Lottos.java +++ b/src/main/java/domain/Lottos.java @@ -1,10 +1,6 @@ package domain; -import view.output.dto.LottoOutput; -import view.output.dto.LottosOutput; - import java.util.List; -import java.util.stream.Collectors; public class Lottos { @@ -18,7 +14,7 @@ public static Lottos create(List lottos) { return new Lottos(lottos); } - public List fetchLottoList() { + public List toList() { return List.copyOf(this.lottos); } } diff --git a/src/main/java/domain/LottosGenerator.java b/src/main/java/domain/LottosGenerator.java index 29919ae02d..eac5e6a26e 100644 --- a/src/main/java/domain/LottosGenerator.java +++ b/src/main/java/domain/LottosGenerator.java @@ -33,6 +33,7 @@ public Lottos generate() { private Lotto generateLotto() { Collections.shuffle(totalLottoNumbers); List numbers = List.copyOf(totalLottoNumbers.subList(0, LOTTO_NUMBERS_SIZE)); + return Lotto.create(numbers); } } diff --git a/src/main/java/view/output/dto/LottoOutput.java b/src/main/java/view/output/dto/LottoOutput.java index 12ff74a18a..938a6cdb25 100644 --- a/src/main/java/view/output/dto/LottoOutput.java +++ b/src/main/java/view/output/dto/LottoOutput.java @@ -1,5 +1,7 @@ package view.output.dto; +import domain.Lotto; + import java.util.List; import java.util.stream.Collectors; @@ -11,11 +13,15 @@ public LottoOutput(List lottoNumbers) { this.lottoNumbers = lottoNumbers; } - public String fetchLottoNumbersStr() { + public String fetchLottoNumbersToStr() { String lottoNumbersStr = this.lottoNumbers.stream() .map(Object::toString) .collect(Collectors.joining(", ")); return "[" + lottoNumbersStr + "]"; } + + public static LottoOutput from(Lotto lotto) { + return new LottoOutput(lotto.fetchLottoNumberList()); + } } diff --git a/src/main/java/view/output/dto/LottoOutputCreator.java b/src/main/java/view/output/dto/LottoOutputCreator.java deleted file mode 100644 index 62a0728ac1..0000000000 --- a/src/main/java/view/output/dto/LottoOutputCreator.java +++ /dev/null @@ -1,22 +0,0 @@ -package view.output.dto; - -import domain.Lotto; -import domain.Lottos; - -import java.util.List; -import java.util.stream.Collectors; - -public class LottoOutputCreator { - - public static LottosOutput createLottosOutput(Lottos lottos) { - List lottoOutputs = lottos.fetchLottoList().stream() - .map(LottoOutputCreator::createLottoOutput) - .collect(Collectors.toList()); - - return new LottosOutput(lottoOutputs); - } - - public static LottoOutput createLottoOutput(Lotto lotto) { - return new LottoOutput(lotto.fetchLottoNumberList()); - } -} diff --git a/src/main/java/view/output/dto/LottosOutput.java b/src/main/java/view/output/dto/LottosOutput.java index b55cbecf94..ee5acdae28 100644 --- a/src/main/java/view/output/dto/LottosOutput.java +++ b/src/main/java/view/output/dto/LottosOutput.java @@ -1,6 +1,6 @@ package view.output.dto; -import domain.Lotto; +import domain.Lottos; import java.util.List; import java.util.stream.Collectors; @@ -15,7 +15,15 @@ public LottosOutput(List lottoOutputs) { public String fetchLottosNumbersStr() { return this.lottoOutputs.stream() - .map(LottoOutput::fetchLottoNumbersStr) + .map(LottoOutput::fetchLottoNumbersToStr) .collect(Collectors.joining("\n")); } + + public static LottosOutput from(Lottos lottos) { + List lottoOutputs = lottos.toList().stream() + .map(LottoOutput::from) + .collect(Collectors.toList()); + + return new LottosOutput(lottoOutputs); + } } diff --git a/src/main/java/view/output/dto/PurchaseOutput.java b/src/main/java/view/output/dto/PurchaseOutput.java index c1681384c3..f4635bcd73 100644 --- a/src/main/java/view/output/dto/PurchaseOutput.java +++ b/src/main/java/view/output/dto/PurchaseOutput.java @@ -1,5 +1,7 @@ package view.output.dto; +import domain.PurchaseCount; + public class PurchaseOutput { private final int purchaseCount; @@ -11,4 +13,9 @@ public PurchaseOutput(int purchaseCount) { public int fetchPurchaseCount() { return this.purchaseCount; } + + public static PurchaseOutput from(PurchaseCount purchaseCount) { + + return new PurchaseOutput(purchaseCount.fetchPurchaseCount()); + } } diff --git a/src/main/java/view/output/dto/PurchaseOutputCreator.java b/src/main/java/view/output/dto/PurchaseOutputCreator.java deleted file mode 100644 index ad521970e2..0000000000 --- a/src/main/java/view/output/dto/PurchaseOutputCreator.java +++ /dev/null @@ -1,10 +0,0 @@ -package view.output.dto; - -import domain.PurchaseCount; - -public abstract class PurchaseOutputCreator { - - public static PurchaseOutput create(PurchaseCount purchaseCount) { - return new PurchaseOutput(purchaseCount.fetchPurchaseCount()); - } -} From 0a5e3ed465ee4d84f5a63c3f063472f62c26cff2 Mon Sep 17 00:00:00 2001 From: kilian Date: Fri, 17 May 2024 11:00:40 +0900 Subject: [PATCH 17/26] =?UTF-8?q?feat=20:=20=EC=A7=80=EB=82=9C=20=EC=A3=BC?= =?UTF-8?q?=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EB=B0=9B=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++-- src/main/java/controller/LottoSimulator.java | 3 ++ src/main/java/exception/code/ErrorCode.java | 3 +- src/main/java/util/PatternMatchUtils.java | 10 ++++++ .../java/view/input/ConsoleInputView.java | 34 +++++++++++++++---- src/main/java/view/input/InputView.java | 3 +- .../view/input/dto/WinningNumbersInput.java | 12 +++++++ .../java/view/output/ConsoleOutputView.java | 4 +-- .../java/view/output/dto/LottosOutput.java | 16 ++++----- .../java/view/output/dto/PurchaseOutput.java | 9 +++-- 10 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 src/main/java/util/PatternMatchUtils.java create mode 100644 src/main/java/view/input/dto/WinningNumbersInput.java diff --git a/README.md b/README.md index 1b17f5c043..14a00a1e96 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ # java-lotto ## 비즈니스 요구 사항 + - 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다. - 로또 1장의 가격은 1000원이다. +- 로또 구입 금액은 0보다 커야 한다. - 로또는 1개이상 구매해야한다. +- 지난 주 당첨 번호는 1, 2, 3, 4, 5, 6과 같은 형식이어야 한다. ## 구현 기능 목록 + - [x] 구입 금액 사용자 입력을 받는다. - [x] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. - [x] 구입한 로또의 갯수를 출력한다. - [x] 구입한 로또의 목록을 생성한다. - [x] 구입한 로또의 목록을 출력한다. -- [ ] 지난 주 당첨 번호를 입력받는다. +- [x] 지난 주 당첨 번호를 입력받는다. - [ ] 보너스 볼을 입력 받는다. - [ ] 당첨 결과를 판단한다. -- [ ] 당첨 결과를 출력한다.력 \ No newline at end of file +- [ ] 당첨 결과를 출력한다. \ No newline at end of file diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index eed03f4003..a1f569dc25 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -4,6 +4,7 @@ import view.input.ConsoleInputView; import view.input.InputView; import view.input.dto.PurchaseInput; +import view.input.dto.WinningNumbersInput; import view.output.ConsoleOutputView; import view.output.OutputView; import view.output.dto.LottosOutput; @@ -25,5 +26,7 @@ public void run() { Lottos lottos = lottosGenerator.generate(); outputView.viewLottos(LottosOutput.from(lottos)); + WinningNumbersInput winningNumbersInput = inputView.inputWinningNumbers(); + System.out.println(winningNumbersInput); } } diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index 846cc20162..58da7a38d0 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -2,7 +2,8 @@ public enum ErrorCode { - ONLY_NUMBER_INPUT, + INVALID_NUMBER_INPUT, + INVALID_NUMBERS_INPUT, INVALID_PURCHASE_COUNT, INVALID_LOTTO_NUMBER_RANGE, INVALID_PURCHASE_AMOUNT diff --git a/src/main/java/util/PatternMatchUtils.java b/src/main/java/util/PatternMatchUtils.java new file mode 100644 index 0000000000..41bf0f5632 --- /dev/null +++ b/src/main/java/util/PatternMatchUtils.java @@ -0,0 +1,10 @@ +package util; + +import java.util.Objects; + +public class PatternMatchUtils { + + public static boolean matches(String regex, String str) { + return Objects.nonNull(str) && str.matches(regex); + } +} diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index 77785119e2..72d6630e9a 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -2,14 +2,22 @@ import exception.InvalidInputException; import util.Console; +import util.PatternMatchUtils; import util.StringUtils; import view.input.dto.PurchaseInput; +import view.input.dto.WinningNumbersInput; -import static exception.code.ErrorCode.*; +import java.util.Arrays; +import java.util.stream.Collectors; -public class ConsoleInputView implements InputView{ +import static exception.code.ErrorCode.INVALID_NUMBERS_INPUT; +import static exception.code.ErrorCode.INVALID_NUMBER_INPUT; + +public class ConsoleInputView implements InputView { private static final String PURCHASE_AMOUNT_NAVIGATION = "구입금액을 입력해 주세요."; + private static final String WINNING_NUMBERS_NAVIGATION = "지난 주 당첨 번호를 입력해 주세요."; + private static final String NUMBERS_INPUT_REGEX = "^(\\d,\\s){5}\\d$"; @Override public PurchaseInput inputPurchaseAmount() { @@ -21,8 +29,16 @@ public PurchaseInput inputPurchaseAmount() { } @Override - public void inputWinningNumbers() { - + public WinningNumbersInput inputWinningNumbers() { + System.out.println(WINNING_NUMBERS_NAVIGATION); + String input = Console.readLine(); + this.validateNumbers(input); + + return new WinningNumbersInput( + Arrays.stream(input.split(", ")) + .map(Integer::parseInt) + .collect(Collectors.toList()) + ); } @Override @@ -31,8 +47,14 @@ public void inputBonusNumber() { } private void validateNumber(String input) { - if(!StringUtils.isNumeric(input)) { - throw new InvalidInputException(ONLY_NUMBER_INPUT, "숫자인 입력값만 허용됩니다."); + if (!StringUtils.isNumeric(input)) { + throw new InvalidInputException(INVALID_NUMBER_INPUT, "숫자인 입력값만 허용됩니다."); + } + } + + private void validateNumbers(String input) { + if (!PatternMatchUtils.matches(NUMBERS_INPUT_REGEX, input)) { + throw new InvalidInputException(INVALID_NUMBERS_INPUT, "번호 입력 형식이 올바르지 않습니다."); } } } diff --git a/src/main/java/view/input/InputView.java b/src/main/java/view/input/InputView.java index 24a1aee575..bfd1971dcb 100644 --- a/src/main/java/view/input/InputView.java +++ b/src/main/java/view/input/InputView.java @@ -1,12 +1,13 @@ package view.input; import view.input.dto.PurchaseInput; +import view.input.dto.WinningNumbersInput; public interface InputView { PurchaseInput inputPurchaseAmount(); - void inputWinningNumbers(); + WinningNumbersInput inputWinningNumbers(); void inputBonusNumber(); } diff --git a/src/main/java/view/input/dto/WinningNumbersInput.java b/src/main/java/view/input/dto/WinningNumbersInput.java new file mode 100644 index 0000000000..eb601df0aa --- /dev/null +++ b/src/main/java/view/input/dto/WinningNumbersInput.java @@ -0,0 +1,12 @@ +package view.input.dto; + +import java.util.List; + +public class WinningNumbersInput { + + private final List WinningNumbers; + + public WinningNumbersInput(List winningNumbers) { + WinningNumbers = winningNumbers; + } +} diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java index c7c0a6003d..7faddce99a 100644 --- a/src/main/java/view/output/ConsoleOutputView.java +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -3,7 +3,7 @@ import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; -public class ConsoleOutputView implements OutputView{ +public class ConsoleOutputView implements OutputView { private static final String PURCHASE_COUNT_NAVIGATION = "%d개를 구매했습니다."; @@ -14,7 +14,7 @@ public void viewPurchaseAmount(PurchaseOutput purchaseOutput) { @Override public void viewLottos(LottosOutput lottosOutput) { - System.out.println(lottosOutput.fetchLottosNumbersStr()); + System.out.println(lottosOutput.fetchLottosNumbersStr() + "\n"); } @Override diff --git a/src/main/java/view/output/dto/LottosOutput.java b/src/main/java/view/output/dto/LottosOutput.java index ee5acdae28..51f5ed7f73 100644 --- a/src/main/java/view/output/dto/LottosOutput.java +++ b/src/main/java/view/output/dto/LottosOutput.java @@ -13,17 +13,17 @@ public LottosOutput(List lottoOutputs) { this.lottoOutputs = lottoOutputs; } + public static LottosOutput from(Lottos lottos) { + return new LottosOutput( + lottos.toList().stream() + .map(LottoOutput::from) + .collect(Collectors.toList()) + ); + } + public String fetchLottosNumbersStr() { return this.lottoOutputs.stream() .map(LottoOutput::fetchLottoNumbersToStr) .collect(Collectors.joining("\n")); } - - public static LottosOutput from(Lottos lottos) { - List lottoOutputs = lottos.toList().stream() - .map(LottoOutput::from) - .collect(Collectors.toList()); - - return new LottosOutput(lottoOutputs); - } } diff --git a/src/main/java/view/output/dto/PurchaseOutput.java b/src/main/java/view/output/dto/PurchaseOutput.java index f4635bcd73..0d10ae171a 100644 --- a/src/main/java/view/output/dto/PurchaseOutput.java +++ b/src/main/java/view/output/dto/PurchaseOutput.java @@ -10,12 +10,11 @@ public PurchaseOutput(int purchaseCount) { this.purchaseCount = purchaseCount; } - public int fetchPurchaseCount() { - return this.purchaseCount; - } - public static PurchaseOutput from(PurchaseCount purchaseCount) { - return new PurchaseOutput(purchaseCount.fetchPurchaseCount()); } + + public int fetchPurchaseCount() { + return this.purchaseCount; + } } From 572309c61ea1ca57faa2439ea488595d4e65fa1d Mon Sep 17 00:00:00 2001 From: kilian Date: Fri, 17 May 2024 14:38:45 +0900 Subject: [PATCH 18/26] =?UTF-8?q?feat=20:=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20validation=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++- src/main/java/controller/LottoSimulator.java | 8 +++- src/main/java/domain/BonusNumber.java | 18 ++++++++ src/main/java/domain/Lotto.java | 27 +++++++++-- src/main/java/domain/LottosResultMaker.java | 26 +++++++++++ src/main/java/domain/WinningNumber.java | 29 ++++++++++++ src/main/java/domain/WinningNumbers.java | 45 +++++++++++++++++++ src/main/java/exception/code/ErrorCode.java | 6 ++- src/main/java/util/CollectionUtils.java | 11 +++++ src/main/java/util/PatternMatchUtils.java | 2 +- .../java/view/input/ConsoleInputView.java | 10 ++++- src/main/java/view/input/InputView.java | 3 +- .../java/view/input/dto/BonusNumberInput.java | 16 +++++++ .../view/input/dto/WinningNumbersInput.java | 16 ++++++- 14 files changed, 208 insertions(+), 14 deletions(-) create mode 100644 src/main/java/domain/BonusNumber.java create mode 100644 src/main/java/domain/LottosResultMaker.java create mode 100644 src/main/java/domain/WinningNumber.java create mode 100644 src/main/java/domain/WinningNumbers.java create mode 100644 src/main/java/util/CollectionUtils.java create mode 100644 src/main/java/view/input/dto/BonusNumberInput.java diff --git a/README.md b/README.md index 14a00a1e96..0c4f19e4fe 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ - 로또 1장의 가격은 1000원이다. - 로또 구입 금액은 0보다 커야 한다. - 로또는 1개이상 구매해야한다. -- 지난 주 당첨 번호는 1, 2, 3, 4, 5, 6과 같은 형식이어야 한다. +- 지난 주 당첨 번호는 "1, 2, 3, 4, 5, 6" 같은 형식이어야 한다. +- 보너스 번호는 당첨 번호에 포함되면 안된다. ## 구현 기능 목록 @@ -16,6 +17,6 @@ - [x] 구입한 로또의 목록을 생성한다. - [x] 구입한 로또의 목록을 출력한다. - [x] 지난 주 당첨 번호를 입력받는다. -- [ ] 보너스 볼을 입력 받는다. +- [x] 보너스 볼을 입력 받는다. - [ ] 당첨 결과를 판단한다. - [ ] 당첨 결과를 출력한다. \ No newline at end of file diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index a1f569dc25..44f83325c2 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -3,6 +3,7 @@ import domain.*; import view.input.ConsoleInputView; import view.input.InputView; +import view.input.dto.BonusNumberInput; import view.input.dto.PurchaseInput; import view.input.dto.WinningNumbersInput; import view.output.ConsoleOutputView; @@ -27,6 +28,11 @@ public void run() { outputView.viewLottos(LottosOutput.from(lottos)); WinningNumbersInput winningNumbersInput = inputView.inputWinningNumbers(); - System.out.println(winningNumbersInput); + WinningNumbers winningNumbers = winningNumbersInput.toWinningNumbers(); + + BonusNumberInput bonusNumberInput = inputView.inputBonusNumber(); + BonusNumber bonusNumber = bonusNumberInput.toBonusNumber(); + + } } diff --git a/src/main/java/domain/BonusNumber.java b/src/main/java/domain/BonusNumber.java new file mode 100644 index 0000000000..649bcfd9fe --- /dev/null +++ b/src/main/java/domain/BonusNumber.java @@ -0,0 +1,18 @@ +package domain; + +public class BonusNumber { + + private final int bonusNumber; + + private BonusNumber(int bonusNumber) { + this.bonusNumber = bonusNumber; + } + + public static BonusNumber create(int bonusNumber) { + return new BonusNumber(bonusNumber); + } + + public int fetchBonusNumber() { + return this.bonusNumber; + } +} diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 7d71fe4e87..25440cb1ff 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -1,8 +1,9 @@ package domain; import exception.DomainValidationException; -import view.output.dto.LottoOutput; +import util.CollectionUtils; +import java.util.HashSet; import java.util.List; import static exception.code.ErrorCode.*; @@ -17,6 +18,8 @@ public class Lotto { private Lotto(List lottoNumbers) { + this.validateNotEmpty(lottoNumbers); + this.validateLottoNumbersUnique(lottoNumbers); this.validateNumberRange(lottoNumbers); this.lottoNumbers = lottoNumbers; } @@ -26,12 +29,24 @@ public static Lotto create(List lottoNumbers) { } private void validateNumberRange(List lottoNumbers) { - if(!isAllLottoNumberRange(lottoNumbers)) { + if (!isAllLottoNumberRange(lottoNumbers)) { throw new DomainValidationException( INVALID_LOTTO_NUMBER_RANGE, String.format("로또 번호의 범위는 %d부터 %d까지 입니다.", MIN_LOTTO_NUMBER_INCLUSIVE, MAX_LOTTO_NUMBER_INCLUSIVE) - ); - }; + ); + } + } + + private void validateNotEmpty(List lottoNumbers) { + if (CollectionUtils.isEmpty(lottoNumbers)) { + throw new DomainValidationException(COLLECTION_MUST_NOT_BE_EMPTY, "로또 번호는 null이거나 empty하면 안됩니다."); + } + } + + private void validateLottoNumbersUnique(List lottoNumbers) { + if (!isUniqueLottoNumbers(lottoNumbers)) { + throw new DomainValidationException(NOT_UNIQUE_LOTTO_NUMBERS, "로또 번호는 모두 달라야 합니다."); + } } private boolean isAllLottoNumberRange(List lottoNumbers) { @@ -43,6 +58,10 @@ private boolean isLottoNumberRange(Integer number) { return number >= MIN_LOTTO_NUMBER_INCLUSIVE && number <= MAX_LOTTO_NUMBER_INCLUSIVE; } + private boolean isUniqueLottoNumbers(List lottoNumbers) { + return new HashSet<>(lottoNumbers).size() == lottoNumbers.size(); + } + public List fetchLottoNumberList() { return List.copyOf(this.lottoNumbers); } diff --git a/src/main/java/domain/LottosResultMaker.java b/src/main/java/domain/LottosResultMaker.java new file mode 100644 index 0000000000..d352841177 --- /dev/null +++ b/src/main/java/domain/LottosResultMaker.java @@ -0,0 +1,26 @@ +package domain; + +import exception.DomainValidationException; + +import static exception.code.ErrorCode.WINNING_NUMBERS_CONTAIN_BONUS_NUMBER; + +public class LottosResultMaker { + + private final Lottos lottos; + private final WinningNumbers winningNumbers; + private final BonusNumber bonusNumber; + + public LottosResultMaker(Lottos lottos, WinningNumbers winningNumbers, BonusNumber bonusNumber) { + this.validateBonusNumberNotContainWinningNumber(winningNumbers, bonusNumber); + this.lottos = lottos; + this.winningNumbers = winningNumbers; + this.bonusNumber = bonusNumber; + } + + private void validateBonusNumberNotContainWinningNumber(WinningNumbers winningNumbers, BonusNumber bonusNumber) { + if (winningNumbers.isContainNumber(bonusNumber.fetchBonusNumber())) { + throw new DomainValidationException(WINNING_NUMBERS_CONTAIN_BONUS_NUMBER, "보너스 번호가 당첨 번호에 포함되어있으면 안됩니다."); + } + } + +} diff --git a/src/main/java/domain/WinningNumber.java b/src/main/java/domain/WinningNumber.java new file mode 100644 index 0000000000..c8c982447f --- /dev/null +++ b/src/main/java/domain/WinningNumber.java @@ -0,0 +1,29 @@ +package domain; + +import java.util.Objects; + +public class WinningNumber { + + private final int winningNumber; + + private WinningNumber(int winningNumber) { + this.winningNumber = winningNumber; + } + + public static WinningNumber create(int winningNumber) { + return new WinningNumber(winningNumber); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WinningNumber that = (WinningNumber) o; + return winningNumber == that.winningNumber; + } + + @Override + public int hashCode() { + return Objects.hash(winningNumber); + } +} diff --git a/src/main/java/domain/WinningNumbers.java b/src/main/java/domain/WinningNumbers.java new file mode 100644 index 0000000000..f8b1bbbc31 --- /dev/null +++ b/src/main/java/domain/WinningNumbers.java @@ -0,0 +1,45 @@ +package domain; + +import exception.DomainValidationException; +import util.CollectionUtils; + +import java.util.HashSet; +import java.util.List; + +import static exception.code.ErrorCode.COLLECTION_MUST_NOT_BE_EMPTY; +import static exception.code.ErrorCode.NOT_UNIQUE_WINNING_NUMBERS; + +public class WinningNumbers { + + private final List winningNumbers; + + private WinningNumbers(List winningNumbers) { + this.validateNotEmpty(winningNumbers); + this.validateAllNumbersUnique(winningNumbers); + this.winningNumbers = winningNumbers; + } + + public static WinningNumbers create(List winningNumbers) { + return new WinningNumbers(winningNumbers); + } + + public boolean isContainNumber(int number) { + return this.winningNumbers.contains(number); + } + + private void validateNotEmpty(List winningNumbers) { + if (CollectionUtils.isEmpty(winningNumbers)) { + throw new DomainValidationException(COLLECTION_MUST_NOT_BE_EMPTY, "당첨 번호는 null이거나 empty이면 안됩니다."); + } + } + + private void validateAllNumbersUnique(List winningNumbers) { + if (!isUniqueWinningNumbers(winningNumbers)) { + throw new DomainValidationException(NOT_UNIQUE_WINNING_NUMBERS, "당첨 번호는 모두 다른 값이여야 합니다."); + } + } + + private boolean isUniqueWinningNumbers(List winningNumbers) { + return new HashSet<>(winningNumbers).size() == winningNumbers.size(); + } +} diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index 58da7a38d0..594dfcdf18 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -6,5 +6,9 @@ public enum ErrorCode { INVALID_NUMBERS_INPUT, INVALID_PURCHASE_COUNT, INVALID_LOTTO_NUMBER_RANGE, - INVALID_PURCHASE_AMOUNT + INVALID_PURCHASE_AMOUNT, + COLLECTION_MUST_NOT_BE_EMPTY, + NOT_UNIQUE_WINNING_NUMBERS, + NOT_UNIQUE_LOTTO_NUMBERS, + WINNING_NUMBERS_CONTAIN_BONUS_NUMBER } diff --git a/src/main/java/util/CollectionUtils.java b/src/main/java/util/CollectionUtils.java new file mode 100644 index 0000000000..48e5691e23 --- /dev/null +++ b/src/main/java/util/CollectionUtils.java @@ -0,0 +1,11 @@ +package util; + +import java.util.Collection; +import java.util.Objects; + +public abstract class CollectionUtils { + + public static boolean isEmpty(Collection collection) { + return Objects.isNull(collection) || collection.isEmpty(); + } +} diff --git a/src/main/java/util/PatternMatchUtils.java b/src/main/java/util/PatternMatchUtils.java index 41bf0f5632..c912fae322 100644 --- a/src/main/java/util/PatternMatchUtils.java +++ b/src/main/java/util/PatternMatchUtils.java @@ -2,7 +2,7 @@ import java.util.Objects; -public class PatternMatchUtils { +public abstract class PatternMatchUtils { public static boolean matches(String regex, String str) { return Objects.nonNull(str) && str.matches(regex); diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index 72d6630e9a..eece37180c 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -4,6 +4,7 @@ import util.Console; import util.PatternMatchUtils; import util.StringUtils; +import view.input.dto.BonusNumberInput; import view.input.dto.PurchaseInput; import view.input.dto.WinningNumbersInput; @@ -17,6 +18,7 @@ public class ConsoleInputView implements InputView { private static final String PURCHASE_AMOUNT_NAVIGATION = "구입금액을 입력해 주세요."; private static final String WINNING_NUMBERS_NAVIGATION = "지난 주 당첨 번호를 입력해 주세요."; + private static final String BONUS_NUMBER_NAVIGATION = "보너스 볼을 입력해 주세요."; private static final String NUMBERS_INPUT_REGEX = "^(\\d,\\s){5}\\d$"; @Override @@ -33,7 +35,7 @@ public WinningNumbersInput inputWinningNumbers() { System.out.println(WINNING_NUMBERS_NAVIGATION); String input = Console.readLine(); this.validateNumbers(input); - + return new WinningNumbersInput( Arrays.stream(input.split(", ")) .map(Integer::parseInt) @@ -42,8 +44,12 @@ public WinningNumbersInput inputWinningNumbers() { } @Override - public void inputBonusNumber() { + public BonusNumberInput inputBonusNumber() { + System.out.println(BONUS_NUMBER_NAVIGATION); + String input = Console.readLine(); + this.validateNumber(input); + return new BonusNumberInput(Integer.parseInt(input)); } private void validateNumber(String input) { diff --git a/src/main/java/view/input/InputView.java b/src/main/java/view/input/InputView.java index bfd1971dcb..33ce17c451 100644 --- a/src/main/java/view/input/InputView.java +++ b/src/main/java/view/input/InputView.java @@ -1,5 +1,6 @@ package view.input; +import view.input.dto.BonusNumberInput; import view.input.dto.PurchaseInput; import view.input.dto.WinningNumbersInput; @@ -9,5 +10,5 @@ public interface InputView { WinningNumbersInput inputWinningNumbers(); - void inputBonusNumber(); + BonusNumberInput inputBonusNumber(); } diff --git a/src/main/java/view/input/dto/BonusNumberInput.java b/src/main/java/view/input/dto/BonusNumberInput.java new file mode 100644 index 0000000000..851047cc52 --- /dev/null +++ b/src/main/java/view/input/dto/BonusNumberInput.java @@ -0,0 +1,16 @@ +package view.input.dto; + +import domain.BonusNumber; + +public class BonusNumberInput { + + private final int bonusNumber; + + public BonusNumberInput(int bonusNumber) { + this.bonusNumber = bonusNumber; + } + + public BonusNumber toBonusNumber() { + return BonusNumber.create(this.bonusNumber); + } +} diff --git a/src/main/java/view/input/dto/WinningNumbersInput.java b/src/main/java/view/input/dto/WinningNumbersInput.java index eb601df0aa..75c41c9322 100644 --- a/src/main/java/view/input/dto/WinningNumbersInput.java +++ b/src/main/java/view/input/dto/WinningNumbersInput.java @@ -1,12 +1,24 @@ package view.input.dto; +import domain.WinningNumber; +import domain.WinningNumbers; + import java.util.List; +import java.util.stream.Collectors; public class WinningNumbersInput { - private final List WinningNumbers; + private final List winningNumbers; public WinningNumbersInput(List winningNumbers) { - WinningNumbers = winningNumbers; + this.winningNumbers = winningNumbers; + } + + public WinningNumbers toWinningNumbers() { + return WinningNumbers.create( + this.winningNumbers.stream() + .map(WinningNumber::create) + .collect(Collectors.toList()) + ); } } From 781d2f106ac07d2a6a68e60832d708e874bb6ff7 Mon Sep 17 00:00:00 2001 From: kilian Date: Fri, 17 May 2024 18:33:13 +0900 Subject: [PATCH 19/26] =?UTF-8?q?feat=20:=20input=20validation=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/controller/LottoSimulator.java | 2 + src/main/java/domain/BonusNumber.java | 6 +++ src/main/java/domain/Lotto.java | 27 ++++++++--- src/main/java/domain/LottoWinning.java | 47 +++++++++++++++++++ src/main/java/domain/LottoWinnings.java | 27 +++++++++++ src/main/java/domain/Lottos.java | 7 +++ src/main/java/domain/LottosGenerator.java | 15 +++--- ...Maker.java => LottosResultCalculator.java} | 11 ++++- src/main/java/domain/WinningNumber.java | 4 ++ src/main/java/domain/WinningNumbers.java | 18 +++++-- src/main/java/exception/code/ErrorCode.java | 2 + .../java/view/input/ConsoleInputView.java | 2 +- .../java/view/input/dto/BonusNumberInput.java | 24 ++++++++++ .../java/view/input/dto/PurchaseInput.java | 10 ++++ .../view/input/dto/WinningNumbersInput.java | 37 +++++++++++++++ 15 files changed, 219 insertions(+), 20 deletions(-) create mode 100644 src/main/java/domain/LottoWinning.java create mode 100644 src/main/java/domain/LottoWinnings.java rename src/main/java/domain/{LottosResultMaker.java => LottosResultCalculator.java} (69%) diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 44f83325c2..3a46124215 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -33,6 +33,8 @@ public void run() { BonusNumberInput bonusNumberInput = inputView.inputBonusNumber(); BonusNumber bonusNumber = bonusNumberInput.toBonusNumber(); + LottosResultCalculator lottosResultCalculator = new LottosResultCalculator(lottos, winningNumbers, bonusNumber); + LottoWinnings lottoWinnings = lottosResultCalculator.calculate(); } } diff --git a/src/main/java/domain/BonusNumber.java b/src/main/java/domain/BonusNumber.java index 649bcfd9fe..5f52e5d8a9 100644 --- a/src/main/java/domain/BonusNumber.java +++ b/src/main/java/domain/BonusNumber.java @@ -15,4 +15,10 @@ public static BonusNumber create(int bonusNumber) { public int fetchBonusNumber() { return this.bonusNumber; } + + public boolean isSameNumber(int number) { + return this.bonusNumber == number; + } + + } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 25440cb1ff..580547b21f 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -13,14 +13,12 @@ public class Lotto { private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; - private final List lottoNumbers; - private Lotto(List lottoNumbers) { - this.validateNotEmpty(lottoNumbers); + this.validateLottoNumbersNotEmpty(lottoNumbers); this.validateLottoNumbersUnique(lottoNumbers); - this.validateNumberRange(lottoNumbers); + this.validateLottoNumbersInRange(lottoNumbers); this.lottoNumbers = lottoNumbers; } @@ -28,7 +26,7 @@ public static Lotto create(List lottoNumbers) { return new Lotto(lottoNumbers); } - private void validateNumberRange(List lottoNumbers) { + private void validateLottoNumbersInRange(List lottoNumbers) { if (!isAllLottoNumberRange(lottoNumbers)) { throw new DomainValidationException( INVALID_LOTTO_NUMBER_RANGE, @@ -37,7 +35,7 @@ private void validateNumberRange(List lottoNumbers) { } } - private void validateNotEmpty(List lottoNumbers) { + private void validateLottoNumbersNotEmpty(List lottoNumbers) { if (CollectionUtils.isEmpty(lottoNumbers)) { throw new DomainValidationException(COLLECTION_MUST_NOT_BE_EMPTY, "로또 번호는 null이거나 empty하면 안됩니다."); } @@ -65,4 +63,21 @@ private boolean isUniqueLottoNumbers(List lottoNumbers) { public List fetchLottoNumberList() { return List.copyOf(this.lottoNumbers); } + + private long countMatchWinningNumbers(WinningNumbers winningNumbers) { + return winningNumbers.countMatchNumbers(this.lottoNumbers); + } + + private long countMatchBonusNumber(BonusNumber bonusNumber) { + return this.lottoNumbers.stream() + .filter(bonusNumber::isSameNumber) + .count(); + } + + public LottoWinning findLottoWinning(WinningNumbers winningNumbers, BonusNumber bonusNumber) { + long matchedWinningNumberCount = this.countMatchWinningNumbers(winningNumbers); + long matchedBonusNumberCount = this.countMatchBonusNumber(bonusNumber); + + return LottoWinning.findLottoWinning(matchedWinningNumberCount, matchedBonusNumberCount); + } } diff --git a/src/main/java/domain/LottoWinning.java b/src/main/java/domain/LottoWinning.java new file mode 100644 index 0000000000..d5b7920987 --- /dev/null +++ b/src/main/java/domain/LottoWinning.java @@ -0,0 +1,47 @@ +package domain; + +import java.util.Arrays; + +public enum LottoWinning { + FIRST_PLACE(2000000000, 6, 0), + SECOND_PLACE(30000000, 5, 1), + THIRD_PLACE(1500000, 5, 0), + FOURTH_PLACE(50000, 4, 0), + FIFTH_PLACE(5000, 3, 0), + ELSE_PLACE(0, 0, 0); + + private final long winningAmount; + + private final long matchWinningNumberCount; + + private final long matchBonusNumberCount; + + LottoWinning(long winningAmount, long matchWinningNumberCount, long matchBonusNumberCount) { + this.winningAmount = winningAmount; + this.matchWinningNumberCount = matchWinningNumberCount; + this.matchBonusNumberCount = matchBonusNumberCount; + } + + public static LottoWinning findLottoWinning(long matchWinningNumberCount, long matchBonusNumberCount) { + return Arrays.stream(LottoWinning.values()) + .filter(lottoWinning -> lottoWinning.isMatchLottoWinning(matchWinningNumberCount, matchBonusNumberCount)) + .findAny() + .orElseGet(() -> ELSE_PLACE); + } + + private boolean isMatchLottoWinning(long matchWinningNumberCount, long matchBonusNumberCount) { + return this.isSameMatchWinningCount(matchWinningNumberCount) && this.isSameMatchBonusNumberCount(matchBonusNumberCount); + } + + private boolean isSameMatchWinningCount(long matchWinningNumberCount) { + return this.matchWinningNumberCount == matchWinningNumberCount; + } + + private boolean isSameMatchBonusNumberCount(long matchBonusNumberCount) { + return this.matchBonusNumberCount == matchBonusNumberCount; + } + + private long fetchWinningAmount() { + return this.winningAmount; + } +} diff --git a/src/main/java/domain/LottoWinnings.java b/src/main/java/domain/LottoWinnings.java new file mode 100644 index 0000000000..5eea51b3d5 --- /dev/null +++ b/src/main/java/domain/LottoWinnings.java @@ -0,0 +1,27 @@ +package domain; + +import exception.DomainValidationException; +import exception.code.ErrorCode; +import util.CollectionUtils; + +import java.util.List; + +public class LottoWinnings { + + private final List lottoWinnings; + + private LottoWinnings(List lottoWinnings) { + this.validateNotEmpty(lottoWinnings); + this.lottoWinnings = lottoWinnings; + } + + public static LottoWinnings create(List lottoWinnings) { + return new LottoWinnings(lottoWinnings); + } + + private void validateNotEmpty(List lottoWinnings) { + if (CollectionUtils.isEmpty(lottoWinnings)) { + throw new DomainValidationException(ErrorCode.COLLECTION_MUST_NOT_BE_EMPTY, "당첨 정보는 null이거나 empty이면 안됩니다."); + } + } +} diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java index eab0ac76a6..91edea8cf7 100644 --- a/src/main/java/domain/Lottos.java +++ b/src/main/java/domain/Lottos.java @@ -1,6 +1,7 @@ package domain; import java.util.List; +import java.util.stream.Collectors; public class Lottos { @@ -17,4 +18,10 @@ public static Lottos create(List lottos) { public List toList() { return List.copyOf(this.lottos); } + + public List findLottoWinnings(WinningNumbers winningNumbers, BonusNumber bonusNumber) { + return this.lottos.stream() + .map(lotto -> lotto.findLottoWinning(winningNumbers, bonusNumber)) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/domain/LottosGenerator.java b/src/main/java/domain/LottosGenerator.java index eac5e6a26e..b84e532ce6 100644 --- a/src/main/java/domain/LottosGenerator.java +++ b/src/main/java/domain/LottosGenerator.java @@ -23,17 +23,18 @@ public LottosGenerator(PurchaseCount purchaseCount) { } public Lottos generate() { - List lottos = IntStream.range(0, this.purchaseCount.fetchPurchaseCount()) - .mapToObj(count -> this.generateLotto()) - .collect(Collectors.toList()); - - return Lottos.create(lottos); + return Lottos.create( + IntStream.range(0, this.purchaseCount.fetchPurchaseCount()) + .mapToObj(count -> this.generateLotto()) + .collect(Collectors.toList()) + ); } private Lotto generateLotto() { Collections.shuffle(totalLottoNumbers); - List numbers = List.copyOf(totalLottoNumbers.subList(0, LOTTO_NUMBERS_SIZE)); + List lottoNumbers = totalLottoNumbers.subList(0, LOTTO_NUMBERS_SIZE); + Collections.sort(lottoNumbers); - return Lotto.create(numbers); + return Lotto.create(List.copyOf(totalLottoNumbers.subList(0, LOTTO_NUMBERS_SIZE))); } } diff --git a/src/main/java/domain/LottosResultMaker.java b/src/main/java/domain/LottosResultCalculator.java similarity index 69% rename from src/main/java/domain/LottosResultMaker.java rename to src/main/java/domain/LottosResultCalculator.java index d352841177..354d2696c4 100644 --- a/src/main/java/domain/LottosResultMaker.java +++ b/src/main/java/domain/LottosResultCalculator.java @@ -2,15 +2,17 @@ import exception.DomainValidationException; +import java.util.List; + import static exception.code.ErrorCode.WINNING_NUMBERS_CONTAIN_BONUS_NUMBER; -public class LottosResultMaker { +public class LottosResultCalculator { private final Lottos lottos; private final WinningNumbers winningNumbers; private final BonusNumber bonusNumber; - public LottosResultMaker(Lottos lottos, WinningNumbers winningNumbers, BonusNumber bonusNumber) { + public LottosResultCalculator(Lottos lottos, WinningNumbers winningNumbers, BonusNumber bonusNumber) { this.validateBonusNumberNotContainWinningNumber(winningNumbers, bonusNumber); this.lottos = lottos; this.winningNumbers = winningNumbers; @@ -23,4 +25,9 @@ private void validateBonusNumberNotContainWinningNumber(WinningNumbers winningNu } } + public LottoWinnings calculate() { + List lottoWinnings = this.lottos.findLottoWinnings(this.winningNumbers, this.bonusNumber); + + return LottoWinnings.create(lottoWinnings); + } } diff --git a/src/main/java/domain/WinningNumber.java b/src/main/java/domain/WinningNumber.java index c8c982447f..0f258df5fc 100644 --- a/src/main/java/domain/WinningNumber.java +++ b/src/main/java/domain/WinningNumber.java @@ -14,6 +14,10 @@ public static WinningNumber create(int winningNumber) { return new WinningNumber(winningNumber); } + public boolean isSameNumber(int number) { + return this.winningNumber == number; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/domain/WinningNumbers.java b/src/main/java/domain/WinningNumbers.java index f8b1bbbc31..c9c48317e1 100644 --- a/src/main/java/domain/WinningNumbers.java +++ b/src/main/java/domain/WinningNumbers.java @@ -23,10 +23,6 @@ public static WinningNumbers create(List winningNumbers) { return new WinningNumbers(winningNumbers); } - public boolean isContainNumber(int number) { - return this.winningNumbers.contains(number); - } - private void validateNotEmpty(List winningNumbers) { if (CollectionUtils.isEmpty(winningNumbers)) { throw new DomainValidationException(COLLECTION_MUST_NOT_BE_EMPTY, "당첨 번호는 null이거나 empty이면 안됩니다."); @@ -42,4 +38,18 @@ private void validateAllNumbersUnique(List winningNumbers) { private boolean isUniqueWinningNumbers(List winningNumbers) { return new HashSet<>(winningNumbers).size() == winningNumbers.size(); } + + public long countMatchNumbers(List numbers) { + return numbers.stream() + .filter(this::isContainNumber) + .count(); + } + + public boolean isContainNumber(int number) { + long count = this.winningNumbers.stream() + .filter(winningNumber -> winningNumber.isSameNumber(number)) + .count(); + + return count > 0; + } } diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index 594dfcdf18..becb0c5ae6 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -3,9 +3,11 @@ public enum ErrorCode { INVALID_NUMBER_INPUT, + INVALID_RANGE_NUMBERS_INPUT, INVALID_NUMBERS_INPUT, INVALID_PURCHASE_COUNT, INVALID_LOTTO_NUMBER_RANGE, + INVALID_BONUS_NUMBER_RANGE, INVALID_PURCHASE_AMOUNT, COLLECTION_MUST_NOT_BE_EMPTY, NOT_UNIQUE_WINNING_NUMBERS, diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index eece37180c..986062a2ce 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -19,7 +19,7 @@ public class ConsoleInputView implements InputView { private static final String PURCHASE_AMOUNT_NAVIGATION = "구입금액을 입력해 주세요."; private static final String WINNING_NUMBERS_NAVIGATION = "지난 주 당첨 번호를 입력해 주세요."; private static final String BONUS_NUMBER_NAVIGATION = "보너스 볼을 입력해 주세요."; - private static final String NUMBERS_INPUT_REGEX = "^(\\d,\\s){5}\\d$"; + private static final String NUMBERS_INPUT_REGEX = "^\\d{1,2}(,\\s\\d{1,2}){5}$"; @Override public PurchaseInput inputPurchaseAmount() { diff --git a/src/main/java/view/input/dto/BonusNumberInput.java b/src/main/java/view/input/dto/BonusNumberInput.java index 851047cc52..7f2a41c645 100644 --- a/src/main/java/view/input/dto/BonusNumberInput.java +++ b/src/main/java/view/input/dto/BonusNumberInput.java @@ -1,16 +1,40 @@ package view.input.dto; import domain.BonusNumber; +import exception.InvalidInputException; + +import static exception.code.ErrorCode.INVALID_BONUS_NUMBER_RANGE; public class BonusNumberInput { + private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; + + private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; + private final int bonusNumber; public BonusNumberInput(int bonusNumber) { + this.validateBonusNumberInRange(bonusNumber); this.bonusNumber = bonusNumber; } public BonusNumber toBonusNumber() { return BonusNumber.create(this.bonusNumber); } + + private void validateBonusNumberInRange(int bonusNumber) { + if (!isNumberInRange(bonusNumber)) { + throw new InvalidInputException( + INVALID_BONUS_NUMBER_RANGE, + String.format("보너스 번호의 범위는 %d이상 %d이하 여야 합니다.", + MIN_LOTTO_NUMBER_INCLUSIVE, + MAX_LOTTO_NUMBER_INCLUSIVE + ) + ); + } + } + + private boolean isNumberInRange(int number) { + return number >= MIN_LOTTO_NUMBER_INCLUSIVE && number <= MAX_LOTTO_NUMBER_INCLUSIVE; + } } diff --git a/src/main/java/view/input/dto/PurchaseInput.java b/src/main/java/view/input/dto/PurchaseInput.java index 78b1305b64..ab0066d47e 100644 --- a/src/main/java/view/input/dto/PurchaseInput.java +++ b/src/main/java/view/input/dto/PurchaseInput.java @@ -1,16 +1,26 @@ package view.input.dto; import domain.PurchaseAmount; +import exception.DomainValidationException; + +import static exception.code.ErrorCode.INVALID_PURCHASE_AMOUNT; public class PurchaseInput { private final int purchaseAmount; public PurchaseInput(int purchaseAmount) { + this.validateAmount(purchaseAmount); this.purchaseAmount = purchaseAmount; } public PurchaseAmount toPurchaseAmount() { return PurchaseAmount.create(purchaseAmount); } + + private void validateAmount(int purchaseAmount) { + if (purchaseAmount <= 0) { + throw new DomainValidationException(INVALID_PURCHASE_AMOUNT, "구입 금액은 0보다 커야합니다."); + } + } } diff --git a/src/main/java/view/input/dto/WinningNumbersInput.java b/src/main/java/view/input/dto/WinningNumbersInput.java index 75c41c9322..4a86f0cd06 100644 --- a/src/main/java/view/input/dto/WinningNumbersInput.java +++ b/src/main/java/view/input/dto/WinningNumbersInput.java @@ -2,15 +2,24 @@ import domain.WinningNumber; import domain.WinningNumbers; +import exception.InvalidInputException; +import util.CollectionUtils; import java.util.List; import java.util.stream.Collectors; +import static exception.code.ErrorCode.COLLECTION_MUST_NOT_BE_EMPTY; +import static exception.code.ErrorCode.INVALID_RANGE_NUMBERS_INPUT; + public class WinningNumbersInput { + private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; + private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; private final List winningNumbers; public WinningNumbersInput(List winningNumbers) { + this.validateWinningNumbersNotEmpty(winningNumbers); + this.validateWinningNumbersInRange(winningNumbers); this.winningNumbers = winningNumbers; } @@ -21,4 +30,32 @@ public WinningNumbers toWinningNumbers() { .collect(Collectors.toList()) ); } + + private void validateWinningNumbersInRange(List winningNumbers) { + if (!this.isWinningNumbersInRange(winningNumbers)) { + throw new InvalidInputException( + INVALID_RANGE_NUMBERS_INPUT, + String.format("당첨 번호의 범위는 %d이상 %d이하 이어야 합니다.", + MIN_LOTTO_NUMBER_INCLUSIVE, + MAX_LOTTO_NUMBER_INCLUSIVE + ) + ); + } + } + + private boolean isWinningNumbersInRange(List winningNumbers) { + return !CollectionUtils.isEmpty(winningNumbers) && + winningNumbers.stream() + .allMatch(this::isNumberInRange); + } + + private boolean isNumberInRange(int number) { + return number >= MIN_LOTTO_NUMBER_INCLUSIVE && number <= MAX_LOTTO_NUMBER_INCLUSIVE; + } + + private void validateWinningNumbersNotEmpty(List winningNumbers) { + if (CollectionUtils.isEmpty(winningNumbers)) { + throw new InvalidInputException(COLLECTION_MUST_NOT_BE_EMPTY, "당첨 번호는 null이거나 empty이면 안됩니다."); + } + } } From ea9d76259a46682251487686b5afbb984aa6f5bd Mon Sep 17 00:00:00 2001 From: kilian Date: Sat, 18 May 2024 19:26:44 +0900 Subject: [PATCH 20/26] =?UTF-8?q?feat=20:=20Constant=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=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/constant/LottoConstants.java | 8 ++++++++ src/main/java/domain/Lotto.java | 10 ++++++---- src/main/java/domain/LottosGenerator.java | 5 +++-- src/main/java/domain/PurchaseCountCalculator.java | 6 +++--- src/main/java/view/input/dto/BonusNumberInput.java | 6 ++---- src/main/java/view/input/dto/WinningNumbersInput.java | 4 ++-- 6 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 src/main/java/constant/LottoConstants.java diff --git a/src/main/java/constant/LottoConstants.java b/src/main/java/constant/LottoConstants.java new file mode 100644 index 0000000000..3b2467a093 --- /dev/null +++ b/src/main/java/constant/LottoConstants.java @@ -0,0 +1,8 @@ +package constant; + +public abstract class LottoConstants { + + public static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; + public static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; + public static final int LOTTO_PRICE = 1000; +} diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 580547b21f..6723fdd26f 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -6,13 +6,12 @@ import java.util.HashSet; import java.util.List; +import static constant.LottoConstants.MAX_LOTTO_NUMBER_INCLUSIVE; +import static constant.LottoConstants.MIN_LOTTO_NUMBER_INCLUSIVE; import static exception.code.ErrorCode.*; public class Lotto { - private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; - private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; - private final List lottoNumbers; private Lotto(List lottoNumbers) { @@ -30,7 +29,10 @@ private void validateLottoNumbersInRange(List lottoNumbers) { if (!isAllLottoNumberRange(lottoNumbers)) { throw new DomainValidationException( INVALID_LOTTO_NUMBER_RANGE, - String.format("로또 번호의 범위는 %d부터 %d까지 입니다.", MIN_LOTTO_NUMBER_INCLUSIVE, MAX_LOTTO_NUMBER_INCLUSIVE) + String.format("로또 번호의 범위는 %d부터 %d까지 입니다.", + MIN_LOTTO_NUMBER_INCLUSIVE, + MAX_LOTTO_NUMBER_INCLUSIVE + ) ); } } diff --git a/src/main/java/domain/LottosGenerator.java b/src/main/java/domain/LottosGenerator.java index b84e532ce6..a241e9028a 100644 --- a/src/main/java/domain/LottosGenerator.java +++ b/src/main/java/domain/LottosGenerator.java @@ -5,10 +5,11 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static constant.LottoConstants.MAX_LOTTO_NUMBER_INCLUSIVE; +import static constant.LottoConstants.MIN_LOTTO_NUMBER_INCLUSIVE; + public class LottosGenerator { - private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; - private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; private static final int LOTTO_NUMBERS_SIZE = 6; private static final List totalLottoNumbers = diff --git a/src/main/java/domain/PurchaseCountCalculator.java b/src/main/java/domain/PurchaseCountCalculator.java index 13de79b983..444069647e 100644 --- a/src/main/java/domain/PurchaseCountCalculator.java +++ b/src/main/java/domain/PurchaseCountCalculator.java @@ -1,8 +1,8 @@ package domain; -public class PurchaseCountCalculator { +import static constant.LottoConstants.LOTTO_PRICE; - private static final int LOTTO_PRICE = 1000; +public class PurchaseCountCalculator { private final PurchaseAmount purchaseAmount; @@ -11,6 +11,6 @@ public PurchaseCountCalculator(PurchaseAmount purchaseAmount) { } public PurchaseCount calculate() { - return PurchaseCount.create(this.purchaseAmount.fetchPurchaseAmount()/LOTTO_PRICE); + return PurchaseCount.create(this.purchaseAmount.fetchPurchaseAmount() / LOTTO_PRICE); } } diff --git a/src/main/java/view/input/dto/BonusNumberInput.java b/src/main/java/view/input/dto/BonusNumberInput.java index 7f2a41c645..26eb3baa4b 100644 --- a/src/main/java/view/input/dto/BonusNumberInput.java +++ b/src/main/java/view/input/dto/BonusNumberInput.java @@ -3,14 +3,12 @@ import domain.BonusNumber; import exception.InvalidInputException; +import static constant.LottoConstants.MAX_LOTTO_NUMBER_INCLUSIVE; +import static constant.LottoConstants.MIN_LOTTO_NUMBER_INCLUSIVE; import static exception.code.ErrorCode.INVALID_BONUS_NUMBER_RANGE; public class BonusNumberInput { - private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; - - private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; - private final int bonusNumber; public BonusNumberInput(int bonusNumber) { diff --git a/src/main/java/view/input/dto/WinningNumbersInput.java b/src/main/java/view/input/dto/WinningNumbersInput.java index 4a86f0cd06..db6be60f67 100644 --- a/src/main/java/view/input/dto/WinningNumbersInput.java +++ b/src/main/java/view/input/dto/WinningNumbersInput.java @@ -8,13 +8,13 @@ import java.util.List; import java.util.stream.Collectors; +import static constant.LottoConstants.MAX_LOTTO_NUMBER_INCLUSIVE; +import static constant.LottoConstants.MIN_LOTTO_NUMBER_INCLUSIVE; import static exception.code.ErrorCode.COLLECTION_MUST_NOT_BE_EMPTY; import static exception.code.ErrorCode.INVALID_RANGE_NUMBERS_INPUT; public class WinningNumbersInput { - private static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; - private static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; private final List winningNumbers; public WinningNumbersInput(List winningNumbers) { From 22a5d550dbada20cae5286a40fc151ed9d396de6 Mon Sep 17 00:00:00 2001 From: kilian Date: Sat, 18 May 2024 22:21:47 +0900 Subject: [PATCH 21/26] =?UTF-8?q?feat=20:=20=EB=8B=B9=EC=B2=A8=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 --- README.md | 4 +- src/main/java/controller/LottoSimulator.java | 4 +- src/main/java/domain/LottoWinning.java | 14 ++++- src/main/java/domain/LottoWinnings.java | 12 ++++ .../exception/InvalidOutputException.java | 13 +++++ src/main/java/exception/code/ErrorCode.java | 3 +- .../java/view/input/ConsoleInputView.java | 1 + .../java/view/output/ConsoleOutputView.java | 56 ++++++++++++++++++- src/main/java/view/output/OutputView.java | 3 +- .../dto/LottoRevenueRateCalculator.java | 21 +++++++ .../view/output/dto/LottoWinningOutput.java | 46 +++++++++++++++ .../dto/LottoWinningStatisticsOutput.java | 30 ++++++++++ .../view/output/dto/LottoWinningsOutput.java | 34 +++++++++++ 13 files changed, 234 insertions(+), 7 deletions(-) create mode 100644 src/main/java/exception/InvalidOutputException.java create mode 100644 src/main/java/view/output/dto/LottoRevenueRateCalculator.java create mode 100644 src/main/java/view/output/dto/LottoWinningOutput.java create mode 100644 src/main/java/view/output/dto/LottoWinningStatisticsOutput.java create mode 100644 src/main/java/view/output/dto/LottoWinningsOutput.java diff --git a/README.md b/README.md index 0c4f19e4fe..8a3e9d8482 100644 --- a/README.md +++ b/README.md @@ -18,5 +18,5 @@ - [x] 구입한 로또의 목록을 출력한다. - [x] 지난 주 당첨 번호를 입력받는다. - [x] 보너스 볼을 입력 받는다. -- [ ] 당첨 결과를 판단한다. -- [ ] 당첨 결과를 출력한다. \ No newline at end of file +- [x] 당첨 결과를 판단한다. +- [x] 당첨 결과를 출력한다. \ No newline at end of file diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 3a46124215..5cb2b74f6f 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -8,6 +8,7 @@ import view.input.dto.WinningNumbersInput; import view.output.ConsoleOutputView; import view.output.OutputView; +import view.output.dto.LottoWinningStatisticsOutput; import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; @@ -35,6 +36,7 @@ public void run() { LottosResultCalculator lottosResultCalculator = new LottosResultCalculator(lottos, winningNumbers, bonusNumber); LottoWinnings lottoWinnings = lottosResultCalculator.calculate(); - + LottoWinningStatisticsOutput lottoWinningStatisticsOutput = LottoWinningStatisticsOutput.from(lottoWinnings, purchaseAmount); + outputView.viewWinningStatistics(lottoWinningStatisticsOutput); } } diff --git a/src/main/java/domain/LottoWinning.java b/src/main/java/domain/LottoWinning.java index d5b7920987..503c6bdac3 100644 --- a/src/main/java/domain/LottoWinning.java +++ b/src/main/java/domain/LottoWinning.java @@ -41,7 +41,19 @@ private boolean isSameMatchBonusNumberCount(long matchBonusNumberCount) { return this.matchBonusNumberCount == matchBonusNumberCount; } - private long fetchWinningAmount() { + public long fetchWinningAmount() { return this.winningAmount; } + + public long fetchMatchWinningNumberCount() { + return this.matchWinningNumberCount; + } + + public boolean isMatchBonusNumber() { + return this.matchBonusNumberCount > 0; + } + + public boolean isEqual(LottoWinning lottoWinning) { + return this == lottoWinning; + } } diff --git a/src/main/java/domain/LottoWinnings.java b/src/main/java/domain/LottoWinnings.java index 5eea51b3d5..0c3272818b 100644 --- a/src/main/java/domain/LottoWinnings.java +++ b/src/main/java/domain/LottoWinnings.java @@ -24,4 +24,16 @@ private void validateNotEmpty(List lottoWinnings) { throw new DomainValidationException(ErrorCode.COLLECTION_MUST_NOT_BE_EMPTY, "당첨 정보는 null이거나 empty이면 안됩니다."); } } + + public long sumAllWinningAmount() { + return this.lottoWinnings.stream() + .mapToLong(LottoWinning::fetchWinningAmount) + .sum(); + } + + public long countMatchLottoWinning(LottoWinning lottoWinning) { + return this.lottoWinnings.stream() + .filter(lottoWinning::isEqual) + .count(); + } } diff --git a/src/main/java/exception/InvalidOutputException.java b/src/main/java/exception/InvalidOutputException.java new file mode 100644 index 0000000000..d9d9b76f1a --- /dev/null +++ b/src/main/java/exception/InvalidOutputException.java @@ -0,0 +1,13 @@ +package exception; + +import exception.code.ErrorCode; + +public class InvalidOutputException extends IllegalArgumentException { + + private final ErrorCode errorCode; + + public InvalidOutputException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = errorCode; + } +} diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index becb0c5ae6..4365d144df 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -12,5 +12,6 @@ public enum ErrorCode { COLLECTION_MUST_NOT_BE_EMPTY, NOT_UNIQUE_WINNING_NUMBERS, NOT_UNIQUE_LOTTO_NUMBERS, - WINNING_NUMBERS_CONTAIN_BONUS_NUMBER + WINNING_NUMBERS_CONTAIN_BONUS_NUMBER, + NOT_MATCHED_LOTTO_WINNING_OUTPUT } diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index 986062a2ce..26ea4f0d31 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -47,6 +47,7 @@ public WinningNumbersInput inputWinningNumbers() { public BonusNumberInput inputBonusNumber() { System.out.println(BONUS_NUMBER_NAVIGATION); String input = Console.readLine(); + System.out.println(); this.validateNumber(input); return new BonusNumberInput(Integer.parseInt(input)); diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java index 7faddce99a..92d05e3251 100644 --- a/src/main/java/view/output/ConsoleOutputView.java +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -1,11 +1,24 @@ package view.output; +import view.output.dto.LottoWinningStatisticsOutput; +import view.output.dto.LottoWinningsOutput; import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; public class ConsoleOutputView implements OutputView { private static final String PURCHASE_COUNT_NAVIGATION = "%d개를 구매했습니다."; + private static final String WINNING_STATISTICS_NAVIGATION = "당첨 통계"; + private static final String WINNING_SEPARATOR = "---------"; + + private static final String MATCH_WINNING_NUMBER_NAVIGATION = "%d개 일치"; + private static final String MATCH_BONUS_NUMBER_NAVIGATION = ", 보너스 볼 일치"; + private static final String WINNING_AMOUNT_NAVIGATION = " (%d원)"; + private static final String MATCH_COUNT_NAVIGATION = " - %d개"; + private static final String WINNING_REVENUE_RATE_NAVIGATION = "총 수익률은 %.2f입니다."; + private static final String LOTTO_LOSS_NAVIGATION = "(기준이 1이기 때문에 결과적으로 손해라는 의미임)"; + private static final String LOTTO_GAIN_NAVIGATION = "(기준이 1이기 때문에 결과적으로 이득이라는 의미임)"; + private static final String LOTTO_BREAK_EVEN_NAVIGATION = "(기준이 1이기 때문에 결과적으로 본전이라는 의미임)"; @Override public void viewPurchaseAmount(PurchaseOutput purchaseOutput) { @@ -18,7 +31,48 @@ public void viewLottos(LottosOutput lottosOutput) { } @Override - public void viewWinningResult() { + public void viewWinningStatistics(LottoWinningStatisticsOutput lottoWinningStatisticsOutput) { + System.out.println(WINNING_STATISTICS_NAVIGATION); + System.out.println(WINNING_SEPARATOR); + LottoWinningsOutput lottoWinningsOutput = lottoWinningStatisticsOutput.fetchWinningsOutput(); + double revenueRate = lottoWinningStatisticsOutput.fetchRevenueRate(); + lottoWinningsOutput.toList().forEach( + lottoWinningOutput -> + System.out.printf( + makeWinningStatisticsNavigation(lottoWinningOutput.isMatchBonusNumber()), + lottoWinningOutput.fetchMatchWinningNumberCount(), + lottoWinningOutput.fetchWinningAmount(), + lottoWinningOutput.fetchMatchCount() + ) + ); + System.out.printf(makeRevenueNavigation(revenueRate), revenueRate); + } + + private String makeWinningStatisticsNavigation(boolean matchBonusNumber) { + String bonusNavigation = ""; + + if (matchBonusNumber) { + bonusNavigation = MATCH_BONUS_NUMBER_NAVIGATION; + } + + return MATCH_WINNING_NUMBER_NAVIGATION + bonusNavigation + WINNING_AMOUNT_NAVIGATION + MATCH_COUNT_NAVIGATION + "\n"; + } + + private String makeRevenueNavigation(double revenueRate) { + String gainNavigation = ""; + + if (revenueRate > 1.0) { + gainNavigation = LOTTO_GAIN_NAVIGATION; + } + + if (revenueRate == 1.0) { + gainNavigation = LOTTO_BREAK_EVEN_NAVIGATION; + } + + if (revenueRate < 1.0) { + gainNavigation = LOTTO_LOSS_NAVIGATION; + } + return WINNING_REVENUE_RATE_NAVIGATION + gainNavigation; } } diff --git a/src/main/java/view/output/OutputView.java b/src/main/java/view/output/OutputView.java index cb2deb3534..b6d800fe94 100644 --- a/src/main/java/view/output/OutputView.java +++ b/src/main/java/view/output/OutputView.java @@ -1,5 +1,6 @@ package view.output; +import view.output.dto.LottoWinningStatisticsOutput; import view.output.dto.LottosOutput; import view.output.dto.PurchaseOutput; @@ -9,5 +10,5 @@ public interface OutputView { void viewLottos(LottosOutput lottosOutput); - void viewWinningResult(); + void viewWinningStatistics(LottoWinningStatisticsOutput lottoWinningStatisticsOutput); } diff --git a/src/main/java/view/output/dto/LottoRevenueRateCalculator.java b/src/main/java/view/output/dto/LottoRevenueRateCalculator.java new file mode 100644 index 0000000000..6878b01798 --- /dev/null +++ b/src/main/java/view/output/dto/LottoRevenueRateCalculator.java @@ -0,0 +1,21 @@ +package view.output.dto; + +import domain.LottoWinnings; +import domain.PurchaseAmount; + +public class LottoRevenueRateCalculator { + + private final LottoWinnings lottoWinnings; + private final PurchaseAmount purchaseAmount; + + public LottoRevenueRateCalculator(LottoWinnings lottoWinnings, PurchaseAmount purchaseAmount) { + this.lottoWinnings = lottoWinnings; + this.purchaseAmount = purchaseAmount; + } + + public double calculate() { + long totalWinningAmount = this.lottoWinnings.sumAllWinningAmount(); + + return (double) totalWinningAmount / purchaseAmount.fetchPurchaseAmount(); + } +} diff --git a/src/main/java/view/output/dto/LottoWinningOutput.java b/src/main/java/view/output/dto/LottoWinningOutput.java new file mode 100644 index 0000000000..a5429649a3 --- /dev/null +++ b/src/main/java/view/output/dto/LottoWinningOutput.java @@ -0,0 +1,46 @@ +package view.output.dto; + +import domain.LottoWinning; + +public class LottoWinningOutput { + + private final long matchWinningNumberCount; + + private final long winningAmount; + + private final boolean isMatchBonusNumber; + + private final long matchCount; + + public LottoWinningOutput(long matchWinningNumberCount, long winningAmount, boolean isMatchBonusNumber, long matchCount) { + this.matchWinningNumberCount = matchWinningNumberCount; + this.winningAmount = winningAmount; + this.isMatchBonusNumber = isMatchBonusNumber; + this.matchCount = matchCount; + } + + public static LottoWinningOutput of(LottoWinning lottoWinning, long matchCount) { + return new LottoWinningOutput( + lottoWinning.fetchMatchWinningNumberCount(), + lottoWinning.fetchWinningAmount(), + lottoWinning.isMatchBonusNumber(), + matchCount + ); + } + + public long fetchMatchWinningNumberCount() { + return matchWinningNumberCount; + } + + public long fetchWinningAmount() { + return winningAmount; + } + + public boolean isMatchBonusNumber() { + return isMatchBonusNumber; + } + + public long fetchMatchCount() { + return matchCount; + } +} diff --git a/src/main/java/view/output/dto/LottoWinningStatisticsOutput.java b/src/main/java/view/output/dto/LottoWinningStatisticsOutput.java new file mode 100644 index 0000000000..11b0606e5b --- /dev/null +++ b/src/main/java/view/output/dto/LottoWinningStatisticsOutput.java @@ -0,0 +1,30 @@ +package view.output.dto; + +import domain.LottoWinnings; +import domain.PurchaseAmount; + +public class LottoWinningStatisticsOutput { + + private final LottoWinningsOutput lottoWinningOutputs; + private final double revenueRate; + + public LottoWinningStatisticsOutput(LottoWinningsOutput lottoWinningOutputs, double revenueRate) { + this.lottoWinningOutputs = lottoWinningOutputs; + this.revenueRate = revenueRate; + } + + public static LottoWinningStatisticsOutput from(LottoWinnings lottoWinnings, PurchaseAmount purchaseAmount) { + return new LottoWinningStatisticsOutput( + LottoWinningsOutput.from(lottoWinnings), + new LottoRevenueRateCalculator(lottoWinnings, purchaseAmount).calculate() + ); + } + + public LottoWinningsOutput fetchWinningsOutput() { + return this.lottoWinningOutputs; + } + + public double fetchRevenueRate() { + return this.revenueRate; + } +} diff --git a/src/main/java/view/output/dto/LottoWinningsOutput.java b/src/main/java/view/output/dto/LottoWinningsOutput.java new file mode 100644 index 0000000000..a878d6d153 --- /dev/null +++ b/src/main/java/view/output/dto/LottoWinningsOutput.java @@ -0,0 +1,34 @@ +package view.output.dto; + +import domain.LottoWinning; +import domain.LottoWinnings; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class LottoWinningsOutput { + + private final List lottoWinningOutputs; + + public LottoWinningsOutput(List lottoWinningOutputs) { + this.lottoWinningOutputs = lottoWinningOutputs; + } + + public static LottoWinningsOutput from(LottoWinnings lottoWinnings) { + return new LottoWinningsOutput( + Arrays.stream(LottoWinning.values()) + .filter(lottoWinning -> !lottoWinning.isEqual(LottoWinning.ELSE_PLACE)) + .map(lottoWinning -> + LottoWinningOutput.of(lottoWinning, lottoWinnings.countMatchLottoWinning(lottoWinning)) + ) + .sorted(Comparator.comparing(LottoWinningOutput::fetchWinningAmount)) + .collect(Collectors.toList()) + ); + } + + public List toList() { + return List.copyOf(this.lottoWinningOutputs); + } +} From 3f6be4f60c4a762a6cce3fff2184f4a0c6c14ac7 Mon Sep 17 00:00:00 2001 From: kilian Date: Sat, 18 May 2024 22:24:20 +0900 Subject: [PATCH 22/26] =?UTF-8?q?feat=20:=20=EB=8B=B9=EC=B2=A8=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/controller/LottoSimulator.java | 4 ++-- ...ttosResultCalculator.java => LottosWinningCalculator.java} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/domain/{LottosResultCalculator.java => LottosWinningCalculator.java} (88%) diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index 5cb2b74f6f..ab9c2be478 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -34,8 +34,8 @@ public void run() { BonusNumberInput bonusNumberInput = inputView.inputBonusNumber(); BonusNumber bonusNumber = bonusNumberInput.toBonusNumber(); - LottosResultCalculator lottosResultCalculator = new LottosResultCalculator(lottos, winningNumbers, bonusNumber); - LottoWinnings lottoWinnings = lottosResultCalculator.calculate(); + LottosWinningCalculator lottosWinningCalculator = new LottosWinningCalculator(lottos, winningNumbers, bonusNumber); + LottoWinnings lottoWinnings = lottosWinningCalculator.calculate(); LottoWinningStatisticsOutput lottoWinningStatisticsOutput = LottoWinningStatisticsOutput.from(lottoWinnings, purchaseAmount); outputView.viewWinningStatistics(lottoWinningStatisticsOutput); } diff --git a/src/main/java/domain/LottosResultCalculator.java b/src/main/java/domain/LottosWinningCalculator.java similarity index 88% rename from src/main/java/domain/LottosResultCalculator.java rename to src/main/java/domain/LottosWinningCalculator.java index 354d2696c4..e719f37a6c 100644 --- a/src/main/java/domain/LottosResultCalculator.java +++ b/src/main/java/domain/LottosWinningCalculator.java @@ -6,13 +6,13 @@ import static exception.code.ErrorCode.WINNING_NUMBERS_CONTAIN_BONUS_NUMBER; -public class LottosResultCalculator { +public class LottosWinningCalculator { private final Lottos lottos; private final WinningNumbers winningNumbers; private final BonusNumber bonusNumber; - public LottosResultCalculator(Lottos lottos, WinningNumbers winningNumbers, BonusNumber bonusNumber) { + public LottosWinningCalculator(Lottos lottos, WinningNumbers winningNumbers, BonusNumber bonusNumber) { this.validateBonusNumberNotContainWinningNumber(winningNumbers, bonusNumber); this.lottos = lottos; this.winningNumbers = winningNumbers; From d3ecc045e48097a58ad5cb16f5efd2807738a528 Mon Sep 17 00:00:00 2001 From: kilian Date: Sun, 19 May 2024 17:26:10 +0900 Subject: [PATCH 23/26] =?UTF-8?q?feat=20:=20=EC=88=98=EB=8F=99=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + src/main/java/controller/LottoSimulator.java | 20 ++++---- src/main/java/domain/AutoPurchaseCount.java | 11 +++++ src/main/java/domain/Lottos.java | 8 ++++ src/main/java/domain/ManualPurchaseCount.java | 12 +++++ src/main/java/domain/PurchaseAmount.java | 8 +++- src/main/java/domain/PurchaseCount.java | 11 ++--- .../java/domain/PurchaseCountCalculator.java | 17 ++++++- src/main/java/exception/code/ErrorCode.java | 1 + src/main/java/util/StringUtils.java | 9 ++++ .../java/view/input/ConsoleInputView.java | 46 +++++++++++++++---- src/main/java/view/input/InputView.java | 8 ++-- .../input/dto/ManualLottoNumberInput.java | 19 ++++++++ .../input/dto/ManualLottoNumbersInput.java | 24 ++++++++++ .../input/dto/ManualPurchaseCountInput.java | 16 +++++++ .../java/view/output/ConsoleOutputView.java | 14 ++++-- src/main/java/view/output/OutputView.java | 4 +- .../view/output/dto/PurchaseCountOutput.java | 26 +++++++++++ .../java/view/output/dto/PurchaseOutput.java | 20 -------- 19 files changed, 217 insertions(+), 59 deletions(-) create mode 100644 src/main/java/domain/AutoPurchaseCount.java create mode 100644 src/main/java/domain/ManualPurchaseCount.java create mode 100644 src/main/java/view/input/dto/ManualLottoNumberInput.java create mode 100644 src/main/java/view/input/dto/ManualLottoNumbersInput.java create mode 100644 src/main/java/view/input/dto/ManualPurchaseCountInput.java create mode 100644 src/main/java/view/output/dto/PurchaseCountOutput.java delete mode 100644 src/main/java/view/output/dto/PurchaseOutput.java diff --git a/README.md b/README.md index 8a3e9d8482..873eb4ab02 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ ## 구현 기능 목록 - [x] 구입 금액 사용자 입력을 받는다. +- [x] 수동으로 구매할 로또 수를 입력한다. +- [x] 수동으로 구매할 번호를 입력한다. - [x] 구입 금액에 맞춰 로또를 구입 갯수를 계산한다. - [x] 구입한 로또의 갯수를 출력한다. - [x] 구입한 로또의 목록을 생성한다. diff --git a/src/main/java/controller/LottoSimulator.java b/src/main/java/controller/LottoSimulator.java index ab9c2be478..6a04ba2e91 100644 --- a/src/main/java/controller/LottoSimulator.java +++ b/src/main/java/controller/LottoSimulator.java @@ -3,14 +3,12 @@ import domain.*; import view.input.ConsoleInputView; import view.input.InputView; -import view.input.dto.BonusNumberInput; -import view.input.dto.PurchaseInput; -import view.input.dto.WinningNumbersInput; +import view.input.dto.*; import view.output.ConsoleOutputView; import view.output.OutputView; import view.output.dto.LottoWinningStatisticsOutput; import view.output.dto.LottosOutput; -import view.output.dto.PurchaseOutput; +import view.output.dto.PurchaseCountOutput; public class LottoSimulator { @@ -20,12 +18,18 @@ public void run() { PurchaseInput purchaseInput = inputView.inputPurchaseAmount(); PurchaseAmount purchaseAmount = purchaseInput.toPurchaseAmount(); + + ManualPurchaseCountInput manualPurchaseCountInput = inputView.inputManualPurchaseCount(); + PurchaseCount manualPurchaseCount = manualPurchaseCountInput.toManualPurchaseCount(); + ManualLottoNumbersInput manualLottoNumbersInput = inputView.inputManualLottoNumbers(manualPurchaseCount.fetchPurchaseCount()); PurchaseCountCalculator purchaseCountCalculator = new PurchaseCountCalculator(purchaseAmount); - PurchaseCount purchaseCount = purchaseCountCalculator.calculate(); - outputView.viewPurchaseAmount(PurchaseOutput.from(purchaseCount)); + PurchaseCount autoPurchaseCount = purchaseCountCalculator.calculateAutoPurchaseCount(manualPurchaseCount); + outputView.viewPurchaseCount(PurchaseCountOutput.of(manualPurchaseCount, autoPurchaseCount)); - LottosGenerator lottosGenerator = new LottosGenerator(purchaseCount); - Lottos lottos = lottosGenerator.generate(); + LottosGenerator lottosGenerator = new LottosGenerator(autoPurchaseCount); + Lottos manualLottos = manualLottoNumbersInput.toLottos(); + Lottos autoLottos = lottosGenerator.generate(); + Lottos lottos = manualLottos.addLottos(autoLottos); outputView.viewLottos(LottosOutput.from(lottos)); WinningNumbersInput winningNumbersInput = inputView.inputWinningNumbers(); diff --git a/src/main/java/domain/AutoPurchaseCount.java b/src/main/java/domain/AutoPurchaseCount.java new file mode 100644 index 0000000000..44ab32adbc --- /dev/null +++ b/src/main/java/domain/AutoPurchaseCount.java @@ -0,0 +1,11 @@ +package domain; + +public class AutoPurchaseCount extends PurchaseCount { + private AutoPurchaseCount(int purchaseCount) { + super(purchaseCount); + } + + public static AutoPurchaseCount create(int purchaseCount) { + return new AutoPurchaseCount(purchaseCount); + } +} diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java index 91edea8cf7..2a0e778868 100644 --- a/src/main/java/domain/Lottos.java +++ b/src/main/java/domain/Lottos.java @@ -1,5 +1,6 @@ package domain; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -24,4 +25,11 @@ public List findLottoWinnings(WinningNumbers winningNumbers, Bonus .map(lotto -> lotto.findLottoWinning(winningNumbers, bonusNumber)) .collect(Collectors.toList()); } + + public Lottos addLottos(Lottos lottos) { + List copyLottos = new ArrayList<>(List.copyOf(this.lottos)); + copyLottos.addAll(lottos.toList()); + + return new Lottos(copyLottos); + } } diff --git a/src/main/java/domain/ManualPurchaseCount.java b/src/main/java/domain/ManualPurchaseCount.java new file mode 100644 index 0000000000..ad3eef2063 --- /dev/null +++ b/src/main/java/domain/ManualPurchaseCount.java @@ -0,0 +1,12 @@ +package domain; + +public class ManualPurchaseCount extends PurchaseCount { + + private ManualPurchaseCount(int purchaseCount) { + super(purchaseCount); + } + + public static ManualPurchaseCount create(int purchaseCount) { + return new ManualPurchaseCount(purchaseCount); + } +} diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index 2f4648b8ef..ce0b571e3a 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -2,7 +2,7 @@ import exception.DomainValidationException; -import static exception.code.ErrorCode.*; +import static exception.code.ErrorCode.INVALID_PURCHASE_AMOUNT; public class PurchaseAmount { @@ -22,8 +22,12 @@ public int fetchPurchaseAmount() { } private void validateAmount(int purchaseAmount) { - if(purchaseAmount <= 0) { + if (purchaseAmount <= 0) { throw new DomainValidationException(INVALID_PURCHASE_AMOUNT, "구입 금액은 0보다 커야합니다."); } } + + public boolean isLowerThan(int purchaseAmount) { + return this.purchaseAmount < purchaseAmount; + } } diff --git a/src/main/java/domain/PurchaseCount.java b/src/main/java/domain/PurchaseCount.java index 49e94e2c26..6ef8b03b61 100644 --- a/src/main/java/domain/PurchaseCount.java +++ b/src/main/java/domain/PurchaseCount.java @@ -1,25 +1,20 @@ package domain; import exception.DomainValidationException; -import view.output.dto.PurchaseOutput; import static exception.code.ErrorCode.INVALID_PURCHASE_COUNT; -public class PurchaseCount { +public abstract class PurchaseCount { private final int purchaseCount; - private PurchaseCount(int purchaseCount) { + protected PurchaseCount(int purchaseCount) { this.validatePurchaseCount(purchaseCount); this.purchaseCount = purchaseCount; } - public static PurchaseCount create(int purchaseCount) { - return new PurchaseCount(purchaseCount); - } - private void validatePurchaseCount(int purchaseCount) { - if(purchaseCount < 1) { + if (purchaseCount < 1) { throw new DomainValidationException(INVALID_PURCHASE_COUNT, "구입 갯수는 1개이상이어야 합니다."); } } diff --git a/src/main/java/domain/PurchaseCountCalculator.java b/src/main/java/domain/PurchaseCountCalculator.java index 444069647e..5c03b4c1a4 100644 --- a/src/main/java/domain/PurchaseCountCalculator.java +++ b/src/main/java/domain/PurchaseCountCalculator.java @@ -1,5 +1,8 @@ package domain; +import exception.DomainValidationException; +import exception.code.ErrorCode; + import static constant.LottoConstants.LOTTO_PRICE; public class PurchaseCountCalculator { @@ -10,7 +13,17 @@ public PurchaseCountCalculator(PurchaseAmount purchaseAmount) { this.purchaseAmount = purchaseAmount; } - public PurchaseCount calculate() { - return PurchaseCount.create(this.purchaseAmount.fetchPurchaseAmount() / LOTTO_PRICE); + public AutoPurchaseCount calculateAutoPurchaseCount(PurchaseCount manualPurchaseCount) { + this.validateEnablePurchaseAmount(manualPurchaseCount); + + return AutoPurchaseCount.create( + this.purchaseAmount.fetchPurchaseAmount() / LOTTO_PRICE - manualPurchaseCount.fetchPurchaseCount() + ); + } + + private void validateEnablePurchaseAmount(PurchaseCount purchaseCount) { + if (this.purchaseAmount.isLowerThan(LOTTO_PRICE * purchaseCount.fetchPurchaseCount())) { + throw new DomainValidationException(ErrorCode.NOT_ENOUGH_PURCHASE_AMOUNT, "구입 금액이 부족합니다."); + } } } diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index 4365d144df..b4a508364f 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -12,6 +12,7 @@ public enum ErrorCode { COLLECTION_MUST_NOT_BE_EMPTY, NOT_UNIQUE_WINNING_NUMBERS, NOT_UNIQUE_LOTTO_NUMBERS, + NOT_ENOUGH_PURCHASE_AMOUNT, WINNING_NUMBERS_CONTAIN_BONUS_NUMBER, NOT_MATCHED_LOTTO_WINNING_OUTPUT } diff --git a/src/main/java/util/StringUtils.java b/src/main/java/util/StringUtils.java index 920ec64e23..4a6003034a 100644 --- a/src/main/java/util/StringUtils.java +++ b/src/main/java/util/StringUtils.java @@ -1,6 +1,9 @@ package util; +import java.util.Arrays; +import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; public abstract class StringUtils { @@ -9,4 +12,10 @@ public abstract class StringUtils { public static boolean isNumeric(String str) { return Objects.nonNull(str) && str.matches(NUMERIC_PATTERN); } + + public static List splitStrToNumbers(String delimiter, String input) { + return Arrays.stream(input.split(delimiter)) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/view/input/ConsoleInputView.java b/src/main/java/view/input/ConsoleInputView.java index 26ea4f0d31..f3da6bb4e9 100644 --- a/src/main/java/view/input/ConsoleInputView.java +++ b/src/main/java/view/input/ConsoleInputView.java @@ -4,12 +4,10 @@ import util.Console; import util.PatternMatchUtils; import util.StringUtils; -import view.input.dto.BonusNumberInput; -import view.input.dto.PurchaseInput; -import view.input.dto.WinningNumbersInput; +import view.input.dto.*; -import java.util.Arrays; import java.util.stream.Collectors; +import java.util.stream.IntStream; import static exception.code.ErrorCode.INVALID_NUMBERS_INPUT; import static exception.code.ErrorCode.INVALID_NUMBER_INPUT; @@ -17,6 +15,8 @@ public class ConsoleInputView implements InputView { private static final String PURCHASE_AMOUNT_NAVIGATION = "구입금액을 입력해 주세요."; + private static final String MANUAL_PURCHASE_COUNT_NAVIGATION = "수동으로 구매할 로또 수를 입력해 주세요."; + private static final String MANUAL_LOTTO_NUMBERS_NAVIGATION = "수동으로 구매할 번호를 입력해 주세요."; private static final String WINNING_NUMBERS_NAVIGATION = "지난 주 당첨 번호를 입력해 주세요."; private static final String BONUS_NUMBER_NAVIGATION = "보너스 볼을 입력해 주세요."; private static final String NUMBERS_INPUT_REGEX = "^\\d{1,2}(,\\s\\d{1,2}){5}$"; @@ -26,21 +26,49 @@ public PurchaseInput inputPurchaseAmount() { System.out.println(PURCHASE_AMOUNT_NAVIGATION); String input = Console.readLine(); this.validateNumber(input); + System.out.println(); return new PurchaseInput(Integer.parseInt(input)); } + @Override + public ManualPurchaseCountInput inputManualPurchaseCount() { + System.out.println(MANUAL_PURCHASE_COUNT_NAVIGATION); + String input = Console.readLine(); + this.validateNumber(input); + System.out.println(); + + return new ManualPurchaseCountInput(Integer.parseInt(input)); + } + + @Override + public ManualLottoNumbersInput inputManualLottoNumbers(int manualPurchaseCount) { + System.out.println(MANUAL_LOTTO_NUMBERS_NAVIGATION); + + ManualLottoNumbersInput manualLottoNumbersInput = new ManualLottoNumbersInput( + IntStream.range(0, manualPurchaseCount) + .mapToObj(count -> { + String input = Console.readLine(); + this.validateNumbers(input); + + return input; + }) + .map(input -> StringUtils.splitStrToNumbers(", ", input)) + .map(ManualLottoNumberInput::new) + .collect(Collectors.toList()) + ); + System.out.println(); + + return manualLottoNumbersInput; + } + @Override public WinningNumbersInput inputWinningNumbers() { System.out.println(WINNING_NUMBERS_NAVIGATION); String input = Console.readLine(); this.validateNumbers(input); - return new WinningNumbersInput( - Arrays.stream(input.split(", ")) - .map(Integer::parseInt) - .collect(Collectors.toList()) - ); + return new WinningNumbersInput(StringUtils.splitStrToNumbers(", ", input)); } @Override diff --git a/src/main/java/view/input/InputView.java b/src/main/java/view/input/InputView.java index 33ce17c451..109fc07c62 100644 --- a/src/main/java/view/input/InputView.java +++ b/src/main/java/view/input/InputView.java @@ -1,13 +1,15 @@ package view.input; -import view.input.dto.BonusNumberInput; -import view.input.dto.PurchaseInput; -import view.input.dto.WinningNumbersInput; +import view.input.dto.*; public interface InputView { PurchaseInput inputPurchaseAmount(); + ManualPurchaseCountInput inputManualPurchaseCount(); + + ManualLottoNumbersInput inputManualLottoNumbers(int manualPurchaseCount); + WinningNumbersInput inputWinningNumbers(); BonusNumberInput inputBonusNumber(); diff --git a/src/main/java/view/input/dto/ManualLottoNumberInput.java b/src/main/java/view/input/dto/ManualLottoNumberInput.java new file mode 100644 index 0000000000..3d22d18fb8 --- /dev/null +++ b/src/main/java/view/input/dto/ManualLottoNumberInput.java @@ -0,0 +1,19 @@ +package view.input.dto; + +import domain.Lotto; + +import java.util.List; + +public class ManualLottoNumberInput { + + private final List lottoNumbers; + + public ManualLottoNumberInput(List lottoNumbers) { + this.lottoNumbers = lottoNumbers; + } + + public Lotto toLotto() { + return Lotto.create(lottoNumbers); + } +} + diff --git a/src/main/java/view/input/dto/ManualLottoNumbersInput.java b/src/main/java/view/input/dto/ManualLottoNumbersInput.java new file mode 100644 index 0000000000..f5f7262d77 --- /dev/null +++ b/src/main/java/view/input/dto/ManualLottoNumbersInput.java @@ -0,0 +1,24 @@ +package view.input.dto; + +import domain.Lottos; + +import java.util.List; +import java.util.stream.Collectors; + +public class ManualLottoNumbersInput { + + private final List lottos; + + public ManualLottoNumbersInput(List lottos) { + this.lottos = lottos; + } + + public Lottos toLottos() { + return Lottos.create( + this.lottos.stream() + .map(ManualLottoNumberInput::toLotto) + .collect(Collectors.toList()) + ); + } + +} diff --git a/src/main/java/view/input/dto/ManualPurchaseCountInput.java b/src/main/java/view/input/dto/ManualPurchaseCountInput.java new file mode 100644 index 0000000000..d8eb7bc7fb --- /dev/null +++ b/src/main/java/view/input/dto/ManualPurchaseCountInput.java @@ -0,0 +1,16 @@ +package view.input.dto; + +import domain.ManualPurchaseCount; + +public class ManualPurchaseCountInput { + + private final int manualPurchaseCount; + + public ManualPurchaseCountInput(int manualPurchaseCount) { + this.manualPurchaseCount = manualPurchaseCount; + } + + public ManualPurchaseCount toManualPurchaseCount() { + return ManualPurchaseCount.create(this.manualPurchaseCount); + } +} diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java index 92d05e3251..25b39d132f 100644 --- a/src/main/java/view/output/ConsoleOutputView.java +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -3,11 +3,11 @@ import view.output.dto.LottoWinningStatisticsOutput; import view.output.dto.LottoWinningsOutput; import view.output.dto.LottosOutput; -import view.output.dto.PurchaseOutput; +import view.output.dto.PurchaseCountOutput; public class ConsoleOutputView implements OutputView { - private static final String PURCHASE_COUNT_NAVIGATION = "%d개를 구매했습니다."; + private static final String PURCHASE_COUNT_NAVIGATION = "수동으로 %d장, 자동으로 %d개를 구매했습니다."; private static final String WINNING_STATISTICS_NAVIGATION = "당첨 통계"; private static final String WINNING_SEPARATOR = "---------"; @@ -21,8 +21,12 @@ public class ConsoleOutputView implements OutputView { private static final String LOTTO_BREAK_EVEN_NAVIGATION = "(기준이 1이기 때문에 결과적으로 본전이라는 의미임)"; @Override - public void viewPurchaseAmount(PurchaseOutput purchaseOutput) { - System.out.printf((PURCHASE_COUNT_NAVIGATION) + "%n", purchaseOutput.fetchPurchaseCount()); + public void viewPurchaseCount(PurchaseCountOutput purchaseCountOutput) { + System.out.printf( + PURCHASE_COUNT_NAVIGATION + "%n", + purchaseCountOutput.fetchManualPurchaseCount(), + purchaseCountOutput.fetchAutoPurchaseCount() + ); } @Override @@ -45,7 +49,7 @@ public void viewWinningStatistics(LottoWinningStatisticsOutput lottoWinningStati lottoWinningOutput.fetchMatchCount() ) ); - System.out.printf(makeRevenueNavigation(revenueRate), revenueRate); + System.out.printf(makeRevenueNavigation(revenueRate), Math.floor(revenueRate * 100) / 100.0); } private String makeWinningStatisticsNavigation(boolean matchBonusNumber) { diff --git a/src/main/java/view/output/OutputView.java b/src/main/java/view/output/OutputView.java index b6d800fe94..9608278c61 100644 --- a/src/main/java/view/output/OutputView.java +++ b/src/main/java/view/output/OutputView.java @@ -2,11 +2,11 @@ import view.output.dto.LottoWinningStatisticsOutput; import view.output.dto.LottosOutput; -import view.output.dto.PurchaseOutput; +import view.output.dto.PurchaseCountOutput; public interface OutputView { - void viewPurchaseAmount(PurchaseOutput purchaseOutput); + void viewPurchaseCount(PurchaseCountOutput purchaseCountOutput); void viewLottos(LottosOutput lottosOutput); diff --git a/src/main/java/view/output/dto/PurchaseCountOutput.java b/src/main/java/view/output/dto/PurchaseCountOutput.java new file mode 100644 index 0000000000..53c3952f91 --- /dev/null +++ b/src/main/java/view/output/dto/PurchaseCountOutput.java @@ -0,0 +1,26 @@ +package view.output.dto; + +import domain.PurchaseCount; + +public class PurchaseCountOutput { + + private final int manualPurchaseCount; + private final int autoPurchaseCount; + + private PurchaseCountOutput(int manualPurchaseCount, int autoPurchaseCount) { + this.manualPurchaseCount = manualPurchaseCount; + this.autoPurchaseCount = autoPurchaseCount; + } + + public static PurchaseCountOutput of(PurchaseCount manualPurchaseCount, PurchaseCount autoPurchaseCount) { + return new PurchaseCountOutput(manualPurchaseCount.fetchPurchaseCount(), autoPurchaseCount.fetchPurchaseCount()); + } + + public int fetchManualPurchaseCount() { + return this.manualPurchaseCount; + } + + public int fetchAutoPurchaseCount() { + return this.autoPurchaseCount; + } +} diff --git a/src/main/java/view/output/dto/PurchaseOutput.java b/src/main/java/view/output/dto/PurchaseOutput.java deleted file mode 100644 index 0d10ae171a..0000000000 --- a/src/main/java/view/output/dto/PurchaseOutput.java +++ /dev/null @@ -1,20 +0,0 @@ -package view.output.dto; - -import domain.PurchaseCount; - -public class PurchaseOutput { - - private final int purchaseCount; - - public PurchaseOutput(int purchaseCount) { - this.purchaseCount = purchaseCount; - } - - public static PurchaseOutput from(PurchaseCount purchaseCount) { - return new PurchaseOutput(purchaseCount.fetchPurchaseCount()); - } - - public int fetchPurchaseCount() { - return this.purchaseCount; - } -} From 3c51b34387012a6dccf1e7db67b8acecbf6700df Mon Sep 17 00:00:00 2001 From: kilian Date: Sun, 19 May 2024 18:16:33 +0900 Subject: [PATCH 24/26] =?UTF-8?q?test=20:=20=EA=B5=AC=EB=A7=A4=20=EA=B0=AF?= =?UTF-8?q?=EC=88=98=20=EA=B3=84=EC=82=B0=EA=B8=B0=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/DomainValidationException.java | 4 ++ .../domain/PurchaseCountCalculatorTest.java | 45 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/test/java/domain/PurchaseCountCalculatorTest.java diff --git a/src/main/java/exception/DomainValidationException.java b/src/main/java/exception/DomainValidationException.java index cc0f270fe5..8677a15745 100644 --- a/src/main/java/exception/DomainValidationException.java +++ b/src/main/java/exception/DomainValidationException.java @@ -10,4 +10,8 @@ public DomainValidationException(ErrorCode errorCode, String message) { super(message); this.errorCode = errorCode; } + + public ErrorCode fetchErrorCode() { + return this.errorCode; + } } diff --git a/src/test/java/domain/PurchaseCountCalculatorTest.java b/src/test/java/domain/PurchaseCountCalculatorTest.java new file mode 100644 index 0000000000..cf7df0dc21 --- /dev/null +++ b/src/test/java/domain/PurchaseCountCalculatorTest.java @@ -0,0 +1,45 @@ +package domain; + +import constant.LottoConstants; +import exception.DomainValidationException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static exception.code.ErrorCode.NOT_ENOUGH_PURCHASE_AMOUNT; + +class PurchaseCountCalculatorTest { + + @Test + @DisplayName("자동 구입 갯수는 수동 구입 갯수를 제외한 나머지를 구매한다.") + void autoPurchaseCountIsAllMinusManualPurchaseCount() { + int purchaseAmountValue = 14000; + int manualCountValue = 10; + + PurchaseAmount purchaseAmount = PurchaseAmount.create(purchaseAmountValue); + PurchaseCount manualPurchaseCount = ManualPurchaseCount.create(manualCountValue); + PurchaseCountCalculator purchaseCountCalculator = new PurchaseCountCalculator(purchaseAmount); + AutoPurchaseCount autoPurchaseCount = purchaseCountCalculator.calculateAutoPurchaseCount(manualPurchaseCount); + + Assertions.assertEquals( + autoPurchaseCount.fetchPurchaseCount(), + (purchaseAmountValue - (LottoConstants.LOTTO_PRICE * manualCountValue)) / LottoConstants.LOTTO_PRICE + ); + } + + @Test + @DisplayName("수동 구매 금액이 구매 금액보다 큰 경우 예외를 발생시킨다.") + void manualPurchaseGreaterThanPurchaseAmount() { + PurchaseAmount purchaseAmount = PurchaseAmount.create(10); + PurchaseCount manualPurchaseCount = ManualPurchaseCount.create(20); + PurchaseCountCalculator purchaseCountCalculator = new PurchaseCountCalculator(purchaseAmount); + + DomainValidationException domainValidationException = Assertions.assertThrows( + DomainValidationException.class, + () -> purchaseCountCalculator.calculateAutoPurchaseCount(manualPurchaseCount) + ); + Assertions.assertSame(domainValidationException.fetchErrorCode(), NOT_ENOUGH_PURCHASE_AMOUNT); + } + + +} \ No newline at end of file From 9bc70a9f1bdcc5f71906454ef9708a32d679e882 Mon Sep 17 00:00:00 2001 From: kilian Date: Sun, 19 May 2024 18:54:24 +0900 Subject: [PATCH 25/26] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/constant/LottoConstants.java | 1 + src/main/java/domain/Lotto.java | 15 ++-- src/main/java/domain/LottosGenerator.java | 7 +- src/main/java/exception/code/ErrorCode.java | 1 + src/test/java/domain/LottoTest.java | 91 +++++++++++++++++++++ 5 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 src/test/java/domain/LottoTest.java diff --git a/src/main/java/constant/LottoConstants.java b/src/main/java/constant/LottoConstants.java index 3b2467a093..a9d5d7ad08 100644 --- a/src/main/java/constant/LottoConstants.java +++ b/src/main/java/constant/LottoConstants.java @@ -5,4 +5,5 @@ public abstract class LottoConstants { public static final int MIN_LOTTO_NUMBER_INCLUSIVE = 1; public static final int MAX_LOTTO_NUMBER_INCLUSIVE = 45; public static final int LOTTO_PRICE = 1000; + public static final int LOTTO_NUMBERS_SIZE = 6; } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 6723fdd26f..0666f29269 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -1,13 +1,11 @@ package domain; import exception.DomainValidationException; -import util.CollectionUtils; import java.util.HashSet; import java.util.List; -import static constant.LottoConstants.MAX_LOTTO_NUMBER_INCLUSIVE; -import static constant.LottoConstants.MIN_LOTTO_NUMBER_INCLUSIVE; +import static constant.LottoConstants.*; import static exception.code.ErrorCode.*; public class Lotto { @@ -15,7 +13,7 @@ public class Lotto { private final List lottoNumbers; private Lotto(List lottoNumbers) { - this.validateLottoNumbersNotEmpty(lottoNumbers); + this.validateLottoNumbersSize(lottoNumbers); this.validateLottoNumbersUnique(lottoNumbers); this.validateLottoNumbersInRange(lottoNumbers); this.lottoNumbers = lottoNumbers; @@ -37,9 +35,12 @@ private void validateLottoNumbersInRange(List lottoNumbers) { } } - private void validateLottoNumbersNotEmpty(List lottoNumbers) { - if (CollectionUtils.isEmpty(lottoNumbers)) { - throw new DomainValidationException(COLLECTION_MUST_NOT_BE_EMPTY, "로또 번호는 null이거나 empty하면 안됩니다."); + private void validateLottoNumbersSize(List lottoNumbers) { + if (lottoNumbers.size() != LOTTO_NUMBERS_SIZE) { + throw new DomainValidationException( + INVALID_LOTTO_NUMBERS_SIZE, + String.format("로또 번호의 갯수는 %d개여야 합니다.", LOTTO_NUMBERS_SIZE) + ); } } diff --git a/src/main/java/domain/LottosGenerator.java b/src/main/java/domain/LottosGenerator.java index a241e9028a..329b2196a4 100644 --- a/src/main/java/domain/LottosGenerator.java +++ b/src/main/java/domain/LottosGenerator.java @@ -5,13 +5,10 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static constant.LottoConstants.MAX_LOTTO_NUMBER_INCLUSIVE; -import static constant.LottoConstants.MIN_LOTTO_NUMBER_INCLUSIVE; +import static constant.LottoConstants.*; public class LottosGenerator { - - private static final int LOTTO_NUMBERS_SIZE = 6; - + private static final List totalLottoNumbers = IntStream.range(MIN_LOTTO_NUMBER_INCLUSIVE, MAX_LOTTO_NUMBER_INCLUSIVE) .boxed() diff --git a/src/main/java/exception/code/ErrorCode.java b/src/main/java/exception/code/ErrorCode.java index b4a508364f..0dd82ab3fe 100644 --- a/src/main/java/exception/code/ErrorCode.java +++ b/src/main/java/exception/code/ErrorCode.java @@ -5,6 +5,7 @@ public enum ErrorCode { INVALID_NUMBER_INPUT, INVALID_RANGE_NUMBERS_INPUT, INVALID_NUMBERS_INPUT, + INVALID_LOTTO_NUMBERS_SIZE, INVALID_PURCHASE_COUNT, INVALID_LOTTO_NUMBER_RANGE, INVALID_BONUS_NUMBER_RANGE, diff --git a/src/test/java/domain/LottoTest.java b/src/test/java/domain/LottoTest.java new file mode 100644 index 0000000000..2c7aeeadd8 --- /dev/null +++ b/src/test/java/domain/LottoTest.java @@ -0,0 +1,91 @@ +package domain; + +import exception.DomainValidationException; +import org.junit.jupiter.api.Assertions; +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.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static exception.code.ErrorCode.*; + +class LottoTest { + + + static Stream invalidLottoRange() { + return Stream.of( + Arguments.arguments(List.of(0, 1, 2, 3, 4, 5)), + Arguments.arguments(List.of(1, 2, 3, 4, 5, 46)), + Arguments.arguments(List.of(-1, -2, -3, -4, -5, -6)) + ); + } + + static Stream invalidLottoNumbersSize() { + return Stream.of( + Arguments.arguments(List.of(1, 2, 3, 4)), + Arguments.arguments(List.of(1, 2, 3, 4, 5)), + Arguments.arguments(List.of(1, 2, 3, 4, 5, 6, 7)), + Arguments.arguments(Collections.emptyList()) + ); + } + + static Stream lottoNumbersAndWinning() { + return Stream.of( + Arguments.arguments(List.of(1, 2, 3, 4, 5, 6), 15, LottoWinning.FIRST_PLACE), + Arguments.arguments(List.of(1, 2, 3, 4, 5, 7), 6, LottoWinning.SECOND_PLACE), + Arguments.arguments(List.of(1, 2, 3, 4, 5, 8), 15, LottoWinning.THIRD_PLACE), + Arguments.arguments(List.of(1, 2, 3, 4, 8, 9), 15, LottoWinning.FOURTH_PLACE), + Arguments.arguments(List.of(1, 2, 3, 8, 9, 10), 15, LottoWinning.FIFTH_PLACE) + ); + } + + @ParameterizedTest(name = "로또 번호 : {0}") + @MethodSource("invalidLottoRange") + @DisplayName("로또 번호는 범위 안에 있어야 한다.") + void lottoInRange(List lottoNumbers) { + DomainValidationException domainValidationException = + Assertions.assertThrows(DomainValidationException.class, () -> Lotto.create(lottoNumbers)); + + Assertions.assertSame(domainValidationException.fetchErrorCode(), INVALID_LOTTO_NUMBER_RANGE); + } + + @ParameterizedTest(name = "로또 번호 : {0}") + @MethodSource("invalidLottoNumbersSize") + @DisplayName("로또의 갯수는 정해져있어야 한다.") + void lottoNumbersFixed(List lottoNumbers) { + DomainValidationException domainValidationException = + Assertions.assertThrows(DomainValidationException.class, () -> Lotto.create(lottoNumbers)); + + Assertions.assertSame(domainValidationException.fetchErrorCode(), INVALID_LOTTO_NUMBERS_SIZE); + } + + @Test + @DisplayName("로또는 모두 다른 값이여야 한다.") + void lottoNumbersAllUnique() { + List lottoNumbers = List.of(1, 1, 2, 3, 4, 5); + DomainValidationException domainValidationException = + Assertions.assertThrows(DomainValidationException.class, () -> Lotto.create(lottoNumbers)); + + Assertions.assertSame(domainValidationException.fetchErrorCode(), NOT_UNIQUE_LOTTO_NUMBERS); + } + + @ParameterizedTest(name = "당첨번호 : {0}, 보너스 번호 : {1}, 당첨 : {2}") + @MethodSource("lottoNumbersAndWinning") + @DisplayName("로또 번호에 따라 당첨 정보를 찾는다.") + void findLottoWinning(List numbers, int bonus, LottoWinning lottoWinning) { + WinningNumbers winningNumbers = WinningNumbers.create(numbers.stream() + .map(WinningNumber::create) + .collect(Collectors.toList()) + ); + BonusNumber bonusNumber = BonusNumber.create(bonus); + Lotto lotto = Lotto.create(List.of(1, 2, 3, 4, 5, 6)); + + Assertions.assertSame(lotto.findLottoWinning(winningNumbers, bonusNumber), lottoWinning); + } +} \ No newline at end of file From 7b5b04a70a14872011cad74b5379aedd97be8d59 Mon Sep 17 00:00:00 2001 From: kilian Date: Sun, 19 May 2024 19:02:41 +0900 Subject: [PATCH 26/26] =?UTF-8?q?test=20:=20=EA=B3=B5=EB=B0=B1=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/output/ConsoleOutputView.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/view/output/ConsoleOutputView.java b/src/main/java/view/output/ConsoleOutputView.java index 25b39d132f..2bf230cf67 100644 --- a/src/main/java/view/output/ConsoleOutputView.java +++ b/src/main/java/view/output/ConsoleOutputView.java @@ -10,7 +10,6 @@ public class ConsoleOutputView implements OutputView { private static final String PURCHASE_COUNT_NAVIGATION = "수동으로 %d장, 자동으로 %d개를 구매했습니다."; private static final String WINNING_STATISTICS_NAVIGATION = "당첨 통계"; private static final String WINNING_SEPARATOR = "---------"; - private static final String MATCH_WINNING_NUMBER_NAVIGATION = "%d개 일치"; private static final String MATCH_BONUS_NUMBER_NAVIGATION = ", 보너스 볼 일치"; private static final String WINNING_AMOUNT_NAVIGATION = " (%d원)";