From 72ce2e7b7e3aa898f249c81dec15597517d6f63b Mon Sep 17 00:00:00 2001 From: suhyun Date: Wed, 29 Nov 2023 09:10:33 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=EA=B5=AC=EC=9E=85=EA=B8=88?= =?UTF-8?q?=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 --- docs/README.md | 6 ++ .../Constants/PurchaseAmountConstant.java | 25 ++++++++ src/main/java/controller/LottoController.java | 9 +++ .../controller/PurchaseAmountController.java | 28 +++++++++ src/main/java/domain/Amount.java | 51 +++++++++++++++ src/main/java/domain/PurchaseAmount.java | 13 ++++ src/main/java/lotto/Application.java | 2 + src/main/java/service/PurchaseService.java | 9 +++ src/main/java/util/EnumUtil.java | 6 ++ .../java/util/message/ExceptionMessage.java | 30 +++++++++ src/main/java/util/message/InputMessage.java | 23 +++++++ src/main/java/util/message/OutputMessage.java | 24 +++++++ src/main/java/view/InputView.java | 12 ++++ src/main/java/view/OutputView.java | 7 +++ src/test/java/domain/wrapper/AmountTest.java | 63 +++++++++++++++++++ 15 files changed, 308 insertions(+) create mode 100644 src/main/java/Constants/PurchaseAmountConstant.java create mode 100644 src/main/java/controller/LottoController.java create mode 100644 src/main/java/controller/PurchaseAmountController.java create mode 100644 src/main/java/domain/Amount.java create mode 100644 src/main/java/domain/PurchaseAmount.java create mode 100644 src/main/java/service/PurchaseService.java create mode 100644 src/main/java/util/EnumUtil.java create mode 100644 src/main/java/util/message/ExceptionMessage.java create mode 100644 src/main/java/util/message/InputMessage.java create mode 100644 src/main/java/util/message/OutputMessage.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java create mode 100644 src/test/java/domain/wrapper/AmountTest.java diff --git a/docs/README.md b/docs/README.md index e69de29bb2d..92cde50da05 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,6 @@ +### 기능 요구사항 + +[ ✅ ] 사용자는 구입금액을 입력한다. +- 구입금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다. + +[ ] 구입금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. \ No newline at end of file diff --git a/src/main/java/Constants/PurchaseAmountConstant.java b/src/main/java/Constants/PurchaseAmountConstant.java new file mode 100644 index 00000000000..d8e4ab06ac9 --- /dev/null +++ b/src/main/java/Constants/PurchaseAmountConstant.java @@ -0,0 +1,25 @@ +package Constants; + +import util.EnumUtil; + +public enum PurchaseAmountConstant implements EnumUtil { + + ONE_THOUSAND(1000), + ZERO(0); + + private final int number; + + PurchaseAmountConstant(final int number){ + this.number = number; + } + + @Override + public String getKey() { + return name(); + } + + @Override + public Integer getValue() { + return number; + } +} diff --git a/src/main/java/controller/LottoController.java b/src/main/java/controller/LottoController.java new file mode 100644 index 00000000000..24e8ec41153 --- /dev/null +++ b/src/main/java/controller/LottoController.java @@ -0,0 +1,9 @@ +package controller; + +import view.InputView; +import view.OutputView; + +public class LottoController { + public void start(){ + } +} diff --git a/src/main/java/controller/PurchaseAmountController.java b/src/main/java/controller/PurchaseAmountController.java new file mode 100644 index 00000000000..fb268404ee7 --- /dev/null +++ b/src/main/java/controller/PurchaseAmountController.java @@ -0,0 +1,28 @@ +package controller; + +import domain.PurchaseAmount; +import service.PurchaseService; +import view.InputView; +import view.OutputView; + +public class PurchaseAmountController { + private final PurchaseService purchaseService; + + public PurchaseAmountController(){ + purchaseService = new PurchaseService(); + } + + public void generatePurchaseAmount(){ + String purchaseAmount = InputView.inputPurchaseAmount(); + try{ + PurchaseAmount amount = createPurchaseAmount(purchaseAmount); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + generatePurchaseAmount(); + } + } + + private PurchaseAmount createPurchaseAmount(final String purchaseAmount){ + return purchaseService.createPurchaseAmount(purchaseAmount); + } +} diff --git a/src/main/java/domain/Amount.java b/src/main/java/domain/Amount.java new file mode 100644 index 00000000000..d6d8c902022 --- /dev/null +++ b/src/main/java/domain/Amount.java @@ -0,0 +1,51 @@ +package domain; + +import Constants.PurchaseAmountConstant; + +import static util.message.ExceptionMessage.*; +import static util.message.ExceptionMessage.UNIT_MESSAGE; + +public class Amount { + private final int amount; + + private Amount(final String purchaseAmount){ + validateBlank(purchaseAmount); + int purchase = validateType(purchaseAmount); + purchase = validateRange(purchase); + amount = validateDivisibleBy1000(purchase); + } + + public static Amount create(final String purchaseAmount){ + return new Amount(purchaseAmount); + } + + private void validateBlank(final String purchaseAmount){ + if (purchaseAmount == null || purchaseAmount.trim().isEmpty()) { + throw new IllegalArgumentException(String.format(BLANK_MESSAGE.getValue(), "구입금액")); + } + } + + private int validateType(final String purchaseAmount) { + int count; + try { + count = Integer.parseInt(purchaseAmount); + } catch (NumberFormatException e) { + throw new IllegalArgumentException((String.format(TYPE_MESSAGE.getValue(), "구입금액"))); + } + return count; + } + + private int validateRange(final int purchaseAmount) { + if (purchaseAmount <= PurchaseAmountConstant.ZERO.getValue()) { + throw new IllegalArgumentException(String.format(RANGE_MESSAGE.getValue(), PurchaseAmountConstant.ZERO.getValue())); + } + return purchaseAmount; + } + + private int validateDivisibleBy1000(final int amount){ + if(amount % PurchaseAmountConstant.ONE_THOUSAND.getValue() != PurchaseAmountConstant.ZERO.getValue()){ + throw new IllegalArgumentException(String.format(UNIT_MESSAGE.getValue(), PurchaseAmountConstant.ONE_THOUSAND.getValue())); + } + return amount; + } +} diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java new file mode 100644 index 00000000000..d86400f0d68 --- /dev/null +++ b/src/main/java/domain/PurchaseAmount.java @@ -0,0 +1,13 @@ +package domain; + +public class PurchaseAmount { + private final Amount amount; + + private PurchaseAmount(final String purchaseAmount){ + this.amount = Amount.create(purchaseAmount); + } + + public static PurchaseAmount create(final String purchaseAmount){ + return new PurchaseAmount(purchaseAmount); + } +} diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba44..fadcbca432c 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,5 +1,7 @@ package lotto; +import view.InputView; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 diff --git a/src/main/java/service/PurchaseService.java b/src/main/java/service/PurchaseService.java new file mode 100644 index 00000000000..5e1b068e200 --- /dev/null +++ b/src/main/java/service/PurchaseService.java @@ -0,0 +1,9 @@ +package service; + +import domain.PurchaseAmount; + +public class PurchaseService { + public PurchaseAmount createPurchaseAmount(final String purchaseAmount){ + return PurchaseAmount.create(purchaseAmount); + } +} diff --git a/src/main/java/util/EnumUtil.java b/src/main/java/util/EnumUtil.java new file mode 100644 index 00000000000..e0c0bcb600a --- /dev/null +++ b/src/main/java/util/EnumUtil.java @@ -0,0 +1,6 @@ +package util; + +public interface EnumUtil { + T1 getKey(); + T2 getValue(); +} diff --git a/src/main/java/util/message/ExceptionMessage.java b/src/main/java/util/message/ExceptionMessage.java new file mode 100644 index 00000000000..e5a86ee1e70 --- /dev/null +++ b/src/main/java/util/message/ExceptionMessage.java @@ -0,0 +1,30 @@ +package util.message; + +import util.EnumUtil; + +public enum ExceptionMessage implements EnumUtil { + BLANK_MESSAGE("%s은(는) 빈 값이 들어올 수 없습니다.") + , LENGTH_MESSAGE("%d글자를 초과하였습니다.") + , INPUT_MESSAGE("입력 중에 예기치 못한 오류가 발생하였습니다. 예외 메시지: %s") + , TYPE_MESSAGE("%s은(는) 숫자만 입력할 수 있습니다.") + , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") + , RANGE_MESSAGE("%d 이상의 값을 입력해 주세요.") + , DUPLICATE_MESSAGE("중복된 값을 입력할 수 없습니다.") + , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다."); + + private final String message; + + ExceptionMessage(final String message) { + this.message = message; + } + + @Override + public String getKey() { + return name(); + } + + @Override + public String getValue() { + return message; + } +} diff --git a/src/main/java/util/message/InputMessage.java b/src/main/java/util/message/InputMessage.java new file mode 100644 index 00000000000..ce2a8caca98 --- /dev/null +++ b/src/main/java/util/message/InputMessage.java @@ -0,0 +1,23 @@ +package util.message; + +import util.EnumUtil; + +public enum InputMessage implements EnumUtil { + GET_PURCHSE_AMOUNT("구입금액을 입력해 주세요."); + private final String message; + + InputMessage(final String message){ + this.message = message; + } + + + @Override + public String getKey() { + return name(); + } + + @Override + public String getValue() { + return name(); + } +} diff --git a/src/main/java/util/message/OutputMessage.java b/src/main/java/util/message/OutputMessage.java new file mode 100644 index 00000000000..3b17031f02f --- /dev/null +++ b/src/main/java/util/message/OutputMessage.java @@ -0,0 +1,24 @@ +package util.message; + +import util.EnumUtil; + +public enum OutputMessage implements EnumUtil{ + ; + + private final String message; + + OutputMessage(final String message){ + this.message = message; + } + + + @Override + public String getKey() { + return name(); + } + + @Override + public String getValue() { + return name(); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..6aa73356a71 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,12 @@ +package view; + +import camp.nextstep.edu.missionutils.Console; + +import static util.message.InputMessage.GET_PURCHSE_AMOUNT; + +public class InputView { + public static String inputPurchaseAmount(){ + System.out.println(GET_PURCHSE_AMOUNT); + return Console.readLine(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000000..f10f2fc7c84 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,7 @@ +package view; + +public class OutputView { + public static void printMessage(String message) { + System.out.println(message); + } +} diff --git a/src/test/java/domain/wrapper/AmountTest.java b/src/test/java/domain/wrapper/AmountTest.java new file mode 100644 index 00000000000..0d8061261ec --- /dev/null +++ b/src/test/java/domain/wrapper/AmountTest.java @@ -0,0 +1,63 @@ +package domain.wrapper; + +import Constants.PurchaseAmountConstant; +import domain.Amount; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static util.message.ExceptionMessage.*; +import static util.message.ExceptionMessage.UNIT_MESSAGE; + +public class AmountTest { + @ParameterizedTest + @DisplayName("구입금액을 올바르게 입력한 경우 예외가 발생하지 않는다.") + @CsvSource("4000") + void givenNormalAmount_thenSuccess(final String purchaseAmount) { + assertThat(Amount.create(purchaseAmount)) + .isInstanceOf(Amount.class); + + assertThatCode(() -> Amount.create(purchaseAmount)) + .doesNotThrowAnyException(); + } + + @ParameterizedTest + @DisplayName("구입금액을 빈값으로 입력한 경우 예외가 발생한다.") + @ValueSource(strings = {"", " ", " ", " ", " ", "\n", "\t", "\r"}) + void givenBlankAmount_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> Amount.create(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(BLANK_MESSAGE.getValue(), "구입금액")); + } + + @ParameterizedTest + @DisplayName("구입금액을 숫자가 아닌 형태로 입력한 경우 예외가 발생한다.") + @ValueSource(strings = {"abc", "12bd"}) + void givenNonNumeric_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> Amount.create(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(TYPE_MESSAGE.getValue(), "구입금액")); + } + + @ParameterizedTest + @DisplayName("구입금액이 0이하인경우 예외가 발생한다.") + @ValueSource(strings = {"-1", "0"}) + void givenLessZero_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> Amount.create(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(RANGE_MESSAGE.getValue(), PurchaseAmountConstant.ZERO.getValue())); + } + + @ParameterizedTest + @DisplayName("구입금액이 1000으로 나누어 떨어지지 않는 경우 예외가 발생한다.") + @ValueSource(strings = {"4565", "1223"}) + void givenNonDivisibleBy1000_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> Amount.create(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(UNIT_MESSAGE.getValue(), PurchaseAmountConstant.ONE_THOUSAND.getValue())); + } +} From cd685bbbc0bfc8395ec9e0451f08b89e29333911 Mon Sep 17 00:00:00 2001 From: suhyun Date: Wed, 29 Nov 2023 14:04:19 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=ED=95=9C=20?= =?UTF-8?q?=EA=B5=AC=EC=9E=85=EA=B8=88=EC=95=A1=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EA=B2=8C=20=EB=A1=9C=EB=98=90=EB=B0=9C=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/Constants/LottosConstant.java | 25 ++++++++++ src/main/java/controller/LottoController.java | 9 ---- .../java/controller/LottosController.java | 50 +++++++++++++++++++ .../controller/PurchaseAmountController.java | 28 ----------- src/main/java/domain/Lotto.java | 48 ++++++++++++++++++ src/main/java/domain/Lottos.java | 40 +++++++++++++++ src/main/java/domain/PurchaseAmount.java | 13 +++++ .../java/domain/{ => wrapper}/Amount.java | 6 ++- src/main/java/dto/LottoDto.java | 26 ++++++++++ src/main/java/lotto/Application.java | 10 +++- src/main/java/lotto/Lotto.java | 20 -------- src/main/java/service/LottosService.java | 22 ++++++++ .../util/exception/DuplicateException.java | 7 +++ .../util/exception/SizeOverException.java | 7 +++ .../java/util/message/ExceptionMessage.java | 5 +- src/main/java/util/message/InputMessage.java | 2 +- src/main/java/util/message/OutputMessage.java | 4 +- src/main/java/view/InputView.java | 2 +- src/main/java/view/OutputView.java | 12 +++++ .../java/{lotto => domain}/LottoTest.java | 6 +-- src/test/java/domain/LottosTest.java | 45 +++++++++++++++++ src/test/java/domain/wrapper/AmountTest.java | 1 - src/test/java/provider/TestProvider.java | 9 ++++ 24 files changed, 327 insertions(+), 72 deletions(-) create mode 100644 src/main/java/Constants/LottosConstant.java delete mode 100644 src/main/java/controller/LottoController.java create mode 100644 src/main/java/controller/LottosController.java delete mode 100644 src/main/java/controller/PurchaseAmountController.java create mode 100644 src/main/java/domain/Lotto.java create mode 100644 src/main/java/domain/Lottos.java rename src/main/java/domain/{ => wrapper}/Amount.java (95%) create mode 100644 src/main/java/dto/LottoDto.java delete mode 100644 src/main/java/lotto/Lotto.java create mode 100644 src/main/java/service/LottosService.java create mode 100644 src/main/java/util/exception/DuplicateException.java create mode 100644 src/main/java/util/exception/SizeOverException.java rename src/test/java/{lotto => domain}/LottoTest.java (84%) create mode 100644 src/test/java/domain/LottosTest.java create mode 100644 src/test/java/provider/TestProvider.java diff --git a/docs/README.md b/docs/README.md index 92cde50da05..7d691c6ba57 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,4 +3,4 @@ [ ✅ ] 사용자는 구입금액을 입력한다. - 구입금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다. -[ ] 구입금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. \ No newline at end of file +[ ✅ ] 구입금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. \ No newline at end of file diff --git a/src/main/java/Constants/LottosConstant.java b/src/main/java/Constants/LottosConstant.java new file mode 100644 index 00000000000..0b320757cb6 --- /dev/null +++ b/src/main/java/Constants/LottosConstant.java @@ -0,0 +1,25 @@ +package Constants; + +import util.EnumUtil; + +public enum LottosConstant implements EnumUtil { + MIN_VALUE(1), + MAX_VALUE(45), + LOTTO_SIZE(6); + + private final int number; + + LottosConstant(final int number){ + this.number = number; + } + + @Override + public String getKey() { + return name(); + } + + @Override + public Integer getValue() { + return number; + } +} diff --git a/src/main/java/controller/LottoController.java b/src/main/java/controller/LottoController.java deleted file mode 100644 index 24e8ec41153..00000000000 --- a/src/main/java/controller/LottoController.java +++ /dev/null @@ -1,9 +0,0 @@ -package controller; - -import view.InputView; -import view.OutputView; - -public class LottoController { - public void start(){ - } -} diff --git a/src/main/java/controller/LottosController.java b/src/main/java/controller/LottosController.java new file mode 100644 index 00000000000..8e34905ec6f --- /dev/null +++ b/src/main/java/controller/LottosController.java @@ -0,0 +1,50 @@ +package controller; + +import domain.PurchaseAmount; +import domain.Lottos; +import dto.LottoDto; +import service.LottosService; +import service.PurchaseService; +import view.InputView; +import view.OutputView; + +import java.util.List; + +public class LottosController { + private final PurchaseService purchaseService; + private final LottosService lottosService; + + public LottosController(){ + purchaseService = new PurchaseService(); + lottosService = new LottosService(); + } + + public void start(){ + PurchaseAmount purchaseAmount = generatePurchaseAmount(); + Lottos purchaseLottos = generateLottos(purchaseAmount); + printPurchaseLottos(purchaseLottos, purchaseAmount.getQuantity()); + } + + private PurchaseAmount generatePurchaseAmount(){ + String purchaseAmount = InputView.inputPurchaseAmount(); + try{ + return createPurchaseAmount(purchaseAmount); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + return generatePurchaseAmount(); + } + } + + private PurchaseAmount createPurchaseAmount(final String purchaseAmount){ + return purchaseService.createPurchaseAmount(purchaseAmount); + } + + private Lottos generateLottos(final PurchaseAmount purchaseAmount){ + return lottosService.createLottos(purchaseAmount); + } + + private void printPurchaseLottos(final Lottos purchaseLottos, final int numberOfPurchased){ + List printPurchaseLottos = lottosService.getPurchaseLottos(purchaseLottos); + OutputView.printPurchaseLottos(printPurchaseLottos, numberOfPurchased); + } +} diff --git a/src/main/java/controller/PurchaseAmountController.java b/src/main/java/controller/PurchaseAmountController.java deleted file mode 100644 index fb268404ee7..00000000000 --- a/src/main/java/controller/PurchaseAmountController.java +++ /dev/null @@ -1,28 +0,0 @@ -package controller; - -import domain.PurchaseAmount; -import service.PurchaseService; -import view.InputView; -import view.OutputView; - -public class PurchaseAmountController { - private final PurchaseService purchaseService; - - public PurchaseAmountController(){ - purchaseService = new PurchaseService(); - } - - public void generatePurchaseAmount(){ - String purchaseAmount = InputView.inputPurchaseAmount(); - try{ - PurchaseAmount amount = createPurchaseAmount(purchaseAmount); - } catch (IllegalArgumentException e){ - OutputView.printMessage(e.getMessage()); - generatePurchaseAmount(); - } - } - - private PurchaseAmount createPurchaseAmount(final String purchaseAmount){ - return purchaseService.createPurchaseAmount(purchaseAmount); - } -} diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java new file mode 100644 index 00000000000..9db4a1aa4f8 --- /dev/null +++ b/src/main/java/domain/Lotto.java @@ -0,0 +1,48 @@ +package domain; + +import util.exception.DuplicateException; +import util.exception.SizeOverException; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static util.message.ExceptionMessage.DUPLICATE_MESSAGE; +import static util.message.ExceptionMessage.SIZE_OVER_MESSAGE; + +public class Lotto { + private final List numbers; + + public Lotto(List numbers) { + validate(numbers); + sort(numbers); + this.numbers = numbers; + } + + public List getNumbers(){ + return numbers; + } + + private void validate(List numbers) { + validateSize(numbers); + validateDuplicate(numbers); + } + + private void validateSize(List numbers){ + if (numbers.size() != 6) { + throw new SizeOverException(String.format(SIZE_OVER_MESSAGE.getValue(), "로또")); + } + } + + private void validateDuplicate(List numbers){ + Set lottos = new HashSet<>(numbers); + if(numbers.size() != lottos.size()){ + throw new DuplicateException(String.format(DUPLICATE_MESSAGE.getValue())); + } + } + + private void sort(List numbers){ + Collections.sort(numbers); + } +} diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java new file mode 100644 index 00000000000..097f50eb2c9 --- /dev/null +++ b/src/main/java/domain/Lottos.java @@ -0,0 +1,40 @@ +package domain; + +import Constants.LottosConstant; +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.List; + +public class Lottos { + private final List lottos; + + public Lottos(int numberOfPurchased){ + lottos = generateLottos(numberOfPurchased); + } + + public static Lottos create(final int numberOfPurchased){ + return new Lottos(numberOfPurchased); + } + + public List getLottos(){ + return lottos; + } + + private List generateLottos(int numberOfPurchased){ + List lottos = new ArrayList<>(); + while(numberOfPurchased-- > 0){ + lottos.add(generateRandomNumbers()); + } + return lottos; + } + + private Lotto generateRandomNumbers(){ + List numbers = Randoms.pickUniqueNumbersInRange( + LottosConstant.MIN_VALUE.getValue(), + LottosConstant.MAX_VALUE.getValue(), + LottosConstant.LOTTO_SIZE.getValue()); + + return new Lotto(numbers); + } +} diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index d86400f0d68..64ab8bc610e 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -1,13 +1,26 @@ package domain; +import Constants.PurchaseAmountConstant; +import domain.wrapper.Amount; + public class PurchaseAmount { private final Amount amount; + private final int quantity; private PurchaseAmount(final String purchaseAmount){ this.amount = Amount.create(purchaseAmount); + this.quantity = calculatequantity(); + } + + public int getQuantity(){ + return quantity; } public static PurchaseAmount create(final String purchaseAmount){ return new PurchaseAmount(purchaseAmount); } + + private int calculatequantity(){ + return amount.getAmount() / PurchaseAmountConstant.ONE_THOUSAND.getValue(); + } } diff --git a/src/main/java/domain/Amount.java b/src/main/java/domain/wrapper/Amount.java similarity index 95% rename from src/main/java/domain/Amount.java rename to src/main/java/domain/wrapper/Amount.java index d6d8c902022..7fa78e9d2ae 100644 --- a/src/main/java/domain/Amount.java +++ b/src/main/java/domain/wrapper/Amount.java @@ -1,4 +1,4 @@ -package domain; +package domain.wrapper; import Constants.PurchaseAmountConstant; @@ -15,6 +15,10 @@ private Amount(final String purchaseAmount){ amount = validateDivisibleBy1000(purchase); } + public int getAmount(){ + return amount; + } + public static Amount create(final String purchaseAmount){ return new Amount(purchaseAmount); } diff --git a/src/main/java/dto/LottoDto.java b/src/main/java/dto/LottoDto.java new file mode 100644 index 00000000000..94696e90e81 --- /dev/null +++ b/src/main/java/dto/LottoDto.java @@ -0,0 +1,26 @@ +package dto; + +import domain.Lotto; + +import java.util.List; + +public class LottoDto { + private final List numbers; + + private LottoDto(List numbers) { + this.numbers = numbers; + } + + public static LottoDto create(List numbers) { + return new LottoDto(numbers); + } + + public List getNumbers() { + return numbers; + } + + @Override + public String toString() { + return numbers.toString(); + } +} diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index fadcbca432c..240c11d45c8 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,9 +1,15 @@ package lotto; -import view.InputView; +import controller.LottosController; public class Application { + + private static final LottosController lottosController = new LottosController(); public static void main(String[] args) { - // TODO: 프로그램 구현 + initLottos(); + } + + private static void initLottos(){ + lottosController.start(); } } diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java deleted file mode 100644 index 519793d1f73..00000000000 --- a/src/main/java/lotto/Lotto.java +++ /dev/null @@ -1,20 +0,0 @@ -package lotto; - -import java.util.List; - -public class Lotto { - private final List numbers; - - public Lotto(List numbers) { - validate(numbers); - this.numbers = numbers; - } - - private void validate(List numbers) { - if (numbers.size() != 6) { - throw new IllegalArgumentException(); - } - } - - // TODO: 추가 기능 구현 -} diff --git a/src/main/java/service/LottosService.java b/src/main/java/service/LottosService.java new file mode 100644 index 00000000000..494c00e0e3f --- /dev/null +++ b/src/main/java/service/LottosService.java @@ -0,0 +1,22 @@ +package service; + +import domain.Lotto; +import domain.PurchaseAmount; +import domain.Lottos; +import dto.LottoDto; + +import java.util.List; +import java.util.stream.Collectors; + +public class LottosService { + public Lottos createLottos(final PurchaseAmount purchaseAmount){ + return Lottos.create(purchaseAmount.getQuantity()); + } + + public List getPurchaseLottos(final Lottos purchaseLottos){ + List lottos = purchaseLottos.getLottos(); + return lottos.stream() + .map(lotto -> LottoDto.create(lotto.getNumbers())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/util/exception/DuplicateException.java b/src/main/java/util/exception/DuplicateException.java new file mode 100644 index 00000000000..a6180ea4617 --- /dev/null +++ b/src/main/java/util/exception/DuplicateException.java @@ -0,0 +1,7 @@ +package util.exception; + +public class DuplicateException extends IllegalArgumentException { + public DuplicateException(final String message) { + super(message); + } +} diff --git a/src/main/java/util/exception/SizeOverException.java b/src/main/java/util/exception/SizeOverException.java new file mode 100644 index 00000000000..3fbcf8fbe22 --- /dev/null +++ b/src/main/java/util/exception/SizeOverException.java @@ -0,0 +1,7 @@ +package util.exception; + +public class SizeOverException extends IllegalArgumentException{ + public SizeOverException(final String message) { + super(message); + } +} diff --git a/src/main/java/util/message/ExceptionMessage.java b/src/main/java/util/message/ExceptionMessage.java index e5a86ee1e70..199f8273563 100644 --- a/src/main/java/util/message/ExceptionMessage.java +++ b/src/main/java/util/message/ExceptionMessage.java @@ -9,8 +9,9 @@ public enum ExceptionMessage implements EnumUtil { , TYPE_MESSAGE("%s은(는) 숫자만 입력할 수 있습니다.") , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") , RANGE_MESSAGE("%d 이상의 값을 입력해 주세요.") - , DUPLICATE_MESSAGE("중복된 값을 입력할 수 없습니다.") - , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다."); + , DUPLICATE_MESSAGE("중복된 값이 있습니다.") + , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다.") + , SIZE_OVER_MESSAGE("%s크기를 초과하였습니다."); private final String message; diff --git a/src/main/java/util/message/InputMessage.java b/src/main/java/util/message/InputMessage.java index ce2a8caca98..9a995ebf4b3 100644 --- a/src/main/java/util/message/InputMessage.java +++ b/src/main/java/util/message/InputMessage.java @@ -18,6 +18,6 @@ public String getKey() { @Override public String getValue() { - return name(); + return message; } } diff --git a/src/main/java/util/message/OutputMessage.java b/src/main/java/util/message/OutputMessage.java index 3b17031f02f..a1b7ffbba82 100644 --- a/src/main/java/util/message/OutputMessage.java +++ b/src/main/java/util/message/OutputMessage.java @@ -3,7 +3,7 @@ import util.EnumUtil; public enum OutputMessage implements EnumUtil{ - ; + LOTTO_PURCHASE_COUNT("%d개를 구매했습니다."); private final String message; @@ -19,6 +19,6 @@ public String getKey() { @Override public String getValue() { - return name(); + return message; } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 6aa73356a71..3bf894d4431 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -6,7 +6,7 @@ public class InputView { public static String inputPurchaseAmount(){ - System.out.println(GET_PURCHSE_AMOUNT); + System.out.println(GET_PURCHSE_AMOUNT.getValue()); return Console.readLine(); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index f10f2fc7c84..f007a2b8e24 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,7 +1,19 @@ package view; +import dto.LottoDto; +import util.message.OutputMessage; + +import java.util.List; + public class OutputView { public static void printMessage(String message) { System.out.println(message); } + + public static void printPurchaseLottos(final List lottoDtos, final int numberOfPurchased){ + System.out.println(String.format(OutputMessage.LOTTO_PURCHASE_COUNT.getValue(), numberOfPurchased)); + for (LottoDto lotto : lottoDtos) { + System.out.println(lotto); + } + } } diff --git a/src/test/java/lotto/LottoTest.java b/src/test/java/domain/LottoTest.java similarity index 84% rename from src/test/java/lotto/LottoTest.java rename to src/test/java/domain/LottoTest.java index 9f5dfe7eb83..3a0bd1b661b 100644 --- a/src/test/java/lotto/LottoTest.java +++ b/src/test/java/domain/LottoTest.java @@ -1,5 +1,6 @@ -package lotto; +package domain; +import domain.Lotto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,10 +19,7 @@ void createLottoByOverSize() { @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.") @Test void createLottoByDuplicatedNumber() { - // TODO: 이 테스트가 통과할 수 있게 구현 코드 작성 assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) .isInstanceOf(IllegalArgumentException.class); } - - // 아래에 추가 테스트 작성 가능 } \ No newline at end of file diff --git a/src/test/java/domain/LottosTest.java b/src/test/java/domain/LottosTest.java new file mode 100644 index 00000000000..3f852906827 --- /dev/null +++ b/src/test/java/domain/LottosTest.java @@ -0,0 +1,45 @@ +package domain; + +import Constants.LottosConstant; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static provider.TestProvider.createTestPurchaseLottos; + +public class LottosTest { + + private Lottos testLottos; + private int numberOfPurchased; + + @BeforeEach + void init(){ + numberOfPurchased = 3; + testLottos = createTestPurchaseLottos(numberOfPurchased); + } + + @DisplayName("구매한 만큼 로또 목록을 생성한다. - 3개의 로또가 모두 서로 다른 숫자로 이루어졌는지 확인한다.") + @Test + void createRandomLottoNumbers() { + List generatedLottos = testLottos.getLottos(); + + assertNotNull(generatedLottos); + assertEquals(numberOfPurchased, generatedLottos.size()); + + for (Lotto lotto : generatedLottos) { + validateLotto(lotto); + } + } + + private void validateLotto(Lotto lotto) { + assertNotNull(lotto); + List numbers = lotto.getNumbers(); + + assertNotNull(numbers); + assertEquals(LottosConstant.LOTTO_SIZE.getValue(), numbers.size()); + } +} diff --git a/src/test/java/domain/wrapper/AmountTest.java b/src/test/java/domain/wrapper/AmountTest.java index 0d8061261ec..d08dd3b7e30 100644 --- a/src/test/java/domain/wrapper/AmountTest.java +++ b/src/test/java/domain/wrapper/AmountTest.java @@ -1,7 +1,6 @@ package domain.wrapper; import Constants.PurchaseAmountConstant; -import domain.Amount; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; diff --git a/src/test/java/provider/TestProvider.java b/src/test/java/provider/TestProvider.java new file mode 100644 index 00000000000..3d67f73d258 --- /dev/null +++ b/src/test/java/provider/TestProvider.java @@ -0,0 +1,9 @@ +package provider; + +import domain.Lottos; + +public class TestProvider { + public static Lottos createTestPurchaseLottos(final int numberOfPurchased) { + return Lottos.create(numberOfPurchased); + } +} From 7c43480fe6a9cbfc0a08e45688bcd735c07c8f78 Mon Sep 17 00:00:00 2001 From: suhyun Date: Wed, 29 Nov 2023 15:32:29 +0900 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20=EC=9E=85=EB=A0=A5=EC=8B=9C=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EC=B2=98=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/LottosController.java | 26 +++----- .../java/controller/PurchaseController.java | 28 +++++++++ src/main/java/domain/Lottos.java | 2 +- src/main/java/domain/PurchaseAmount.java | 23 ++++--- src/main/java/domain/WinningNumbers.java | 4 ++ src/main/java/domain/wrapper/Amount.java | 55 ---------------- src/main/java/lotto/Application.java | 6 +- src/main/java/service/PurchaseService.java | 2 +- .../constants/Constants.java} | 7 +-- .../constants}/LottosConstant.java | 2 +- .../java/util/message/ExceptionMessage.java | 4 +- src/main/java/util/message/InputMessage.java | 3 +- .../validator/PurchaseAmountValidator.java | 11 ++++ src/main/java/validator/Validator.java | 28 +++++++++ .../validator/WinningNumbersValidator.java | 4 ++ src/main/java/view/InputView.java | 11 +++- src/test/java/domain/LottosTest.java | 2 +- src/test/java/domain/PurchaseAmountTest.java | 35 +++++++++++ src/test/java/domain/wrapper/AmountTest.java | 62 ------------------- .../PurchaseAmountValidatorTest.java | 40 ++++++++++++ 20 files changed, 200 insertions(+), 155 deletions(-) create mode 100644 src/main/java/controller/PurchaseController.java create mode 100644 src/main/java/domain/WinningNumbers.java delete mode 100644 src/main/java/domain/wrapper/Amount.java rename src/main/java/{Constants/PurchaseAmountConstant.java => util/constants/Constants.java} (66%) rename src/main/java/{Constants => util/constants}/LottosConstant.java (94%) create mode 100644 src/main/java/validator/PurchaseAmountValidator.java create mode 100644 src/main/java/validator/Validator.java create mode 100644 src/main/java/validator/WinningNumbersValidator.java create mode 100644 src/test/java/domain/PurchaseAmountTest.java delete mode 100644 src/test/java/domain/wrapper/AmountTest.java create mode 100644 src/test/java/validator/PurchaseAmountValidatorTest.java diff --git a/src/main/java/controller/LottosController.java b/src/main/java/controller/LottosController.java index 8e34905ec6f..1bbf4fe2df5 100644 --- a/src/main/java/controller/LottosController.java +++ b/src/main/java/controller/LottosController.java @@ -10,33 +10,19 @@ import java.util.List; +import static view.InputView.inputWinnging; + public class LottosController { - private final PurchaseService purchaseService; private final LottosService lottosService; public LottosController(){ - purchaseService = new PurchaseService(); lottosService = new LottosService(); } - public void start(){ - PurchaseAmount purchaseAmount = generatePurchaseAmount(); + public void start(final PurchaseAmount purchaseAmount){ Lottos purchaseLottos = generateLottos(purchaseAmount); printPurchaseLottos(purchaseLottos, purchaseAmount.getQuantity()); - } - - private PurchaseAmount generatePurchaseAmount(){ - String purchaseAmount = InputView.inputPurchaseAmount(); - try{ - return createPurchaseAmount(purchaseAmount); - } catch (IllegalArgumentException e){ - OutputView.printMessage(e.getMessage()); - return generatePurchaseAmount(); - } - } - - private PurchaseAmount createPurchaseAmount(final String purchaseAmount){ - return purchaseService.createPurchaseAmount(purchaseAmount); + generateWinngingAndBonus(); } private Lottos generateLottos(final PurchaseAmount purchaseAmount){ @@ -47,4 +33,8 @@ private void printPurchaseLottos(final Lottos purchaseLottos, final int numberOf List printPurchaseLottos = lottosService.getPurchaseLottos(purchaseLottos); OutputView.printPurchaseLottos(printPurchaseLottos, numberOfPurchased); } + + private void generateWinngingAndBonus(){ + String winngNumbers = inputWinnging(); + } } diff --git a/src/main/java/controller/PurchaseController.java b/src/main/java/controller/PurchaseController.java new file mode 100644 index 00000000000..e0386ebe165 --- /dev/null +++ b/src/main/java/controller/PurchaseController.java @@ -0,0 +1,28 @@ +package controller; + +import domain.PurchaseAmount; +import service.PurchaseService; +import view.InputView; +import view.OutputView; + +public class PurchaseController { + private final PurchaseService purchaseService; + + public PurchaseController(){ + purchaseService = new PurchaseService(); + } + + public PurchaseAmount generatePurchaseAmount(){ + int purchaseAmount = InputView.inputPurchaseAmount(); + try{ + return createPurchaseAmount(purchaseAmount); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + return generatePurchaseAmount(); + } + } + + private PurchaseAmount createPurchaseAmount(final int purchaseAmount){ + return purchaseService.createPurchaseAmount(purchaseAmount); + } +} diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java index 097f50eb2c9..de2f34d301b 100644 --- a/src/main/java/domain/Lottos.java +++ b/src/main/java/domain/Lottos.java @@ -1,6 +1,6 @@ package domain; -import Constants.LottosConstant; +import util.constants.LottosConstant; import camp.nextstep.edu.missionutils.Randoms; import java.util.ArrayList; diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index 64ab8bc610e..d02b69fdd05 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -1,14 +1,16 @@ package domain; -import Constants.PurchaseAmountConstant; -import domain.wrapper.Amount; +import util.constants.Constants; + +import static util.message.ExceptionMessage.UNIT_MESSAGE; public class PurchaseAmount { - private final Amount amount; + private final int amount; private final int quantity; - private PurchaseAmount(final String purchaseAmount){ - this.amount = Amount.create(purchaseAmount); + private PurchaseAmount(final int purchaseAmount){ + validateDivisibleBy1000(purchaseAmount); + this.amount = purchaseAmount; this.quantity = calculatequantity(); } @@ -16,11 +18,18 @@ public int getQuantity(){ return quantity; } - public static PurchaseAmount create(final String purchaseAmount){ + public static PurchaseAmount create(final int purchaseAmount){ return new PurchaseAmount(purchaseAmount); } private int calculatequantity(){ - return amount.getAmount() / PurchaseAmountConstant.ONE_THOUSAND.getValue(); + return amount / Constants.ONE_THOUSAND.getValue(); + } + + private static int validateDivisibleBy1000(final int amount){ + if(amount % Constants.ONE_THOUSAND.getValue() != Constants.ZERO.getValue()){ + throw new IllegalArgumentException(String.format(UNIT_MESSAGE.getValue(), Constants.ONE_THOUSAND.getValue())); + } + return amount; } } diff --git a/src/main/java/domain/WinningNumbers.java b/src/main/java/domain/WinningNumbers.java new file mode 100644 index 00000000000..4956b8768f4 --- /dev/null +++ b/src/main/java/domain/WinningNumbers.java @@ -0,0 +1,4 @@ +package domain; + +public class WinningNumbers { +} diff --git a/src/main/java/domain/wrapper/Amount.java b/src/main/java/domain/wrapper/Amount.java deleted file mode 100644 index 7fa78e9d2ae..00000000000 --- a/src/main/java/domain/wrapper/Amount.java +++ /dev/null @@ -1,55 +0,0 @@ -package domain.wrapper; - -import Constants.PurchaseAmountConstant; - -import static util.message.ExceptionMessage.*; -import static util.message.ExceptionMessage.UNIT_MESSAGE; - -public class Amount { - private final int amount; - - private Amount(final String purchaseAmount){ - validateBlank(purchaseAmount); - int purchase = validateType(purchaseAmount); - purchase = validateRange(purchase); - amount = validateDivisibleBy1000(purchase); - } - - public int getAmount(){ - return amount; - } - - public static Amount create(final String purchaseAmount){ - return new Amount(purchaseAmount); - } - - private void validateBlank(final String purchaseAmount){ - if (purchaseAmount == null || purchaseAmount.trim().isEmpty()) { - throw new IllegalArgumentException(String.format(BLANK_MESSAGE.getValue(), "구입금액")); - } - } - - private int validateType(final String purchaseAmount) { - int count; - try { - count = Integer.parseInt(purchaseAmount); - } catch (NumberFormatException e) { - throw new IllegalArgumentException((String.format(TYPE_MESSAGE.getValue(), "구입금액"))); - } - return count; - } - - private int validateRange(final int purchaseAmount) { - if (purchaseAmount <= PurchaseAmountConstant.ZERO.getValue()) { - throw new IllegalArgumentException(String.format(RANGE_MESSAGE.getValue(), PurchaseAmountConstant.ZERO.getValue())); - } - return purchaseAmount; - } - - private int validateDivisibleBy1000(final int amount){ - if(amount % PurchaseAmountConstant.ONE_THOUSAND.getValue() != PurchaseAmountConstant.ZERO.getValue()){ - throw new IllegalArgumentException(String.format(UNIT_MESSAGE.getValue(), PurchaseAmountConstant.ONE_THOUSAND.getValue())); - } - return amount; - } -} diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 240c11d45c8..297554ff205 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,15 +1,19 @@ package lotto; import controller.LottosController; +import controller.PurchaseController; +import domain.PurchaseAmount; public class Application { private static final LottosController lottosController = new LottosController(); + private static final PurchaseController purchaseController = new PurchaseController(); public static void main(String[] args) { initLottos(); } private static void initLottos(){ - lottosController.start(); + PurchaseAmount purchaseAmount = purchaseController.generatePurchaseAmount(); + lottosController.start(purchaseAmount); } } diff --git a/src/main/java/service/PurchaseService.java b/src/main/java/service/PurchaseService.java index 5e1b068e200..fd7796bc4b5 100644 --- a/src/main/java/service/PurchaseService.java +++ b/src/main/java/service/PurchaseService.java @@ -3,7 +3,7 @@ import domain.PurchaseAmount; public class PurchaseService { - public PurchaseAmount createPurchaseAmount(final String purchaseAmount){ + public PurchaseAmount createPurchaseAmount(final int purchaseAmount){ return PurchaseAmount.create(purchaseAmount); } } diff --git a/src/main/java/Constants/PurchaseAmountConstant.java b/src/main/java/util/constants/Constants.java similarity index 66% rename from src/main/java/Constants/PurchaseAmountConstant.java rename to src/main/java/util/constants/Constants.java index d8e4ab06ac9..ee36f782554 100644 --- a/src/main/java/Constants/PurchaseAmountConstant.java +++ b/src/main/java/util/constants/Constants.java @@ -1,15 +1,14 @@ -package Constants; +package util.constants; import util.EnumUtil; -public enum PurchaseAmountConstant implements EnumUtil { - +public enum Constants implements EnumUtil { ONE_THOUSAND(1000), ZERO(0); private final int number; - PurchaseAmountConstant(final int number){ + Constants(final int number){ this.number = number; } diff --git a/src/main/java/Constants/LottosConstant.java b/src/main/java/util/constants/LottosConstant.java similarity index 94% rename from src/main/java/Constants/LottosConstant.java rename to src/main/java/util/constants/LottosConstant.java index 0b320757cb6..1cd96cb6934 100644 --- a/src/main/java/Constants/LottosConstant.java +++ b/src/main/java/util/constants/LottosConstant.java @@ -1,4 +1,4 @@ -package Constants; +package util.constants; import util.EnumUtil; diff --git a/src/main/java/util/message/ExceptionMessage.java b/src/main/java/util/message/ExceptionMessage.java index 199f8273563..7cd99df2c19 100644 --- a/src/main/java/util/message/ExceptionMessage.java +++ b/src/main/java/util/message/ExceptionMessage.java @@ -3,10 +3,10 @@ import util.EnumUtil; public enum ExceptionMessage implements EnumUtil { - BLANK_MESSAGE("%s은(는) 빈 값이 들어올 수 없습니다.") + BLANK_MESSAGE("입력은 빈 값이 들어올 수 없습니다.") , LENGTH_MESSAGE("%d글자를 초과하였습니다.") , INPUT_MESSAGE("입력 중에 예기치 못한 오류가 발생하였습니다. 예외 메시지: %s") - , TYPE_MESSAGE("%s은(는) 숫자만 입력할 수 있습니다.") + , TYPE_MESSAGE("숫자만 입력할 수 있습니다.") , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") , RANGE_MESSAGE("%d 이상의 값을 입력해 주세요.") , DUPLICATE_MESSAGE("중복된 값이 있습니다.") diff --git a/src/main/java/util/message/InputMessage.java b/src/main/java/util/message/InputMessage.java index 9a995ebf4b3..54ce9b0ffb5 100644 --- a/src/main/java/util/message/InputMessage.java +++ b/src/main/java/util/message/InputMessage.java @@ -3,7 +3,8 @@ import util.EnumUtil; public enum InputMessage implements EnumUtil { - GET_PURCHSE_AMOUNT("구입금액을 입력해 주세요."); + GET_PURCHSE_AMOUNT("구입금액을 입력해 주세요."), + GET_WINNING_NUMBERS("당첨 번호를 입력해 주세요."); private final String message; InputMessage(final String message){ diff --git a/src/main/java/validator/PurchaseAmountValidator.java b/src/main/java/validator/PurchaseAmountValidator.java new file mode 100644 index 00000000000..5ee3aefef9c --- /dev/null +++ b/src/main/java/validator/PurchaseAmountValidator.java @@ -0,0 +1,11 @@ +package validator; + +import util.constants.Constants; + +public class PurchaseAmountValidator extends Validator{ + public static int isRightPurchaseAmount(String input) { + validateBlank(input); + int amount = validateType(input); + return validateRange(amount, Constants.ZERO.getValue()); + } +} diff --git a/src/main/java/validator/Validator.java b/src/main/java/validator/Validator.java new file mode 100644 index 00000000000..ab706e32ac4 --- /dev/null +++ b/src/main/java/validator/Validator.java @@ -0,0 +1,28 @@ +package validator; + +import static util.message.ExceptionMessage.*; + +public class Validator { + protected static void validateBlank(final String input) { + if (input == null || input.trim().isEmpty()) { + throw new IllegalArgumentException(BLANK_MESSAGE.getValue()); + } + } + + protected static int validateType(final String input) { + int count; + try { + count = Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(TYPE_MESSAGE.getValue()); + } + return count; + } + + protected static int validateRange(final int input, final int range) { + if (input <= range) { + throw new IllegalArgumentException(String.format(RANGE_MESSAGE.getValue(), range)); + } + return input; + } +} diff --git a/src/main/java/validator/WinningNumbersValidator.java b/src/main/java/validator/WinningNumbersValidator.java new file mode 100644 index 00000000000..a0ab2a187e1 --- /dev/null +++ b/src/main/java/validator/WinningNumbersValidator.java @@ -0,0 +1,4 @@ +package validator; + +public class WinningNumbersValidator { +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 3bf894d4431..cf0ac58aa3c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,12 +1,21 @@ package view; import camp.nextstep.edu.missionutils.Console; +import validator.PurchaseAmountValidator; +import validator.Validator; import static util.message.InputMessage.GET_PURCHSE_AMOUNT; +import static util.message.InputMessage.GET_WINNING_NUMBERS; public class InputView { - public static String inputPurchaseAmount(){ + public static int inputPurchaseAmount(){ System.out.println(GET_PURCHSE_AMOUNT.getValue()); + String input = Console.readLine(); + return PurchaseAmountValidator.isRightPurchaseAmount(input); + } + + public static String inputWinnging(){ + System.out.println(GET_WINNING_NUMBERS.getValue()); return Console.readLine(); } } diff --git a/src/test/java/domain/LottosTest.java b/src/test/java/domain/LottosTest.java index 3f852906827..7091737cf54 100644 --- a/src/test/java/domain/LottosTest.java +++ b/src/test/java/domain/LottosTest.java @@ -1,6 +1,6 @@ package domain; -import Constants.LottosConstant; +import util.constants.LottosConstant; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/PurchaseAmountTest.java b/src/test/java/domain/PurchaseAmountTest.java new file mode 100644 index 00000000000..2356da0e5df --- /dev/null +++ b/src/test/java/domain/PurchaseAmountTest.java @@ -0,0 +1,35 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import util.constants.Constants; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static util.message.ExceptionMessage.*; +import static util.message.ExceptionMessage.UNIT_MESSAGE; + +public class PurchaseAmountTest { + @ParameterizedTest + @DisplayName("구입금액을 올바르게 입력한 경우 예외가 발생하지 않는다.") + @CsvSource("4000") + void givenNormalAmount_thenSuccess(final int purchaseAmount) { + assertThat(PurchaseAmount.create(purchaseAmount)) + .isInstanceOf(PurchaseAmount.class); + + assertThatCode(() -> PurchaseAmount.create(purchaseAmount)) + .doesNotThrowAnyException(); + } + + @ParameterizedTest + @DisplayName("구입금액이 1000으로 나누어 떨어지지 않는 경우 예외가 발생한다.") + @ValueSource(strings = {"4565", "1223"}) + void givenNonDivisibleBy1000_thenFail(final int purchaseAmount) { + assertThatThrownBy(() -> PurchaseAmount.create(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(UNIT_MESSAGE.getValue(), Constants.ONE_THOUSAND.getValue())); + } +} diff --git a/src/test/java/domain/wrapper/AmountTest.java b/src/test/java/domain/wrapper/AmountTest.java deleted file mode 100644 index d08dd3b7e30..00000000000 --- a/src/test/java/domain/wrapper/AmountTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package domain.wrapper; - -import Constants.PurchaseAmountConstant; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.ValueSource; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static util.message.ExceptionMessage.*; -import static util.message.ExceptionMessage.UNIT_MESSAGE; - -public class AmountTest { - @ParameterizedTest - @DisplayName("구입금액을 올바르게 입력한 경우 예외가 발생하지 않는다.") - @CsvSource("4000") - void givenNormalAmount_thenSuccess(final String purchaseAmount) { - assertThat(Amount.create(purchaseAmount)) - .isInstanceOf(Amount.class); - - assertThatCode(() -> Amount.create(purchaseAmount)) - .doesNotThrowAnyException(); - } - - @ParameterizedTest - @DisplayName("구입금액을 빈값으로 입력한 경우 예외가 발생한다.") - @ValueSource(strings = {"", " ", " ", " ", " ", "\n", "\t", "\r"}) - void givenBlankAmount_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> Amount.create(purchaseAmount)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining(String.format(BLANK_MESSAGE.getValue(), "구입금액")); - } - - @ParameterizedTest - @DisplayName("구입금액을 숫자가 아닌 형태로 입력한 경우 예외가 발생한다.") - @ValueSource(strings = {"abc", "12bd"}) - void givenNonNumeric_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> Amount.create(purchaseAmount)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining(String.format(TYPE_MESSAGE.getValue(), "구입금액")); - } - - @ParameterizedTest - @DisplayName("구입금액이 0이하인경우 예외가 발생한다.") - @ValueSource(strings = {"-1", "0"}) - void givenLessZero_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> Amount.create(purchaseAmount)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining(String.format(RANGE_MESSAGE.getValue(), PurchaseAmountConstant.ZERO.getValue())); - } - - @ParameterizedTest - @DisplayName("구입금액이 1000으로 나누어 떨어지지 않는 경우 예외가 발생한다.") - @ValueSource(strings = {"4565", "1223"}) - void givenNonDivisibleBy1000_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> Amount.create(purchaseAmount)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining(String.format(UNIT_MESSAGE.getValue(), PurchaseAmountConstant.ONE_THOUSAND.getValue())); - } -} diff --git a/src/test/java/validator/PurchaseAmountValidatorTest.java b/src/test/java/validator/PurchaseAmountValidatorTest.java new file mode 100644 index 00000000000..09764951b79 --- /dev/null +++ b/src/test/java/validator/PurchaseAmountValidatorTest.java @@ -0,0 +1,40 @@ +package validator; + +import domain.PurchaseAmount; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import util.constants.Constants; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static util.constants.Constants.ZERO; +import static util.message.ExceptionMessage.*; + +public class PurchaseAmountValidatorTest { + @ParameterizedTest + @DisplayName("구입금액을 빈값으로 입력한 경우 예외가 발생한다.") + @ValueSource(strings = {"", " ", " ", " ", " ", "\n", "\t", "\r"}) + void givenBlankAmount_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> PurchaseAmountValidator.isRightPurchaseAmount(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(BLANK_MESSAGE.getValue())); + } + + @ParameterizedTest + @DisplayName("구입금액을 숫자가 아닌 형태로 입력한 경우 예외가 발생한다.") + @ValueSource(strings = {"abc", "12bd"}) + void givenNonNumeric_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> PurchaseAmountValidator.isRightPurchaseAmount(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(TYPE_MESSAGE.getValue())); + } + + @ParameterizedTest + @DisplayName("구입금액이 0이하인경우 예외가 발생한다.") + @ValueSource(strings = {"-1", "0"}) + void givenLessZero_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> PurchaseAmountValidator.isRightPurchaseAmount(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(RANGE_MESSAGE.getValue(), Constants.ZERO.getValue())); + } +} From 86107379a97378850456a0fd47531d8e0ea837f7 Mon Sep 17 00:00:00 2001 From: suhyun Date: Wed, 29 Nov 2023 17:19:20 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=206=EA=B0=9C=EC=9D=98=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EB=90=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=EB=A1=9C=20=EC=9D=B4=EB=A3=A8=EC=96=B4=EC=A7=84=20?= =?UTF-8?q?=EB=8B=B9=EC=B2=A8=EB=B2=88=ED=98=B8=EB=A5=BC=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/LottosController.java | 19 ++++++- .../java/controller/PurchaseController.java | 2 +- src/main/java/domain/Lottos.java | 8 +-- src/main/java/domain/PurchaseAmount.java | 10 ++-- src/main/java/domain/WinningNumbers.java | 25 ++++++++ src/main/java/service/LottosService.java | 5 ++ ...ttosConstant.java => LottosConstants.java} | 4 +- .../java/util/message/ExceptionMessage.java | 4 +- .../validator/PurchaseAmountValidator.java | 2 +- .../validator/WinningNumbersValidator.java | 57 ++++++++++++++++++- src/main/java/view/InputView.java | 10 +++- src/test/java/domain/LottosTest.java | 4 +- src/test/java/domain/WinningNumbersTest.java | 41 +++++++++++++ src/test/java/provider/TestProvider.java | 7 +++ .../PurchaseAmountValidatorTest.java | 6 +- .../validator/WinningNumbersValidators.java | 36 ++++++++++++ 16 files changed, 214 insertions(+), 26 deletions(-) rename src/main/java/util/constants/{LottosConstant.java => LottosConstants.java} (75%) create mode 100644 src/test/java/domain/WinningNumbersTest.java create mode 100644 src/test/java/validator/WinningNumbersValidators.java diff --git a/src/main/java/controller/LottosController.java b/src/main/java/controller/LottosController.java index 1bbf4fe2df5..4fcb7f973f4 100644 --- a/src/main/java/controller/LottosController.java +++ b/src/main/java/controller/LottosController.java @@ -2,6 +2,7 @@ import domain.PurchaseAmount; import domain.Lottos; +import domain.WinningNumbers; import dto.LottoDto; import service.LottosService; import service.PurchaseService; @@ -10,8 +11,6 @@ import java.util.List; -import static view.InputView.inputWinnging; - public class LottosController { private final LottosService lottosService; @@ -35,6 +34,20 @@ private void printPurchaseLottos(final Lottos purchaseLottos, final int numberOf } private void generateWinngingAndBonus(){ - String winngNumbers = inputWinnging(); + generateWinngingNumbers(); + } + + private WinningNumbers generateWinngingNumbers(){ + try{ + List winningNumbers = InputView.inputWinngingNumbers(); + return createWinngingNumbers(winningNumbers); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + return generateWinngingNumbers(); + } + } + + private WinningNumbers createWinngingNumbers(final List winningNumbers){ + return lottosService.createWinningNumbers(winningNumbers); } } diff --git a/src/main/java/controller/PurchaseController.java b/src/main/java/controller/PurchaseController.java index e0386ebe165..1a2dd3828ed 100644 --- a/src/main/java/controller/PurchaseController.java +++ b/src/main/java/controller/PurchaseController.java @@ -13,8 +13,8 @@ public PurchaseController(){ } public PurchaseAmount generatePurchaseAmount(){ - int purchaseAmount = InputView.inputPurchaseAmount(); try{ + int purchaseAmount = InputView.inputPurchaseAmount(); return createPurchaseAmount(purchaseAmount); } catch (IllegalArgumentException e){ OutputView.printMessage(e.getMessage()); diff --git a/src/main/java/domain/Lottos.java b/src/main/java/domain/Lottos.java index de2f34d301b..1cfb6af9256 100644 --- a/src/main/java/domain/Lottos.java +++ b/src/main/java/domain/Lottos.java @@ -1,6 +1,6 @@ package domain; -import util.constants.LottosConstant; +import util.constants.LottosConstants; import camp.nextstep.edu.missionutils.Randoms; import java.util.ArrayList; @@ -31,9 +31,9 @@ private List generateLottos(int numberOfPurchased){ private Lotto generateRandomNumbers(){ List numbers = Randoms.pickUniqueNumbersInRange( - LottosConstant.MIN_VALUE.getValue(), - LottosConstant.MAX_VALUE.getValue(), - LottosConstant.LOTTO_SIZE.getValue()); + LottosConstants.MIN_VALUE.getValue(), + LottosConstants.MAX_VALUE.getValue(), + LottosConstants.LOTTO_SIZE.getValue()); return new Lotto(numbers); } diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index d02b69fdd05..8e0ca3fea0e 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -8,20 +8,20 @@ public class PurchaseAmount { private final int amount; private final int quantity; - private PurchaseAmount(final int purchaseAmount){ + private PurchaseAmount(final int purchaseAmount) { validateDivisibleBy1000(purchaseAmount); this.amount = purchaseAmount; this.quantity = calculatequantity(); } - public int getQuantity(){ - return quantity; - } - public static PurchaseAmount create(final int purchaseAmount){ return new PurchaseAmount(purchaseAmount); } + public int getQuantity(){ + return quantity; + } + private int calculatequantity(){ return amount / Constants.ONE_THOUSAND.getValue(); } diff --git a/src/main/java/domain/WinningNumbers.java b/src/main/java/domain/WinningNumbers.java index 4956b8768f4..68159029491 100644 --- a/src/main/java/domain/WinningNumbers.java +++ b/src/main/java/domain/WinningNumbers.java @@ -1,4 +1,29 @@ package domain; +import util.exception.DuplicateException; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static util.message.ExceptionMessage.DUPLICATE_MESSAGE; + public class WinningNumbers { + private final List numbers; + + private WinningNumbers(final List inputWinningNumbers) { + validateDuplicate(inputWinningNumbers); + numbers = inputWinningNumbers; + } + + public static WinningNumbers create(final List inputWinningNumbers){ + return new WinningNumbers(inputWinningNumbers); + } + + private void validateDuplicate(final List inputWinningNumbers){ + Set numbers = new HashSet<>(inputWinningNumbers); + if(numbers.size() != inputWinningNumbers.size()){ + throw new DuplicateException(String.format(DUPLICATE_MESSAGE.getValue())); + } + } } diff --git a/src/main/java/service/LottosService.java b/src/main/java/service/LottosService.java index 494c00e0e3f..6f40010d2e3 100644 --- a/src/main/java/service/LottosService.java +++ b/src/main/java/service/LottosService.java @@ -3,6 +3,7 @@ import domain.Lotto; import domain.PurchaseAmount; import domain.Lottos; +import domain.WinningNumbers; import dto.LottoDto; import java.util.List; @@ -19,4 +20,8 @@ public List getPurchaseLottos(final Lottos purchaseLottos){ .map(lotto -> LottoDto.create(lotto.getNumbers())) .collect(Collectors.toList()); } + + public WinningNumbers createWinningNumbers(final List winningNumbers){ + return WinningNumbers.create(winningNumbers); + } } diff --git a/src/main/java/util/constants/LottosConstant.java b/src/main/java/util/constants/LottosConstants.java similarity index 75% rename from src/main/java/util/constants/LottosConstant.java rename to src/main/java/util/constants/LottosConstants.java index 1cd96cb6934..7eb2b154ef2 100644 --- a/src/main/java/util/constants/LottosConstant.java +++ b/src/main/java/util/constants/LottosConstants.java @@ -2,14 +2,14 @@ import util.EnumUtil; -public enum LottosConstant implements EnumUtil { +public enum LottosConstants implements EnumUtil { MIN_VALUE(1), MAX_VALUE(45), LOTTO_SIZE(6); private final int number; - LottosConstant(final int number){ + LottosConstants(final int number){ this.number = number; } diff --git a/src/main/java/util/message/ExceptionMessage.java b/src/main/java/util/message/ExceptionMessage.java index 7cd99df2c19..4bb926fa2a3 100644 --- a/src/main/java/util/message/ExceptionMessage.java +++ b/src/main/java/util/message/ExceptionMessage.java @@ -9,14 +9,16 @@ public enum ExceptionMessage implements EnumUtil { , TYPE_MESSAGE("숫자만 입력할 수 있습니다.") , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") , RANGE_MESSAGE("%d 이상의 값을 입력해 주세요.") + , RANGE_START_BETWEEND_END("d와 %d 사이의 값을 입력해주세요.") , DUPLICATE_MESSAGE("중복된 값이 있습니다.") , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다.") , SIZE_OVER_MESSAGE("%s크기를 초과하였습니다."); private final String message; + private static final String ERROR_TAG = "[ERROR] "; ExceptionMessage(final String message) { - this.message = message; + this.message = ERROR_TAG + message; } @Override diff --git a/src/main/java/validator/PurchaseAmountValidator.java b/src/main/java/validator/PurchaseAmountValidator.java index 5ee3aefef9c..270caad6ad6 100644 --- a/src/main/java/validator/PurchaseAmountValidator.java +++ b/src/main/java/validator/PurchaseAmountValidator.java @@ -3,7 +3,7 @@ import util.constants.Constants; public class PurchaseAmountValidator extends Validator{ - public static int isRightPurchaseAmount(String input) { + public static int validate(String input) { validateBlank(input); int amount = validateType(input); return validateRange(amount, Constants.ZERO.getValue()); diff --git a/src/main/java/validator/WinningNumbersValidator.java b/src/main/java/validator/WinningNumbersValidator.java index a0ab2a187e1..f33154f8d9b 100644 --- a/src/main/java/validator/WinningNumbersValidator.java +++ b/src/main/java/validator/WinningNumbersValidator.java @@ -1,4 +1,59 @@ package validator; -public class WinningNumbersValidator { +import util.constants.LottosConstants; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import static util.message.ExceptionMessage.*; + +public class WinningNumbersValidator extends Validator{ + + private static final String COMMA = ","; + public static List validate(String input) { + validateBlank(input); + return validateNumbers(input); + } + + private static List validateNumbers(String input){ + String[] inputs = input.split(COMMA); + validateSize(inputs); + List numbers = validateNumeric(inputs); + validateRange(LottosConstants.MIN_VALUE.getValue(), LottosConstants.MAX_VALUE.getValue(), numbers); + return numbers; + } + + private static void validateSize(String[] inputs){ + if(inputs.length != LottosConstants.LOTTO_SIZE.getValue()){ + throw new IllegalArgumentException(BLANK_MESSAGE.getValue()); + } + } + + private static List validateNumeric(String[] inputs){ + List numbers = new ArrayList<>(); + for(String number : inputs){ + if(!isNumeric(number.trim())){ + throw new IllegalArgumentException(BLANK_MESSAGE.getValue()); + } + numbers.add(changeStringToInt(number)); + } + return numbers; + } + + private static int changeStringToInt(String number){ + return Integer.parseInt(number); + } + + private static boolean isNumeric(String str){ + return Pattern.matches("\\d+", str); + } + + protected static void validateRange(final int start, final int end, final List numbers) { + for(int number : numbers){ + if (number >= start && number <= end) { + throw new IllegalArgumentException(String.format(RANGE_START_BETWEEND_END.getValue(), start, end)); + } + } + } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index cf0ac58aa3c..7d4dddebf20 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -3,6 +3,9 @@ import camp.nextstep.edu.missionutils.Console; import validator.PurchaseAmountValidator; import validator.Validator; +import validator.WinningNumbersValidator; + +import java.util.List; import static util.message.InputMessage.GET_PURCHSE_AMOUNT; import static util.message.InputMessage.GET_WINNING_NUMBERS; @@ -11,11 +14,12 @@ public class InputView { public static int inputPurchaseAmount(){ System.out.println(GET_PURCHSE_AMOUNT.getValue()); String input = Console.readLine(); - return PurchaseAmountValidator.isRightPurchaseAmount(input); + return PurchaseAmountValidator.validate(input); } - public static String inputWinnging(){ + public static List inputWinngingNumbers(){ System.out.println(GET_WINNING_NUMBERS.getValue()); - return Console.readLine(); + String input = Console.readLine(); + return WinningNumbersValidator.validate(input); } } diff --git a/src/test/java/domain/LottosTest.java b/src/test/java/domain/LottosTest.java index 7091737cf54..68553cc37cc 100644 --- a/src/test/java/domain/LottosTest.java +++ b/src/test/java/domain/LottosTest.java @@ -1,6 +1,6 @@ package domain; -import util.constants.LottosConstant; +import util.constants.LottosConstants; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -40,6 +40,6 @@ private void validateLotto(Lotto lotto) { List numbers = lotto.getNumbers(); assertNotNull(numbers); - assertEquals(LottosConstant.LOTTO_SIZE.getValue(), numbers.size()); + assertEquals(LottosConstants.LOTTO_SIZE.getValue(), numbers.size()); } } diff --git a/src/test/java/domain/WinningNumbersTest.java b/src/test/java/domain/WinningNumbersTest.java new file mode 100644 index 00000000000..5c6f1f7d528 --- /dev/null +++ b/src/test/java/domain/WinningNumbersTest.java @@ -0,0 +1,41 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import util.constants.Constants; +import util.exception.DuplicateException; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static provider.TestProvider.createTestPurchaseLottos; +import static provider.TestProvider.createTestWinningNumbers; +import static util.message.ExceptionMessage.UNIT_MESSAGE; + +public class WinningNumbersTest { + + @DisplayName("당첨번호를 올바르게 입력한 경우 예외가 발생하지 않는다.") + @Test + void givenNormalWinningNumbers_thenSuccess() { + assertThat(WinningNumbers.create(new ArrayList<>(List.of(1,2,3,4,5,6)))) + .isInstanceOf(WinningNumbers.class); + + assertThatCode(() -> WinningNumbers.create(List.of(1,2,3,4,5,6))) + .doesNotThrowAnyException(); + } + + @DisplayName("당첨번호를 중복으로 입력한 경우 예외가 발생하지 않는다.") + @Test + void givenDuplicateWinningNumbers_thenFail() { + assertThatThrownBy(() -> WinningNumbers.create(new ArrayList<>(List.of(1,2,3,4,5,5)))) + .isInstanceOf(IllegalArgumentException.class); + } +} + + diff --git a/src/test/java/provider/TestProvider.java b/src/test/java/provider/TestProvider.java index 3d67f73d258..0b85658e469 100644 --- a/src/test/java/provider/TestProvider.java +++ b/src/test/java/provider/TestProvider.java @@ -1,9 +1,16 @@ package provider; import domain.Lottos; +import domain.WinningNumbers; + +import java.util.List; public class TestProvider { public static Lottos createTestPurchaseLottos(final int numberOfPurchased) { return Lottos.create(numberOfPurchased); } + + public static WinningNumbers createTestWinningNumbers(final List numbers){ + return WinningNumbers.create(numbers); + } } diff --git a/src/test/java/validator/PurchaseAmountValidatorTest.java b/src/test/java/validator/PurchaseAmountValidatorTest.java index 09764951b79..bf7d11ee65d 100644 --- a/src/test/java/validator/PurchaseAmountValidatorTest.java +++ b/src/test/java/validator/PurchaseAmountValidatorTest.java @@ -15,7 +15,7 @@ public class PurchaseAmountValidatorTest { @DisplayName("구입금액을 빈값으로 입력한 경우 예외가 발생한다.") @ValueSource(strings = {"", " ", " ", " ", " ", "\n", "\t", "\r"}) void givenBlankAmount_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> PurchaseAmountValidator.isRightPurchaseAmount(purchaseAmount)) + assertThatThrownBy(() -> PurchaseAmountValidator.validate(purchaseAmount)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining(String.format(BLANK_MESSAGE.getValue())); } @@ -24,7 +24,7 @@ void givenBlankAmount_thenFail(final String purchaseAmount) { @DisplayName("구입금액을 숫자가 아닌 형태로 입력한 경우 예외가 발생한다.") @ValueSource(strings = {"abc", "12bd"}) void givenNonNumeric_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> PurchaseAmountValidator.isRightPurchaseAmount(purchaseAmount)) + assertThatThrownBy(() -> PurchaseAmountValidator.validate(purchaseAmount)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining(String.format(TYPE_MESSAGE.getValue())); } @@ -33,7 +33,7 @@ void givenNonNumeric_thenFail(final String purchaseAmount) { @DisplayName("구입금액이 0이하인경우 예외가 발생한다.") @ValueSource(strings = {"-1", "0"}) void givenLessZero_thenFail(final String purchaseAmount) { - assertThatThrownBy(() -> PurchaseAmountValidator.isRightPurchaseAmount(purchaseAmount)) + assertThatThrownBy(() -> PurchaseAmountValidator.validate(purchaseAmount)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining(String.format(RANGE_MESSAGE.getValue(), Constants.ZERO.getValue())); } diff --git a/src/test/java/validator/WinningNumbersValidators.java b/src/test/java/validator/WinningNumbersValidators.java new file mode 100644 index 00000000000..b8f91a143d9 --- /dev/null +++ b/src/test/java/validator/WinningNumbersValidators.java @@ -0,0 +1,36 @@ +package validator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class WinningNumbersValidators { + + @DisplayName("당첨 번호의 개수가 6개가 넘어가면 예외가 발생한다.") + @ParameterizedTest + @CsvSource({"1,2,3,4,5,6,7"}) + void createWinningNumbersByOverSize(final String numbers) { + assertThatThrownBy(() -> WinningNumbersValidator.validate(numbers)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("당첨 번호에 문자가 있으면 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"1,ㅇ.ㄹㅇㄹ", ",,,,"}) + void createWinningNumbersNumeric(final String numbers) { + assertThatThrownBy(() -> WinningNumbersValidator.validate(numbers)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("당첨 번호가 범위를 벗어나면 예외가 발생한다.") + @ParameterizedTest + @CsvSource({"1,2,3,4,5,46"}) + void createWinningNumbersRange(final String numbers) { + assertThatThrownBy(() -> WinningNumbersValidator.validate(numbers)) + .isInstanceOf(IllegalArgumentException.class); + } +} From 5b9329bea3ee00b5e0930b4e75dfce07642329b7 Mon Sep 17 00:00:00 2001 From: suhyun Date: Wed, 29 Nov 2023 18:07:18 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=EB=B3=B4=EB=84=88=EC=8A=A4?= =?UTF-8?q?=EB=B2=88=ED=98=B8=EB=A5=BC=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/LottosController.java | 18 +++++- src/main/java/domain/BonusNumber.java | 13 +++++ src/main/java/service/LottosService.java | 9 +-- .../java/util/message/ExceptionMessage.java | 2 +- src/main/java/util/message/InputMessage.java | 3 +- src/main/java/validator/BonusValidator.java | 20 +++++++ .../validator/PurchaseAmountValidator.java | 2 +- .../validator/WinningNumbersValidator.java | 8 +-- src/main/java/view/InputView.java | 11 +++- src/test/java/domain/BonusNumberTest.java | 21 +++++++ .../java/validator/BonusValidatorTest.java | 55 +++++++++++++++++++ .../validator/WinningNumbersValidators.java | 22 +++++--- 12 files changed, 160 insertions(+), 24 deletions(-) create mode 100644 src/main/java/domain/BonusNumber.java create mode 100644 src/main/java/validator/BonusValidator.java create mode 100644 src/test/java/domain/BonusNumberTest.java create mode 100644 src/test/java/validator/BonusValidatorTest.java diff --git a/src/main/java/controller/LottosController.java b/src/main/java/controller/LottosController.java index 4fcb7f973f4..28cbaf8e73f 100644 --- a/src/main/java/controller/LottosController.java +++ b/src/main/java/controller/LottosController.java @@ -1,5 +1,6 @@ package controller; +import domain.BonusNumber; import domain.PurchaseAmount; import domain.Lottos; import domain.WinningNumbers; @@ -34,7 +35,8 @@ private void printPurchaseLottos(final Lottos purchaseLottos, final int numberOf } private void generateWinngingAndBonus(){ - generateWinngingNumbers(); + WinningNumbers winningNumbers = generateWinngingNumbers(); + BonusNumber bonusNumber = generateBonusNumber(); } private WinningNumbers generateWinngingNumbers(){ @@ -47,7 +49,21 @@ private WinningNumbers generateWinngingNumbers(){ } } + private BonusNumber generateBonusNumber(){ + try{ + int number = InputView.inputBonusNumber(); + return createBonusNumber(number); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + return generateBonusNumber(); + } + } + private WinningNumbers createWinngingNumbers(final List winningNumbers){ return lottosService.createWinningNumbers(winningNumbers); } + + private BonusNumber createBonusNumber(final int bonusNumber){ + return lottosService.createBonusNumber(bonusNumber); + } } diff --git a/src/main/java/domain/BonusNumber.java b/src/main/java/domain/BonusNumber.java new file mode 100644 index 00000000000..bfa7d62366d --- /dev/null +++ b/src/main/java/domain/BonusNumber.java @@ -0,0 +1,13 @@ +package domain; + +public class BonusNumber { + private final int bonusNumber; + + private BonusNumber(final int number) { + bonusNumber = number; + } + + public static BonusNumber create(final int number){ + return new BonusNumber(number); + } +} diff --git a/src/main/java/service/LottosService.java b/src/main/java/service/LottosService.java index 6f40010d2e3..b3ae2eaf9ee 100644 --- a/src/main/java/service/LottosService.java +++ b/src/main/java/service/LottosService.java @@ -1,9 +1,6 @@ package service; -import domain.Lotto; -import domain.PurchaseAmount; -import domain.Lottos; -import domain.WinningNumbers; +import domain.*; import dto.LottoDto; import java.util.List; @@ -24,4 +21,8 @@ public List getPurchaseLottos(final Lottos purchaseLottos){ public WinningNumbers createWinningNumbers(final List winningNumbers){ return WinningNumbers.create(winningNumbers); } + + public BonusNumber createBonusNumber(final int bonusNumber){ + return BonusNumber.create(bonusNumber); + } } diff --git a/src/main/java/util/message/ExceptionMessage.java b/src/main/java/util/message/ExceptionMessage.java index 4bb926fa2a3..459f37770c4 100644 --- a/src/main/java/util/message/ExceptionMessage.java +++ b/src/main/java/util/message/ExceptionMessage.java @@ -9,7 +9,7 @@ public enum ExceptionMessage implements EnumUtil { , TYPE_MESSAGE("숫자만 입력할 수 있습니다.") , UNIT_MESSAGE("%d원 단위로 입력해 주세요.") , RANGE_MESSAGE("%d 이상의 값을 입력해 주세요.") - , RANGE_START_BETWEEND_END("d와 %d 사이의 값을 입력해주세요.") + , RANGE_START_BETWEEND_END("%d와 %d 사이의 값을 입력해주세요.") , DUPLICATE_MESSAGE("중복된 값이 있습니다.") , NO_RESOURCE_MESSAGE("%s(이)가 존재하지 않습니다.") , SIZE_OVER_MESSAGE("%s크기를 초과하였습니다."); diff --git a/src/main/java/util/message/InputMessage.java b/src/main/java/util/message/InputMessage.java index 54ce9b0ffb5..967f5f348c3 100644 --- a/src/main/java/util/message/InputMessage.java +++ b/src/main/java/util/message/InputMessage.java @@ -4,7 +4,8 @@ public enum InputMessage implements EnumUtil { GET_PURCHSE_AMOUNT("구입금액을 입력해 주세요."), - GET_WINNING_NUMBERS("당첨 번호를 입력해 주세요."); + GET_WINNING_NUMBERS("\n당첨 번호를 입력해 주세요."), + GET_BONUS_NUMBER("\n보너스 번호를 입력해 주세요."); private final String message; InputMessage(final String message){ diff --git a/src/main/java/validator/BonusValidator.java b/src/main/java/validator/BonusValidator.java new file mode 100644 index 00000000000..24ab33595a0 --- /dev/null +++ b/src/main/java/validator/BonusValidator.java @@ -0,0 +1,20 @@ +package validator; + +import java.util.List; + +import static util.message.ExceptionMessage.RANGE_START_BETWEEND_END; + +public class BonusValidator extends Validator{ + public static int validate(String input){ + validateBlank(input); + int number = validateType(input); + return validateRange(1,45, number); + } + + protected static int validateRange(final int start, final int end, final int number) { + if (number < start || number > end) { + throw new IllegalArgumentException(String.format(RANGE_START_BETWEEND_END.getValue(), start, end)); + } + return number; + } +} diff --git a/src/main/java/validator/PurchaseAmountValidator.java b/src/main/java/validator/PurchaseAmountValidator.java index 270caad6ad6..843b0746e6b 100644 --- a/src/main/java/validator/PurchaseAmountValidator.java +++ b/src/main/java/validator/PurchaseAmountValidator.java @@ -6,6 +6,6 @@ public class PurchaseAmountValidator extends Validator{ public static int validate(String input) { validateBlank(input); int amount = validateType(input); - return validateRange(amount, Constants.ZERO.getValue()); + return validateRange(amount, 0); } } diff --git a/src/main/java/validator/WinningNumbersValidator.java b/src/main/java/validator/WinningNumbersValidator.java index f33154f8d9b..142707a73b8 100644 --- a/src/main/java/validator/WinningNumbersValidator.java +++ b/src/main/java/validator/WinningNumbersValidator.java @@ -20,13 +20,13 @@ private static List validateNumbers(String input){ String[] inputs = input.split(COMMA); validateSize(inputs); List numbers = validateNumeric(inputs); - validateRange(LottosConstants.MIN_VALUE.getValue(), LottosConstants.MAX_VALUE.getValue(), numbers); + validateRange(1,45, numbers); return numbers; } private static void validateSize(String[] inputs){ if(inputs.length != LottosConstants.LOTTO_SIZE.getValue()){ - throw new IllegalArgumentException(BLANK_MESSAGE.getValue()); + throw new IllegalArgumentException(String.format(SIZE_OVER_MESSAGE.getValue(), "로또")); } } @@ -34,7 +34,7 @@ private static List validateNumeric(String[] inputs){ List numbers = new ArrayList<>(); for(String number : inputs){ if(!isNumeric(number.trim())){ - throw new IllegalArgumentException(BLANK_MESSAGE.getValue()); + throw new IllegalArgumentException(TYPE_MESSAGE.getValue()); } numbers.add(changeStringToInt(number)); } @@ -51,7 +51,7 @@ private static boolean isNumeric(String str){ protected static void validateRange(final int start, final int end, final List numbers) { for(int number : numbers){ - if (number >= start && number <= end) { + if (number < start || number > end) { throw new IllegalArgumentException(String.format(RANGE_START_BETWEEND_END.getValue(), start, end)); } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 7d4dddebf20..e57830f6ce7 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,14 +1,13 @@ package view; import camp.nextstep.edu.missionutils.Console; +import validator.BonusValidator; import validator.PurchaseAmountValidator; -import validator.Validator; import validator.WinningNumbersValidator; import java.util.List; -import static util.message.InputMessage.GET_PURCHSE_AMOUNT; -import static util.message.InputMessage.GET_WINNING_NUMBERS; +import static util.message.InputMessage.*; public class InputView { public static int inputPurchaseAmount(){ @@ -22,4 +21,10 @@ public static List inputWinngingNumbers(){ String input = Console.readLine(); return WinningNumbersValidator.validate(input); } + + public static int inputBonusNumber(){ + System.out.println(GET_BONUS_NUMBER.getValue()); + String input = Console.readLine(); + return BonusValidator.validate(input); + } } diff --git a/src/test/java/domain/BonusNumberTest.java b/src/test/java/domain/BonusNumberTest.java new file mode 100644 index 00000000000..c48a663e686 --- /dev/null +++ b/src/test/java/domain/BonusNumberTest.java @@ -0,0 +1,21 @@ +package domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThatCode; + +public class BonusNumberTest { + @ParameterizedTest + @DisplayName("보너스번호을 올바르게 입력한 경우 예외가 발생하지 않는다.") + @CsvSource("40") + void givenNormalBonus_thenSuccess(final int bonusNumber) { + Assertions.assertThat(BonusNumber.create(bonusNumber)) + .isInstanceOf(BonusNumber.class); + + assertThatCode(() -> BonusNumber.create(bonusNumber)) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/validator/BonusValidatorTest.java b/src/test/java/validator/BonusValidatorTest.java new file mode 100644 index 00000000000..e6c25388457 --- /dev/null +++ b/src/test/java/validator/BonusValidatorTest.java @@ -0,0 +1,55 @@ +package validator; + +import domain.BonusNumber; +import domain.PurchaseAmount; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import util.constants.Constants; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static util.message.ExceptionMessage.*; +import static util.message.ExceptionMessage.RANGE_MESSAGE; + +public class BonusValidatorTest { + + @ParameterizedTest + @DisplayName("보너스번호를 ") + @ValueSource(strings = {"4565", "1223"}) + void givenNonRangeBonus_thenFail(final int purchaseAmount) { + assertThatThrownBy(() -> PurchaseAmount.create(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(UNIT_MESSAGE.getValue(), Constants.ONE_THOUSAND.getValue())); + } + + @ParameterizedTest + @DisplayName("보너스번호를 빈값으로 입력한 경우 예외가 발생한다.") + @ValueSource(strings = {"", " ", " ", " ", " ", "\n", "\t", "\r"}) + void givenBlankAmount_thenFail(final String bonus) { + assertThatThrownBy(() -> BonusValidator.validate(bonus)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(BLANK_MESSAGE.getValue())); + } + + @ParameterizedTest + @DisplayName("보너스번호를 숫자가 아닌 형태로 입력한 경우 예외가 발생한다.") + @ValueSource(strings = {"abc", "12bd"}) + void givenNonNumeric_thenFail(final String bonus) { + assertThatThrownBy(() -> BonusValidator.validate(bonus)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(TYPE_MESSAGE.getValue())); + } + + @ParameterizedTest + @DisplayName("보너스번호를 범위에 벗어나면 예외가 발생한다.") + @ValueSource(strings = {"-1", "49"}) + void givenLessZero_thenFail(final String purchaseAmount) { + assertThatThrownBy(() -> BonusValidator.validate(purchaseAmount)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(RANGE_START_BETWEEND_END.getValue(), 1, 45)); + } +} diff --git a/src/test/java/validator/WinningNumbersValidators.java b/src/test/java/validator/WinningNumbersValidators.java index b8f91a143d9..37a70a374ed 100644 --- a/src/test/java/validator/WinningNumbersValidators.java +++ b/src/test/java/validator/WinningNumbersValidators.java @@ -7,6 +7,7 @@ import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static util.message.ExceptionMessage.*; public class WinningNumbersValidators { @@ -15,22 +16,25 @@ public class WinningNumbersValidators { @CsvSource({"1,2,3,4,5,6,7"}) void createWinningNumbersByOverSize(final String numbers) { assertThatThrownBy(() -> WinningNumbersValidator.validate(numbers)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage((String.format(SIZE_OVER_MESSAGE.getValue(), "로또"))); } @DisplayName("당첨 번호에 문자가 있으면 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {"1,ㅇ.ㄹㅇㄹ", ",,,,"}) - void createWinningNumbersNumeric(final String numbers) { + @Test + void createWinningNumbersNumericVer1() { + String numbers = "1,,d,fd,fdf,dfef"; assertThatThrownBy(() -> WinningNumbersValidator.validate(numbers)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(String.format(TYPE_MESSAGE.getValue()));; } @DisplayName("당첨 번호가 범위를 벗어나면 예외가 발생한다.") - @ParameterizedTest - @CsvSource({"1,2,3,4,5,46"}) - void createWinningNumbersRange(final String numbers) { + @Test + void createWinningNumbersRange() { + String numbers = "1,3,45,100,1,0"; assertThatThrownBy(() -> WinningNumbersValidator.validate(numbers)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage((String.format(RANGE_START_BETWEEND_END.getValue(), 1, 45))); } } From d28635adc4e615b1d3035a019204ee0a75d1a076 Mon Sep 17 00:00:00 2001 From: suhyun Date: Wed, 29 Nov 2023 18:08:58 +0900 Subject: [PATCH 6/7] =?UTF-8?q?docs:=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EB=AA=A9=EB=A1=9D=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 7d691c6ba57..741b3a9fe88 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,4 +3,8 @@ [ ✅ ] 사용자는 구입금액을 입력한다. - 구입금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다. -[ ✅ ] 구입금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. \ No newline at end of file +[ ✅ ] 구입금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. + +[ ✅ ] 당첨번호를 입력한다. + +[ ✅ ] 보너스번호를 입력한다. \ No newline at end of file From 6cfa1f6abe18f168f14465a5691ab09f0b573ff2 Mon Sep 17 00:00:00 2001 From: suhyun Date: Thu, 30 Nov 2023 10:29:14 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=ED=86=B5?= =?UTF-8?q?=EA=B3=84=EC=99=80=20=EC=88=98=EC=9D=B5=EB=A5=A0=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 +- .../java/controller/LottosController.java | 44 ++---------- .../java/controller/WinningController.java | 61 ++++++++++++++++ src/main/java/domain/BonusNumber.java | 4 ++ src/main/java/domain/Lotto.java | 15 ++-- src/main/java/domain/PurchaseAmount.java | 4 ++ src/main/java/domain/Rank.java | 59 +++++++++++++++ src/main/java/domain/WinningNumbers.java | 4 ++ src/main/java/domain/WinningResult.java | 72 +++++++++++++++++++ src/main/java/dto/WinningResultDto.java | 36 ++++++++++ src/main/java/lotto/Application.java | 7 +- src/main/java/service/LottosService.java | 8 --- src/main/java/service/WinningService.java | 41 +++++++++++ src/main/java/util/constants/Constants.java | 3 +- src/main/java/util/message/OutputMessage.java | 5 +- src/main/java/view/InputView.java | 6 +- src/main/java/view/OutputView.java | 7 ++ .../{ => view}/validator/BonusValidator.java | 4 +- .../validator/PurchaseAmountValidator.java | 4 +- .../java/{ => view}/validator/Validator.java | 2 +- .../validator/WinningNumbersValidator.java | 2 +- src/test/java/domain/RankTest.java | 51 +++++++++++++ src/test/java/domain/WinningResultTest.java | 45 ++++++++++++ src/test/java/provider/TestProvider.java | 10 +++ .../java/validator/BonusValidatorTest.java | 6 +- .../PurchaseAmountValidatorTest.java | 3 +- .../validator/WinningNumbersValidators.java | 2 +- 27 files changed, 433 insertions(+), 78 deletions(-) create mode 100644 src/main/java/controller/WinningController.java create mode 100644 src/main/java/domain/Rank.java create mode 100644 src/main/java/domain/WinningResult.java create mode 100644 src/main/java/dto/WinningResultDto.java create mode 100644 src/main/java/service/WinningService.java rename src/main/java/{ => view}/validator/BonusValidator.java (93%) rename src/main/java/{ => view}/validator/PurchaseAmountValidator.java (80%) rename src/main/java/{ => view}/validator/Validator.java (97%) rename src/main/java/{ => view}/validator/WinningNumbersValidator.java (98%) create mode 100644 src/test/java/domain/RankTest.java create mode 100644 src/test/java/domain/WinningResultTest.java diff --git a/docs/README.md b/docs/README.md index 741b3a9fe88..7386e1cc252 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,4 +7,8 @@ [ ✅ ] 당첨번호를 입력한다. -[ ✅ ] 보너스번호를 입력한다. \ No newline at end of file +[ ✅ ] 보너스번호를 입력한다. + +[ ✅ ] 당첨통계를 출력한다. + +[ ✅ ] 수익률을 계산한다. \ No newline at end of file diff --git a/src/main/java/controller/LottosController.java b/src/main/java/controller/LottosController.java index 28cbaf8e73f..99efa992cfa 100644 --- a/src/main/java/controller/LottosController.java +++ b/src/main/java/controller/LottosController.java @@ -1,9 +1,6 @@ package controller; -import domain.BonusNumber; -import domain.PurchaseAmount; -import domain.Lottos; -import domain.WinningNumbers; +import domain.*; import dto.LottoDto; import service.LottosService; import service.PurchaseService; @@ -14,15 +11,17 @@ public class LottosController { private final LottosService lottosService; + private Lottos lottos; public LottosController(){ lottosService = new LottosService(); } - public void start(final PurchaseAmount purchaseAmount){ + public Lottos start(final PurchaseAmount purchaseAmount){ Lottos purchaseLottos = generateLottos(purchaseAmount); + lottos = purchaseLottos; printPurchaseLottos(purchaseLottos, purchaseAmount.getQuantity()); - generateWinngingAndBonus(); + return lottos; } private Lottos generateLottos(final PurchaseAmount purchaseAmount){ @@ -33,37 +32,4 @@ private void printPurchaseLottos(final Lottos purchaseLottos, final int numberOf List printPurchaseLottos = lottosService.getPurchaseLottos(purchaseLottos); OutputView.printPurchaseLottos(printPurchaseLottos, numberOfPurchased); } - - private void generateWinngingAndBonus(){ - WinningNumbers winningNumbers = generateWinngingNumbers(); - BonusNumber bonusNumber = generateBonusNumber(); - } - - private WinningNumbers generateWinngingNumbers(){ - try{ - List winningNumbers = InputView.inputWinngingNumbers(); - return createWinngingNumbers(winningNumbers); - } catch (IllegalArgumentException e){ - OutputView.printMessage(e.getMessage()); - return generateWinngingNumbers(); - } - } - - private BonusNumber generateBonusNumber(){ - try{ - int number = InputView.inputBonusNumber(); - return createBonusNumber(number); - } catch (IllegalArgumentException e){ - OutputView.printMessage(e.getMessage()); - return generateBonusNumber(); - } - } - - private WinningNumbers createWinngingNumbers(final List winningNumbers){ - return lottosService.createWinningNumbers(winningNumbers); - } - - private BonusNumber createBonusNumber(final int bonusNumber){ - return lottosService.createBonusNumber(bonusNumber); - } } diff --git a/src/main/java/controller/WinningController.java b/src/main/java/controller/WinningController.java new file mode 100644 index 00000000000..28989ef5dc8 --- /dev/null +++ b/src/main/java/controller/WinningController.java @@ -0,0 +1,61 @@ +package controller; + +import domain.*; +import dto.WinningResultDto; +import service.WinningService; +import view.InputView; +import view.OutputView; + +import java.util.List; + +public class WinningController { + private final WinningService winningService; + + public WinningController(){ + winningService = new WinningService(); + } + + public void generateWinngingAndBonus(final Lottos lottos, final int purchaseAmount){ + WinningNumbers winningNumbers = generateWinngingNumbers(); + BonusNumber bonusNumber = generateBonusNumber(); + printWinningStaticsAndProfit(winningNumbers, bonusNumber, lottos, purchaseAmount); + } + + private WinningNumbers generateWinngingNumbers(){ + try{ + List winningNumbers = InputView.inputWinngingNumbers(); + return createWinngingNumbers(winningNumbers); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + return generateWinngingNumbers(); + } + } + + private BonusNumber generateBonusNumber(){ + try{ + int number = InputView.inputBonusNumber(); + return createBonusNumber(number); + } catch (IllegalArgumentException e){ + OutputView.printMessage(e.getMessage()); + return generateBonusNumber(); + } + } + + private WinningNumbers createWinngingNumbers(final List winningNumbers){ + return winningService.createWinningNumbers(winningNumbers); + } + + private BonusNumber createBonusNumber(final int bonusNumber){ + return winningService.createBonusNumber(bonusNumber); + } + + private void printWinningStaticsAndProfit(final WinningNumbers winningNumbers, final BonusNumber bonusNumber, final Lottos lottos, final int purchaseAmount){ + generateWinningResult(winningNumbers, bonusNumber); + WinningResultDto winningResultDto = winningService.calculateProfitAndRateOfProfit(lottos.getLottos(), purchaseAmount); + OutputView.printWinningStatics(winningResultDto); + } + + private WinningResult generateWinningResult(final WinningNumbers winningNumbers, final BonusNumber bonusNumber){ + return winningService.createWinningResult(winningNumbers, bonusNumber); + } +} diff --git a/src/main/java/domain/BonusNumber.java b/src/main/java/domain/BonusNumber.java index bfa7d62366d..117266fb77a 100644 --- a/src/main/java/domain/BonusNumber.java +++ b/src/main/java/domain/BonusNumber.java @@ -10,4 +10,8 @@ private BonusNumber(final int number) { public static BonusNumber create(final int number){ return new BonusNumber(number); } + + public int getBonusNumber(){ + return bonusNumber; + } } diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 9db4a1aa4f8..c1a7d3c419d 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -3,10 +3,7 @@ import util.exception.DuplicateException; import util.exception.SizeOverException; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import static util.message.ExceptionMessage.DUPLICATE_MESSAGE; import static util.message.ExceptionMessage.SIZE_OVER_MESSAGE; @@ -16,8 +13,8 @@ public class Lotto { public Lotto(List numbers) { validate(numbers); - sort(numbers); - this.numbers = numbers; + List numberList = sort(numbers); + this.numbers = numberList; } public List getNumbers(){ @@ -42,7 +39,9 @@ private void validateDuplicate(List numbers){ } } - private void sort(List numbers){ - Collections.sort(numbers); + private List sort(List numbers){ + List numberList = new ArrayList<>(numbers); + Collections.sort(numberList); + return numberList; } } diff --git a/src/main/java/domain/PurchaseAmount.java b/src/main/java/domain/PurchaseAmount.java index 8e0ca3fea0e..fbd9411a544 100644 --- a/src/main/java/domain/PurchaseAmount.java +++ b/src/main/java/domain/PurchaseAmount.java @@ -22,6 +22,10 @@ public int getQuantity(){ return quantity; } + public int getAmount(){ + return amount; + } + private int calculatequantity(){ return amount / Constants.ONE_THOUSAND.getValue(); } diff --git a/src/main/java/domain/Rank.java b/src/main/java/domain/Rank.java new file mode 100644 index 00000000000..7f1474e6adb --- /dev/null +++ b/src/main/java/domain/Rank.java @@ -0,0 +1,59 @@ +package domain; + +import util.constants.Constants; + +public enum Rank { + FIFTH(3, 5_000, "3개 일치 (5,000원) - "), + FOURTH(4, 50_000, "4개 일치 (50,000원) - "), + THIRD(5, 1_500_000, "5개 일치 (1,500,000원) - "), + SECOND(5, 30_000_000, "5개 일치, 보너스 볼 일치 (30,000,000원) - "), + FIRST(6, 2_000_000_000, "6개 일치 (2,000,000,000원) - "); + + private int countOfMatch; + private int prize; + private String message; + + Rank(int countOfMatch, int prize, String message){ + this.countOfMatch = countOfMatch; + this.prize = prize; + this.message = message; + } + + public int getCountOfMatch(){ + return countOfMatch; + } + + public int getPrize(){ + return prize; + } + + public String getMessage(){ + return message; + } + + public static Rank calculateRank(int countOfMatchNumbers, boolean isMatchBonus){ + for(Rank rank : values()){ + if(rank.matches(countOfMatchNumbers, isMatchBonus)){ + return rank; + } + } + return null; + } + + private boolean matches(int countOfMatchNumbers, boolean isMatchBonus){ + if(this == SECOND){ + return checkSecond(countOfMatchNumbers, isMatchBonus); + } + return checkRemaining(countOfMatchNumbers, isMatchBonus); + } + + private boolean checkSecond(int countOfMatchNumbers, boolean isMatchBonus){ + return this.countOfMatch == countOfMatchNumbers && isMatchBonus; + } + + private boolean checkRemaining(int countOfMatchNumbers, boolean isMatchBonus){ + return this.countOfMatch == countOfMatchNumbers && !isMatchBonus; + } + + +} diff --git a/src/main/java/domain/WinningNumbers.java b/src/main/java/domain/WinningNumbers.java index 68159029491..5f51bb4fa4a 100644 --- a/src/main/java/domain/WinningNumbers.java +++ b/src/main/java/domain/WinningNumbers.java @@ -20,6 +20,10 @@ public static WinningNumbers create(final List inputWinningNumbers){ return new WinningNumbers(inputWinningNumbers); } + public List getNumbers(){ + return numbers; + } + private void validateDuplicate(final List inputWinningNumbers){ Set numbers = new HashSet<>(inputWinningNumbers); if(numbers.size() != inputWinningNumbers.size()){ diff --git a/src/main/java/domain/WinningResult.java b/src/main/java/domain/WinningResult.java new file mode 100644 index 00000000000..120aabcb26e --- /dev/null +++ b/src/main/java/domain/WinningResult.java @@ -0,0 +1,72 @@ +package domain; + +import java.util.HashMap; +import java.util.List; + +public class WinningResult { + private final WinningNumbers winningNumbers; + private final BonusNumber bonusNumber; + private final HashMap winningResult; + private double totalPrize; + private double rateOfProfit; + + private WinningResult(WinningNumbers winningNumbers, BonusNumber bonusNumber){ + this.winningNumbers = winningNumbers; + this.bonusNumber = bonusNumber; + this.winningResult = new HashMap<>(); + initWinningResult(); + } + + public static WinningResult create(WinningNumbers winningNumbers, BonusNumber bonusNumber){ + return new WinningResult(winningNumbers, bonusNumber); + } + + public double getRateOfProfit(){ + return rateOfProfit; + } + + public HashMap getWinningResult(){ + return winningResult; + } + + private void initWinningResult(){ + for (Rank rank : Rank.values()) { + winningResult.put(rank, 0); + } + } + + public void calculateProfit(List lottos){ + for(Lotto lotto : lottos){ + calculate(getMatchNumbers(lotto, winningNumbers), isMatchBonusNumber(lotto, bonusNumber)); + } + } + + public void calculateRateOfProfit(int amount){ + rateOfProfit = (totalPrize / (double) amount) * 100; + } + + private void calculate(int countOfMatchNumber, boolean isMatchBonus){ + Rank rank = Rank.calculateRank(countOfMatchNumber, isMatchBonus); + if(rank != null){ + winningResult.put(rank, winningResult.get(rank) + 1); + addTotalPrize(rank.getPrize()); + } + } + + private void addTotalPrize(int prize){ + totalPrize += prize; + } + + private int getMatchNumbers(Lotto lotto, WinningNumbers winningNumbers){ + List lottoNumbers = lotto.getNumbers(); + List winningNums = winningNumbers.getNumbers(); + long matchedCount = lottoNumbers.stream() + .filter(winningNums::contains) + .count(); + return (int) matchedCount; + } + + private boolean isMatchBonusNumber(Lotto lotto, BonusNumber bonusNumber){ + return lotto.getNumbers().contains(bonusNumber.getBonusNumber()); + } +} diff --git a/src/main/java/dto/WinningResultDto.java b/src/main/java/dto/WinningResultDto.java new file mode 100644 index 00000000000..128286c8e0a --- /dev/null +++ b/src/main/java/dto/WinningResultDto.java @@ -0,0 +1,36 @@ +package dto; + +import domain.Rank; +import domain.WinningResult; + +import java.util.List; +import java.util.Map; + +public class WinningResultDto { + private final Map winningResult; + private final double rateOfProfit; + private static final String COUNT = "개\n"; + + private WinningResultDto(final WinningResult winningResult) { + this.winningResult = winningResult.getWinningResult(); + rateOfProfit = winningResult.getRateOfProfit(); + } + + public static WinningResultDto create(final WinningResult winningResult) { + return new WinningResultDto(winningResult); + } + + public String formatRateOfReturn(){ + double value = Math.round(rateOfProfit * 10.0) / 10.0; + return String.format("%.1f", value); + } + + public String generateResultString() { + StringBuilder resultString = new StringBuilder(); + for (Rank rank : Rank.values()) { + int count = winningResult.getOrDefault(rank, 0); + resultString.append(rank.getMessage()).append(count).append(COUNT); + } + return resultString.toString(); + } +} diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 297554ff205..d4c6dc7e2dc 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -2,18 +2,23 @@ import controller.LottosController; import controller.PurchaseController; +import controller.WinningController; +import domain.Lottos; import domain.PurchaseAmount; public class Application { private static final LottosController lottosController = new LottosController(); private static final PurchaseController purchaseController = new PurchaseController(); + + private static final WinningController winningController = new WinningController(); public static void main(String[] args) { initLottos(); } private static void initLottos(){ PurchaseAmount purchaseAmount = purchaseController.generatePurchaseAmount(); - lottosController.start(purchaseAmount); + Lottos lottos = lottosController.start(purchaseAmount); + winningController.generateWinngingAndBonus(lottos, purchaseAmount.getAmount()); } } diff --git a/src/main/java/service/LottosService.java b/src/main/java/service/LottosService.java index b3ae2eaf9ee..7dc962368bb 100644 --- a/src/main/java/service/LottosService.java +++ b/src/main/java/service/LottosService.java @@ -17,12 +17,4 @@ public List getPurchaseLottos(final Lottos purchaseLottos){ .map(lotto -> LottoDto.create(lotto.getNumbers())) .collect(Collectors.toList()); } - - public WinningNumbers createWinningNumbers(final List winningNumbers){ - return WinningNumbers.create(winningNumbers); - } - - public BonusNumber createBonusNumber(final int bonusNumber){ - return BonusNumber.create(bonusNumber); - } } diff --git a/src/main/java/service/WinningService.java b/src/main/java/service/WinningService.java new file mode 100644 index 00000000000..cfc24cc09aa --- /dev/null +++ b/src/main/java/service/WinningService.java @@ -0,0 +1,41 @@ +package service; + +import domain.BonusNumber; +import domain.Lotto; +import domain.WinningNumbers; +import domain.WinningResult; +import dto.WinningResultDto; + +import java.util.List; + +public class WinningService { + + private WinningResult winningResult; + + public WinningNumbers createWinningNumbers(final List winningNumbers){ + return WinningNumbers.create(winningNumbers); + } + + public BonusNumber createBonusNumber(final int bonusNumber){ + return BonusNumber.create(bonusNumber); + } + + public WinningResult createWinningResult(final WinningNumbers winningNumbers, final BonusNumber bonusNumber){ + winningResult = WinningResult.create(winningNumbers, bonusNumber); + return winningResult; + } + + public WinningResultDto calculateProfitAndRateOfProfit(final List lottos, final int purchaseAmount){ + calculateProfit(lottos); + calculateRateOfProfit(purchaseAmount); + return WinningResultDto.create(winningResult); + } + + private void calculateProfit(final List lottos){ + winningResult.calculateProfit(lottos); + } + + private void calculateRateOfProfit(final int purchaseAmount){ + winningResult.calculateRateOfProfit(purchaseAmount); + } +} diff --git a/src/main/java/util/constants/Constants.java b/src/main/java/util/constants/Constants.java index ee36f782554..fffc700ea56 100644 --- a/src/main/java/util/constants/Constants.java +++ b/src/main/java/util/constants/Constants.java @@ -4,7 +4,8 @@ public enum Constants implements EnumUtil { ONE_THOUSAND(1000), - ZERO(0); + ZERO(0), + WINNING_MIN_COUNT(3); private final int number; diff --git a/src/main/java/util/message/OutputMessage.java b/src/main/java/util/message/OutputMessage.java index a1b7ffbba82..c1c4592a02d 100644 --- a/src/main/java/util/message/OutputMessage.java +++ b/src/main/java/util/message/OutputMessage.java @@ -3,7 +3,10 @@ import util.EnumUtil; public enum OutputMessage implements EnumUtil{ - LOTTO_PURCHASE_COUNT("%d개를 구매했습니다."); + LOTTO_PURCHASE_COUNT("\n%d개를 구매했습니다."), + WINNING_STATICS("\n당첨통계\n" + "---"), + TOTAL_RATE_OF_PROFIT_START("총 수익률은 "), + TOTAL_RATE_OF_PROFIT_END("%입니다."); private final String message; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index e57830f6ce7..20d83ccdee6 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,9 +1,9 @@ package view; import camp.nextstep.edu.missionutils.Console; -import validator.BonusValidator; -import validator.PurchaseAmountValidator; -import validator.WinningNumbersValidator; +import view.validator.BonusValidator; +import view.validator.PurchaseAmountValidator; +import view.validator.WinningNumbersValidator; import java.util.List; diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index f007a2b8e24..e1e650cddfa 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import dto.LottoDto; +import dto.WinningResultDto; import util.message.OutputMessage; import java.util.List; @@ -16,4 +17,10 @@ public static void printPurchaseLottos(final List lottoDtos, final int System.out.println(lotto); } } + + public static void printWinningStatics(final WinningResultDto winningResultDto){ + System.out.println(OutputMessage.WINNING_STATICS.getValue()); + System.out.print(winningResultDto.generateResultString()); + System.out.println(OutputMessage.TOTAL_RATE_OF_PROFIT_START.getValue() + winningResultDto.formatRateOfReturn() + OutputMessage.TOTAL_RATE_OF_PROFIT_END.getValue()); + } } diff --git a/src/main/java/validator/BonusValidator.java b/src/main/java/view/validator/BonusValidator.java similarity index 93% rename from src/main/java/validator/BonusValidator.java rename to src/main/java/view/validator/BonusValidator.java index 24ab33595a0..db262df3cc5 100644 --- a/src/main/java/validator/BonusValidator.java +++ b/src/main/java/view/validator/BonusValidator.java @@ -1,6 +1,4 @@ -package validator; - -import java.util.List; +package view.validator; import static util.message.ExceptionMessage.RANGE_START_BETWEEND_END; diff --git a/src/main/java/validator/PurchaseAmountValidator.java b/src/main/java/view/validator/PurchaseAmountValidator.java similarity index 80% rename from src/main/java/validator/PurchaseAmountValidator.java rename to src/main/java/view/validator/PurchaseAmountValidator.java index 843b0746e6b..ce9248d89e5 100644 --- a/src/main/java/validator/PurchaseAmountValidator.java +++ b/src/main/java/view/validator/PurchaseAmountValidator.java @@ -1,6 +1,4 @@ -package validator; - -import util.constants.Constants; +package view.validator; public class PurchaseAmountValidator extends Validator{ public static int validate(String input) { diff --git a/src/main/java/validator/Validator.java b/src/main/java/view/validator/Validator.java similarity index 97% rename from src/main/java/validator/Validator.java rename to src/main/java/view/validator/Validator.java index ab706e32ac4..620f2585083 100644 --- a/src/main/java/validator/Validator.java +++ b/src/main/java/view/validator/Validator.java @@ -1,4 +1,4 @@ -package validator; +package view.validator; import static util.message.ExceptionMessage.*; diff --git a/src/main/java/validator/WinningNumbersValidator.java b/src/main/java/view/validator/WinningNumbersValidator.java similarity index 98% rename from src/main/java/validator/WinningNumbersValidator.java rename to src/main/java/view/validator/WinningNumbersValidator.java index 142707a73b8..a2564e8c7fb 100644 --- a/src/main/java/validator/WinningNumbersValidator.java +++ b/src/main/java/view/validator/WinningNumbersValidator.java @@ -1,4 +1,4 @@ -package validator; +package view.validator; import util.constants.LottosConstants; diff --git a/src/test/java/domain/RankTest.java b/src/test/java/domain/RankTest.java new file mode 100644 index 00000000000..99535dc2883 --- /dev/null +++ b/src/test/java/domain/RankTest.java @@ -0,0 +1,51 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class RankTest { + @DisplayName("당첨 번호 개수와 보너스 당첨 여부에 따른 등수를 검증한다. 6개가 일치하였다면, 1등.") + @Test + void checkFirst() { + assertThat(Rank.calculateRank(6, false)) + .isEqualTo(Rank.FIRST); + } + + @DisplayName("당첨 번호 개수와 보너스 당첨 여부에 따른 등수를 검증한다. 5개가 일치하면서 보너스번호까지 맞추었다면, 2등.") + @Test + void checkSecond(){ + assertThat(Rank.calculateRank(5, true)) + .isEqualTo(Rank.SECOND); + } + + @DisplayName("당첨 번호 개수와 보너스 당첨 여부에 따른 등수를 검증한다. 5개가 일치하면서 보너스번호는 맞추지 못했다면, 3등.") + @Test + void checkThird(){ + assertThat(Rank.calculateRank(5, false)) + .isEqualTo(Rank.THIRD); + } + + @DisplayName("당첨 번호 개수와 보너스 당첨 여부에 따른 등수를 검증한다. 4개가 일치하면, 4등.") + @Test + void checkFourth(){ + assertThat(Rank.calculateRank(4, false)) + .isEqualTo(Rank.FOURTH); + } + + @DisplayName("당첨 번호 개수와 보너스 당첨 여부에 따른 등수를 검증합니다. 3개가 일치하면, 5등입니다.") + @Test + void checkFifth(){ + assertThat(Rank.calculateRank(3, false)) + .isEqualTo(Rank.FIFTH); + } + + @DisplayName("1등부터 5등이 아닌 나머지 등수를 검증합니다.") + @Test + void checkNonTopFiveRanks(){ + Rank result = Rank.calculateRank(2, false); + assertNull(result); + } +} diff --git a/src/test/java/domain/WinningResultTest.java b/src/test/java/domain/WinningResultTest.java new file mode 100644 index 00000000000..1580dadf784 --- /dev/null +++ b/src/test/java/domain/WinningResultTest.java @@ -0,0 +1,45 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static provider.TestProvider.*; + +public class WinningResultTest { + + private WinningNumbers winningNumbers; + private BonusNumber bonusNumber; + private WinningResult winningResult; + + @BeforeEach + void init(){ + List winnings = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6)); + bonusNumber = createTestBonusNumber(7); + winningNumbers = createTestWinningNumbers(winnings); + winningResult = createWinningResult(winningNumbers, bonusNumber); + } + @DisplayName("주어진 로또목록과 당첨번호를 토대로 당첨내역이 올바르게 반환하는지 검증한다.") + @Test + void checkGetWinningResult() { + + List lottos = new ArrayList<>(); + lottos.add(new Lotto(List.of(1, 2, 3, 4, 5, 6))); + lottos.add(new Lotto(List.of(1, 2, 3, 4, 5, 7))); + + winningResult.calculateProfit(lottos); + + HashMap result = winningResult.getWinningResult(); + + assertEquals(1, result.get(Rank.FIRST)); + assertEquals(1, result.get(Rank.SECOND)); + assertEquals(0, result.get(Rank.THIRD)); + assertEquals(0, result.get(Rank.FOURTH)); + assertEquals(0, result.get(Rank.FIFTH)); + } +} diff --git a/src/test/java/provider/TestProvider.java b/src/test/java/provider/TestProvider.java index 0b85658e469..ab02a64903c 100644 --- a/src/test/java/provider/TestProvider.java +++ b/src/test/java/provider/TestProvider.java @@ -1,7 +1,9 @@ package provider; +import domain.BonusNumber; import domain.Lottos; import domain.WinningNumbers; +import domain.WinningResult; import java.util.List; @@ -13,4 +15,12 @@ public static Lottos createTestPurchaseLottos(final int numberOfPurchased) { public static WinningNumbers createTestWinningNumbers(final List numbers){ return WinningNumbers.create(numbers); } + + public static BonusNumber createTestBonusNumber(final int number){ + return BonusNumber.create(number); + } + + public static WinningResult createWinningResult(final WinningNumbers winningNumbers, final BonusNumber bonusNumber){ + return WinningResult.create(winningNumbers, bonusNumber); + } } diff --git a/src/test/java/validator/BonusValidatorTest.java b/src/test/java/validator/BonusValidatorTest.java index e6c25388457..a3495578b51 100644 --- a/src/test/java/validator/BonusValidatorTest.java +++ b/src/test/java/validator/BonusValidatorTest.java @@ -1,19 +1,15 @@ package validator; -import domain.BonusNumber; import domain.PurchaseAmount; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import util.constants.Constants; +import view.validator.BonusValidator; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static util.message.ExceptionMessage.*; -import static util.message.ExceptionMessage.RANGE_MESSAGE; public class BonusValidatorTest { diff --git a/src/test/java/validator/PurchaseAmountValidatorTest.java b/src/test/java/validator/PurchaseAmountValidatorTest.java index bf7d11ee65d..e5e24390f5a 100644 --- a/src/test/java/validator/PurchaseAmountValidatorTest.java +++ b/src/test/java/validator/PurchaseAmountValidatorTest.java @@ -1,13 +1,12 @@ package validator; -import domain.PurchaseAmount; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import util.constants.Constants; +import view.validator.PurchaseAmountValidator; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static util.constants.Constants.ZERO; import static util.message.ExceptionMessage.*; public class PurchaseAmountValidatorTest { diff --git a/src/test/java/validator/WinningNumbersValidators.java b/src/test/java/validator/WinningNumbersValidators.java index 37a70a374ed..0d6deb5dcb4 100644 --- a/src/test/java/validator/WinningNumbersValidators.java +++ b/src/test/java/validator/WinningNumbersValidators.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.ValueSource; +import view.validator.WinningNumbersValidator; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static util.message.ExceptionMessage.*;