From cc2f76850c341b061ccfd1356e2baaf3ce06a2e7 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 12 May 2024 12:50:31 +0900 Subject: [PATCH 01/15] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..61f144aafe --- /dev/null +++ b/docs/README.md @@ -0,0 +1,15 @@ +# 기능 요구사항 +### 로또 구매 +* 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발급한다. +* 로또 1장의 가격은 1000원이다. + +### 지난 주 당첨 번호 비교 +* 지난 주 당첨 번호와 보너스 볼 번호를 입력받는다. +* 발급된 로또와 비교하여 당첨 통계를 생성한다. + * 3개 일치 (5000원) + * 4개 일치 (50000원) + * 5개 일치 (1500000원) + * 5개 일치, 보너스 볼 일치(30000000원) + * 6개 일치 (2000000000원) +* 총 수익률을 계산해서 출력해준다. + * 수익률은 구매한 금액 / 총 당첨 금액 계산값을 소수점 두 자리 수까지 나타낸 수이다. From 11778342d49aeb2ce3e35fca131b591aa43fbfbe Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 12 May 2024 16:14:50 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=EA=B5=AC=EB=A7=A4=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EC=9E=85=EB=A0=A5,=20=EA=B5=AC=EB=A7=A4=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=EB=A7=8C=ED=81=BC=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 13 ++++++ src/main/java/controller/AmountRequest.java | 26 +++++++++++ .../java/lotto/LottoNumberCollection.java | 43 +++++++++++++++++++ src/main/java/lotto/PhraseLottoExecutor.java | 20 +++++++++ src/main/java/utils/Console.java | 27 ++++++++++++ src/main/java/validator/AmountValidator.java | 12 ++++++ src/main/java/validator/InputValidator.java | 13 ++++++ src/main/java/view/InputView.java | 21 +++++++++ src/main/java/view/OutputView.java | 33 ++++++++++++++ 9 files changed, 208 insertions(+) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/controller/AmountRequest.java create mode 100644 src/main/java/lotto/LottoNumberCollection.java create mode 100644 src/main/java/lotto/PhraseLottoExecutor.java create mode 100644 src/main/java/utils/Console.java create mode 100644 src/main/java/validator/AmountValidator.java create mode 100644 src/main/java/validator/InputValidator.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/OutputView.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 0000000000..26942f2efe --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,13 @@ +import controller.AmountRequest; +import lotto.PhraseLottoExecutor; +import view.InputView; + +public class Application { + + public static void main(String[] args) { + AmountRequest amountRequest = InputView.inputAmount(); + PhraseLottoExecutor phraseLottoExecutor = new PhraseLottoExecutor(amountRequest); + phraseLottoExecutor.phraseLotto(); + } + +} \ No newline at end of file diff --git a/src/main/java/controller/AmountRequest.java b/src/main/java/controller/AmountRequest.java new file mode 100644 index 0000000000..f5a019975f --- /dev/null +++ b/src/main/java/controller/AmountRequest.java @@ -0,0 +1,26 @@ +package controller; + +import validator.AmountValidator; + +public class AmountRequest { + private final int lottoAmount; + + private static final int LOTTO_PRICE = 1000; + + private AmountRequest(final int lottoAmount) { + this.lottoAmount = lottoAmount; + } + + public static AmountRequest of(final int lottoAmount) { + AmountValidator.validateAmountNegative(lottoAmount); + return new AmountRequest(lottoAmount); + } + + public int getLottoAmount() { + return this.lottoAmount; + } + + public int fetchPhraseLottoCount() { + return (int) this.lottoAmount / LOTTO_PRICE; + } +} diff --git a/src/main/java/lotto/LottoNumberCollection.java b/src/main/java/lotto/LottoNumberCollection.java new file mode 100644 index 0000000000..83eff2775a --- /dev/null +++ b/src/main/java/lotto/LottoNumberCollection.java @@ -0,0 +1,43 @@ +package lotto; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.IntStream; + +public class LottoNumberCollection { + + private final List> pickLottoNumbers; + + private static final List LOTTO_NUMBERS = new ArrayList<>(); + private final static int LOTTO_NUMBER_COUNT = 6; + + static { + for (int i = 1; i <= 45; i++) { + LOTTO_NUMBERS.add(i); + } + } + + private LottoNumberCollection(final List> pickLottoNumbers) { + this.pickLottoNumbers = pickLottoNumbers; + } + + public static LottoNumberCollection issuanceLotto(final int lottoCount) { + List> newPickedLottoNumbers = new ArrayList<>(); + for (int i = 0; i < lottoCount; i++) { + List lottoNumbers = new ArrayList<>(); + Collections.shuffle(LOTTO_NUMBERS); + + IntStream.range(0, LOTTO_NUMBER_COUNT).forEach(index -> { + lottoNumbers.add(LOTTO_NUMBERS.get(index)); + }); + newPickedLottoNumbers.add(lottoNumbers); + } + + return new LottoNumberCollection(newPickedLottoNumbers); + } + + public List> getPickLottoNumbers() { + return List.copyOf(this.pickLottoNumbers); + } +} diff --git a/src/main/java/lotto/PhraseLottoExecutor.java b/src/main/java/lotto/PhraseLottoExecutor.java new file mode 100644 index 0000000000..fef0df7d6a --- /dev/null +++ b/src/main/java/lotto/PhraseLottoExecutor.java @@ -0,0 +1,20 @@ +package lotto; + +import controller.AmountRequest; +import view.OutputView; + +public class PhraseLottoExecutor { + private final AmountRequest amountRequest; + + public PhraseLottoExecutor(final AmountRequest amountRequest) { + this.amountRequest = amountRequest; + } + + public void phraseLotto() { + int phraseLottoCount = this.amountRequest.fetchPhraseLottoCount(); + LottoNumberCollection lottoNumberCollection = LottoNumberCollection.issuanceLotto(phraseLottoCount); + + OutputView.outputPhraseLotto(phraseLottoCount, lottoNumberCollection); + } + +} diff --git a/src/main/java/utils/Console.java b/src/main/java/utils/Console.java new file mode 100644 index 0000000000..10db2f888f --- /dev/null +++ b/src/main/java/utils/Console.java @@ -0,0 +1,27 @@ +package utils; + +import java.util.Scanner; + +public class Console { + private static Scanner scanner; + + private Console() {} + + public static String readLine() { + return getInstance().nextLine(); + } + + public static void close() { + if (scanner != null) { + scanner.close(); + scanner = null; + } + } + + private static Scanner getInstance() { + if (scanner == null) { + scanner = new Scanner(System.in); + } + return scanner; + } +} \ No newline at end of file diff --git a/src/main/java/validator/AmountValidator.java b/src/main/java/validator/AmountValidator.java new file mode 100644 index 0000000000..b76579d0d6 --- /dev/null +++ b/src/main/java/validator/AmountValidator.java @@ -0,0 +1,12 @@ +package validator; + +public class AmountValidator { + + private static final String NEGATIVE_EXCEPTION_MESSAGE = "[ERROR] 금액은 음수로 입력할 수 없습니다."; + + public static void validateAmountNegative(final int lottoAmount) { + if (lottoAmount < 0) { + throw new IllegalArgumentException(NEGATIVE_EXCEPTION_MESSAGE); + } + } +} diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java new file mode 100644 index 0000000000..99fdb3c8cf --- /dev/null +++ b/src/main/java/validator/InputValidator.java @@ -0,0 +1,13 @@ +package validator; + +public class InputValidator { + private static final String NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; + + public static void validateAmountNotNumber(final String amountInput) { + try { + Integer.parseInt(amountInput); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(NOT_NUMBER_EXCEPTION_MESSAGE); + } + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000000..8993db6b17 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,21 @@ +package view; + +import controller.AmountRequest; +import utils.Console; +import validator.InputValidator; + +public class InputView { + private static final String INPUT_AMOUNT_MESSAGE = "구입금액을 입력해 주세요."; + + public static AmountRequest inputAmount() { + System.out.println(INPUT_AMOUNT_MESSAGE); + try { + String amountInput = Console.readLine(); + InputValidator.validateAmountNotNumber(amountInput); + return AmountRequest.of(Integer.parseInt(amountInput)); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return inputAmount(); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000000..b0bc9612c7 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,33 @@ +package view; + +import lotto.LottoNumberCollection; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class OutputView { + private static final String PHRASE_LOTTO_MESSAGE = "%d개를 구매했습니다."; + private static final String SQUARE_BRACKETS_OPEN = "["; + private static final String SQUARE_BRACKETS_CLOSE = "]"; + private static final String REST_DELIMITER = ", "; + + public static void outputPhraseLotto(final int phraseLottoCount, final LottoNumberCollection lottoNumberCollection) { + System.out.println(String.format(PHRASE_LOTTO_MESSAGE, phraseLottoCount)); + List> pickLottoNumbers = lottoNumberCollection.getPickLottoNumbers(); + + for (List lottoNumbers : pickLottoNumbers) { + StringBuilder lottoNumberStringBuilder = new StringBuilder(SQUARE_BRACKETS_OPEN); + Collections.sort(lottoNumbers); + String lottoNumberString = lottoNumbers.stream() + .map(number -> Integer.toString(number)) + .collect(Collectors.joining(REST_DELIMITER)); + + lottoNumberStringBuilder.append(lottoNumberString); + lottoNumberStringBuilder.append(SQUARE_BRACKETS_CLOSE); + + System.out.println(lottoNumberStringBuilder); + } + } + +} From 27be596124740a761fa8a651ca670e78e26b4f59 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 12 May 2024 17:04:46 +0900 Subject: [PATCH 03/15] =?UTF-8?q?modify:=20LottoNumberCollection=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1=20=ED=95=84=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 3 +- src/main/java/domain/PhraseLottoExecutor.java | 44 +++++++++++++++++++ .../java/lotto/LottoNumberCollection.java | 43 ------------------ src/main/java/lotto/PhraseLottoExecutor.java | 20 --------- src/main/java/view/OutputView.java | 28 ++++++------ src/main/java/vo/LottoNumberCollection.java | 21 +++++++++ 6 files changed, 82 insertions(+), 77 deletions(-) create mode 100644 src/main/java/domain/PhraseLottoExecutor.java delete mode 100644 src/main/java/lotto/LottoNumberCollection.java delete mode 100644 src/main/java/lotto/PhraseLottoExecutor.java create mode 100644 src/main/java/vo/LottoNumberCollection.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 26942f2efe..771f50b489 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,5 @@ import controller.AmountRequest; -import lotto.PhraseLottoExecutor; +import domain.PhraseLottoExecutor; import view.InputView; public class Application { @@ -8,6 +8,7 @@ public static void main(String[] args) { AmountRequest amountRequest = InputView.inputAmount(); PhraseLottoExecutor phraseLottoExecutor = new PhraseLottoExecutor(amountRequest); phraseLottoExecutor.phraseLotto(); + phraseLottoExecutor.pickLottoNumber(); } } \ No newline at end of file diff --git a/src/main/java/domain/PhraseLottoExecutor.java b/src/main/java/domain/PhraseLottoExecutor.java new file mode 100644 index 0000000000..5551500d4f --- /dev/null +++ b/src/main/java/domain/PhraseLottoExecutor.java @@ -0,0 +1,44 @@ +package domain; + +import controller.AmountRequest; +import view.OutputView; +import vo.LottoNumberCollection; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.IntStream; + +public class PhraseLottoExecutor { + private final AmountRequest amountRequest; + + private static final List LOTTO_NUMBERS = new ArrayList<>(); + private final static int LOTTO_NUMBER_COUNT = 6; + + static { + for (int i = 1; i <= 45; i++) { + LOTTO_NUMBERS.add(i); + } + } + + public PhraseLottoExecutor(final AmountRequest amountRequest) { + this.amountRequest = amountRequest; + } + + public void phraseLotto() { + OutputView.outputPhraseLotto(this.amountRequest.fetchPhraseLottoCount()); + } + + public void pickLottoNumber() { + for (int i = 0; i < this.amountRequest.fetchPhraseLottoCount(); i++) { + List pickLottoNumbers = new ArrayList<>(); + Collections.shuffle(LOTTO_NUMBERS); + IntStream.range(0, LOTTO_NUMBER_COUNT).forEach(index -> { + pickLottoNumbers.add(LOTTO_NUMBERS.get(index)); + }); + + OutputView.outputPickedLottoNumber(LottoNumberCollection.of(pickLottoNumbers)); + } + } + +} diff --git a/src/main/java/lotto/LottoNumberCollection.java b/src/main/java/lotto/LottoNumberCollection.java deleted file mode 100644 index 83eff2775a..0000000000 --- a/src/main/java/lotto/LottoNumberCollection.java +++ /dev/null @@ -1,43 +0,0 @@ -package lotto; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.IntStream; - -public class LottoNumberCollection { - - private final List> pickLottoNumbers; - - private static final List LOTTO_NUMBERS = new ArrayList<>(); - private final static int LOTTO_NUMBER_COUNT = 6; - - static { - for (int i = 1; i <= 45; i++) { - LOTTO_NUMBERS.add(i); - } - } - - private LottoNumberCollection(final List> pickLottoNumbers) { - this.pickLottoNumbers = pickLottoNumbers; - } - - public static LottoNumberCollection issuanceLotto(final int lottoCount) { - List> newPickedLottoNumbers = new ArrayList<>(); - for (int i = 0; i < lottoCount; i++) { - List lottoNumbers = new ArrayList<>(); - Collections.shuffle(LOTTO_NUMBERS); - - IntStream.range(0, LOTTO_NUMBER_COUNT).forEach(index -> { - lottoNumbers.add(LOTTO_NUMBERS.get(index)); - }); - newPickedLottoNumbers.add(lottoNumbers); - } - - return new LottoNumberCollection(newPickedLottoNumbers); - } - - public List> getPickLottoNumbers() { - return List.copyOf(this.pickLottoNumbers); - } -} diff --git a/src/main/java/lotto/PhraseLottoExecutor.java b/src/main/java/lotto/PhraseLottoExecutor.java deleted file mode 100644 index fef0df7d6a..0000000000 --- a/src/main/java/lotto/PhraseLottoExecutor.java +++ /dev/null @@ -1,20 +0,0 @@ -package lotto; - -import controller.AmountRequest; -import view.OutputView; - -public class PhraseLottoExecutor { - private final AmountRequest amountRequest; - - public PhraseLottoExecutor(final AmountRequest amountRequest) { - this.amountRequest = amountRequest; - } - - public void phraseLotto() { - int phraseLottoCount = this.amountRequest.fetchPhraseLottoCount(); - LottoNumberCollection lottoNumberCollection = LottoNumberCollection.issuanceLotto(phraseLottoCount); - - OutputView.outputPhraseLotto(phraseLottoCount, lottoNumberCollection); - } - -} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index b0bc9612c7..d0dd197092 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,7 +1,8 @@ package view; -import lotto.LottoNumberCollection; +import vo.LottoNumberCollection; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -12,22 +13,23 @@ public class OutputView { private static final String SQUARE_BRACKETS_CLOSE = "]"; private static final String REST_DELIMITER = ", "; - public static void outputPhraseLotto(final int phraseLottoCount, final LottoNumberCollection lottoNumberCollection) { + public static void outputPhraseLotto(final int phraseLottoCount) { System.out.println(String.format(PHRASE_LOTTO_MESSAGE, phraseLottoCount)); - List> pickLottoNumbers = lottoNumberCollection.getPickLottoNumbers(); + } + + public static void outputPickedLottoNumber(final LottoNumberCollection lottoNumberCollection) { + StringBuilder lottoNumberStringBuilder = new StringBuilder(SQUARE_BRACKETS_OPEN); + List pickLottoNumbers = new ArrayList<>(lottoNumberCollection.getPickLottoNumbers()); + Collections.sort(pickLottoNumbers); - for (List lottoNumbers : pickLottoNumbers) { - StringBuilder lottoNumberStringBuilder = new StringBuilder(SQUARE_BRACKETS_OPEN); - Collections.sort(lottoNumbers); - String lottoNumberString = lottoNumbers.stream() - .map(number -> Integer.toString(number)) - .collect(Collectors.joining(REST_DELIMITER)); + String lottoNumberString = pickLottoNumbers.stream() + .map(number -> Integer.toString(number)) + .collect(Collectors.joining(REST_DELIMITER)); - lottoNumberStringBuilder.append(lottoNumberString); - lottoNumberStringBuilder.append(SQUARE_BRACKETS_CLOSE); + lottoNumberStringBuilder.append(lottoNumberString); + lottoNumberStringBuilder.append(SQUARE_BRACKETS_CLOSE); - System.out.println(lottoNumberStringBuilder); - } + System.out.println(lottoNumberStringBuilder); } } diff --git a/src/main/java/vo/LottoNumberCollection.java b/src/main/java/vo/LottoNumberCollection.java new file mode 100644 index 0000000000..fc79892a72 --- /dev/null +++ b/src/main/java/vo/LottoNumberCollection.java @@ -0,0 +1,21 @@ +package vo; + +import java.util.ArrayList; +import java.util.List; + +public class LottoNumberCollection { + + private final List pickLottoNumbers = new ArrayList<>(); + + private LottoNumberCollection(final List pickLottoNumbers) { + this.pickLottoNumbers.addAll(pickLottoNumbers); + } + + public static LottoNumberCollection of(final List pickLottoNumbers) { + return new LottoNumberCollection(pickLottoNumbers); + } + + public List getPickLottoNumbers() { + return List.copyOf(this.pickLottoNumbers); + } +} From aa533b690e4d495fdf3776d43ad04ddd3d5bc44a Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 12 May 2024 17:46:42 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20=EC=A7=80=EB=82=9C=20=EC=A3=BC=20?= =?UTF-8?q?=EB=8B=B9=EC=B2=A8=20=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EB=B0=9B=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 7 +++- src/main/java/controller/AmountRequest.java | 3 +- .../java/controller/WinningNumberRequest.java | 26 ++++++++++++++ src/main/java/domain/PhraseLottoExecutor.java | 11 ++++-- src/main/java/validator/InputValidator.java | 36 +++++++++++++++++++ src/main/java/view/InputView.java | 21 +++++++++-- .../java/vo/LottoNumberCollectionList.java | 24 +++++++++++++ 7 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 src/main/java/controller/WinningNumberRequest.java create mode 100644 src/main/java/vo/LottoNumberCollectionList.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 771f50b489..67c282fc1a 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,6 +1,8 @@ import controller.AmountRequest; +import controller.WinningNumberRequest; import domain.PhraseLottoExecutor; import view.InputView; +import vo.LottoNumberCollectionList; public class Application { @@ -8,7 +10,10 @@ public static void main(String[] args) { AmountRequest amountRequest = InputView.inputAmount(); PhraseLottoExecutor phraseLottoExecutor = new PhraseLottoExecutor(amountRequest); phraseLottoExecutor.phraseLotto(); - phraseLottoExecutor.pickLottoNumber(); + LottoNumberCollectionList lottoNumberCollectionList = phraseLottoExecutor.pickLottoNumber(); + + WinningNumberRequest winningNumberRequest = InputView.inputWinningNumber(); + } } \ No newline at end of file diff --git a/src/main/java/controller/AmountRequest.java b/src/main/java/controller/AmountRequest.java index f5a019975f..57a075e121 100644 --- a/src/main/java/controller/AmountRequest.java +++ b/src/main/java/controller/AmountRequest.java @@ -11,7 +11,8 @@ private AmountRequest(final int lottoAmount) { this.lottoAmount = lottoAmount; } - public static AmountRequest of(final int lottoAmount) { + public static AmountRequest of(final String lottoAmountInput) { + final int lottoAmount = Integer.parseInt(lottoAmountInput); AmountValidator.validateAmountNegative(lottoAmount); return new AmountRequest(lottoAmount); } diff --git a/src/main/java/controller/WinningNumberRequest.java b/src/main/java/controller/WinningNumberRequest.java new file mode 100644 index 0000000000..1f0b74a7dd --- /dev/null +++ b/src/main/java/controller/WinningNumberRequest.java @@ -0,0 +1,26 @@ +package controller; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class WinningNumberRequest { + private final List winningNumbers; + + private static final String WINNING_NUMBER_SPLIT_REGEX = ","; + + private WinningNumberRequest(final List winningNumbers) { + this.winningNumbers = winningNumbers; + } + + public static WinningNumberRequest of(final String winningNumberInput) { + return new WinningNumberRequest(generateWinningNumber(winningNumberInput)); + } + + private static List generateWinningNumber(final String winningNumberInput) { + String[] splitInput = winningNumberInput.split(WINNING_NUMBER_SPLIT_REGEX); + return Arrays.stream(splitInput) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/domain/PhraseLottoExecutor.java b/src/main/java/domain/PhraseLottoExecutor.java index 5551500d4f..6c0c4ecde1 100644 --- a/src/main/java/domain/PhraseLottoExecutor.java +++ b/src/main/java/domain/PhraseLottoExecutor.java @@ -3,6 +3,7 @@ import controller.AmountRequest; import view.OutputView; import vo.LottoNumberCollection; +import vo.LottoNumberCollectionList; import java.util.ArrayList; import java.util.Collections; @@ -29,7 +30,9 @@ public void phraseLotto() { OutputView.outputPhraseLotto(this.amountRequest.fetchPhraseLottoCount()); } - public void pickLottoNumber() { + public LottoNumberCollectionList pickLottoNumber() { + List lottoNumberCollectionList = new ArrayList<>(); + for (int i = 0; i < this.amountRequest.fetchPhraseLottoCount(); i++) { List pickLottoNumbers = new ArrayList<>(); Collections.shuffle(LOTTO_NUMBERS); @@ -37,8 +40,12 @@ public void pickLottoNumber() { pickLottoNumbers.add(LOTTO_NUMBERS.get(index)); }); - OutputView.outputPickedLottoNumber(LottoNumberCollection.of(pickLottoNumbers)); + final LottoNumberCollection lottoNumberCollection = LottoNumberCollection.of(pickLottoNumbers); + OutputView.outputPickedLottoNumber(lottoNumberCollection); + lottoNumberCollectionList.add(lottoNumberCollection); } + + return LottoNumberCollectionList.of(lottoNumberCollectionList); } } diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java index 99fdb3c8cf..bcc0afbaf6 100644 --- a/src/main/java/validator/InputValidator.java +++ b/src/main/java/validator/InputValidator.java @@ -2,6 +2,10 @@ public class InputValidator { private static final String NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; + private static final String WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 당첨 번호는 6개여야 합니다."; + private static final String WINNING_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 당첨 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; + private static final String WINNING_NUMBER_SPLIT_REGEX = ","; + private static final int WINNING_NUMBER_COUNT = 6; public static void validateAmountNotNumber(final String amountInput) { try { @@ -10,4 +14,36 @@ public static void validateAmountNotNumber(final String amountInput) { throw new IllegalArgumentException(NOT_NUMBER_EXCEPTION_MESSAGE); } } + + public static void validateWinningNumberInput(final String winningNumberInput) { + String trimmedInput = winningNumberInput.trim(); + String[] splitInput = trimmedInput.split(WINNING_NUMBER_SPLIT_REGEX); + + validateWinningNumberCount(splitInput); + + for (String input : splitInput) { + validateWinningNumber(input); + } + } + + private static void validateWinningNumberCount(String[] splitInput) { + if (splitInput.length != WINNING_NUMBER_COUNT) { + throw new IllegalArgumentException(WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE); + } + } + + private static void validateWinningNumber(final String input) { + try { + int winningNumber = Integer.parseInt(input); + validateWinningNumberRange(winningNumber); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(WINNING_NUMBER_NOT_NUMBER_MESSAGE); + } + } + + private static void validateWinningNumberRange(int winningNumber) { + if (winningNumber <= 0 || winningNumber > 45) { + throw new IllegalArgumentException(WINNING_NUMBER_NOT_NUMBER_MESSAGE); + } + } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 8993db6b17..b5ad1315bd 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,21 +1,36 @@ package view; import controller.AmountRequest; +import controller.WinningNumberRequest; import utils.Console; import validator.InputValidator; public class InputView { private static final String INPUT_AMOUNT_MESSAGE = "구입금액을 입력해 주세요."; + private static final String INPUT_WINNING_NUMBER_MESSAGE = "지난 주 당첨 번호를 입력해 주세요."; + private static final String INPUT_BONUS_NUMBER_MESSAGE = "보너스 볼을 입력해 주세요."; public static AmountRequest inputAmount() { System.out.println(INPUT_AMOUNT_MESSAGE); try { - String amountInput = Console.readLine(); - InputValidator.validateAmountNotNumber(amountInput); - return AmountRequest.of(Integer.parseInt(amountInput)); + final String lottoAmountInput = Console.readLine(); + InputValidator.validateAmountNotNumber(lottoAmountInput); + return AmountRequest.of(lottoAmountInput); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); return inputAmount(); } } + + public static WinningNumberRequest inputWinningNumber() { + System.out.println(INPUT_WINNING_NUMBER_MESSAGE); + try { + final String winningNumberInput = Console.readLine(); + InputValidator.validateWinningNumberInput(winningNumberInput); + return WinningNumberRequest.of(winningNumberInput); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return inputWinningNumber(); + } + } } diff --git a/src/main/java/vo/LottoNumberCollectionList.java b/src/main/java/vo/LottoNumberCollectionList.java new file mode 100644 index 0000000000..4146496d5a --- /dev/null +++ b/src/main/java/vo/LottoNumberCollectionList.java @@ -0,0 +1,24 @@ +package vo; + +import java.util.ArrayList; +import java.util.List; + +public class LottoNumberCollectionList { + private final List lottoNumberCollectionList = new ArrayList<>(); + + private LottoNumberCollectionList(final List lottoNumberCollectionList) { + this.lottoNumberCollectionList.addAll(lottoNumberCollectionList); + } + + public static LottoNumberCollectionList of(final List lottoNumberCollectionList) { + return new LottoNumberCollectionList(lottoNumberCollectionList); + } + + public void addLottoNumberCollection(final LottoNumberCollection lottoNumberCollection) { + this.lottoNumberCollectionList.add(lottoNumberCollection); + } + + public List getLottoNumberCollectionList() { + return List.copyOf(this.lottoNumberCollectionList); + } +} From 64baade181b156ddc8b6a19a7491ee1599060b48 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 17:14:05 +0900 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20=EC=A7=80=EB=82=9C=EC=A3=BC=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=A7=9E=EC=B6=98=20=EA=B0=9C=EC=88=98?= =?UTF-8?q?=EA=B0=80=20=EB=AA=87=20=EA=B0=9C=EC=9D=B8=EC=A7=80=20=ED=86=B5?= =?UTF-8?q?=EA=B3=84=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 7 ++- .../java/controller/BonusNumberRequest.java | 21 +++++++++ .../java/controller/WinningNumberRequest.java | 6 ++- .../java/domain/WinningConfirmExecutor.java | 47 +++++++++++++++++++ .../FiveBonusMatchWinningStrategy.java | 10 ++++ .../strategy/FiveMatchWinningStrategy.java | 10 ++++ .../strategy/FourMatchWinningStrategy.java | 10 ++++ .../strategy/SixMatchWinningStrategy.java | 10 ++++ .../strategy/ThreeMatchWinningStrategy.java | 10 ++++ .../java/strategy/WinningPriceStrategy.java | 7 +++ .../strategy/WinningPriceStrategyFactory.java | 22 +++++++++ src/main/java/validator/InputValidator.java | 30 ++++++++++-- src/main/java/view/InputView.java | 13 +++++ src/main/java/view/OutputView.java | 11 +++++ src/main/java/vo/LottoNumberCollection.java | 11 +++++ src/main/java/vo/WinningTypeCollection.java | 44 +++++++++++++++++ src/main/java/vo/enums/WinningType.java | 25 ++++++++++ src/main/java/vo/param/WinningMatchParam.java | 35 ++++++++++++++ 18 files changed, 322 insertions(+), 7 deletions(-) create mode 100644 src/main/java/controller/BonusNumberRequest.java create mode 100644 src/main/java/domain/WinningConfirmExecutor.java create mode 100644 src/main/java/strategy/FiveBonusMatchWinningStrategy.java create mode 100644 src/main/java/strategy/FiveMatchWinningStrategy.java create mode 100644 src/main/java/strategy/FourMatchWinningStrategy.java create mode 100644 src/main/java/strategy/SixMatchWinningStrategy.java create mode 100644 src/main/java/strategy/ThreeMatchWinningStrategy.java create mode 100644 src/main/java/strategy/WinningPriceStrategy.java create mode 100644 src/main/java/strategy/WinningPriceStrategyFactory.java create mode 100644 src/main/java/vo/WinningTypeCollection.java create mode 100644 src/main/java/vo/enums/WinningType.java create mode 100644 src/main/java/vo/param/WinningMatchParam.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 67c282fc1a..3c242c83b9 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,8 +1,11 @@ import controller.AmountRequest; +import controller.BonusNumberRequest; import controller.WinningNumberRequest; import domain.PhraseLottoExecutor; +import domain.WinningConfirmExecutor; import view.InputView; import vo.LottoNumberCollectionList; +import vo.WinningTypeCollection; public class Application { @@ -13,7 +16,9 @@ public static void main(String[] args) { LottoNumberCollectionList lottoNumberCollectionList = phraseLottoExecutor.pickLottoNumber(); WinningNumberRequest winningNumberRequest = InputView.inputWinningNumber(); - + BonusNumberRequest bonusNumberRequest = InputView.inputBonusNumber(); + WinningConfirmExecutor winningConfirmExecutor = new WinningConfirmExecutor(lottoNumberCollectionList, winningNumberRequest, bonusNumberRequest); + WinningTypeCollection winningTypeCollection = winningConfirmExecutor.confirmWinningType(); } } \ No newline at end of file diff --git a/src/main/java/controller/BonusNumberRequest.java b/src/main/java/controller/BonusNumberRequest.java new file mode 100644 index 0000000000..85e025de3f --- /dev/null +++ b/src/main/java/controller/BonusNumberRequest.java @@ -0,0 +1,21 @@ +package controller; + +public class BonusNumberRequest { + private final int bonusNumber; + + private BonusNumberRequest(final int bonusNumber) { + this.bonusNumber = bonusNumber; + } + + public static BonusNumberRequest of(final String bonusNumberInput) { + return new BonusNumberRequest(generateBonusNumber(bonusNumberInput)); + } + + private static int generateBonusNumber(final String bonusNumberInput) { + return Integer.parseInt(bonusNumberInput); + } + + public int getBonusNumber() { + return this.bonusNumber; + } +} diff --git a/src/main/java/controller/WinningNumberRequest.java b/src/main/java/controller/WinningNumberRequest.java index 1f0b74a7dd..272cde923e 100644 --- a/src/main/java/controller/WinningNumberRequest.java +++ b/src/main/java/controller/WinningNumberRequest.java @@ -18,9 +18,13 @@ public static WinningNumberRequest of(final String winningNumberInput) { } private static List generateWinningNumber(final String winningNumberInput) { - String[] splitInput = winningNumberInput.split(WINNING_NUMBER_SPLIT_REGEX); + String[] splitInput = winningNumberInput.trim().split(WINNING_NUMBER_SPLIT_REGEX); return Arrays.stream(splitInput) .map(Integer::parseInt) .collect(Collectors.toList()); } + + public List getWinningNumbers() { + return List.copyOf(this.winningNumbers); + } } diff --git a/src/main/java/domain/WinningConfirmExecutor.java b/src/main/java/domain/WinningConfirmExecutor.java new file mode 100644 index 0000000000..4976820b65 --- /dev/null +++ b/src/main/java/domain/WinningConfirmExecutor.java @@ -0,0 +1,47 @@ +package domain; + +import controller.BonusNumberRequest; +import controller.WinningNumberRequest; +import strategy.WinningPriceStrategy; +import strategy.WinningPriceStrategyFactory; +import view.OutputView; +import vo.LottoNumberCollection; +import vo.LottoNumberCollectionList; +import vo.WinningTypeCollection; +import vo.param.WinningMatchParam; + +import java.util.List; +import java.util.Optional; + +public class WinningConfirmExecutor { + private final LottoNumberCollectionList lottoNumberCollectionList; + private final WinningNumberRequest winningNumberRequest; + private final BonusNumberRequest bonusNumberRequest; + + public WinningConfirmExecutor(final LottoNumberCollectionList lottoNumberCollectionList, + final WinningNumberRequest winningNumberRequest, + final BonusNumberRequest bonusNumberRequest) { + this.lottoNumberCollectionList = lottoNumberCollectionList; + this.winningNumberRequest = winningNumberRequest; + this.bonusNumberRequest = bonusNumberRequest; + } + + public WinningTypeCollection confirmWinningType() { + final WinningTypeCollection winningTypeCollection = new WinningTypeCollection(); + final List pickedLottoNumberCollectionList = this.lottoNumberCollectionList.getLottoNumberCollectionList(); + + for (LottoNumberCollection pickedLottoNumberCollection : pickedLottoNumberCollectionList) { + int winningMatchCount = pickedLottoNumberCollection.countWinningMatch(this.winningNumberRequest.getWinningNumbers()); + boolean isMatchBonus = pickedLottoNumberCollection.isMatchBonus(this.bonusNumberRequest.getBonusNumber()); + + Optional optionalStrategy = Optional.ofNullable( + WinningPriceStrategyFactory.getInstance().create(WinningMatchParam.from(winningMatchCount, isMatchBonus)) + ); + optionalStrategy.ifPresent(winningPriceStrategy -> winningTypeCollection.addWinningType(winningPriceStrategy.fetchWinningType())); + } + + OutputView.outputLottoWinningPrice(winningTypeCollection); + return winningTypeCollection; + } + +} diff --git a/src/main/java/strategy/FiveBonusMatchWinningStrategy.java b/src/main/java/strategy/FiveBonusMatchWinningStrategy.java new file mode 100644 index 0000000000..2242a2604a --- /dev/null +++ b/src/main/java/strategy/FiveBonusMatchWinningStrategy.java @@ -0,0 +1,10 @@ +package strategy; + +import vo.enums.WinningType; + +public class FiveBonusMatchWinningStrategy implements WinningPriceStrategy { + @Override + public WinningType fetchWinningType() { + return WinningType.FIVE_BONUS_MATCH; + } +} diff --git a/src/main/java/strategy/FiveMatchWinningStrategy.java b/src/main/java/strategy/FiveMatchWinningStrategy.java new file mode 100644 index 0000000000..c9f54b7ebf --- /dev/null +++ b/src/main/java/strategy/FiveMatchWinningStrategy.java @@ -0,0 +1,10 @@ +package strategy; + +import vo.enums.WinningType; + +public class FiveMatchWinningStrategy implements WinningPriceStrategy { + @Override + public WinningType fetchWinningType() { + return WinningType.FIVE_MATCH; + } +} diff --git a/src/main/java/strategy/FourMatchWinningStrategy.java b/src/main/java/strategy/FourMatchWinningStrategy.java new file mode 100644 index 0000000000..3505a0274a --- /dev/null +++ b/src/main/java/strategy/FourMatchWinningStrategy.java @@ -0,0 +1,10 @@ +package strategy; + +import vo.enums.WinningType; + +public class FourMatchWinningStrategy implements WinningPriceStrategy { + @Override + public WinningType fetchWinningType() { + return WinningType.FOUR_MATCH; + } +} diff --git a/src/main/java/strategy/SixMatchWinningStrategy.java b/src/main/java/strategy/SixMatchWinningStrategy.java new file mode 100644 index 0000000000..d4f9634b75 --- /dev/null +++ b/src/main/java/strategy/SixMatchWinningStrategy.java @@ -0,0 +1,10 @@ +package strategy; + +import vo.enums.WinningType; + +public class SixMatchWinningStrategy implements WinningPriceStrategy { + @Override + public WinningType fetchWinningType() { + return WinningType.SIX_MATCH; + } +} diff --git a/src/main/java/strategy/ThreeMatchWinningStrategy.java b/src/main/java/strategy/ThreeMatchWinningStrategy.java new file mode 100644 index 0000000000..962996d0c8 --- /dev/null +++ b/src/main/java/strategy/ThreeMatchWinningStrategy.java @@ -0,0 +1,10 @@ +package strategy; + +import vo.enums.WinningType; + +public class ThreeMatchWinningStrategy implements WinningPriceStrategy { + @Override + public WinningType fetchWinningType() { + return WinningType.THREE_MATCH; + } +} diff --git a/src/main/java/strategy/WinningPriceStrategy.java b/src/main/java/strategy/WinningPriceStrategy.java new file mode 100644 index 0000000000..fbf475af7c --- /dev/null +++ b/src/main/java/strategy/WinningPriceStrategy.java @@ -0,0 +1,7 @@ +package strategy; + +import vo.enums.WinningType; + +public interface WinningPriceStrategy { + WinningType fetchWinningType(); +} diff --git a/src/main/java/strategy/WinningPriceStrategyFactory.java b/src/main/java/strategy/WinningPriceStrategyFactory.java new file mode 100644 index 0000000000..89b53005de --- /dev/null +++ b/src/main/java/strategy/WinningPriceStrategyFactory.java @@ -0,0 +1,22 @@ +package strategy; + +import vo.param.WinningMatchParam; + +public class WinningPriceStrategyFactory { + private static final WinningPriceStrategyFactory INSTANCE = new WinningPriceStrategyFactory(); + + private WinningPriceStrategyFactory() {} + + public static WinningPriceStrategyFactory getInstance() { + return INSTANCE; + } + + public WinningPriceStrategy create(final WinningMatchParam winningMatchParam) { + if (winningMatchParam.isThreeMatch()) return new ThreeMatchWinningStrategy(); + if (winningMatchParam.isFourMatch()) return new FourMatchWinningStrategy(); + if (winningMatchParam.isFiveMatch()) return new FiveMatchWinningStrategy(); + if (winningMatchParam.isFiveBonusMatch()) return new FiveBonusMatchWinningStrategy(); + if (winningMatchParam.isSixMatch()) return new SixMatchWinningStrategy(); + return null; + } +} diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java index bcc0afbaf6..4e0ecfd846 100644 --- a/src/main/java/validator/InputValidator.java +++ b/src/main/java/validator/InputValidator.java @@ -4,6 +4,7 @@ public class InputValidator { private static final String NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; private static final String WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 당첨 번호는 6개여야 합니다."; private static final String WINNING_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 당첨 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; + private static final String BONUS_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 보너스 볼 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; private static final String WINNING_NUMBER_SPLIT_REGEX = ","; private static final int WINNING_NUMBER_COUNT = 6; @@ -16,8 +17,7 @@ public static void validateAmountNotNumber(final String amountInput) { } public static void validateWinningNumberInput(final String winningNumberInput) { - String trimmedInput = winningNumberInput.trim(); - String[] splitInput = trimmedInput.split(WINNING_NUMBER_SPLIT_REGEX); + String[] splitInput = winningNumberInput.trim().split(WINNING_NUMBER_SPLIT_REGEX); validateWinningNumberCount(splitInput); @@ -26,7 +26,7 @@ public static void validateWinningNumberInput(final String winningNumberInput) { } } - private static void validateWinningNumberCount(String[] splitInput) { + private static void validateWinningNumberCount(final String[] splitInput) { if (splitInput.length != WINNING_NUMBER_COUNT) { throw new IllegalArgumentException(WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE); } @@ -41,9 +41,29 @@ private static void validateWinningNumber(final String input) { } } - private static void validateWinningNumberRange(int winningNumber) { - if (winningNumber <= 0 || winningNumber > 45) { + private static void validateWinningNumberRange(final int winningNumber) { + if (!isLottoNumberRange(winningNumber)) { throw new IllegalArgumentException(WINNING_NUMBER_NOT_NUMBER_MESSAGE); } } + + private static boolean isLottoNumberRange(final int number) { + return number > 0 && number < 46; + } + + public static void validateBonusNumberInput(final String bonusNumberInput) { + try { + int bonusNumber = Integer.parseInt(bonusNumberInput); + + validateBonusNumberRange(bonusNumber); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(BONUS_NUMBER_NOT_NUMBER_MESSAGE); + } + } + + private static void validateBonusNumberRange(int bonusNumber) { + if (!isLottoNumberRange(bonusNumber)) { + throw new IllegalArgumentException(BONUS_NUMBER_NOT_NUMBER_MESSAGE); + } + } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index b5ad1315bd..92cb32018a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,6 +1,7 @@ package view; import controller.AmountRequest; +import controller.BonusNumberRequest; import controller.WinningNumberRequest; import utils.Console; import validator.InputValidator; @@ -33,4 +34,16 @@ public static WinningNumberRequest inputWinningNumber() { return inputWinningNumber(); } } + + public static BonusNumberRequest inputBonusNumber() { + System.out.println(INPUT_BONUS_NUMBER_MESSAGE); + try { + final String bonusNumberInput = Console.readLine(); + InputValidator.validateBonusNumberInput(bonusNumberInput); + return BonusNumberRequest.of(bonusNumberInput); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return inputBonusNumber(); + } + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index d0dd197092..979aba9954 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,10 +1,13 @@ package view; import vo.LottoNumberCollection; +import vo.WinningTypeCollection; +import vo.enums.WinningType; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class OutputView { @@ -32,4 +35,12 @@ public static void outputPickedLottoNumber(final LottoNumberCollection lottoNumb System.out.println(lottoNumberStringBuilder); } + public static void outputLottoWinningPrice(final WinningTypeCollection winningTypeCollection) { + Map winningTypeVsMatchCountMap = winningTypeCollection.fetchMapOfWinningTypeVsMatchCount(); + + for (WinningType winningType : winningTypeCollection.getAllWinningType()) { + System.out.println(String.format("%s - %d개", winningType.getTitle(), winningTypeVsMatchCountMap.get(winningType))); + } + } + } diff --git a/src/main/java/vo/LottoNumberCollection.java b/src/main/java/vo/LottoNumberCollection.java index fc79892a72..154ce49c72 100644 --- a/src/main/java/vo/LottoNumberCollection.java +++ b/src/main/java/vo/LottoNumberCollection.java @@ -18,4 +18,15 @@ public static LottoNumberCollection of(final List pickLottoNumbers) { public List getPickLottoNumbers() { return List.copyOf(this.pickLottoNumbers); } + + public int countWinningMatch(final List winningNumbers) { + return (int) this.pickLottoNumbers.stream() + .filter(winningNumbers::contains) + .count(); + } + + public boolean isMatchBonus(final int bonusNumber) { + return this.pickLottoNumbers.stream() + .anyMatch(pickNumber -> pickNumber == bonusNumber); + } } diff --git a/src/main/java/vo/WinningTypeCollection.java b/src/main/java/vo/WinningTypeCollection.java new file mode 100644 index 0000000000..7f064a7f05 --- /dev/null +++ b/src/main/java/vo/WinningTypeCollection.java @@ -0,0 +1,44 @@ +package vo; + +import vo.enums.WinningType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class WinningTypeCollection { + private final List winningTypes = new ArrayList<>(); + + private static final List allWinningType = List.of( + WinningType.THREE_MATCH, + WinningType.FOUR_MATCH, + WinningType.FIVE_MATCH, + WinningType.FIVE_BONUS_MATCH, + WinningType.SIX_MATCH + ); + + public WinningTypeCollection() {} + + public void addWinningType(final WinningType winningType) { + this.winningTypes.add(winningType); + } + + public Map fetchMapOfWinningTypeVsMatchCount() { + return allWinningType.stream() + .collect(Collectors.toMap( + winningType -> winningType, + winningType -> winningTypes.stream().filter(winningType::equals).count() + )); + } + + public int calculateTotalWinningPrice() { + return winningTypes.stream() + .mapToInt(WinningType::getWinningPrice) + .sum(); + } + + public List getAllWinningType() { + return List.copyOf(allWinningType); + } +} diff --git a/src/main/java/vo/enums/WinningType.java b/src/main/java/vo/enums/WinningType.java new file mode 100644 index 0000000000..ef42d0c2b1 --- /dev/null +++ b/src/main/java/vo/enums/WinningType.java @@ -0,0 +1,25 @@ +package vo.enums; + +public enum WinningType { + THREE_MATCH("3개 일치 (5000원)", 5000), + FOUR_MATCH("4개 일치 (50000원)", 50000), + FIVE_MATCH("5개 일치 (1500000원)", 1500000), + FIVE_BONUS_MATCH("5개 일치, 보너스 볼 일치(30000000원)", 30000000), + SIX_MATCH("6개 일치 (2000000000원)", 2000000000); + + private String title; + private int winningPrice; + + WinningType(final String title, final int winningPrice) { + this.title = title; + this.winningPrice =winningPrice; + } + + public String getTitle() { + return this.title; + } + + public int getWinningPrice() { + return this.winningPrice; + } +} diff --git a/src/main/java/vo/param/WinningMatchParam.java b/src/main/java/vo/param/WinningMatchParam.java new file mode 100644 index 0000000000..18dd4b4b0d --- /dev/null +++ b/src/main/java/vo/param/WinningMatchParam.java @@ -0,0 +1,35 @@ +package vo.param; + +public class WinningMatchParam { + private final int winningMatchCount; + private final boolean isMatchBonus; + + private WinningMatchParam(final int winningMatchCount, final boolean isMatchBonus) { + this.winningMatchCount = winningMatchCount; + this.isMatchBonus = isMatchBonus; + } + + public static WinningMatchParam from(final int winningMatchCount, final boolean isMatchBonus) { + return new WinningMatchParam(winningMatchCount, isMatchBonus); + } + + public boolean isThreeMatch() { + return this.winningMatchCount == 3; + } + + public boolean isFourMatch() { + return this.winningMatchCount == 4; + } + + public boolean isFiveMatch() { + return this.winningMatchCount == 5 && !isMatchBonus; + } + + public boolean isFiveBonusMatch() { + return this.winningMatchCount == 5 && isMatchBonus; + } + + public boolean isSixMatch() { + return this.winningMatchCount == 6; + } +} From 0b778beb9a23da1cd08fdbe2dc84bc274e781268 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 18:27:06 +0900 Subject: [PATCH 06/15] =?UTF-8?q?feat:=20=EC=88=98=EC=9D=B5=EB=A5=A0=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EB=B0=8F=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 4 ++++ .../java/domain/RateCalculateExecutor.java | 22 +++++++++++++++++++ src/main/java/view/OutputView.java | 5 +++++ 3 files changed, 31 insertions(+) create mode 100644 src/main/java/domain/RateCalculateExecutor.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 3c242c83b9..a409f2c4ba 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -2,6 +2,7 @@ import controller.BonusNumberRequest; import controller.WinningNumberRequest; import domain.PhraseLottoExecutor; +import domain.RateCalculateExecutor; import domain.WinningConfirmExecutor; import view.InputView; import vo.LottoNumberCollectionList; @@ -19,6 +20,9 @@ public static void main(String[] args) { BonusNumberRequest bonusNumberRequest = InputView.inputBonusNumber(); WinningConfirmExecutor winningConfirmExecutor = new WinningConfirmExecutor(lottoNumberCollectionList, winningNumberRequest, bonusNumberRequest); WinningTypeCollection winningTypeCollection = winningConfirmExecutor.confirmWinningType(); + + RateCalculateExecutor rateCalculateExecutor = new RateCalculateExecutor(amountRequest, winningTypeCollection); + rateCalculateExecutor.calculateRate(); } } \ No newline at end of file diff --git a/src/main/java/domain/RateCalculateExecutor.java b/src/main/java/domain/RateCalculateExecutor.java new file mode 100644 index 0000000000..4f68312ffd --- /dev/null +++ b/src/main/java/domain/RateCalculateExecutor.java @@ -0,0 +1,22 @@ +package domain; + +import controller.AmountRequest; +import view.OutputView; +import vo.WinningTypeCollection; + +public class RateCalculateExecutor { + private final AmountRequest amountRequest; + private final WinningTypeCollection winningTypeCollection; + + public RateCalculateExecutor(final AmountRequest amountRequest, final WinningTypeCollection winningTypeCollection) { + this.amountRequest = amountRequest; + this.winningTypeCollection = winningTypeCollection; + } + + public void calculateRate() { + // 수익률은 소수점 둘째 자리까지 출력 + final double rate = Math.round(winningTypeCollection.calculateTotalWinningPrice() / amountRequest.getLottoAmount()); + OutputView.outputRateOfReturn(rate); + + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 979aba9954..2141436c0e 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -12,6 +12,7 @@ public class OutputView { private static final String PHRASE_LOTTO_MESSAGE = "%d개를 구매했습니다."; + private static final String TOTAL_RATE_MESSAGE = "총 수익률은 %.2f입니다."; private static final String SQUARE_BRACKETS_OPEN = "["; private static final String SQUARE_BRACKETS_CLOSE = "]"; private static final String REST_DELIMITER = ", "; @@ -43,4 +44,8 @@ public static void outputLottoWinningPrice(final WinningTypeCollection winningTy } } + public static void outputRateOfReturn(final double rate) { + System.out.println(String.format(TOTAL_RATE_MESSAGE, rate)); + } + } From ef5951f474b105673b32f5876744131d3a2c70e3 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 18:32:08 +0900 Subject: [PATCH 07/15] =?UTF-8?q?modify:=20=EB=8B=B9=EC=B2=A8=20=ED=86=B5?= =?UTF-8?q?=EA=B3=84=20=EC=B6=9C=EB=A0=A5=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 2141436c0e..12f3edc6f5 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -12,10 +12,12 @@ public class OutputView { private static final String PHRASE_LOTTO_MESSAGE = "%d개를 구매했습니다."; + private static final String WINNING_STATISTICS_MESSAGE = "당첨 통계\n---------"; private static final String TOTAL_RATE_MESSAGE = "총 수익률은 %.2f입니다."; private static final String SQUARE_BRACKETS_OPEN = "["; private static final String SQUARE_BRACKETS_CLOSE = "]"; private static final String REST_DELIMITER = ", "; + private static final String WINNING_FORMAT = "%s - %d개"; public static void outputPhraseLotto(final int phraseLottoCount) { System.out.println(String.format(PHRASE_LOTTO_MESSAGE, phraseLottoCount)); @@ -38,9 +40,10 @@ public static void outputPickedLottoNumber(final LottoNumberCollection lottoNumb public static void outputLottoWinningPrice(final WinningTypeCollection winningTypeCollection) { Map winningTypeVsMatchCountMap = winningTypeCollection.fetchMapOfWinningTypeVsMatchCount(); + System.out.println(WINNING_STATISTICS_MESSAGE); for (WinningType winningType : winningTypeCollection.getAllWinningType()) { - System.out.println(String.format("%s - %d개", winningType.getTitle(), winningTypeVsMatchCountMap.get(winningType))); + System.out.println(String.format(WINNING_FORMAT, winningType.getTitle(), winningTypeVsMatchCountMap.get(winningType))); } } From 3183b402d39d122c0d167dc115c8014634c1a3ce Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 18:59:21 +0900 Subject: [PATCH 08/15] =?UTF-8?q?modify:=20=EB=A1=9C=EB=98=90=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=B0=9B?= =?UTF-8?q?=EC=9D=84=20=EC=8B=9C=20=EA=B3=B5=EB=B0=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 17 ++++++++++++----- .../java/controller/WinningNumberRequest.java | 4 +++- src/main/java/validator/InputValidator.java | 4 +++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index a409f2c4ba..1f24814d6f 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -12,17 +12,24 @@ public class Application { public static void main(String[] args) { AmountRequest amountRequest = InputView.inputAmount(); + + WinningTypeCollection winningTypeCollection = retrieveWinning(receivePhraseLotto(amountRequest)); + + RateCalculateExecutor rateCalculateExecutor = new RateCalculateExecutor(amountRequest, winningTypeCollection); + rateCalculateExecutor.calculateRate(); + } + + private static LottoNumberCollectionList receivePhraseLotto(final AmountRequest amountRequest) { PhraseLottoExecutor phraseLottoExecutor = new PhraseLottoExecutor(amountRequest); phraseLottoExecutor.phraseLotto(); - LottoNumberCollectionList lottoNumberCollectionList = phraseLottoExecutor.pickLottoNumber(); + return phraseLottoExecutor.pickLottoNumber(); + } + private static WinningTypeCollection retrieveWinning(final LottoNumberCollectionList lottoNumberCollectionList) { WinningNumberRequest winningNumberRequest = InputView.inputWinningNumber(); BonusNumberRequest bonusNumberRequest = InputView.inputBonusNumber(); WinningConfirmExecutor winningConfirmExecutor = new WinningConfirmExecutor(lottoNumberCollectionList, winningNumberRequest, bonusNumberRequest); - WinningTypeCollection winningTypeCollection = winningConfirmExecutor.confirmWinningType(); - - RateCalculateExecutor rateCalculateExecutor = new RateCalculateExecutor(amountRequest, winningTypeCollection); - rateCalculateExecutor.calculateRate(); + return winningConfirmExecutor.confirmWinningType(); } } \ No newline at end of file diff --git a/src/main/java/controller/WinningNumberRequest.java b/src/main/java/controller/WinningNumberRequest.java index 272cde923e..c098ec42cb 100644 --- a/src/main/java/controller/WinningNumberRequest.java +++ b/src/main/java/controller/WinningNumberRequest.java @@ -18,7 +18,9 @@ public static WinningNumberRequest of(final String winningNumberInput) { } private static List generateWinningNumber(final String winningNumberInput) { - String[] splitInput = winningNumberInput.trim().split(WINNING_NUMBER_SPLIT_REGEX); + String[] splitInput = winningNumberInput + .replaceAll(" ", "") + .split(WINNING_NUMBER_SPLIT_REGEX); return Arrays.stream(splitInput) .map(Integer::parseInt) .collect(Collectors.toList()); diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java index 4e0ecfd846..8bd4d3f91a 100644 --- a/src/main/java/validator/InputValidator.java +++ b/src/main/java/validator/InputValidator.java @@ -17,7 +17,9 @@ public static void validateAmountNotNumber(final String amountInput) { } public static void validateWinningNumberInput(final String winningNumberInput) { - String[] splitInput = winningNumberInput.trim().split(WINNING_NUMBER_SPLIT_REGEX); + String[] splitInput = winningNumberInput + .replaceAll(" ", "") + .split(WINNING_NUMBER_SPLIT_REGEX); validateWinningNumberCount(splitInput); From 2deb60b69119b32cb0f6e044a4d081412aad28c5 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 21:21:07 +0900 Subject: [PATCH 09/15] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 12 +++-- src/main/java/controller/AmountRequest.java | 2 +- .../java/controller/BonusNumberRequest.java | 2 +- .../java/controller/ManualNumberRequest.java | 41 ++++++++++++++ .../java/controller/WinningNumberRequest.java | 2 +- src/main/java/domain/PhraseLottoExecutor.java | 4 +- src/main/java/validator/InputValidator.java | 54 ++++++++++++++++--- src/main/java/view/InputView.java | 36 +++++++++++-- src/main/java/vo/LottoNumberCollection.java | 2 +- .../java/vo/LottoNumberCollectionList.java | 6 ++- 10 files changed, 140 insertions(+), 21 deletions(-) create mode 100644 src/main/java/controller/ManualNumberRequest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 1f24814d6f..58e094d57d 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,6 @@ import controller.AmountRequest; import controller.BonusNumberRequest; +import controller.ManualNumberRequest; import controller.WinningNumberRequest; import domain.PhraseLottoExecutor; import domain.RateCalculateExecutor; @@ -11,11 +12,12 @@ public class Application { public static void main(String[] args) { - AmountRequest amountRequest = InputView.inputAmount(); - - WinningTypeCollection winningTypeCollection = retrieveWinning(receivePhraseLotto(amountRequest)); - - RateCalculateExecutor rateCalculateExecutor = new RateCalculateExecutor(amountRequest, winningTypeCollection); + final AmountRequest amountRequest = InputView.inputAmount(); + final ManualNumberRequest manualNumberRequest = InputView.inputManual(); + final WinningTypeCollection winningTypeCollection = retrieveWinning( + receivePhraseLotto(amountRequest) + ); + final RateCalculateExecutor rateCalculateExecutor = new RateCalculateExecutor(amountRequest, winningTypeCollection); rateCalculateExecutor.calculateRate(); } diff --git a/src/main/java/controller/AmountRequest.java b/src/main/java/controller/AmountRequest.java index 57a075e121..883d47451a 100644 --- a/src/main/java/controller/AmountRequest.java +++ b/src/main/java/controller/AmountRequest.java @@ -11,7 +11,7 @@ private AmountRequest(final int lottoAmount) { this.lottoAmount = lottoAmount; } - public static AmountRequest of(final String lottoAmountInput) { + public static AmountRequest from(final String lottoAmountInput) { final int lottoAmount = Integer.parseInt(lottoAmountInput); AmountValidator.validateAmountNegative(lottoAmount); return new AmountRequest(lottoAmount); diff --git a/src/main/java/controller/BonusNumberRequest.java b/src/main/java/controller/BonusNumberRequest.java index 85e025de3f..7335bbaef4 100644 --- a/src/main/java/controller/BonusNumberRequest.java +++ b/src/main/java/controller/BonusNumberRequest.java @@ -7,7 +7,7 @@ private BonusNumberRequest(final int bonusNumber) { this.bonusNumber = bonusNumber; } - public static BonusNumberRequest of(final String bonusNumberInput) { + public static BonusNumberRequest from(final String bonusNumberInput) { return new BonusNumberRequest(generateBonusNumber(bonusNumberInput)); } diff --git a/src/main/java/controller/ManualNumberRequest.java b/src/main/java/controller/ManualNumberRequest.java new file mode 100644 index 0000000000..de0fe6b539 --- /dev/null +++ b/src/main/java/controller/ManualNumberRequest.java @@ -0,0 +1,41 @@ +package controller; + +import vo.LottoNumberCollection; +import vo.LottoNumberCollectionList; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ManualNumberRequest { + private final int manualCount; + private final LottoNumberCollectionList lottoNumberCollectionList; + + private static final String LOTTO_NUMBER_SPLIT_REGEX = ","; + + private ManualNumberRequest(final int manualCount, final LottoNumberCollectionList lottoNumberCollectionList) { + this.manualCount = manualCount; + this.lottoNumberCollectionList = lottoNumberCollectionList; + } + + public static ManualNumberRequest of(final int manualCount, final List manualNumberInputs) { + final List lottoNumberCollectionList = manualNumberInputs.stream() + .map(manualInput -> { + String[] splitInput = manualInput.replaceAll(" ", "").split(LOTTO_NUMBER_SPLIT_REGEX); + return LottoNumberCollection.from(Arrays.stream(splitInput) + .map(Integer::parseInt) + .collect(Collectors.toList())); + }) + .collect(Collectors.toList()); + + return new ManualNumberRequest(manualCount, LottoNumberCollectionList.from(lottoNumberCollectionList)); + } + + public int getManualCount() { + return manualCount; + } + + public LottoNumberCollectionList getLottoNumberCollectionList() { + return lottoNumberCollectionList; + } +} diff --git a/src/main/java/controller/WinningNumberRequest.java b/src/main/java/controller/WinningNumberRequest.java index c098ec42cb..9c78880809 100644 --- a/src/main/java/controller/WinningNumberRequest.java +++ b/src/main/java/controller/WinningNumberRequest.java @@ -13,7 +13,7 @@ private WinningNumberRequest(final List winningNumbers) { this.winningNumbers = winningNumbers; } - public static WinningNumberRequest of(final String winningNumberInput) { + public static WinningNumberRequest from(final String winningNumberInput) { return new WinningNumberRequest(generateWinningNumber(winningNumberInput)); } diff --git a/src/main/java/domain/PhraseLottoExecutor.java b/src/main/java/domain/PhraseLottoExecutor.java index 6c0c4ecde1..33855bb634 100644 --- a/src/main/java/domain/PhraseLottoExecutor.java +++ b/src/main/java/domain/PhraseLottoExecutor.java @@ -40,12 +40,12 @@ public LottoNumberCollectionList pickLottoNumber() { pickLottoNumbers.add(LOTTO_NUMBERS.get(index)); }); - final LottoNumberCollection lottoNumberCollection = LottoNumberCollection.of(pickLottoNumbers); + final LottoNumberCollection lottoNumberCollection = LottoNumberCollection.from(pickLottoNumbers); OutputView.outputPickedLottoNumber(lottoNumberCollection); lottoNumberCollectionList.add(lottoNumberCollection); } - return LottoNumberCollectionList.of(lottoNumberCollectionList); + return LottoNumberCollectionList.from(lottoNumberCollectionList); } } diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java index 8bd4d3f91a..a3a1460945 100644 --- a/src/main/java/validator/InputValidator.java +++ b/src/main/java/validator/InputValidator.java @@ -1,25 +1,67 @@ package validator; +import java.util.Arrays; +import java.util.List; + public class InputValidator { - private static final String NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; + private static final String AMOUNT_NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; + private static final String MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 로또 수의 입력은 0 이상의 정수여야 합니다."; + private static final String MANUAL_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 번호는 6개여야 합니다."; + private static final String MANUAL_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 수동으로 구매할 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; private static final String WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 당첨 번호는 6개여야 합니다."; private static final String WINNING_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 당첨 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; private static final String BONUS_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 보너스 볼 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; - private static final String WINNING_NUMBER_SPLIT_REGEX = ","; - private static final int WINNING_NUMBER_COUNT = 6; + private static final String NUMBER_INPUT_SPLIT_REGEX = ","; + private static final int LOTTO_NUMBER_COUNT = 6; public static void validateAmountNotNumber(final String amountInput) { try { Integer.parseInt(amountInput); } catch (NumberFormatException e) { - throw new IllegalArgumentException(NOT_NUMBER_EXCEPTION_MESSAGE); + throw new IllegalArgumentException(AMOUNT_NOT_NUMBER_EXCEPTION_MESSAGE); + } + } + + public static void validateManualCountNotNumber(final String manualCountInput) { + try { + Integer.parseInt(manualCountInput); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE); + } + } + + public static void validateManualNumberInput(final List manualNumberInputs) { + manualNumberInputs.forEach(manualNumberInput -> { + String[] splitInput = manualNumberInput + .replaceAll(" ", "") + .split(NUMBER_INPUT_SPLIT_REGEX); + + if (splitInput.length != LOTTO_NUMBER_COUNT) { + throw new IllegalArgumentException(MANUAL_NUMBER_COUNT_EXCEPTION_MESSAGE); + } + + validateManualNumber(splitInput); + }); + } + + private static void validateManualNumber(String[] splitInput) { + try { + Arrays.stream(splitInput) + .map(Integer::parseInt) + .forEach(manualNumber -> { + if (isLottoNumberRange(manualNumber)) { + throw new IllegalArgumentException(MANUAL_NUMBER_NOT_NUMBER_MESSAGE); + } + }); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(MANUAL_NUMBER_NOT_NUMBER_MESSAGE); } } public static void validateWinningNumberInput(final String winningNumberInput) { String[] splitInput = winningNumberInput .replaceAll(" ", "") - .split(WINNING_NUMBER_SPLIT_REGEX); + .split(NUMBER_INPUT_SPLIT_REGEX); validateWinningNumberCount(splitInput); @@ -29,7 +71,7 @@ public static void validateWinningNumberInput(final String winningNumberInput) { } private static void validateWinningNumberCount(final String[] splitInput) { - if (splitInput.length != WINNING_NUMBER_COUNT) { + if (splitInput.length != LOTTO_NUMBER_COUNT) { throw new IllegalArgumentException(WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE); } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 92cb32018a..7c7573d2ec 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -2,12 +2,19 @@ import controller.AmountRequest; import controller.BonusNumberRequest; +import controller.ManualNumberRequest; import controller.WinningNumberRequest; import utils.Console; import validator.InputValidator; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + public class InputView { private static final String INPUT_AMOUNT_MESSAGE = "구입금액을 입력해 주세요."; + private static final String INPUT_MANUAL_COUNT_MESSAGE = "수동으로 구매할 로또 수를 입력해 주세요."; + private static final String INPUT_MANUAL_NUMBER_MESSAGE = "수동으로 구매할 번호를 입력해 주세요."; private static final String INPUT_WINNING_NUMBER_MESSAGE = "지난 주 당첨 번호를 입력해 주세요."; private static final String INPUT_BONUS_NUMBER_MESSAGE = "보너스 볼을 입력해 주세요."; @@ -16,19 +23,42 @@ public static AmountRequest inputAmount() { try { final String lottoAmountInput = Console.readLine(); InputValidator.validateAmountNotNumber(lottoAmountInput); - return AmountRequest.of(lottoAmountInput); + return AmountRequest.from(lottoAmountInput); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); return inputAmount(); } } + public static ManualNumberRequest inputManual() { + System.out.println(INPUT_MANUAL_COUNT_MESSAGE); + try { + return fetchManualNumberRequest(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return inputManual(); + } + } + + private static ManualNumberRequest fetchManualNumberRequest() { + List manualNumberInputs = new ArrayList<>(); + + final String manualCountInput = Console.readLine(); + InputValidator.validateManualCountNotNumber(manualCountInput); + final int manualCount = Integer.parseInt(manualCountInput); + + System.out.println(INPUT_MANUAL_NUMBER_MESSAGE); + IntStream.range(0, manualCount).forEach(value -> manualNumberInputs.add(Console.readLine())); + InputValidator.validateManualNumberInput(manualNumberInputs); + return ManualNumberRequest.of(manualCount, manualNumberInputs); + } + public static WinningNumberRequest inputWinningNumber() { System.out.println(INPUT_WINNING_NUMBER_MESSAGE); try { final String winningNumberInput = Console.readLine(); InputValidator.validateWinningNumberInput(winningNumberInput); - return WinningNumberRequest.of(winningNumberInput); + return WinningNumberRequest.from(winningNumberInput); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); return inputWinningNumber(); @@ -40,7 +70,7 @@ public static BonusNumberRequest inputBonusNumber() { try { final String bonusNumberInput = Console.readLine(); InputValidator.validateBonusNumberInput(bonusNumberInput); - return BonusNumberRequest.of(bonusNumberInput); + return BonusNumberRequest.from(bonusNumberInput); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); return inputBonusNumber(); diff --git a/src/main/java/vo/LottoNumberCollection.java b/src/main/java/vo/LottoNumberCollection.java index 154ce49c72..72ad830991 100644 --- a/src/main/java/vo/LottoNumberCollection.java +++ b/src/main/java/vo/LottoNumberCollection.java @@ -11,7 +11,7 @@ private LottoNumberCollection(final List pickLottoNumbers) { this.pickLottoNumbers.addAll(pickLottoNumbers); } - public static LottoNumberCollection of(final List pickLottoNumbers) { + public static LottoNumberCollection from(final List pickLottoNumbers) { return new LottoNumberCollection(pickLottoNumbers); } diff --git a/src/main/java/vo/LottoNumberCollectionList.java b/src/main/java/vo/LottoNumberCollectionList.java index 4146496d5a..a0434a4210 100644 --- a/src/main/java/vo/LottoNumberCollectionList.java +++ b/src/main/java/vo/LottoNumberCollectionList.java @@ -10,7 +10,7 @@ private LottoNumberCollectionList(final List lottoNumberC this.lottoNumberCollectionList.addAll(lottoNumberCollectionList); } - public static LottoNumberCollectionList of(final List lottoNumberCollectionList) { + public static LottoNumberCollectionList from(final List lottoNumberCollectionList) { return new LottoNumberCollectionList(lottoNumberCollectionList); } @@ -18,6 +18,10 @@ public void addLottoNumberCollection(final LottoNumberCollection lottoNumberColl this.lottoNumberCollectionList.add(lottoNumberCollection); } + public void addAllLottoNumberCollection(final LottoNumberCollectionList lottoNumberCollectionList) { + this.lottoNumberCollectionList.addAll(lottoNumberCollectionList.getLottoNumberCollectionList()); + } + public List getLottoNumberCollectionList() { return List.copyOf(this.lottoNumberCollectionList); } From 6d71e6265b373e0666c545d58140f5c4378bb2c0 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 22:00:23 +0900 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20=EC=88=98=EB=8F=99=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=EB=A7=A4=ED=95=9C=20=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=8B=9C=20=ED=99=95=EC=9D=B8=ED=95=98?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 8 ++--- src/main/java/domain/PhraseLottoExecutor.java | 29 ++++++++++++----- src/main/java/validator/InputValidator.java | 10 ++++-- src/main/java/view/InputView.java | 10 +++--- src/main/java/view/OutputView.java | 32 ++++++++----------- 5 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 58e094d57d..3985ba6971 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -13,16 +13,16 @@ public class Application { public static void main(String[] args) { final AmountRequest amountRequest = InputView.inputAmount(); - final ManualNumberRequest manualNumberRequest = InputView.inputManual(); + final ManualNumberRequest manualNumberRequest = InputView.inputManual(amountRequest.getLottoAmount()); final WinningTypeCollection winningTypeCollection = retrieveWinning( - receivePhraseLotto(amountRequest) + receivePhraseLotto(amountRequest, manualNumberRequest) ); final RateCalculateExecutor rateCalculateExecutor = new RateCalculateExecutor(amountRequest, winningTypeCollection); rateCalculateExecutor.calculateRate(); } - private static LottoNumberCollectionList receivePhraseLotto(final AmountRequest amountRequest) { - PhraseLottoExecutor phraseLottoExecutor = new PhraseLottoExecutor(amountRequest); + private static LottoNumberCollectionList receivePhraseLotto(final AmountRequest amountRequest, final ManualNumberRequest manualNumberRequest) { + PhraseLottoExecutor phraseLottoExecutor = new PhraseLottoExecutor(amountRequest, manualNumberRequest); phraseLottoExecutor.phraseLotto(); return phraseLottoExecutor.pickLottoNumber(); } diff --git a/src/main/java/domain/PhraseLottoExecutor.java b/src/main/java/domain/PhraseLottoExecutor.java index 33855bb634..8a79bcdc16 100644 --- a/src/main/java/domain/PhraseLottoExecutor.java +++ b/src/main/java/domain/PhraseLottoExecutor.java @@ -1,6 +1,7 @@ package domain; import controller.AmountRequest; +import controller.ManualNumberRequest; import view.OutputView; import vo.LottoNumberCollection; import vo.LottoNumberCollectionList; @@ -12,6 +13,7 @@ public class PhraseLottoExecutor { private final AmountRequest amountRequest; + private final ManualNumberRequest manualNumberRequest; private static final List LOTTO_NUMBERS = new ArrayList<>(); private final static int LOTTO_NUMBER_COUNT = 6; @@ -22,30 +24,41 @@ public class PhraseLottoExecutor { } } - public PhraseLottoExecutor(final AmountRequest amountRequest) { + public PhraseLottoExecutor(final AmountRequest amountRequest, final ManualNumberRequest manualNumberRequest) { this.amountRequest = amountRequest; + this.manualNumberRequest = manualNumberRequest; } public void phraseLotto() { - OutputView.outputPhraseLotto(this.amountRequest.fetchPhraseLottoCount()); + OutputView.outputPhraseLotto(this.manualNumberRequest.getManualCount(), calculateRandomPickCount()); } public LottoNumberCollectionList pickLottoNumber() { - List lottoNumberCollectionList = new ArrayList<>(); + List lottoNumberCollectionRequest = fetchRandomLottoNumberCollectionList(); - for (int i = 0; i < this.amountRequest.fetchPhraseLottoCount(); i++) { + LottoNumberCollectionList lottoNumberCollectionList = this.manualNumberRequest.getLottoNumberCollectionList(); + lottoNumberCollectionList.addAllLottoNumberCollection(LottoNumberCollectionList.from(lottoNumberCollectionRequest)); + OutputView.outputPickedLottoNumber(lottoNumberCollectionList); + return lottoNumberCollectionList; + } + + private List fetchRandomLottoNumberCollectionList() { + List lottoNumberCollectionRequest = new ArrayList<>(); + + for (int i = 0; i < calculateRandomPickCount(); i++) { List pickLottoNumbers = new ArrayList<>(); Collections.shuffle(LOTTO_NUMBERS); IntStream.range(0, LOTTO_NUMBER_COUNT).forEach(index -> { pickLottoNumbers.add(LOTTO_NUMBERS.get(index)); }); - final LottoNumberCollection lottoNumberCollection = LottoNumberCollection.from(pickLottoNumbers); - OutputView.outputPickedLottoNumber(lottoNumberCollection); - lottoNumberCollectionList.add(lottoNumberCollection); + lottoNumberCollectionRequest.add(LottoNumberCollection.from(pickLottoNumbers)); } + return lottoNumberCollectionRequest; + } - return LottoNumberCollectionList.from(lottoNumberCollectionList); + private int calculateRandomPickCount() { + return this.amountRequest.fetchPhraseLottoCount() - this.manualNumberRequest.getManualCount(); } } diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java index a3a1460945..3b21f6e6d9 100644 --- a/src/main/java/validator/InputValidator.java +++ b/src/main/java/validator/InputValidator.java @@ -6,6 +6,7 @@ public class InputValidator { private static final String AMOUNT_NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; private static final String MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 로또 수의 입력은 0 이상의 정수여야 합니다."; + private static final String MANUAL_COUNT_NOT_BIGGER_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 로또 수는 구매한 로또 수보다 클 수 없습니다."; private static final String MANUAL_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 번호는 6개여야 합니다."; private static final String MANUAL_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 수동으로 구매할 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; private static final String WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 당첨 번호는 6개여야 합니다."; @@ -22,9 +23,12 @@ public static void validateAmountNotNumber(final String amountInput) { } } - public static void validateManualCountNotNumber(final String manualCountInput) { + public static void validateManualCountNotNumber(final String manualCountInput, final int lottoAmount) { try { - Integer.parseInt(manualCountInput); + int manualCount = Integer.parseInt(manualCountInput); + if (manualCount > lottoAmount) { + throw new IllegalArgumentException(MANUAL_COUNT_NOT_BIGGER_EXCEPTION_MESSAGE); + } } catch (NumberFormatException e) { throw new IllegalArgumentException(MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE); } @@ -49,7 +53,7 @@ private static void validateManualNumber(String[] splitInput) { Arrays.stream(splitInput) .map(Integer::parseInt) .forEach(manualNumber -> { - if (isLottoNumberRange(manualNumber)) { + if (!isLottoNumberRange(manualNumber)) { throw new IllegalArgumentException(MANUAL_NUMBER_NOT_NUMBER_MESSAGE); } }); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 7c7573d2ec..2a1b50d98b 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -30,21 +30,21 @@ public static AmountRequest inputAmount() { } } - public static ManualNumberRequest inputManual() { + public static ManualNumberRequest inputManual(final int lottoAmount) { System.out.println(INPUT_MANUAL_COUNT_MESSAGE); try { - return fetchManualNumberRequest(); + return fetchManualNumberRequest(lottoAmount); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); - return inputManual(); + return inputManual(lottoAmount); } } - private static ManualNumberRequest fetchManualNumberRequest() { + private static ManualNumberRequest fetchManualNumberRequest(final int lottoAmount) { List manualNumberInputs = new ArrayList<>(); final String manualCountInput = Console.readLine(); - InputValidator.validateManualCountNotNumber(manualCountInput); + InputValidator.validateManualCountNotNumber(manualCountInput, lottoAmount); final int manualCount = Integer.parseInt(manualCountInput); System.out.println(INPUT_MANUAL_NUMBER_MESSAGE); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 12f3edc6f5..dde4f0085e 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,41 +1,35 @@ package view; import vo.LottoNumberCollection; +import vo.LottoNumberCollectionList; import vo.WinningTypeCollection; import vo.enums.WinningType; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class OutputView { - private static final String PHRASE_LOTTO_MESSAGE = "%d개를 구매했습니다."; + private static final String PHRASE_LOTTO_MESSAGE = "수동으로 %d개, 자동으로 %d개를 구매했습니다."; private static final String WINNING_STATISTICS_MESSAGE = "당첨 통계\n---------"; private static final String TOTAL_RATE_MESSAGE = "총 수익률은 %.2f입니다."; - private static final String SQUARE_BRACKETS_OPEN = "["; - private static final String SQUARE_BRACKETS_CLOSE = "]"; + private static final String SQUARE_BRACKETS_FOR_LOTTO_NUMBER = "[%s]"; private static final String REST_DELIMITER = ", "; private static final String WINNING_FORMAT = "%s - %d개"; - public static void outputPhraseLotto(final int phraseLottoCount) { - System.out.println(String.format(PHRASE_LOTTO_MESSAGE, phraseLottoCount)); + public static void outputPhraseLotto(final int manualCount, final int randomCount) { + System.out.println(String.format(PHRASE_LOTTO_MESSAGE, manualCount, randomCount)); } - public static void outputPickedLottoNumber(final LottoNumberCollection lottoNumberCollection) { - StringBuilder lottoNumberStringBuilder = new StringBuilder(SQUARE_BRACKETS_OPEN); - List pickLottoNumbers = new ArrayList<>(lottoNumberCollection.getPickLottoNumbers()); - Collections.sort(pickLottoNumbers); + public static void outputPickedLottoNumber(final LottoNumberCollectionList lottoNumberCollectionList) { + List lottoNumberCollections = lottoNumberCollectionList.getLottoNumberCollectionList(); + lottoNumberCollections.forEach(lottoNumberCollection -> { + String collectPickLottoNumber = lottoNumberCollection.getPickLottoNumbers().stream() + .map(Object::toString) + .collect(Collectors.joining(REST_DELIMITER)); - String lottoNumberString = pickLottoNumbers.stream() - .map(number -> Integer.toString(number)) - .collect(Collectors.joining(REST_DELIMITER)); - - lottoNumberStringBuilder.append(lottoNumberString); - lottoNumberStringBuilder.append(SQUARE_BRACKETS_CLOSE); - - System.out.println(lottoNumberStringBuilder); + System.out.println(String.format(SQUARE_BRACKETS_FOR_LOTTO_NUMBER, collectPickLottoNumber)); + }); } public static void outputLottoWinningPrice(final WinningTypeCollection winningTypeCollection) { From 1d4105d11286858299b8e15d3515ba31903a4d89 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 22:41:47 +0900 Subject: [PATCH 11/15] =?UTF-8?q?test:=20=EC=9E=85=EB=A0=A5=20=EC=9C=A0?= =?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/validator/InputValidatorTest.java | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/test/java/validator/InputValidatorTest.java diff --git a/src/test/java/validator/InputValidatorTest.java b/src/test/java/validator/InputValidatorTest.java new file mode 100644 index 0000000000..f1f131a192 --- /dev/null +++ b/src/test/java/validator/InputValidatorTest.java @@ -0,0 +1,116 @@ +package validator; + +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.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class InputValidatorTest { + private static final String AMOUNT_NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 금액의 입력은 0 이상의 정수여야 합니다."; + private static final String MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 로또 수의 입력은 0 이상의 정수여야 합니다."; + private static final String MANUAL_COUNT_NOT_BIGGER_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 로또 수는 구매한 로또 수보다 클 수 없습니다."; + private static final String MANUAL_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 수동으로 구매할 번호는 6개여야 합니다."; + private static final String MANUAL_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 수동으로 구매할 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; + private static final String WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE = "[ERROR] 당첨 번호는 6개여야 합니다."; + private static final String WINNING_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 당첨 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; + private static final String BONUS_NUMBER_NOT_NUMBER_MESSAGE = "[ERROR] 보너스 볼 번호는 1부터 45까지의 숫자로 이루어져야 합니다."; + + @Test + void 구매한_로또_개수_입력_유효성을_검사한다() { + String alphabetInput = "a"; + String koreanInput = "가"; + + IllegalArgumentException actual1 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateAmountNotNumber(alphabetInput)); + IllegalArgumentException actual2 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateAmountNotNumber(koreanInput)); + + assertAll( + () -> assertThat(actual1.getMessage()).isEqualTo(AMOUNT_NOT_NUMBER_EXCEPTION_MESSAGE), + () -> assertThat(actual2.getMessage()).isEqualTo(AMOUNT_NOT_NUMBER_EXCEPTION_MESSAGE) + ); + } + + @Test + void 수동_구매_개수_입력_유효성을_검사한다() { + String alphabetInput = "a"; + String koreanInput = "가"; + String manualCount = "6"; + int lottoAmount = 5; + + IllegalArgumentException actual1 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualCountNotNumber(alphabetInput, lottoAmount)); + IllegalArgumentException actual2 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualCountNotNumber(koreanInput, lottoAmount)); + IllegalArgumentException actual3 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualCountNotNumber(manualCount, lottoAmount)); + + assertAll( + () -> assertThat(actual1.getMessage()).isEqualTo(MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE), + () -> assertThat(actual2.getMessage()).isEqualTo(MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE), + () -> assertThat(actual3.getMessage()).isEqualTo(MANUAL_COUNT_NOT_BIGGER_EXCEPTION_MESSAGE) + ); + } + + @Test + void 수동으로_구매한_로또_번호_유효성을_검사한다() { + List alphabetInputs = List.of("a, b, c, d, e, f"); + List koreanInputs = List.of("가, 나, 다, 라, 마, 바"); + List manyNumberInputs = List.of("1, 2, 3, 4, 5, 6, 7"); + List fewNumberInputs = List.of("1, 2, 3, 4, 5"); + List outRangeNumberInputs = List.of("41, 42, 43 ,44 ,45 ,46"); + + IllegalArgumentException actual1 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualNumberInput(alphabetInputs)); + IllegalArgumentException actual2 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualNumberInput(koreanInputs)); + IllegalArgumentException actual3 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualNumberInput(manyNumberInputs)); + IllegalArgumentException actual4 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualNumberInput(fewNumberInputs)); + IllegalArgumentException actual5 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateManualNumberInput(outRangeNumberInputs)); + + assertAll( + () -> assertThat(actual1.getMessage()).isEqualTo(MANUAL_NUMBER_NOT_NUMBER_MESSAGE), + () -> assertThat(actual2.getMessage()).isEqualTo(MANUAL_NUMBER_NOT_NUMBER_MESSAGE), + () -> assertThat(actual3.getMessage()).isEqualTo(MANUAL_NUMBER_COUNT_EXCEPTION_MESSAGE), + () -> assertThat(actual4.getMessage()).isEqualTo(MANUAL_NUMBER_COUNT_EXCEPTION_MESSAGE), + () -> assertThat(actual5.getMessage()).isEqualTo(MANUAL_NUMBER_NOT_NUMBER_MESSAGE) + ); + } + + @Test + void 저번_당첨번호_입력_유효성을_검사한다() { + String alphabetInput = "a, b, c, d, e, f"; + String koreanInput = "가, 나, 다, 라, 마, 바"; + String manyNumberInput = "1, 2, 3, 4, 5, 6, 7"; + String fewNumberInput = "1, 2, 3, 4, 5"; + String outRangeInput = "41, 42, 43, 44, 45, 46"; + + IllegalArgumentException actual1 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateWinningNumberInput(alphabetInput)); + IllegalArgumentException actual2 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateWinningNumberInput(koreanInput)); + IllegalArgumentException actual3 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateWinningNumberInput(manyNumberInput)); + IllegalArgumentException actual4 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateWinningNumberInput(fewNumberInput)); + IllegalArgumentException actual5 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateWinningNumberInput(outRangeInput)); + + assertAll( + () -> assertThat(actual1.getMessage()).isEqualTo(WINNING_NUMBER_NOT_NUMBER_MESSAGE), + () -> assertThat(actual2.getMessage()).isEqualTo(WINNING_NUMBER_NOT_NUMBER_MESSAGE), + () -> assertThat(actual3.getMessage()).isEqualTo(WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE), + () -> assertThat(actual4.getMessage()).isEqualTo(WINNING_NUMBER_COUNT_EXCEPTION_MESSAGE), + () -> assertThat(actual5.getMessage()).isEqualTo(WINNING_NUMBER_NOT_NUMBER_MESSAGE) + ); + } + + @Test + void 보너스_번호_입력_유효성을_검사한다() { + String alphabetInput = "a"; + String koreanInput = "가"; + String outRangeInput = "46"; + + IllegalArgumentException actual1 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateBonusNumberInput(alphabetInput)); + IllegalArgumentException actual2 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateBonusNumberInput(koreanInput)); + IllegalArgumentException actual3 = assertThrows(IllegalArgumentException.class, () -> InputValidator.validateBonusNumberInput(outRangeInput)); + + assertAll( + () -> assertThat(actual1.getMessage()).isEqualTo(BONUS_NUMBER_NOT_NUMBER_MESSAGE), + () -> assertThat(actual2.getMessage()).isEqualTo(BONUS_NUMBER_NOT_NUMBER_MESSAGE), + () -> assertThat(actual3.getMessage()).isEqualTo(BONUS_NUMBER_NOT_NUMBER_MESSAGE) + ); + } + +} \ No newline at end of file From 7afd95c9353183751ef8bf2b17394ff62010205b Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sat, 18 May 2024 22:53:51 +0900 Subject: [PATCH 12/15] =?UTF-8?q?refactor:=20=EC=9C=A0=ED=9A=A8=EC=84=B1?= =?UTF-8?q?=20=EA=B2=80=EC=82=AC=20=EC=A4=91=20=EB=B6=84=EA=B8=B0=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/validator/InputValidator.java | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/java/validator/InputValidator.java b/src/main/java/validator/InputValidator.java index 3b21f6e6d9..5de886af8f 100644 --- a/src/main/java/validator/InputValidator.java +++ b/src/main/java/validator/InputValidator.java @@ -26,14 +26,18 @@ public static void validateAmountNotNumber(final String amountInput) { public static void validateManualCountNotNumber(final String manualCountInput, final int lottoAmount) { try { int manualCount = Integer.parseInt(manualCountInput); - if (manualCount > lottoAmount) { - throw new IllegalArgumentException(MANUAL_COUNT_NOT_BIGGER_EXCEPTION_MESSAGE); - } + validateManualCountLeastThanLottoAmount(lottoAmount, manualCount); } catch (NumberFormatException e) { throw new IllegalArgumentException(MANUAL_COUNT_NOT_NUMBER_EXCEPTION_MESSAGE); } } + private static void validateManualCountLeastThanLottoAmount(int lottoAmount, int manualCount) { + if (manualCount > lottoAmount) { + throw new IllegalArgumentException(MANUAL_COUNT_NOT_BIGGER_EXCEPTION_MESSAGE); + } + } + public static void validateManualNumberInput(final List manualNumberInputs) { manualNumberInputs.forEach(manualNumberInput -> { String[] splitInput = manualNumberInput @@ -52,16 +56,18 @@ private static void validateManualNumber(String[] splitInput) { try { Arrays.stream(splitInput) .map(Integer::parseInt) - .forEach(manualNumber -> { - if (!isLottoNumberRange(manualNumber)) { - throw new IllegalArgumentException(MANUAL_NUMBER_NOT_NUMBER_MESSAGE); - } - }); + .forEach(InputValidator::validateManualNumberRange); } catch (NumberFormatException e) { throw new IllegalArgumentException(MANUAL_NUMBER_NOT_NUMBER_MESSAGE); } } + private static void validateManualNumberRange(final int manualNumber) { + if (!isLottoNumberRange(manualNumber)) { + throw new IllegalArgumentException(MANUAL_NUMBER_NOT_NUMBER_MESSAGE); + } + } + public static void validateWinningNumberInput(final String winningNumberInput) { String[] splitInput = winningNumberInput .replaceAll(" ", "") @@ -109,7 +115,7 @@ public static void validateBonusNumberInput(final String bonusNumberInput) { } } - private static void validateBonusNumberRange(int bonusNumber) { + private static void validateBonusNumberRange(final int bonusNumber) { if (!isLottoNumberRange(bonusNumber)) { throw new IllegalArgumentException(BONUS_NUMBER_NOT_NUMBER_MESSAGE); } From 81b2527e2ad6bb372171403052bc1cb4d1253f2e Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 19 May 2024 10:33:01 +0900 Subject: [PATCH 13/15] =?UTF-8?q?test:=20=EB=8B=B9=EC=B2=A8=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=ED=86=B5=EA=B3=84=20=EC=B6=9C=EB=A0=A5=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/IOTest.java | 25 ++++++++ .../domain/WinningConfirmExecutorTest.java | 59 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/test/java/domain/IOTest.java create mode 100644 src/test/java/domain/WinningConfirmExecutorTest.java diff --git a/src/test/java/domain/IOTest.java b/src/test/java/domain/IOTest.java new file mode 100644 index 0000000000..06f1725834 --- /dev/null +++ b/src/test/java/domain/IOTest.java @@ -0,0 +1,25 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +public abstract class IOTest { + private ByteArrayOutputStream byteArrayOutputStream; + + protected void systemIn(final String input) { + System.setIn(new ByteArrayInputStream(input.getBytes())); + } + + @BeforeEach + void setUp() { + byteArrayOutputStream = new ByteArrayOutputStream(); + System.setOut(new PrintStream(byteArrayOutputStream)); + } + + protected String fetchOutput() { + return byteArrayOutputStream.toString(); + } +} diff --git a/src/test/java/domain/WinningConfirmExecutorTest.java b/src/test/java/domain/WinningConfirmExecutorTest.java new file mode 100644 index 0000000000..77f28d8aa2 --- /dev/null +++ b/src/test/java/domain/WinningConfirmExecutorTest.java @@ -0,0 +1,59 @@ +package domain; + +import controller.BonusNumberRequest; +import controller.WinningNumberRequest; +import org.junit.jupiter.api.Test; +import vo.LottoNumberCollection; +import vo.LottoNumberCollectionList; +import vo.enums.WinningType; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +class WinningConfirmExecutorTest extends IOTest { + + private static final String WINNING_FORMAT = "%s - %d개"; + + @Test + void 당첨_금액_통계_출력_확인하기() { + WinningConfirmExecutor sut = new WinningConfirmExecutor(createLottoNumberCollectionList(), + createWinningNumberRequest(), + createBonusNumberRequest()); + + sut.confirmWinningType(); + + assertAll( + () -> assertThat(fetchOutput()).contains(String.format(WINNING_FORMAT, WinningType.THREE_MATCH.getTitle(), 1)), + () -> assertThat(fetchOutput()).contains(String.format(WINNING_FORMAT, WinningType.FOUR_MATCH.getTitle(), 1)), + () -> assertThat(fetchOutput()).contains(String.format(WINNING_FORMAT, WinningType.FIVE_BONUS_MATCH.getTitle(), 1)) + ); + } + + private LottoNumberCollectionList createLottoNumberCollectionList() { + return LottoNumberCollectionList.from(createLottoNumberCollection()); + } + + private List createLottoNumberCollection() { + List pickLottoNumbers1 = List.of(1, 2, 3, 8, 9, 10); + List pickLottoNumbers2 = List.of(1, 2, 3, 4, 8, 9); + List pickLottoNumbers3 = List.of(1, 2, 3, 4, 5, 7); + + List> pickLottoNumberList = List.of(pickLottoNumbers1, pickLottoNumbers2, pickLottoNumbers3); + return pickLottoNumberList.stream() + .map(LottoNumberCollection::from) + .collect(Collectors.toList()); + } + + private WinningNumberRequest createWinningNumberRequest() { + String winningNumberInput = "1, 2, 3, 4, 5, 6"; + return WinningNumberRequest.from(winningNumberInput); + } + + private BonusNumberRequest createBonusNumberRequest() { + String bonusNumberInput = "7"; + return BonusNumberRequest.from(bonusNumberInput); + } +} \ No newline at end of file From e029076420d87b334d0c739239c6cdeca72564d7 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 19 May 2024 10:40:18 +0900 Subject: [PATCH 14/15] =?UTF-8?q?test:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EC=9E=85=20=EC=B6=9C=EB=A0=A5=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/PhraseLottoExecutorTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/java/domain/PhraseLottoExecutorTest.java diff --git a/src/test/java/domain/PhraseLottoExecutorTest.java b/src/test/java/domain/PhraseLottoExecutorTest.java new file mode 100644 index 0000000000..aac05b65dd --- /dev/null +++ b/src/test/java/domain/PhraseLottoExecutorTest.java @@ -0,0 +1,33 @@ +package domain; + +import controller.AmountRequest; +import controller.ManualNumberRequest; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class PhraseLottoExecutorTest extends IOTest { + private static final String PHRASE_LOTTO_MESSAGE = "수동으로 %d개, 자동으로 %d개를 구매했습니다."; + + @Test + void 로또_구입_메시지_출력을_확인한다() { + PhraseLottoExecutor sut = new PhraseLottoExecutor(createAmountRequest(), createManualNumberRequest()); + + sut.phraseLotto(); + + assertThat(fetchOutput()).contains(String.format(PHRASE_LOTTO_MESSAGE, 1, 4)); + } + + private AmountRequest createAmountRequest() { + String amountInput = "5000"; + return AmountRequest.from(amountInput); + } + + private ManualNumberRequest createManualNumberRequest() { + int manualCount = 1; + List manualNumberInputs = List.of("1, 2, 3, 4, 5, 6"); + return ManualNumberRequest.of(manualCount, manualNumberInputs); + } +} \ No newline at end of file From 68ebdcc16fa16ca4449f8ccb12c7ce0ae072c885 Mon Sep 17 00:00:00 2001 From: lgm1007 Date: Sun, 19 May 2024 23:04:38 +0900 Subject: [PATCH 15/15] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=88=98=EB=8F=99=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EA=B5=AC=EB=A7=A4=20=EB=82=B4=EC=9A=A9=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/README.md b/docs/README.md index 61f144aafe..58939acae8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,3 +13,8 @@ * 6개 일치 (2000000000원) * 총 수익률을 계산해서 출력해준다. * 수익률은 구매한 금액 / 총 당첨 금액 계산값을 소수점 두 자리 수까지 나타낸 수이다. + +### 수동 로또 구매 +* 로또 구입 금액 입력 후 수동 구매 수량을 입력받는다. +* 수동 구매 수량을 입력받은 후 수동으로 구매할 로또 번호를 구매 수량만큼 입력받는다. +* 자동 구매권 수량은 총 구매한 개수 - 수동 구매 수량이다. \ No newline at end of file