From d711e56af25a9d402815f4aeedff071ab2b76959 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 13:59:30 +0900 Subject: [PATCH 01/25] =?UTF-8?q?docs:=20=EB=AF=B8=EC=85=981=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index 9594b6c872..1f9daa8a48 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,33 @@ 로또 미션 저장소 # [미션 리드미](https://github.com/talmood/private-mission-README/tree/main/%EB%AF%B8%EC%85%98%203%20-%20%EB%A1%9C%EB%98%90) + +# 미션 1 - 로또 +## 기능 요구 사항 +- 로또 구입 금액을 입력 받는다. + - 로또 구입 금액은 숫자여야 한다. + - 로또 한 장의 가격은 1000원이다. + - 최소 구입 금액은 1000원이다. + - 로또 구입 금액은 1000원 단위여야 한다. +- 로또 구입 금액만큼 로또를 발급한다. + - 로또 한 장의 가격은 1000원이다. +- 로또 1장은 6개의 랜덤 숫자를 가진다. + - 로또 숫자는 1부터 45까지의 숫자이다. + - 로또 숫자는 중복되지 않는다. + - 로또 숫자는 오름차순으로 정렬되어 있다. +- 지난주 당첨 번호를 입력 받는다. + - 지난주 당첨 번호는 1부터 45까지의 숫자이다. + - 지난주 당첨 번호는 중복되지 않는다. + - 지난주 당첨 번호는 오름차순으로 정렬되어 있다. +- 지난 주 보너스 볼을 입력 받는다. + - 보너스 볼은 1부터 45까지의 숫자이다. + - 보너스 볼은 지난주 당첨 번호와 중복되지 않는다. + - 보너스 볼은 오름차순으로 정렬되어 있다. +- 당첨 통계를 출력한다. + - 3개 일치, 4개 일치, 5개 일치, 5개 일치 + 보너스 볼 일치, 6개 일치의 당첨 통계를 출력한다. + - 당첨 통계는 로또 당첨 금액을 기준으로 한다. + - 당첨 통계는 로또 당첨 개수를 기준으로 한다. + - 당첨 통계는 로또 당첨 금액과 로또 당첨 개수를 출력한다. +- 총 수익률을 계산한다. + - 총 수익률은 (총 당첨 금액 - 로또 구입 금액) / 로또 구입 금액으로 계산한다. + - 총 수익률은 소수점 둘째 자리까지 출력한다. (소수점 셋째 자리에서 버림 처리한다.) \ No newline at end of file From c51a07454ab08f4cf43c0bf3ecb4d7412e382e2c Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 14:09:00 +0900 Subject: [PATCH 02/25] =?UTF-8?q?feat:=20Application.java=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/lotto/Application.java diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java new file mode 100644 index 0000000000..5f5e2ae3c5 --- /dev/null +++ b/src/main/java/lotto/Application.java @@ -0,0 +1,8 @@ +package lotto; + +public class Application { + + public static void main(String[] args) { + + } +} From c99868924c5e0aff7a3a87b1d8b916ea3d8871bd Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 14:09:38 +0900 Subject: [PATCH 03/25] =?UTF-8?q?feat:=20StringUtil.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/utils/StringUtil.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/lotto/utils/StringUtil.java diff --git a/src/main/java/lotto/utils/StringUtil.java b/src/main/java/lotto/utils/StringUtil.java new file mode 100644 index 0000000000..9d35270722 --- /dev/null +++ b/src/main/java/lotto/utils/StringUtil.java @@ -0,0 +1,13 @@ +package lotto.utils; + +import java.util.Objects; + +public abstract class StringUtil { + + private StringUtil() { + } + + public static boolean isBlank(final String str) { + return Objects.isNull(str) || str.trim().isEmpty(); + } +} From e043085797fa5ccd314b4c387c91b73d8605f38c Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 19:51:05 +0900 Subject: [PATCH 04/25] =?UTF-8?q?feat:=20Lotto=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/request/Lotto.java | 46 ++++++++++++++++++++ src/main/java/lotto/request/LottoNumber.java | 39 +++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/main/java/lotto/request/Lotto.java create mode 100644 src/main/java/lotto/request/LottoNumber.java diff --git a/src/main/java/lotto/request/Lotto.java b/src/main/java/lotto/request/Lotto.java new file mode 100644 index 0000000000..5f3baec66f --- /dev/null +++ b/src/main/java/lotto/request/Lotto.java @@ -0,0 +1,46 @@ +package lotto.request; + +import java.util.List; + +public class Lotto { + + private static final int LOTTO_SIZE = 6; + + private final List lottoNumbers; + private final LottoNumber bonusNumber; + + private Lotto(final List lottoNumbers, final LottoNumber bonusNumber) { + validate(lottoNumbers, bonusNumber); + this.lottoNumbers = lottoNumbers; + this.bonusNumber = bonusNumber; + } + + public static Lotto of(final List lottoNumbers, final LottoNumber bonusNumber) { + return new Lotto(lottoNumbers, bonusNumber); + } + + private static void validate(final List lottoNumbers, final LottoNumber bonusNumber) { + validateSize(lottoNumbers); + validateDuplicate(lottoNumbers, bonusNumber); + } + + private static void validateSize(List lottoNumbers) { + if (lottoNumbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + } + } + + private static void validateDuplicate(final List lottoNumbers, final LottoNumber bonusNumber) { + if (lottoNumbers.stream().distinct().count() != LOTTO_SIZE) { + throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); + } + + if (lottoNumbers.contains(bonusNumber)) { + throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + } + + public List getLottoNumbers() { + return List.copyOf(lottoNumbers); + } +} diff --git a/src/main/java/lotto/request/LottoNumber.java b/src/main/java/lotto/request/LottoNumber.java new file mode 100644 index 0000000000..6e8b6b5d1d --- /dev/null +++ b/src/main/java/lotto/request/LottoNumber.java @@ -0,0 +1,39 @@ +package lotto.request; + +import java.util.Objects; + +public class LottoNumber { + + private static final int MIN_NUMBER = 1; + private static final int MAX_NUMBER = 45; + + private final int number; + + private LottoNumber(final int number) { + validate(number); + this.number = number; + } + + public static LottoNumber from(final int number) { + return new LottoNumber(number); + } + + private static void validate(final int number) { + if (number < MIN_NUMBER || number > MAX_NUMBER) { + throw new IllegalArgumentException("로또 번호는 1부터 45까지의 숫자만 가능합니다."); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LottoNumber that = (LottoNumber) o; + return number == that.number; + } + + @Override + public int hashCode() { + return Objects.hash(number); + } +} From 510efdde70e64310acc82c044504bfc2b3bc1121 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 19:53:44 +0900 Subject: [PATCH 05/25] =?UTF-8?q?fix:=20Lotto=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/{request => domain}/Lotto.java | 2 +- src/main/java/lotto/{request => domain}/LottoNumber.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/lotto/{request => domain}/Lotto.java (98%) rename src/main/java/lotto/{request => domain}/LottoNumber.java (97%) diff --git a/src/main/java/lotto/request/Lotto.java b/src/main/java/lotto/domain/Lotto.java similarity index 98% rename from src/main/java/lotto/request/Lotto.java rename to src/main/java/lotto/domain/Lotto.java index 5f3baec66f..1391cbb246 100644 --- a/src/main/java/lotto/request/Lotto.java +++ b/src/main/java/lotto/domain/Lotto.java @@ -1,4 +1,4 @@ -package lotto.request; +package lotto.domain; import java.util.List; diff --git a/src/main/java/lotto/request/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java similarity index 97% rename from src/main/java/lotto/request/LottoNumber.java rename to src/main/java/lotto/domain/LottoNumber.java index 6e8b6b5d1d..8178399260 100644 --- a/src/main/java/lotto/request/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -1,4 +1,4 @@ -package lotto.request; +package lotto.domain; import java.util.Objects; From 8b80c42b4647d4174d87b7b8a438e25c2d90972b Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 19:57:04 +0900 Subject: [PATCH 06/25] =?UTF-8?q?feat:=20Console.java=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/utils/Console.java | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/lotto/utils/Console.java diff --git a/src/main/java/lotto/utils/Console.java b/src/main/java/lotto/utils/Console.java new file mode 100644 index 0000000000..5d88af5929 --- /dev/null +++ b/src/main/java/lotto/utils/Console.java @@ -0,0 +1,29 @@ +package lotto.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; + } +} From 1124b57316d69aa2e2ef9342f18823db115b3fcc Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 20:05:55 +0900 Subject: [PATCH 07/25] =?UTF-8?q?feat:=20PatternUtil.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/utils/PatternUtil.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/lotto/utils/PatternUtil.java diff --git a/src/main/java/lotto/utils/PatternUtil.java b/src/main/java/lotto/utils/PatternUtil.java new file mode 100644 index 0000000000..5065eaf261 --- /dev/null +++ b/src/main/java/lotto/utils/PatternUtil.java @@ -0,0 +1,16 @@ +package lotto.utils; + +import java.util.Objects; +import java.util.regex.Pattern; + +public abstract class PatternUtil { + private PatternUtil() { + } + + public static boolean isMatched(final String str, final String pattern) { + if (Objects.isNull(str) || Objects.isNull(pattern)) { + return false; + } + return Pattern.matches(pattern, str); + } +} From f447fb1774c7b41086b95fc3e9da31c9706b69be Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 20:14:30 +0900 Subject: [PATCH 08/25] =?UTF-8?q?feat:=20Lotto=20=EA=B5=AC=EC=9E=85=20requ?= =?UTF-8?q?est=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lotto/request/LottoPurchaseRequest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/lotto/request/LottoPurchaseRequest.java diff --git a/src/main/java/lotto/request/LottoPurchaseRequest.java b/src/main/java/lotto/request/LottoPurchaseRequest.java new file mode 100644 index 0000000000..85a68d2184 --- /dev/null +++ b/src/main/java/lotto/request/LottoPurchaseRequest.java @@ -0,0 +1,50 @@ +package lotto.request; + +import lotto.utils.PatternUtil; + +public class LottoPurchaseRequest { + private static final int MIN_PURCHASE_AMOUNT = 1000; + private static final int UNIT_PURCHASE_AMOUNT = 1000; + private static final String PURCHASE_AMOUNT_REGEX = "^[0-9]*$"; + + private static final String ERROR_PURCHASE_AMOUNT_NOT_A_NUMBER = "[ERROR] 구입 금액은 숫자여야 합니다."; + private static final String ERROR_PURCHASE_AMOUNT_TOO_LOW = "[ERROR] 구입 금액은 1000원 이상이어야 합니다."; + private static final String ERROR_PURCHASE_AMOUNT_NOT_MULTIPLE_OF_1000 = "[ERROR] 구입 금액은 1000원 단위여야 합니다."; + + private final int purchaseAmount; + + private LottoPurchaseRequest(final int purchaseAmount) { + this.purchaseAmount = purchaseAmount; + } + + public static LottoPurchaseRequest of(final String purchaseAmount) { + validate(purchaseAmount); + return new LottoPurchaseRequest(Integer.parseInt(purchaseAmount)); + } + + private static void validate (final String purchaseAmount) { + validateInputPattern(purchaseAmount); + validatePurchaseAmount(Integer.parseInt(purchaseAmount)); + } + + private static void validateInputPattern(final String purchaseAmount) { + if (!PatternUtil.isMatched(purchaseAmount, PURCHASE_AMOUNT_REGEX)) { + throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_NOT_A_NUMBER); + } + } + + private static void validatePurchaseAmount(final int purchaseAmount) { + if (purchaseAmount < MIN_PURCHASE_AMOUNT) { + throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_TOO_LOW); + } + + if (purchaseAmount % UNIT_PURCHASE_AMOUNT != 0) { + throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_NOT_MULTIPLE_OF_1000); + } + } + + public int getPurchaseCount() { + return purchaseAmount / UNIT_PURCHASE_AMOUNT; + } + +} From fbfedef6c07c622587857277c98f1832726db566 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 20:52:28 +0900 Subject: [PATCH 09/25] =?UTF-8?q?feat:=20=EA=B5=AC=EB=A7=A4=ED=95=9C=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EA=B0=9D=EC=B2=B4,=20=EB=8B=B9=EC=B2=A8?= =?UTF-8?q?=20=EB=A1=9C=EB=98=90=20=EA=B0=9D=EC=B2=B4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/Lotto.java | 46 ------------------- .../java/lotto/domain/PurchasedLotto.java | 34 ++++++++++++++ src/main/java/lotto/domain/WinningLotto.java | 45 ++++++++++++++++++ 3 files changed, 79 insertions(+), 46 deletions(-) delete mode 100644 src/main/java/lotto/domain/Lotto.java create mode 100644 src/main/java/lotto/domain/PurchasedLotto.java create mode 100644 src/main/java/lotto/domain/WinningLotto.java diff --git a/src/main/java/lotto/domain/Lotto.java b/src/main/java/lotto/domain/Lotto.java deleted file mode 100644 index 1391cbb246..0000000000 --- a/src/main/java/lotto/domain/Lotto.java +++ /dev/null @@ -1,46 +0,0 @@ -package lotto.domain; - -import java.util.List; - -public class Lotto { - - private static final int LOTTO_SIZE = 6; - - private final List lottoNumbers; - private final LottoNumber bonusNumber; - - private Lotto(final List lottoNumbers, final LottoNumber bonusNumber) { - validate(lottoNumbers, bonusNumber); - this.lottoNumbers = lottoNumbers; - this.bonusNumber = bonusNumber; - } - - public static Lotto of(final List lottoNumbers, final LottoNumber bonusNumber) { - return new Lotto(lottoNumbers, bonusNumber); - } - - private static void validate(final List lottoNumbers, final LottoNumber bonusNumber) { - validateSize(lottoNumbers); - validateDuplicate(lottoNumbers, bonusNumber); - } - - private static void validateSize(List lottoNumbers) { - if (lottoNumbers.size() != LOTTO_SIZE) { - throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); - } - } - - private static void validateDuplicate(final List lottoNumbers, final LottoNumber bonusNumber) { - if (lottoNumbers.stream().distinct().count() != LOTTO_SIZE) { - throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); - } - - if (lottoNumbers.contains(bonusNumber)) { - throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); - } - } - - public List getLottoNumbers() { - return List.copyOf(lottoNumbers); - } -} diff --git a/src/main/java/lotto/domain/PurchasedLotto.java b/src/main/java/lotto/domain/PurchasedLotto.java new file mode 100644 index 0000000000..e2212b0441 --- /dev/null +++ b/src/main/java/lotto/domain/PurchasedLotto.java @@ -0,0 +1,34 @@ +package lotto.domain; + +import java.util.List; +import java.util.Set; + +public class PurchasedLotto { + + private static final int LOTTO_NUMBER_SIZE = 6; + + private final Set lottoNumbers; + + private PurchasedLotto(final Set lottoNumbers) { + validate(lottoNumbers); + this.lottoNumbers = lottoNumbers; + } + + public static PurchasedLotto of(final Set lottoNumbers) { + return new PurchasedLotto(lottoNumbers); + } + + private static void validate(final Set lottoNumbers) { + validateSize(lottoNumbers); + } + + private static void validateSize(Set lottoNumbers) { + if (lottoNumbers.size() != LOTTO_NUMBER_SIZE) { + throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + } + } + + public Set getLottoNumbers() { + return Set.copyOf(lottoNumbers); + } +} diff --git a/src/main/java/lotto/domain/WinningLotto.java b/src/main/java/lotto/domain/WinningLotto.java new file mode 100644 index 0000000000..665214c807 --- /dev/null +++ b/src/main/java/lotto/domain/WinningLotto.java @@ -0,0 +1,45 @@ +package lotto.domain; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +public class WinningLotto { + + private static final int LOTTO_SIZE = 6; + + private final Set lottoNumbers; + private final LottoNumber bonusNumber; + + private WinningLotto(final Set lottoNumbers, final LottoNumber bonusNumber) { + validate(lottoNumbers, bonusNumber); + this.lottoNumbers = new HashSet<>(lottoNumbers); + this.bonusNumber = bonusNumber; + } + + public static WinningLotto of(final Set lottoNumbers, final LottoNumber bonusNumber) { + return new WinningLotto(lottoNumbers, bonusNumber); + } + + private static void validate(final Set lottoNumbers, final LottoNumber bonusNumber) { + validateSize(lottoNumbers); + validateDuplicate(lottoNumbers, bonusNumber); + } + + private static void validateSize(Set lottoNumbers) { + if (lottoNumbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + } + } + + private static void validateDuplicate(final Set lottoNumbers, final LottoNumber bonusNumber) { + if (lottoNumbers.contains(bonusNumber)) { + throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + } + + public Set getLottoNumbers() { + return Set.copyOf(lottoNumbers); + } +} From 9c14bae0fce0461e7f552ccc2b05bc9803e7daf7 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:12:58 +0900 Subject: [PATCH 10/25] =?UTF-8?q?fix:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/request/LottoPurchaseRequest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/request/LottoPurchaseRequest.java b/src/main/java/lotto/request/LottoPurchaseRequest.java index 85a68d2184..1965a1f5a2 100644 --- a/src/main/java/lotto/request/LottoPurchaseRequest.java +++ b/src/main/java/lotto/request/LottoPurchaseRequest.java @@ -17,7 +17,7 @@ private LottoPurchaseRequest(final int purchaseAmount) { this.purchaseAmount = purchaseAmount; } - public static LottoPurchaseRequest of(final String purchaseAmount) { + public static LottoPurchaseRequest from(final String purchaseAmount) { validate(purchaseAmount); return new LottoPurchaseRequest(Integer.parseInt(purchaseAmount)); } @@ -43,7 +43,7 @@ private static void validatePurchaseAmount(final int purchaseAmount) { } } - public int getPurchaseCount() { + public int calculatePurchaseCount() { return purchaseAmount / UNIT_PURCHASE_AMOUNT; } From c82ab37fcaf133e1e7f853fc70aa85ab541e75e6 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:13:19 +0900 Subject: [PATCH 11/25] =?UTF-8?q?feat:=20ResultView.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/view/ResultView.java | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/lotto/view/ResultView.java diff --git a/src/main/java/lotto/view/ResultView.java b/src/main/java/lotto/view/ResultView.java new file mode 100644 index 0000000000..288d20ba31 --- /dev/null +++ b/src/main/java/lotto/view/ResultView.java @@ -0,0 +1,31 @@ +package lotto.view; + +import lotto.domain.LottoNumber; +import lotto.domain.PurchasedLotto; + +import java.util.List; +import java.util.stream.Collectors; + +public class ResultView { + + private static final String PURCHASE_AMOUNT_MESSAGE = "%d개를 구매했습니다."; + + private ResultView() { + } + + public static void printPurchaseAmount(final int purchaseAmount) { + System.out.println(String.format(PURCHASE_AMOUNT_MESSAGE, purchaseAmount)); + } + + public static void printPurchasedLottos(final List purchasedLottos) { + purchasedLottos.forEach(ResultView::printPurchasedLotto); + } + + private static void printPurchasedLotto(final PurchasedLotto purchasedLotto) { + final List lottoNumbers = purchasedLotto.getLottoNumbers().stream() + .map(LottoNumber::getNumber) + .collect(Collectors.toList()); + + System.out.println(lottoNumbers); + } +} \ No newline at end of file From 0578a1dcf6d2c7e758469e1fc722be3a8ff885b6 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:13:44 +0900 Subject: [PATCH 12/25] =?UTF-8?q?fix:=20linkedHashSet=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/PurchasedLotto.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/domain/PurchasedLotto.java b/src/main/java/lotto/domain/PurchasedLotto.java index e2212b0441..999a802079 100644 --- a/src/main/java/lotto/domain/PurchasedLotto.java +++ b/src/main/java/lotto/domain/PurchasedLotto.java @@ -1,6 +1,6 @@ package lotto.domain; -import java.util.List; +import java.util.LinkedHashSet; import java.util.Set; public class PurchasedLotto { @@ -29,6 +29,6 @@ private static void validateSize(Set lottoNumbers) { } public Set getLottoNumbers() { - return Set.copyOf(lottoNumbers); + return new LinkedHashSet<>(lottoNumbers); } } From 78a4987b4090ebacf55af38d357c8c03976229fb Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:14:25 +0900 Subject: [PATCH 13/25] =?UTF-8?q?feat:=20InputView.java=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/view/InputView.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/lotto/view/InputView.java diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java new file mode 100644 index 0000000000..9355352664 --- /dev/null +++ b/src/main/java/lotto/view/InputView.java @@ -0,0 +1,22 @@ +package lotto.view; + +import lotto.request.LottoPurchaseRequest; +import lotto.utils.Console; + +public class InputView { + + private static final String INPUT_PURCHASE_AMOUNT_MESSAGE = "구입금액을 입력해 주세요."; + private static final String INPUT_LAST_WEEK_WINNING_NUMBERS_MESSAGE = "지난 주 당첨 번호를 입력해 주세요."; + private static final String INPUT_BONUS_BALL_MESSAGE = "보너스 볼을 입력해 주세요."; + + private InputView() { + } + + public static LottoPurchaseRequest inputPurchaseAmount() { + System.out.println(INPUT_PURCHASE_AMOUNT_MESSAGE); + return LottoPurchaseRequest.from(Console.readLine()); + } + + public static void inputLastWeekWinningNumbers() { + } +} From 44303a7497f20ee24c48b62f0930b06d31c8a6cd Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:14:50 +0900 Subject: [PATCH 14/25] =?UTF-8?q?feat:=20Application.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 5f5e2ae3c5..fabcca4dfa 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,8 +1,10 @@ package lotto; +import lotto.controller.LottoMachine; + public class Application { public static void main(String[] args) { - + LottoMachine.run(); } } From 1b508e2cdeb553a366b17423b99e484c5883cc8f Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:15:25 +0900 Subject: [PATCH 15/25] =?UTF-8?q?feat:=20LottoGenerator.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/controller/LottoGenerator.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/main/java/lotto/controller/LottoGenerator.java diff --git a/src/main/java/lotto/controller/LottoGenerator.java b/src/main/java/lotto/controller/LottoGenerator.java new file mode 100644 index 0000000000..68f75272c6 --- /dev/null +++ b/src/main/java/lotto/controller/LottoGenerator.java @@ -0,0 +1,45 @@ +package lotto.controller; + +import lotto.domain.LottoNumber; +import lotto.domain.PurchasedLotto; + +import java.util.*; + +public class LottoGenerator { + + private final List lottoNumbers; + + public LottoGenerator() { + this.lottoNumbers = initializeLottoNumbers(); + } + + private List initializeLottoNumbers() { + final List lottoNumbers = new ArrayList<>(); + for (int i = 1; i <= 45; i++) { + lottoNumbers.add(i); + } + return lottoNumbers; + } + + public List generatePurchasedLottos(final int purchaseCount) { + final List purchasedLottos = new ArrayList<>(); + for (int i = 0; i < purchaseCount; i++) { + purchasedLottos.add(generatePurchasedLotto()); + } + return purchasedLottos; + } + + private PurchasedLotto generatePurchasedLotto() { + final List shuffledNumbers = new ArrayList<>(lottoNumbers); + Collections.shuffle(shuffledNumbers); + + final List generatedLottoNumbers = new ArrayList<>(shuffledNumbers.subList(0, 6)); + Collections.sort(generatedLottoNumbers); + + final List lottoNumbers = generatedLottoNumbers.stream() + .map(LottoNumber::from) + .toList(); + + return PurchasedLotto.of(new LinkedHashSet<>(lottoNumbers)); + } +} From db157cab39e68a01890e198a67373e11948936fd Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:15:50 +0900 Subject: [PATCH 16/25] =?UTF-8?q?feat:=20LottoMachine.java=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/controller/LottoMachine.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/lotto/controller/LottoMachine.java diff --git a/src/main/java/lotto/controller/LottoMachine.java b/src/main/java/lotto/controller/LottoMachine.java new file mode 100644 index 0000000000..429207a0d3 --- /dev/null +++ b/src/main/java/lotto/controller/LottoMachine.java @@ -0,0 +1,39 @@ +package lotto.controller; + +import lotto.domain.PurchasedLotto; +import lotto.request.LottoPurchaseRequest; +import lotto.view.InputView; +import lotto.view.ResultView; + +import java.util.List; + +public class LottoMachine { + + private LottoMachine() { + } + + public static void run() { + final int purchaseCount = inputPurchaseAmount(); + ResultView.printPurchaseAmount(purchaseCount); + generateLottoNumbers(purchaseCount); + + } + + + private static int inputPurchaseAmount() { + final LottoPurchaseRequest lottoPurchaseRequest = InputView.inputPurchaseAmount(); + return lottoPurchaseRequest.calculatePurchaseCount(); + } + + private static void generateLottoNumbers(final int purchaseCount) { + LottoGenerator lottoGenerator = new LottoGenerator(); + final List purchasedLottos = lottoGenerator.generatePurchasedLottos(purchaseCount); + ResultView.printPurchasedLottos(purchasedLottos); + } + + // 지난 주 당첨 번호를 입력받는 메서드 + private static void inputLastWeekWinningNumbers() { + InputView.inputLastWeekWinningNumbers(); + } + +} From b9e2833e68b154fb44d7133a080fce93bfa8ff76 Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:16:38 +0900 Subject: [PATCH 17/25] =?UTF-8?q?feat:=20LottoNumber.java=20=EC=97=90=20ge?= =?UTF-8?q?tter=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoNumber.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java index 8178399260..74413827bf 100644 --- a/src/main/java/lotto/domain/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -24,6 +24,10 @@ private static void validate(final int number) { } } + public int getNumber() { + return number; + } + @Override public boolean equals(Object o) { if (this == o) return true; From 592c58dcea4e89a64ef5eb73483f3a87c718a82c Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 22:55:44 +0900 Subject: [PATCH 18/25] =?UTF-8?q?feat:=20Lotto=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=9D=BC=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/LottoNumbers.java | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/lotto/domain/LottoNumbers.java diff --git a/src/main/java/lotto/domain/LottoNumbers.java b/src/main/java/lotto/domain/LottoNumbers.java new file mode 100644 index 0000000000..8177f00b31 --- /dev/null +++ b/src/main/java/lotto/domain/LottoNumbers.java @@ -0,0 +1,38 @@ +package lotto.domain; + +import java.util.List; +import java.util.Set; + +public class LottoNumbers { + + private static final int LOTTO_NUMBER_SIZE = 6; + + private final List lottoNumbers; + + private LottoNumbers(final List lottoNumbers) { + validateSize(lottoNumbers); + validateDuplicate(lottoNumbers); + this.lottoNumbers = lottoNumbers; + } + + public static LottoNumbers from(final List lottoNumbers) { + return new LottoNumbers(lottoNumbers); + } + + private void validateSize(final List lottoNumbers) { + if (lottoNumbers.size() != LOTTO_NUMBER_SIZE) { + throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + } + } + + private void validateDuplicate(final List lottoNumbers) { + final Set lottoNumberSet = Set.copyOf(lottoNumbers); + if (lottoNumberSet.size() != LOTTO_NUMBER_SIZE) { + throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); + } + } + + public List getLottoNumbers() { + return List.copyOf(lottoNumbers); + } +} From 6cbec13b18a088d6c543e225104d3648f4e5c7ac Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 23:24:37 +0900 Subject: [PATCH 19/25] =?UTF-8?q?fix:=20lottoNumbers=20=EC=9D=BC=EA=B8=89?= =?UTF-8?q?=20=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/controller/LottoGenerator.java | 19 ++++++------- .../java/lotto/controller/LottoMachine.java | 3 +-- src/main/java/lotto/domain/LottoNumbers.java | 26 +++++++++--------- .../java/lotto/domain/PurchasedLotto.java | 27 ++++++++----------- src/main/java/lotto/view/ResultView.java | 8 +++--- 5 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src/main/java/lotto/controller/LottoGenerator.java b/src/main/java/lotto/controller/LottoGenerator.java index 68f75272c6..a9ad1c4942 100644 --- a/src/main/java/lotto/controller/LottoGenerator.java +++ b/src/main/java/lotto/controller/LottoGenerator.java @@ -1,19 +1,22 @@ package lotto.controller; import lotto.domain.LottoNumber; +import lotto.domain.LottoNumbers; import lotto.domain.PurchasedLotto; import java.util.*; public class LottoGenerator { - private final List lottoNumbers; + private static final int LOTTO_NUMBER_SIZE = 6; + + private final List candidateLottoNumbers; public LottoGenerator() { - this.lottoNumbers = initializeLottoNumbers(); + this.candidateLottoNumbers = initializeCandidateNumbers(); } - private List initializeLottoNumbers() { + private List initializeCandidateNumbers() { final List lottoNumbers = new ArrayList<>(); for (int i = 1; i <= 45; i++) { lottoNumbers.add(i); @@ -30,16 +33,14 @@ public List generatePurchasedLottos(final int purchaseCount) { } private PurchasedLotto generatePurchasedLotto() { - final List shuffledNumbers = new ArrayList<>(lottoNumbers); + final List shuffledNumbers = new ArrayList<>(candidateLottoNumbers); Collections.shuffle(shuffledNumbers); - final List generatedLottoNumbers = new ArrayList<>(shuffledNumbers.subList(0, 6)); - Collections.sort(generatedLottoNumbers); - - final List lottoNumbers = generatedLottoNumbers.stream() + final List lottoNumbers = shuffledNumbers.stream() + .limit(LOTTO_NUMBER_SIZE) .map(LottoNumber::from) .toList(); - return PurchasedLotto.of(new LinkedHashSet<>(lottoNumbers)); + return PurchasedLotto.of(LottoNumbers.from(lottoNumbers)); } } diff --git a/src/main/java/lotto/controller/LottoMachine.java b/src/main/java/lotto/controller/LottoMachine.java index 429207a0d3..a40f0f6fff 100644 --- a/src/main/java/lotto/controller/LottoMachine.java +++ b/src/main/java/lotto/controller/LottoMachine.java @@ -19,14 +19,13 @@ public static void run() { } - private static int inputPurchaseAmount() { final LottoPurchaseRequest lottoPurchaseRequest = InputView.inputPurchaseAmount(); return lottoPurchaseRequest.calculatePurchaseCount(); } private static void generateLottoNumbers(final int purchaseCount) { - LottoGenerator lottoGenerator = new LottoGenerator(); + final LottoGenerator lottoGenerator = new LottoGenerator(); final List purchasedLottos = lottoGenerator.generatePurchasedLottos(purchaseCount); ResultView.printPurchasedLottos(purchasedLottos); } diff --git a/src/main/java/lotto/domain/LottoNumbers.java b/src/main/java/lotto/domain/LottoNumbers.java index 8177f00b31..0a42f6a33a 100644 --- a/src/main/java/lotto/domain/LottoNumbers.java +++ b/src/main/java/lotto/domain/LottoNumbers.java @@ -7,32 +7,32 @@ public class LottoNumbers { private static final int LOTTO_NUMBER_SIZE = 6; - private final List lottoNumbers; + private final List numbers; - private LottoNumbers(final List lottoNumbers) { - validateSize(lottoNumbers); - validateDuplicate(lottoNumbers); - this.lottoNumbers = lottoNumbers; + private LottoNumbers(final List numbers) { + validateSize(numbers); + validateDuplicate(numbers); + this.numbers = numbers; } - public static LottoNumbers from(final List lottoNumbers) { - return new LottoNumbers(lottoNumbers); + public static LottoNumbers from(final List numbers) { + return new LottoNumbers(numbers); } - private void validateSize(final List lottoNumbers) { - if (lottoNumbers.size() != LOTTO_NUMBER_SIZE) { + private void validateSize(final List numbers) { + if (numbers.size() != LOTTO_NUMBER_SIZE) { throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); } } - private void validateDuplicate(final List lottoNumbers) { - final Set lottoNumberSet = Set.copyOf(lottoNumbers); + private void validateDuplicate(final List numbers) { + final Set lottoNumberSet = Set.copyOf(numbers); if (lottoNumberSet.size() != LOTTO_NUMBER_SIZE) { throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); } } - public List getLottoNumbers() { - return List.copyOf(lottoNumbers); + public List getNumbers() { + return List.copyOf(numbers); } } diff --git a/src/main/java/lotto/domain/PurchasedLotto.java b/src/main/java/lotto/domain/PurchasedLotto.java index 999a802079..bf08c3bd08 100644 --- a/src/main/java/lotto/domain/PurchasedLotto.java +++ b/src/main/java/lotto/domain/PurchasedLotto.java @@ -1,34 +1,29 @@ package lotto.domain; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.List; +import java.util.Objects; public class PurchasedLotto { - private static final int LOTTO_NUMBER_SIZE = 6; + private final LottoNumbers lottoNumbers; - private final Set lottoNumbers; - - private PurchasedLotto(final Set lottoNumbers) { + private PurchasedLotto(final LottoNumbers lottoNumbers) { validate(lottoNumbers); this.lottoNumbers = lottoNumbers; } - public static PurchasedLotto of(final Set lottoNumbers) { + public static PurchasedLotto of(final LottoNumbers lottoNumbers) { return new PurchasedLotto(lottoNumbers); } - private static void validate(final Set lottoNumbers) { - validateSize(lottoNumbers); - } - - private static void validateSize(Set lottoNumbers) { - if (lottoNumbers.size() != LOTTO_NUMBER_SIZE) { - throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + private static void validate(final LottoNumbers lottoNumbers) { + if (Objects.isNull(lottoNumbers)) { + throw new IllegalArgumentException("lotto numbers must not be null"); } } - public Set getLottoNumbers() { - return new LinkedHashSet<>(lottoNumbers); + public List getLottoNumbers() { + return List.copyOf(lottoNumbers.getNumbers()); } + } diff --git a/src/main/java/lotto/view/ResultView.java b/src/main/java/lotto/view/ResultView.java index 288d20ba31..901de3107d 100644 --- a/src/main/java/lotto/view/ResultView.java +++ b/src/main/java/lotto/view/ResultView.java @@ -3,8 +3,9 @@ import lotto.domain.LottoNumber; import lotto.domain.PurchasedLotto; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; public class ResultView { @@ -22,10 +23,11 @@ public static void printPurchasedLottos(final List purchasedLott } private static void printPurchasedLotto(final PurchasedLotto purchasedLotto) { - final List lottoNumbers = purchasedLotto.getLottoNumbers().stream() + final List lottoNumbers = new ArrayList<>(purchasedLotto.getLottoNumbers().stream() .map(LottoNumber::getNumber) - .collect(Collectors.toList()); + .toList()); + Collections.sort(lottoNumbers); System.out.println(lottoNumbers); } } \ No newline at end of file From 702fb80caa96a54f0dd03e32cb2ee4d67c56492e Mon Sep 17 00:00:00 2001 From: rueun Date: Sun, 19 May 2024 23:35:23 +0900 Subject: [PATCH 20/25] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EA=B0=9D=EC=B2=B4=20=EC=9D=BC=EA=B8=89=20=EC=BB=AC?= =?UTF-8?q?=EB=A0=89=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/controller/LottoGenerator.java | 2 +- .../java/lotto/domain/PurchasedLotto.java | 2 +- src/main/java/lotto/domain/WinningLotto.java | 35 ++++++------------- 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/main/java/lotto/controller/LottoGenerator.java b/src/main/java/lotto/controller/LottoGenerator.java index a9ad1c4942..a478306dc6 100644 --- a/src/main/java/lotto/controller/LottoGenerator.java +++ b/src/main/java/lotto/controller/LottoGenerator.java @@ -41,6 +41,6 @@ private PurchasedLotto generatePurchasedLotto() { .map(LottoNumber::from) .toList(); - return PurchasedLotto.of(LottoNumbers.from(lottoNumbers)); + return PurchasedLotto.from(LottoNumbers.from(lottoNumbers)); } } diff --git a/src/main/java/lotto/domain/PurchasedLotto.java b/src/main/java/lotto/domain/PurchasedLotto.java index bf08c3bd08..e62b92582a 100644 --- a/src/main/java/lotto/domain/PurchasedLotto.java +++ b/src/main/java/lotto/domain/PurchasedLotto.java @@ -12,7 +12,7 @@ private PurchasedLotto(final LottoNumbers lottoNumbers) { this.lottoNumbers = lottoNumbers; } - public static PurchasedLotto of(final LottoNumbers lottoNumbers) { + public static PurchasedLotto from(final LottoNumbers lottoNumbers) { return new PurchasedLotto(lottoNumbers); } diff --git a/src/main/java/lotto/domain/WinningLotto.java b/src/main/java/lotto/domain/WinningLotto.java index 665214c807..ff8069097c 100644 --- a/src/main/java/lotto/domain/WinningLotto.java +++ b/src/main/java/lotto/domain/WinningLotto.java @@ -1,45 +1,32 @@ package lotto.domain; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.TreeSet; public class WinningLotto { - - private static final int LOTTO_SIZE = 6; - - private final Set lottoNumbers; + private final LottoNumbers lottoNumbers; private final LottoNumber bonusNumber; - private WinningLotto(final Set lottoNumbers, final LottoNumber bonusNumber) { + private WinningLotto(final LottoNumbers lottoNumbers, final LottoNumber bonusNumber) { validate(lottoNumbers, bonusNumber); - this.lottoNumbers = new HashSet<>(lottoNumbers); + this.lottoNumbers = lottoNumbers; this.bonusNumber = bonusNumber; } - public static WinningLotto of(final Set lottoNumbers, final LottoNumber bonusNumber) { + public static WinningLotto of(final LottoNumbers lottoNumbers, final LottoNumber bonusNumber) { return new WinningLotto(lottoNumbers, bonusNumber); } - private static void validate(final Set lottoNumbers, final LottoNumber bonusNumber) { - validateSize(lottoNumbers); - validateDuplicate(lottoNumbers, bonusNumber); - } - - private static void validateSize(Set lottoNumbers) { - if (lottoNumbers.size() != LOTTO_SIZE) { - throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); + public static void validate(final LottoNumbers lottoNumbers, final LottoNumber bonusNumber) { + if (lottoNumbers.getNumbers().contains(bonusNumber)) { + throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); } } - private static void validateDuplicate(final Set lottoNumbers, final LottoNumber bonusNumber) { - if (lottoNumbers.contains(bonusNumber)) { - throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); - } + public List getLottoNumbers() { + return List.copyOf(lottoNumbers.getNumbers()); } - public Set getLottoNumbers() { - return Set.copyOf(lottoNumbers); + public LottoNumber getBonusNumber() { + return bonusNumber; } } From 177d249fc3841c455b36b6a52ded8d22f65df85c Mon Sep 17 00:00:00 2001 From: rueun Date: Mon, 20 May 2024 00:03:37 +0900 Subject: [PATCH 21/25] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=20request=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/LastWeekBonusNumberRequest.java | 30 +++++++++++++++ .../request/LastWeekWinningLottoRequest.java | 37 +++++++++++++++++++ .../java/lotto/utils/CommaNumberSplitter.java | 21 +++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/main/java/lotto/request/LastWeekBonusNumberRequest.java create mode 100644 src/main/java/lotto/request/LastWeekWinningLottoRequest.java create mode 100644 src/main/java/lotto/utils/CommaNumberSplitter.java diff --git a/src/main/java/lotto/request/LastWeekBonusNumberRequest.java b/src/main/java/lotto/request/LastWeekBonusNumberRequest.java new file mode 100644 index 0000000000..af64b0bcce --- /dev/null +++ b/src/main/java/lotto/request/LastWeekBonusNumberRequest.java @@ -0,0 +1,30 @@ +package lotto.request; + +import java.util.Objects; + +public class LastWeekBonusNumberRequest { + + private static final String INPUT_PATTERN = "^\\d+$"; + private static final String ERROR_INPUT_PATTERN = "[ERROR] 보너스 볼은 숫자로 입력해야 합니다."; + + private final int bonusNumber; + + private LastWeekBonusNumberRequest(final int bonusNumber) { + this.bonusNumber = bonusNumber; + } + + public static LastWeekBonusNumberRequest from(final String bonusNumber) { + validateInputPattern(bonusNumber); + return new LastWeekBonusNumberRequest(Integer.parseInt(bonusNumber)); + } + + private static void validateInputPattern(final String bonusNumber) { + if (Objects.isNull(bonusNumber) || !bonusNumber.matches(INPUT_PATTERN)) { + throw new IllegalArgumentException(ERROR_INPUT_PATTERN); + } + } + + public int getBonusNumber() { + return bonusNumber; + } +} diff --git a/src/main/java/lotto/request/LastWeekWinningLottoRequest.java b/src/main/java/lotto/request/LastWeekWinningLottoRequest.java new file mode 100644 index 0000000000..d3355b344a --- /dev/null +++ b/src/main/java/lotto/request/LastWeekWinningLottoRequest.java @@ -0,0 +1,37 @@ +package lotto.request; + +import lotto.utils.CommaNumberSplitter; +import lotto.utils.PatternUtil; + +import java.util.List; + +public class LastWeekWinningLottoRequest { + + private static final String INPUT_PATTERN = "^\\d+(,\\d+)$"; + private static final String ERROR_LOTTO_INPUT_PATTERN = "[ERROR] 로또 번호는 ,로 구분된 숫자여야 합니다."; + + private final List lottoNumbers; + + private LastWeekWinningLottoRequest(final List lottoNumbers) { + this.lottoNumbers = lottoNumbers; + } + + public static LastWeekWinningLottoRequest from(final String lastWeekWinningNumbers) { + validateInputPattern(lastWeekWinningNumbers); + return new LastWeekWinningLottoRequest(parseLottoNumbers(lastWeekWinningNumbers)); + } + + private static void validateInputPattern(final String lastWeekWinningNumbers) { + if (!PatternUtil.isMatched(lastWeekWinningNumbers, INPUT_PATTERN)) { + throw new IllegalArgumentException(ERROR_LOTTO_INPUT_PATTERN); + } + } + + private static List parseLottoNumbers(final String lastWeekWinningNumbers) { + return CommaNumberSplitter.split(lastWeekWinningNumbers); + } + + public List getLottoNumbers() { + return List.copyOf(lottoNumbers); + } +} diff --git a/src/main/java/lotto/utils/CommaNumberSplitter.java b/src/main/java/lotto/utils/CommaNumberSplitter.java new file mode 100644 index 0000000000..8bdec44551 --- /dev/null +++ b/src/main/java/lotto/utils/CommaNumberSplitter.java @@ -0,0 +1,21 @@ +package lotto.utils; + +import java.util.Arrays; +import java.util.List; + +public class CommaNumberSplitter { + private static final String DELIMITER = ","; + + private CommaNumberSplitter() { + } + + public static List split(final String str) { + if (StringUtil.isBlank(str)) { + throw new IllegalArgumentException("split string must not be blank"); + } + + return Arrays.stream(str.split(DELIMITER)) + .map(Integer::parseInt) + .toList(); + } +} From 7ff9e65a30f0585d59bf9dca42eb30cb4cb3bd87 Mon Sep 17 00:00:00 2001 From: rueun Date: Mon, 20 May 2024 02:35:53 +0900 Subject: [PATCH 22/25] =?UTF-8?q?feat:=20=EA=B0=81=20prize=20=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EB=8A=94=20printer=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/constrant/LottoConstant.java | 10 +++ .../java/lotto/controller/LottoMachine.java | 28 ++++++-- src/main/java/lotto/domain/LottoNumber.java | 8 +-- src/main/java/lotto/domain/LottoNumbers.java | 14 +++- .../java/lotto/domain/PurchasedLotto.java | 7 ++ src/main/java/lotto/domain/prize/Prize.java | 40 ++++++++++++ .../java/lotto/domain/prize/PrizeResult.java | 64 +++++++++++++++++++ .../request/LastWeekBonusNumberRequest.java | 30 --------- .../request/LastWeekWinningLottoRequest.java | 35 ++++++++-- .../lotto/request/LottoPurchaseRequest.java | 19 +++--- .../java/lotto/utils/CommaNumberSplitter.java | 1 + src/main/java/lotto/view/InputView.java | 8 ++- src/main/java/lotto/view/ResultView.java | 24 +++++++ .../view/printer/DefaultPrizePrinter.java | 11 ++++ .../java/lotto/view/printer/PrizePrinter.java | 5 ++ .../view/printer/PrizePrinterFactory.java | 20 ++++++ .../view/printer/SecondPrizePrinter.java | 11 ++++ 17 files changed, 277 insertions(+), 58 deletions(-) create mode 100644 src/main/java/lotto/constrant/LottoConstant.java create mode 100644 src/main/java/lotto/domain/prize/Prize.java create mode 100644 src/main/java/lotto/domain/prize/PrizeResult.java delete mode 100644 src/main/java/lotto/request/LastWeekBonusNumberRequest.java create mode 100644 src/main/java/lotto/view/printer/DefaultPrizePrinter.java create mode 100644 src/main/java/lotto/view/printer/PrizePrinter.java create mode 100644 src/main/java/lotto/view/printer/PrizePrinterFactory.java create mode 100644 src/main/java/lotto/view/printer/SecondPrizePrinter.java diff --git a/src/main/java/lotto/constrant/LottoConstant.java b/src/main/java/lotto/constrant/LottoConstant.java new file mode 100644 index 0000000000..33b33ae3e1 --- /dev/null +++ b/src/main/java/lotto/constrant/LottoConstant.java @@ -0,0 +1,10 @@ +package lotto.constrant; + +public class LottoConstant { + private LottoConstant() { + } + public static final int LOTTO_PRICE = 1000; + public static final int LOTTO_NUMBER_SIZE = 6; + public static final int MIN_LOTTO_NUMBER = 1; + public static final int MAX_LOTTO_NUMBER = 45; +} diff --git a/src/main/java/lotto/controller/LottoMachine.java b/src/main/java/lotto/controller/LottoMachine.java index a40f0f6fff..7a7e15a362 100644 --- a/src/main/java/lotto/controller/LottoMachine.java +++ b/src/main/java/lotto/controller/LottoMachine.java @@ -1,6 +1,9 @@ package lotto.controller; import lotto.domain.PurchasedLotto; +import lotto.domain.WinningLotto; +import lotto.domain.prize.PrizeResult; +import lotto.request.LastWeekWinningLottoRequest; import lotto.request.LottoPurchaseRequest; import lotto.view.InputView; import lotto.view.ResultView; @@ -14,9 +17,12 @@ private LottoMachine() { public static void run() { final int purchaseCount = inputPurchaseAmount(); - ResultView.printPurchaseAmount(purchaseCount); - generateLottoNumbers(purchaseCount); + printPurchaseAmount(purchaseCount); + final List purchasedLottos = generateLottoNumbers(purchaseCount); + final WinningLotto winningLotto = inputLastWeekWinningNumbers(); + + printWinningStatistics(purchasedLottos, winningLotto); } private static int inputPurchaseAmount() { @@ -24,15 +30,25 @@ private static int inputPurchaseAmount() { return lottoPurchaseRequest.calculatePurchaseCount(); } - private static void generateLottoNumbers(final int purchaseCount) { + private static List generateLottoNumbers(final int purchaseCount) { final LottoGenerator lottoGenerator = new LottoGenerator(); final List purchasedLottos = lottoGenerator.generatePurchasedLottos(purchaseCount); ResultView.printPurchasedLottos(purchasedLottos); + return purchasedLottos; + } + + private static WinningLotto inputLastWeekWinningNumbers() { + final LastWeekWinningLottoRequest lastWeekWinningLottoRequest = InputView.inputLastWeekWinningNumbers(); + return lastWeekWinningLottoRequest.generateWinningLotto(); + } + + private static void printPurchaseAmount(final int purchaseAmount) { + ResultView.printPurchaseAmount(purchaseAmount); } - // 지난 주 당첨 번호를 입력받는 메서드 - private static void inputLastWeekWinningNumbers() { - InputView.inputLastWeekWinningNumbers(); + private static void printWinningStatistics(final List purchasedLottos, final WinningLotto winningLotto) { + final PrizeResult prizeResult = PrizeResult.from(purchasedLottos, winningLotto); + ResultView.printWinningStatistics(prizeResult); } } diff --git a/src/main/java/lotto/domain/LottoNumber.java b/src/main/java/lotto/domain/LottoNumber.java index 74413827bf..157193c0b4 100644 --- a/src/main/java/lotto/domain/LottoNumber.java +++ b/src/main/java/lotto/domain/LottoNumber.java @@ -2,10 +2,10 @@ import java.util.Objects; -public class LottoNumber { +import static lotto.constrant.LottoConstant.MAX_LOTTO_NUMBER; +import static lotto.constrant.LottoConstant.MIN_LOTTO_NUMBER; - private static final int MIN_NUMBER = 1; - private static final int MAX_NUMBER = 45; +public class LottoNumber { private final int number; @@ -19,7 +19,7 @@ public static LottoNumber from(final int number) { } private static void validate(final int number) { - if (number < MIN_NUMBER || number > MAX_NUMBER) { + if (number < MIN_LOTTO_NUMBER || number > MAX_LOTTO_NUMBER) { throw new IllegalArgumentException("로또 번호는 1부터 45까지의 숫자만 가능합니다."); } } diff --git a/src/main/java/lotto/domain/LottoNumbers.java b/src/main/java/lotto/domain/LottoNumbers.java index 0a42f6a33a..8ef3d28455 100644 --- a/src/main/java/lotto/domain/LottoNumbers.java +++ b/src/main/java/lotto/domain/LottoNumbers.java @@ -3,9 +3,9 @@ import java.util.List; import java.util.Set; -public class LottoNumbers { +import static lotto.constrant.LottoConstant.LOTTO_NUMBER_SIZE; - private static final int LOTTO_NUMBER_SIZE = 6; +public class LottoNumbers { private final List numbers; @@ -35,4 +35,14 @@ private void validateDuplicate(final List numbers) { public List getNumbers() { return List.copyOf(numbers); } + + public int calculateMatchCounts(final List winningNumbers) { + return (int) numbers.stream() + .filter(winningNumbers::contains) + .count(); + } + + public boolean containsBonusNumber(final LottoNumber bonusNumber) { + return numbers.contains(bonusNumber); + } } diff --git a/src/main/java/lotto/domain/PurchasedLotto.java b/src/main/java/lotto/domain/PurchasedLotto.java index e62b92582a..36ac78edc7 100644 --- a/src/main/java/lotto/domain/PurchasedLotto.java +++ b/src/main/java/lotto/domain/PurchasedLotto.java @@ -26,4 +26,11 @@ public List getLottoNumbers() { return List.copyOf(lottoNumbers.getNumbers()); } + public int calculateMatchCounts(final WinningLotto winningLotto) { + return lottoNumbers.calculateMatchCounts(winningLotto.getLottoNumbers()); + } + + public boolean containsBonusNumber(final WinningLotto winningLotto) { + return lottoNumbers.containsBonusNumber(winningLotto.getBonusNumber()); + } } diff --git a/src/main/java/lotto/domain/prize/Prize.java b/src/main/java/lotto/domain/prize/Prize.java new file mode 100644 index 0000000000..b7ff27e3ca --- /dev/null +++ b/src/main/java/lotto/domain/prize/Prize.java @@ -0,0 +1,40 @@ +package lotto.domain.prize; + +public enum Prize { + NONE(0, false, 0), + FIFTH(3, false, 5000), + FOURTH(4, false, 50000), + THIRD(5, false, 1500000), + SECOND(5, true, 30000000), + FIRST(6, false, 2000000000); + + private final int matchCount; + private final boolean matchBonus; + private final int money; + + Prize(final int matchCount, final boolean matchBonus, final int money) { + this.matchCount = matchCount; + this.matchBonus = matchBonus; + this.money = money; + } + + public static Prize of(final int matchCount, final boolean matchBonus) { + if (matchCount == SECOND.matchCount && matchBonus) { + return SECOND; + } + for (final Prize prize : values()) { + if (prize.matchCount == matchCount) { + return prize; + } + } + return NONE; + } + + public int getMatchCount() { + return matchCount; + } + + public int getMoney() { + return money; + } +} diff --git a/src/main/java/lotto/domain/prize/PrizeResult.java b/src/main/java/lotto/domain/prize/PrizeResult.java new file mode 100644 index 0000000000..d0ee8fa563 --- /dev/null +++ b/src/main/java/lotto/domain/prize/PrizeResult.java @@ -0,0 +1,64 @@ +package lotto.domain.prize; + +import lotto.constrant.LottoConstant; +import lotto.domain.PurchasedLotto; +import lotto.domain.WinningLotto; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class PrizeResult { + private final Map prizeCounts; + + private PrizeResult() { + prizeCounts = new EnumMap<>(Prize.class); + initializeCounts(); + } + + private void initializeCounts() { + Arrays.stream(Prize.values()) + .forEach(prize -> prizeCounts.put(prize, 0)); + } + + public static PrizeResult from(final List purchasedLottos, final WinningLotto winningLotto) { + final PrizeResult prizeResult = new PrizeResult(); + purchasedLottos.forEach(purchasedLotto -> prizeResult.calculateAndRecordPrize(purchasedLotto, winningLotto)); + return prizeResult; + } + + private void calculateAndRecordPrize(final PurchasedLotto purchasedLotto, final WinningLotto winningLotto) { + final int matchCount = purchasedLotto.calculateMatchCounts(winningLotto); + final boolean isContainBonusNumber = purchasedLotto.containsBonusNumber(winningLotto); + + final Prize prize = Prize.of(matchCount, isContainBonusNumber); + prizeCounts.put(prize, prizeCounts.get(prize) + 1); + } + + public Map getPrizeCounts() { + return prizeCounts; + } + + public double calculateEarningRate() { + final long totalPrize = calculateTotalPrize(); + final long totalPurchaseAmount = calculateTotalPurchaseAmount(); + final double earningRate = (double) totalPrize / totalPurchaseAmount; + return Math.floor(earningRate * 100) / 100.0; + } + + + private long calculateTotalPrize() { + return prizeCounts.entrySet().stream() + .mapToInt(entry -> entry.getKey().getMoney() * entry.getValue()) + .sum(); + } + + private long calculateTotalPurchaseAmount() { + final long totalPurchaseCount = prizeCounts.values().stream() + .mapToLong(Integer::longValue) + .sum(); + + return totalPurchaseCount * LottoConstant.LOTTO_PRICE; + } +} diff --git a/src/main/java/lotto/request/LastWeekBonusNumberRequest.java b/src/main/java/lotto/request/LastWeekBonusNumberRequest.java deleted file mode 100644 index af64b0bcce..0000000000 --- a/src/main/java/lotto/request/LastWeekBonusNumberRequest.java +++ /dev/null @@ -1,30 +0,0 @@ -package lotto.request; - -import java.util.Objects; - -public class LastWeekBonusNumberRequest { - - private static final String INPUT_PATTERN = "^\\d+$"; - private static final String ERROR_INPUT_PATTERN = "[ERROR] 보너스 볼은 숫자로 입력해야 합니다."; - - private final int bonusNumber; - - private LastWeekBonusNumberRequest(final int bonusNumber) { - this.bonusNumber = bonusNumber; - } - - public static LastWeekBonusNumberRequest from(final String bonusNumber) { - validateInputPattern(bonusNumber); - return new LastWeekBonusNumberRequest(Integer.parseInt(bonusNumber)); - } - - private static void validateInputPattern(final String bonusNumber) { - if (Objects.isNull(bonusNumber) || !bonusNumber.matches(INPUT_PATTERN)) { - throw new IllegalArgumentException(ERROR_INPUT_PATTERN); - } - } - - public int getBonusNumber() { - return bonusNumber; - } -} diff --git a/src/main/java/lotto/request/LastWeekWinningLottoRequest.java b/src/main/java/lotto/request/LastWeekWinningLottoRequest.java index d3355b344a..45b04d216a 100644 --- a/src/main/java/lotto/request/LastWeekWinningLottoRequest.java +++ b/src/main/java/lotto/request/LastWeekWinningLottoRequest.java @@ -1,24 +1,34 @@ package lotto.request; +import lotto.domain.LottoNumber; +import lotto.domain.LottoNumbers; +import lotto.domain.WinningLotto; import lotto.utils.CommaNumberSplitter; import lotto.utils.PatternUtil; import java.util.List; +import java.util.Objects; public class LastWeekWinningLottoRequest { - private static final String INPUT_PATTERN = "^\\d+(,\\d+)$"; + private static final String INPUT_PATTERN = "^\\d+(\\s*,\\s*\\d+)*$"; private static final String ERROR_LOTTO_INPUT_PATTERN = "[ERROR] 로또 번호는 ,로 구분된 숫자여야 합니다."; + private static final String BONUS_INPUT_PATTERN = "^\\d+$"; + private static final String ERROR_BONUS_INPUT_PATTERN = "[ERROR] 보너스 볼은 숫자로 입력해야 합니다."; + private final List lottoNumbers; + private final int bonusNumber; - private LastWeekWinningLottoRequest(final List lottoNumbers) { + private LastWeekWinningLottoRequest(final List lottoNumbers, final int bonusNumber) { this.lottoNumbers = lottoNumbers; + this.bonusNumber = bonusNumber; } - public static LastWeekWinningLottoRequest from(final String lastWeekWinningNumbers) { + public static LastWeekWinningLottoRequest from(final String lastWeekWinningNumbers, final String bonusNumber) { validateInputPattern(lastWeekWinningNumbers); - return new LastWeekWinningLottoRequest(parseLottoNumbers(lastWeekWinningNumbers)); + validateBonusInputPattern(bonusNumber); + return new LastWeekWinningLottoRequest(parseLottoNumbers(lastWeekWinningNumbers), Integer.parseInt(bonusNumber)); } private static void validateInputPattern(final String lastWeekWinningNumbers) { @@ -27,11 +37,24 @@ private static void validateInputPattern(final String lastWeekWinningNumbers) { } } + private static void validateBonusInputPattern(final String bonusNumber) { + if (Objects.isNull(bonusNumber) || !bonusNumber.matches(BONUS_INPUT_PATTERN)) { + throw new IllegalArgumentException(ERROR_BONUS_INPUT_PATTERN); + } + } + private static List parseLottoNumbers(final String lastWeekWinningNumbers) { return CommaNumberSplitter.split(lastWeekWinningNumbers); } - public List getLottoNumbers() { - return List.copyOf(lottoNumbers); + + public WinningLotto generateWinningLotto() { + final LottoNumbers generatedLottoNumbers = LottoNumbers.from(this.lottoNumbers.stream() + .map(LottoNumber::from) + .toList()); + + final LottoNumber generatedBonusNumber = LottoNumber.from(this.bonusNumber); + + return WinningLotto.of(generatedLottoNumbers, generatedBonusNumber); } } diff --git a/src/main/java/lotto/request/LottoPurchaseRequest.java b/src/main/java/lotto/request/LottoPurchaseRequest.java index 1965a1f5a2..fe684578ac 100644 --- a/src/main/java/lotto/request/LottoPurchaseRequest.java +++ b/src/main/java/lotto/request/LottoPurchaseRequest.java @@ -2,14 +2,15 @@ import lotto.utils.PatternUtil; +import static lotto.constrant.LottoConstant.LOTTO_PRICE; + public class LottoPurchaseRequest { - private static final int MIN_PURCHASE_AMOUNT = 1000; - private static final int UNIT_PURCHASE_AMOUNT = 1000; private static final String PURCHASE_AMOUNT_REGEX = "^[0-9]*$"; private static final String ERROR_PURCHASE_AMOUNT_NOT_A_NUMBER = "[ERROR] 구입 금액은 숫자여야 합니다."; - private static final String ERROR_PURCHASE_AMOUNT_TOO_LOW = "[ERROR] 구입 금액은 1000원 이상이어야 합니다."; - private static final String ERROR_PURCHASE_AMOUNT_NOT_MULTIPLE_OF_1000 = "[ERROR] 구입 금액은 1000원 단위여야 합니다."; + private static final String ERROR_PURCHASE_AMOUNT_TOO_LOW = "[ERROR] 구입 금액은 %d원 이상이어야 합니다."; + private static final String ERROR_PURCHASE_AMOUNT_NOT_MULTIPLE_OF_LOTTO_PRICE = "[ERROR] 로또 구입 금액은 %d원 단위여야 합니다."; + private final int purchaseAmount; @@ -34,17 +35,17 @@ private static void validateInputPattern(final String purchaseAmount) { } private static void validatePurchaseAmount(final int purchaseAmount) { - if (purchaseAmount < MIN_PURCHASE_AMOUNT) { - throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_TOO_LOW); + if (purchaseAmount < LOTTO_PRICE) { + throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_TOO_LOW.formatted(LOTTO_PRICE)); } - if (purchaseAmount % UNIT_PURCHASE_AMOUNT != 0) { - throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_NOT_MULTIPLE_OF_1000); + if (purchaseAmount % LOTTO_PRICE != 0) { + throw new IllegalArgumentException(ERROR_PURCHASE_AMOUNT_NOT_MULTIPLE_OF_LOTTO_PRICE.formatted(LOTTO_PRICE)); } } public int calculatePurchaseCount() { - return purchaseAmount / UNIT_PURCHASE_AMOUNT; + return purchaseAmount / LOTTO_PRICE; } } diff --git a/src/main/java/lotto/utils/CommaNumberSplitter.java b/src/main/java/lotto/utils/CommaNumberSplitter.java index 8bdec44551..e85fb7fb12 100644 --- a/src/main/java/lotto/utils/CommaNumberSplitter.java +++ b/src/main/java/lotto/utils/CommaNumberSplitter.java @@ -15,6 +15,7 @@ public static List split(final String str) { } return Arrays.stream(str.split(DELIMITER)) + .map(String::trim) .map(Integer::parseInt) .toList(); } diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java index 9355352664..16d1c21313 100644 --- a/src/main/java/lotto/view/InputView.java +++ b/src/main/java/lotto/view/InputView.java @@ -1,5 +1,6 @@ package lotto.view; +import lotto.request.LastWeekWinningLottoRequest; import lotto.request.LottoPurchaseRequest; import lotto.utils.Console; @@ -17,6 +18,11 @@ public static LottoPurchaseRequest inputPurchaseAmount() { return LottoPurchaseRequest.from(Console.readLine()); } - public static void inputLastWeekWinningNumbers() { + public static LastWeekWinningLottoRequest inputLastWeekWinningNumbers() { + System.out.println(INPUT_LAST_WEEK_WINNING_NUMBERS_MESSAGE); + final String lastWeekWinningNumbers = Console.readLine(); + System.out.println(INPUT_BONUS_BALL_MESSAGE); + final String bonusNumber = Console.readLine(); + return LastWeekWinningLottoRequest.from(lastWeekWinningNumbers, bonusNumber); } } diff --git a/src/main/java/lotto/view/ResultView.java b/src/main/java/lotto/view/ResultView.java index 901de3107d..a8afb019cb 100644 --- a/src/main/java/lotto/view/ResultView.java +++ b/src/main/java/lotto/view/ResultView.java @@ -2,6 +2,10 @@ import lotto.domain.LottoNumber; import lotto.domain.PurchasedLotto; +import lotto.domain.prize.Prize; +import lotto.domain.prize.PrizeResult; +import lotto.view.printer.PrizePrinterFactory; +import lotto.view.printer.PrizePrinter; import java.util.ArrayList; import java.util.Collections; @@ -11,6 +15,10 @@ public class ResultView { private static final String PURCHASE_AMOUNT_MESSAGE = "%d개를 구매했습니다."; + private static final String WINNING_STATISTICS_MESSAGE = "당첨 통계"; + private static final String WINNING_STATISTICS_SEPARATOR = "---------"; + private static final String TOTAL_EARNING_RATE = "총 수익률은 %.2f입니다."; + private ResultView() { } @@ -30,4 +38,20 @@ private static void printPurchasedLotto(final PurchasedLotto purchasedLotto) { Collections.sort(lottoNumbers); System.out.println(lottoNumbers); } + + public static void printWinningStatistics(final PrizeResult prizeResult) { + System.out.println(WINNING_STATISTICS_MESSAGE); + System.out.println(WINNING_STATISTICS_SEPARATOR); + + prizeResult.getPrizeCounts().forEach((prize, count) -> { + if (prize == Prize.NONE) { + return; + } + + final PrizePrinter prizePrinter = PrizePrinterFactory.generatePrinter(prize); + prizePrinter.print(prize.getMatchCount(), prize.getMoney(), count); + }); + + System.out.println(String.format(TOTAL_EARNING_RATE, prizeResult.calculateEarningRate())); + } } \ No newline at end of file diff --git a/src/main/java/lotto/view/printer/DefaultPrizePrinter.java b/src/main/java/lotto/view/printer/DefaultPrizePrinter.java new file mode 100644 index 0000000000..e90fee9069 --- /dev/null +++ b/src/main/java/lotto/view/printer/DefaultPrizePrinter.java @@ -0,0 +1,11 @@ +package lotto.view.printer; + +public class DefaultPrizePrinter implements PrizePrinter { + + private static final String WINNING_STATISTICS_FORMAT = "%d개 일치 (%d원)- %d개"; + + @Override + public void print(final int matchCount, final int money, final int count) { + System.out.println(String.format(WINNING_STATISTICS_FORMAT, matchCount, money, count)); + } +} \ No newline at end of file diff --git a/src/main/java/lotto/view/printer/PrizePrinter.java b/src/main/java/lotto/view/printer/PrizePrinter.java new file mode 100644 index 0000000000..fc5ac37d82 --- /dev/null +++ b/src/main/java/lotto/view/printer/PrizePrinter.java @@ -0,0 +1,5 @@ +package lotto.view.printer; + +public interface PrizePrinter { + void print(int matchCount, int money, int count); +} \ No newline at end of file diff --git a/src/main/java/lotto/view/printer/PrizePrinterFactory.java b/src/main/java/lotto/view/printer/PrizePrinterFactory.java new file mode 100644 index 0000000000..a864a2652f --- /dev/null +++ b/src/main/java/lotto/view/printer/PrizePrinterFactory.java @@ -0,0 +1,20 @@ +package lotto.view.printer; + +import lotto.domain.prize.Prize; + +import java.util.EnumMap; +import java.util.Map; + +public class PrizePrinterFactory { + private static final Map printers = new EnumMap<>(Prize.class); + + private PrizePrinterFactory() {} + + static { + printers.put(Prize.SECOND, new SecondPrizePrinter()); + } + + public static PrizePrinter generatePrinter(final Prize prize) { + return printers.getOrDefault(prize, new DefaultPrizePrinter()); + } +} \ No newline at end of file diff --git a/src/main/java/lotto/view/printer/SecondPrizePrinter.java b/src/main/java/lotto/view/printer/SecondPrizePrinter.java new file mode 100644 index 0000000000..c0c55c2324 --- /dev/null +++ b/src/main/java/lotto/view/printer/SecondPrizePrinter.java @@ -0,0 +1,11 @@ +package lotto.view.printer; + +public class SecondPrizePrinter implements PrizePrinter { + + private static final String BONUS_BALL_FORMAT = "%d개 일치, 보너스 볼 일치 (%d원) - %d개"; + + @Override + public void print(final int matchCount, final int money, final int count) { + System.out.println(String.format(BONUS_BALL_FORMAT, matchCount, money, count)); + } +} \ No newline at end of file From 17395be1a8b316422cc02f0e372e676646ce99e8 Mon Sep 17 00:00:00 2001 From: rueun Date: Mon, 20 May 2024 02:53:49 +0900 Subject: [PATCH 23/25] =?UTF-8?q?test:=20LottoNumbersTest.java,=20LottoNum?= =?UTF-8?q?berTest.java=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/domain/LottoNumberTest.java | 30 ++++++++ .../java/lotto/domain/LottoNumbersTest.java | 68 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/test/java/lotto/domain/LottoNumberTest.java create mode 100644 src/test/java/lotto/domain/LottoNumbersTest.java diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java new file mode 100644 index 0000000000..db025a43e7 --- /dev/null +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -0,0 +1,30 @@ +package lotto.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.*; + +class LottoNumberTest { + + @ParameterizedTest + @DisplayName("로또 번호 생성") + @ValueSource(ints = {1, 45}) + void createLottoNumber(int number) { + // when + LottoNumber lottoNumber = LottoNumber.from(number); + + // then + assertEquals(number, lottoNumber.getNumber()); + } + + @ParameterizedTest + @DisplayName("로또 번호 생성 실패") + @ValueSource(ints = {0, 46}) + void createLottoNumberFail(int number) { + // when & then + assertThrows(IllegalArgumentException.class, () -> LottoNumber.from(number)) + .getMessage().equals("로또 번호는 1부터 45까지의 숫자만 가능합니다."); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/LottoNumbersTest.java b/src/test/java/lotto/domain/LottoNumbersTest.java new file mode 100644 index 0000000000..2008a5d79b --- /dev/null +++ b/src/test/java/lotto/domain/LottoNumbersTest.java @@ -0,0 +1,68 @@ +package lotto.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class LottoNumbersTest { + + @Test + @DisplayName("로또 번호 생성") + void createLottoNumbers() { + // given + List numbers = Arrays.asList( + LottoNumber.from(1), + LottoNumber.from(2), + LottoNumber.from(3), + LottoNumber.from(4), + LottoNumber.from(5), + LottoNumber.from(6) + ); + + // when + LottoNumbers lottoNumbers = LottoNumbers.from(numbers); + + // then + assertEquals(numbers, lottoNumbers.getNumbers()); + } + + @Test + @DisplayName("로또 번호 생성 실패: 로또 번호가 6개가 아닌 경우") + void createLottoNumbersFailSize() { + // given + List numbers = Arrays.asList( + LottoNumber.from(1), + LottoNumber.from(2), + LottoNumber.from(3), + LottoNumber.from(4), + LottoNumber.from(5) + ); + + // when & then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> LottoNumbers.from(numbers)); + assertEquals("로또 번호는 6개여야 합니다.", exception.getMessage()); + } + + @Test + @DisplayName("로또 번호 생성 실패: 로또 번호가 중복되는 경우") + void createLottoNumbersFailDuplicate() { + // given + List numbers = Arrays.asList( + LottoNumber.from(1), + LottoNumber.from(2), + LottoNumber.from(3), + LottoNumber.from(4), + LottoNumber.from(5), + LottoNumber.from(5) + ); + + // when & then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> LottoNumbers.from(numbers)); + assertEquals("로또 번호는 중복될 수 없습니다.", exception.getMessage()); + } +} \ No newline at end of file From 1daa85ecf284b70d5d744e6865a28a0fe7cb3387 Mon Sep 17 00:00:00 2001 From: rueun Date: Mon, 20 May 2024 03:14:02 +0900 Subject: [PATCH 24/25] =?UTF-8?q?fix:=20=EB=A1=9C=EB=98=90=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/domain/PurchasedLotto.java | 13 ++----------- src/main/java/lotto/domain/prize/PrizeResult.java | 9 +++++---- src/main/java/lotto/view/ResultView.java | 2 +- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/lotto/domain/PurchasedLotto.java b/src/main/java/lotto/domain/PurchasedLotto.java index 36ac78edc7..98ceb04a50 100644 --- a/src/main/java/lotto/domain/PurchasedLotto.java +++ b/src/main/java/lotto/domain/PurchasedLotto.java @@ -1,6 +1,5 @@ package lotto.domain; -import java.util.List; import java.util.Objects; public class PurchasedLotto { @@ -22,15 +21,7 @@ private static void validate(final LottoNumbers lottoNumbers) { } } - public List getLottoNumbers() { - return List.copyOf(lottoNumbers.getNumbers()); - } - - public int calculateMatchCounts(final WinningLotto winningLotto) { - return lottoNumbers.calculateMatchCounts(winningLotto.getLottoNumbers()); - } - - public boolean containsBonusNumber(final WinningLotto winningLotto) { - return lottoNumbers.containsBonusNumber(winningLotto.getBonusNumber()); + public LottoNumbers getLottoNumbers() { + return lottoNumbers; } } diff --git a/src/main/java/lotto/domain/prize/PrizeResult.java b/src/main/java/lotto/domain/prize/PrizeResult.java index d0ee8fa563..1463dfd647 100644 --- a/src/main/java/lotto/domain/prize/PrizeResult.java +++ b/src/main/java/lotto/domain/prize/PrizeResult.java @@ -1,6 +1,7 @@ package lotto.domain.prize; import lotto.constrant.LottoConstant; +import lotto.domain.LottoNumbers; import lotto.domain.PurchasedLotto; import lotto.domain.WinningLotto; @@ -24,13 +25,13 @@ private void initializeCounts() { public static PrizeResult from(final List purchasedLottos, final WinningLotto winningLotto) { final PrizeResult prizeResult = new PrizeResult(); - purchasedLottos.forEach(purchasedLotto -> prizeResult.calculateAndRecordPrize(purchasedLotto, winningLotto)); + purchasedLottos.forEach(purchasedLotto -> prizeResult.calculateAndRecordPrize(purchasedLotto.getLottoNumbers(), winningLotto)); return prizeResult; } - private void calculateAndRecordPrize(final PurchasedLotto purchasedLotto, final WinningLotto winningLotto) { - final int matchCount = purchasedLotto.calculateMatchCounts(winningLotto); - final boolean isContainBonusNumber = purchasedLotto.containsBonusNumber(winningLotto); + private void calculateAndRecordPrize(final LottoNumbers lottoNumbers, final WinningLotto winningLotto) { + final int matchCount = lottoNumbers.calculateMatchCounts(winningLotto.getLottoNumbers()); + final boolean isContainBonusNumber = lottoNumbers.containsBonusNumber(winningLotto.getBonusNumber()); final Prize prize = Prize.of(matchCount, isContainBonusNumber); prizeCounts.put(prize, prizeCounts.get(prize) + 1); diff --git a/src/main/java/lotto/view/ResultView.java b/src/main/java/lotto/view/ResultView.java index a8afb019cb..ff30bb15e8 100644 --- a/src/main/java/lotto/view/ResultView.java +++ b/src/main/java/lotto/view/ResultView.java @@ -31,7 +31,7 @@ public static void printPurchasedLottos(final List purchasedLott } private static void printPurchasedLotto(final PurchasedLotto purchasedLotto) { - final List lottoNumbers = new ArrayList<>(purchasedLotto.getLottoNumbers().stream() + final List lottoNumbers = new ArrayList<>(purchasedLotto.getLottoNumbers().getNumbers().stream() .map(LottoNumber::getNumber) .toList()); From ba77aa6101b45e328c718c1ac4aa2873ac692e2b Mon Sep 17 00:00:00 2001 From: rueun Date: Mon, 20 May 2024 03:17:31 +0900 Subject: [PATCH 25/25] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/lotto/domain/LottoNumberTest.java | 5 ++- .../java/lotto/domain/PurchasedLottoTest.java | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/test/java/lotto/domain/PurchasedLottoTest.java diff --git a/src/test/java/lotto/domain/LottoNumberTest.java b/src/test/java/lotto/domain/LottoNumberTest.java index db025a43e7..bfc9ccff0b 100644 --- a/src/test/java/lotto/domain/LottoNumberTest.java +++ b/src/test/java/lotto/domain/LottoNumberTest.java @@ -24,7 +24,8 @@ void createLottoNumber(int number) { @ValueSource(ints = {0, 46}) void createLottoNumberFail(int number) { // when & then - assertThrows(IllegalArgumentException.class, () -> LottoNumber.from(number)) - .getMessage().equals("로또 번호는 1부터 45까지의 숫자만 가능합니다."); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> LottoNumber.from(number)); + assertEquals("로또 번호는 1부터 45까지의 숫자만 가능합니다.", exception.getMessage()); } } \ No newline at end of file diff --git a/src/test/java/lotto/domain/PurchasedLottoTest.java b/src/test/java/lotto/domain/PurchasedLottoTest.java new file mode 100644 index 0000000000..8d1892671d --- /dev/null +++ b/src/test/java/lotto/domain/PurchasedLottoTest.java @@ -0,0 +1,44 @@ +package lotto.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class PurchasedLottoTest { + + @Test + @DisplayName("로또 번호 생성") + void createPurchasedLotto() { + // given + List numbers = Arrays.asList( + LottoNumber.from(1), + LottoNumber.from(2), + LottoNumber.from(3), + LottoNumber.from(4), + LottoNumber.from(5), + LottoNumber.from(6) + ); + LottoNumbers lottoNumbers = LottoNumbers.from(numbers); + + // when + PurchasedLotto purchasedLotto = PurchasedLotto.from(lottoNumbers); + + // then + assertEquals(lottoNumbers, purchasedLotto.getLottoNumbers()); + } + + @Test + @DisplayName("로또 번호 생성 실패: 로또 번호가 null인 경우") + void createPurchasedLottoFailNull() { + // given + LottoNumbers lottoNumbers = null; + + // when & then + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> PurchasedLotto.from(lottoNumbers)); + assertEquals("lotto numbers must not be null", exception.getMessage()); + } +} \ No newline at end of file