From 8b7f9c7e66f3fe4e64f82867b80f6ae89e654d16 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:11:12 +0900 Subject: [PATCH 01/22] refactor : edit Lotto package structure --- src/main/java/lotto/Lotto.java | 20 ----------------- src/main/java/lotto/lotto/Lotto.java | 33 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 20 deletions(-) delete mode 100644 src/main/java/lotto/Lotto.java create mode 100644 src/main/java/lotto/lotto/Lotto.java diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java deleted file mode 100644 index 519793d1f7..0000000000 --- a/src/main/java/lotto/Lotto.java +++ /dev/null @@ -1,20 +0,0 @@ -package lotto; - -import java.util.List; - -public class Lotto { - private final List numbers; - - public Lotto(List numbers) { - validate(numbers); - this.numbers = numbers; - } - - private void validate(List numbers) { - if (numbers.size() != 6) { - throw new IllegalArgumentException(); - } - } - - // TODO: 추가 기능 구현 -} diff --git a/src/main/java/lotto/lotto/Lotto.java b/src/main/java/lotto/lotto/Lotto.java new file mode 100644 index 0000000000..dc8542186e --- /dev/null +++ b/src/main/java/lotto/lotto/Lotto.java @@ -0,0 +1,33 @@ +package lotto.lotto; + +import java.util.List; +import java.util.stream.Collectors; + +public class Lotto { + private final List numbers; + private static final int LENGTH = 6; + + public Lotto(List numbers) { + validate(numbers); + this.numbers = numbers; + } + + private void validate(List numbers) { + if (numbers.size() != LENGTH) { + throw new IllegalArgumentException(); + } + } + + // TODO: 추가 기능 구현 + + public Prize comparePrize(Lotto winningLotto, int bonus) { + return null; + } + + @Override + public String toString() { + return "[" + + numbers.stream().map(String::valueOf).collect(Collectors.joining(",")) + + "]"; + } +} From a97de0046bc8858e17fe981a310278591bb73a65 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:11:51 +0900 Subject: [PATCH 02/22] feat : add LottoBundle, LottoService --- src/main/java/lotto/lotto/LottoBundle.java | 64 +++++++++++++++++++ src/main/java/lotto/lotto/LottoService.java | 70 +++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/main/java/lotto/lotto/LottoBundle.java create mode 100644 src/main/java/lotto/lotto/LottoService.java diff --git a/src/main/java/lotto/lotto/LottoBundle.java b/src/main/java/lotto/lotto/LottoBundle.java new file mode 100644 index 0000000000..374f676b51 --- /dev/null +++ b/src/main/java/lotto/lotto/LottoBundle.java @@ -0,0 +1,64 @@ +package lotto.lotto; + +import lotto.util.LottoUtil; +import lotto.util.UserOutput; + +import java.util.ArrayList; +import java.util.List; + +public class LottoBundle { + private List lottos = new ArrayList<>(); + private Lotto winningLotto ; + private int bonus; + + + /** + * lottoNum의 수만큼 새로운 로또 생성하기 + */ + public void createLottos(int lottoNum) { + for (int i = 0; i < lottoNum; i++) { + Lotto lotto = new Lotto(LottoUtil.createLotto()); + lottos.add(lotto); + } + } + + // 당첨번호 입력받기 + public void setWinningLotto(List winningNumList){ + Lotto lotto = new Lotto(winningNumList); + this.winningLotto = lotto; + } + + // 보너스번호 입력받기 + public void setBonus(int bonus){ + this.bonus = bonus; + } + + // 로또 출력하기 + public void printLottos() { + StringBuilder sb = new StringBuilder(); + + for (Lotto lotto : lottos){ + sb.append(lotto).append("\n"); + } + + UserOutput.printLottos(0, sb.toString()); + } + + // 당첨 통계 출력하기 + public void printResult() { + String str = ""; + + int[] prizeStat = getPrizeStat(); + int totalreward = getTotalReward(prizeStat); + + UserOutput.printResult(str); + } + + public int[] getPrizeStat() { + return new int[Prize.values().length]; + } + public int getTotalReward(int[] prizeStat){ + return 0; + } + +} diff --git a/src/main/java/lotto/lotto/LottoService.java b/src/main/java/lotto/lotto/LottoService.java new file mode 100644 index 0000000000..7517770ab9 --- /dev/null +++ b/src/main/java/lotto/lotto/LottoService.java @@ -0,0 +1,70 @@ +package lotto.lotto; + +import lotto.purchase.PurchaseService; +import lotto.util.UserInput; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class LottoService { + + public void run() { + LottoBundle bundle = new LottoBundle(); + + // 구입금액 입력받기 + String userInput = UserInput.getCostInput(); + int cost = getNum(userInput); + int lottoNum = PurchaseService.getLottoNum(cost); + bundle.createLottos(lottoNum); + + // 로또 출력하기 + bundle.printLottos(); + + // 당첨번호 입력받기 + userInput = UserInput.getLottoInput(); + List winningList = getNumList(userInput); + bundle.setWinningLotto(winningList); + + // 보너스번호 입력받기 + userInput = UserInput.getBonusInput(); + int bonus = getNum(userInput); + bundle.setBonus(bonus); + + // 당첨 통계 출력하기 + bundle.printResult(); + } + + + public int getNum (String input) { + int num; + try { + num = Integer.parseInt(input); + } catch (NumberFormatException ne) { + throw new IllegalArgumentException("[ERROR] 정수를 입력해주세요."); + } + return num; + } + + public List getNumList(String input) { + + List strList = new ArrayList<>( + Arrays.asList( + input.split(",") + ) + ); + + List numList = strList.stream() + .map(s -> { + try { + return Integer.parseInt(s); + } catch (NumberFormatException ne) { + throw new IllegalArgumentException("[ERROR] 정수와 ,로 이루어진 배열을 입력해주세요."); + } + } ).collect(Collectors.toList()); + + return numList; + } + +} From ec15121ed4987cbedd300951dddda60ad810d2e3 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:12:04 +0900 Subject: [PATCH 03/22] feat : add utils --- src/main/java/lotto/util/LottoUtil.java | 21 ++++++++++++++++++ src/main/java/lotto/util/UserInput.java | 27 ++++++++++++++++++++++++ src/main/java/lotto/util/UserOutput.java | 20 ++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/java/lotto/util/LottoUtil.java create mode 100644 src/main/java/lotto/util/UserInput.java create mode 100644 src/main/java/lotto/util/UserOutput.java diff --git a/src/main/java/lotto/util/LottoUtil.java b/src/main/java/lotto/util/LottoUtil.java new file mode 100644 index 0000000000..d75e74a372 --- /dev/null +++ b/src/main/java/lotto/util/LottoUtil.java @@ -0,0 +1,21 @@ +package lotto.util; + +import camp.nextstep.edu.missionutils.Randoms; +import lotto.config.LottoConfig; + +import java.util.List; + +public class LottoUtil { + + private LottoUtil() { + } + + public static List createLotto() { + return Randoms.pickUniqueNumbersInRange( + LottoConfig.LOTTO_MIN_NUM, + LottoConfig.LOTTO_MAX_NUM, + LottoConfig.LOTTO_NUM_LENGTH + ); + } + +} diff --git a/src/main/java/lotto/util/UserInput.java b/src/main/java/lotto/util/UserInput.java new file mode 100644 index 0000000000..a7f06eb0a6 --- /dev/null +++ b/src/main/java/lotto/util/UserInput.java @@ -0,0 +1,27 @@ +package lotto.util; + +import camp.nextstep.edu.missionutils.Console; + +import java.util.Scanner; + +public class UserInput { + + private UserInput() { + } + + public static String getCostInput() { + System.out.println("구입금액을 입력해 주세요."); + return Console.readLine().trim(); + } + + public static String getLottoInput(){ + System.out.println("당첨 번호를 입력해 주세요."); + return Console.readLine().trim(); + } + + public static String getBonusInput(){ + System.out.println("보너스 번호를 입력해 주세요."); + return Console.readLine().trim(); + } + +} diff --git a/src/main/java/lotto/util/UserOutput.java b/src/main/java/lotto/util/UserOutput.java new file mode 100644 index 0000000000..f7e1c63491 --- /dev/null +++ b/src/main/java/lotto/util/UserOutput.java @@ -0,0 +1,20 @@ +package lotto.util; + +public class UserOutput { + + private UserOutput() { + } + + public static void printLottos(int num, String lottoStr) { + StringBuilder sb = new StringBuilder(); + sb.append(num).append("개를 구매했습니다.\n").append(lottoStr); + System.out.println(sb); + } + + public static void printResult(String resultStr){ + System.out.println( "당첨 통계\n" + + "---\n"); + System.out.println(resultStr); + } + +} From 0ada73bb6e1639da931b6da7fc19f52d381f597f Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:12:23 +0900 Subject: [PATCH 04/22] feat : add purchase --- .../java/lotto/purchase/PurchaseService.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/lotto/purchase/PurchaseService.java diff --git a/src/main/java/lotto/purchase/PurchaseService.java b/src/main/java/lotto/purchase/PurchaseService.java new file mode 100644 index 0000000000..811436d000 --- /dev/null +++ b/src/main/java/lotto/purchase/PurchaseService.java @@ -0,0 +1,17 @@ +package lotto.purchase; + +public class PurchaseService { + + private final static int PRICE_PER_LOTTO = 1000; + + private PurchaseService() { + } + + /** + * 텍스트 입력을 lotto 수로 변환 + */ + public static int getLottoNum(int cost) { + return 0; + } + +} From 583242a03e811bae7f3298e7622fb081f274de23 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:12:34 +0900 Subject: [PATCH 05/22] feat : add Prize --- src/main/java/lotto/lotto/Prize.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/lotto/lotto/Prize.java diff --git a/src/main/java/lotto/lotto/Prize.java b/src/main/java/lotto/lotto/Prize.java new file mode 100644 index 0000000000..1e7cc6d3be --- /dev/null +++ b/src/main/java/lotto/lotto/Prize.java @@ -0,0 +1,22 @@ +package lotto.lotto; + +public enum Prize { + FIFTH(3, false, 5000, "3개 일치"), + FOURTH(4, false, 50000, "4개 일치"), + THIRD(5, false, 1500000, "5개 일치"), + SECOND(5, true, 30000000, "5개 일치, 보너스 볼 일치"), + FIRST(6, false, 2000000000, "6개 일치"); + + + private final int matchNum; + private final boolean bonus; + private final int reward; + private final String toString; + + Prize(int matchNum, boolean bonus, int reward, String toString) { + this.matchNum = matchNum; + this.bonus = bonus; + this.reward = reward; + this.toString = toString; + } +} From 6ba126556be61d9a81c6111d0f03463bfb940de0 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:12:42 +0900 Subject: [PATCH 06/22] feat : add configs --- src/main/java/lotto/config/LottoConfig.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/lotto/config/LottoConfig.java diff --git a/src/main/java/lotto/config/LottoConfig.java b/src/main/java/lotto/config/LottoConfig.java new file mode 100644 index 0000000000..7ff9325031 --- /dev/null +++ b/src/main/java/lotto/config/LottoConfig.java @@ -0,0 +1,12 @@ +package lotto.config; + +public class LottoConfig { + + private LottoConfig() { + } + + public final static int LOTTO_NUM_LENGTH = 6; + public final static int LOTTO_MIN_NUM = 1; + public final static int LOTTO_MAX_NUM = 45; + +} From f51b94dc099cd3b18d353b188fecc16268ad4d95 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:13:00 +0900 Subject: [PATCH 07/22] test : add test for LottoService --- .../java/lotto/lotto/LottoServiceTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/test/java/lotto/lotto/LottoServiceTest.java diff --git a/src/test/java/lotto/lotto/LottoServiceTest.java b/src/test/java/lotto/lotto/LottoServiceTest.java new file mode 100644 index 0000000000..342eed0129 --- /dev/null +++ b/src/test/java/lotto/lotto/LottoServiceTest.java @@ -0,0 +1,61 @@ +package lotto.lotto; + +import lotto.purchase.PurchaseService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class LottoServiceTest { + + @ParameterizedTest + @DisplayName("getNumList 동작 테스트") + @CsvSource(value = {"1,1","2,2","3,3","4,4"}, delimiter = ':') + void getNum_동작(String input, int expected) { + // given + LottoService lottoService = new LottoService(); + // when + int test = lottoService.getNum(input); + // then + assertThat(test).isEqualTo(expected); + } + + @ParameterizedTest + @DisplayName("getNumList 예와 테스트") + @ValueSource(strings = {"a", "--1", ",,3"}) + void getNum_예와(String input) { + // given + LottoService lottoService = new LottoService(); + // when & then + assertThatThrownBy(()->lottoService.getNum(input)) + .isInstanceOf(IllegalArgumentException.class); + } + + + @ParameterizedTest + @DisplayName("getNumList 동작 테스트") + @ValueSource(strings = {"1", "1,2", "1,200,3000,2,1", "99999,99999,99999,99999,99999,99999"}) + void getNumList_동작(String input) { + // given + LottoService lottoService = new LottoService(); + // when & then + assertThatThrownBy(()->lottoService.getNumList(input)) + .doesNotThrowAnyException(); + } + + @ParameterizedTest + @DisplayName("getNumList 예외 테스트") + @ValueSource(strings = {"1,,", "d,s,1", "--1,2,3"}) + void getNumList_예외(String input) { + // given + LottoService lottoService = new LottoService(); + // when & then + assertThatThrownBy(()->lottoService.getNumList(input)) + .isInstanceOf(IllegalArgumentException.class); + } + +} \ No newline at end of file From 77b2e3693df4e5c181ab724e98076d187300c516 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:13:10 +0900 Subject: [PATCH 08/22] test : add test for Lotto --- src/test/java/lotto/LottoTest.java | 27 --------- src/test/java/lotto/lotto/LottoTest.java | 76 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 27 deletions(-) delete mode 100644 src/test/java/lotto/LottoTest.java create mode 100644 src/test/java/lotto/lotto/LottoTest.java diff --git a/src/test/java/lotto/LottoTest.java b/src/test/java/lotto/LottoTest.java deleted file mode 100644 index 0f3af0f6c4..0000000000 --- a/src/test/java/lotto/LottoTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package lotto; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -class LottoTest { - @DisplayName("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.") - @Test - void createLottoByOverSize() { - assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7))) - .isInstanceOf(IllegalArgumentException.class); - } - - @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.") - @Test - void createLottoByDuplicatedNumber() { - // TODO: 이 테스트가 통과할 수 있게 구현 코드 작성 - assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) - .isInstanceOf(IllegalArgumentException.class); - } - - // 아래에 추가 테스트 작성 가능 -} diff --git a/src/test/java/lotto/lotto/LottoTest.java b/src/test/java/lotto/lotto/LottoTest.java new file mode 100644 index 0000000000..e318cb4f53 --- /dev/null +++ b/src/test/java/lotto/lotto/LottoTest.java @@ -0,0 +1,76 @@ +package lotto.lotto; + +import lotto.lotto.Lotto; +import lotto.util.LottoUtil; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoTest { + @DisplayName("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.") + @Test + void createLottoByOverSize() { + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7))) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.") + @Test + void createLottoByDuplicatedNumber() { + // TODO: 이 테스트가 통과할 수 있게 구현 코드 작성 + assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) + .isInstanceOf(IllegalArgumentException.class); + } + + + List> testList = new ArrayList<>(List.of( + List.of(1, 2, 3, 10, 11, 12), + List.of(1, 2, 3, 4, 11, 12), + List.of(1, 2, 3, 4, 5, 12), + List.of(1, 2, 3, 4, 5, 7), + List.of(1, 2, 3, 4, 5, 6) + )); + + @ParameterizedTest + @DisplayName("comparePrize 동작 테스트") + @CsvSource(value = {"1:FIFTH", "2:FOURTH", "3:THIRD", "4:SECOND", "5:FIRST"}, delimiter = ':') + void comparePrize_동작(int testNum, String prizeName) { + // given + Lotto myLotto = new Lotto(testList.get(testNum)); + Lotto winningLotto = new Lotto(List.of(1, 2, 3, 4, 5, 6)); + int bonus = 7; + + // when + Prize p = myLotto.comparePrize(winningLotto, bonus); + + // then + assertThat(p).isEqualTo(Prize.valueOf(prizeName)); + } + + @ParameterizedTest + @DisplayName("toString 동작 테스트") + @CsvSource(value = { + "1:[1, 2, 3, 10, 11, 12]", + "2:[1, 2, 3, 4, 11, 12]", + "3:[1, 2, 3, 4, 5, 12]" + }, delimiter = ':') + void toString_동작(int testNum, String expected) { + // given + Lotto myLotto = new Lotto(testList.get(testNum)); + + // when + String test = myLotto.toString(); + + // then + assertThat(test).isEqualTo(expected); + } + +} From a063735f674c8e91ee724d4437949847568b6a75 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 13:13:20 +0900 Subject: [PATCH 09/22] test : add test for PurchaseService --- .../lotto/purchase/PurchaseServiceTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/test/java/lotto/purchase/PurchaseServiceTest.java diff --git a/src/test/java/lotto/purchase/PurchaseServiceTest.java b/src/test/java/lotto/purchase/PurchaseServiceTest.java new file mode 100644 index 0000000000..9299aad4e7 --- /dev/null +++ b/src/test/java/lotto/purchase/PurchaseServiceTest.java @@ -0,0 +1,35 @@ +package lotto.purchase; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +class PurchaseServiceTest { + + @ParameterizedTest + @DisplayName("getLottoNum 동작 테스트") + @CsvSource(value = {"1000,1", "2000,2", "3000,3", "4000,4"}, delimiter = ',') + void getLottoNum_동작(int cost, int expect) { + // when + int test = PurchaseService.getLottoNum(cost); + // then + assertThat(test).isEqualTo(expect); + } + + @ParameterizedTest + @DisplayName("getLottoNum 예외 테스트") + @ValueSource(ints = {0, 1005, 2050, 3500}) + void getLottoNum_예외(int cost) { + // when & then + assertThatThrownBy(() -> + PurchaseService.getLottoNum(cost) + ).isInstanceOf(IllegalArgumentException.class); + } + +} \ No newline at end of file From 5b0a3d42e4b980a0f457bdfed3f72477509f4394 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 22:51:11 +0900 Subject: [PATCH 10/22] test : edit LottoTest --- src/test/java/lotto/lotto/LottoTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/lotto/lotto/LottoTest.java b/src/test/java/lotto/lotto/LottoTest.java index e318cb4f53..078f0704ca 100644 --- a/src/test/java/lotto/lotto/LottoTest.java +++ b/src/test/java/lotto/lotto/LottoTest.java @@ -41,7 +41,7 @@ void createLottoByDuplicatedNumber() { @ParameterizedTest @DisplayName("comparePrize 동작 테스트") - @CsvSource(value = {"1:FIFTH", "2:FOURTH", "3:THIRD", "4:SECOND", "5:FIRST"}, delimiter = ':') + @CsvSource(value = {"0:FIFTH", "1:FOURTH", "2:THIRD", "3:SECOND", "4:FIRST"}, delimiter = ':') void comparePrize_동작(int testNum, String prizeName) { // given Lotto myLotto = new Lotto(testList.get(testNum)); @@ -58,9 +58,9 @@ void createLottoByDuplicatedNumber() { @ParameterizedTest @DisplayName("toString 동작 테스트") @CsvSource(value = { - "1:[1, 2, 3, 10, 11, 12]", - "2:[1, 2, 3, 4, 11, 12]", - "3:[1, 2, 3, 4, 5, 12]" + "0:[1, 2, 3, 10, 11, 12]", + "1:[1, 2, 3, 4, 11, 12]", + "2:[1, 2, 3, 4, 5, 12]" }, delimiter = ':') void toString_동작(int testNum, String expected) { // given From 524424243dcda3535ebbac3f4aa4cb622a3c3892 Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 22:51:28 +0900 Subject: [PATCH 11/22] feat : edit main method --- src/main/java/lotto/Application.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..bcf5546bb0 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,10 @@ package lotto; +import lotto.lotto.LottoService; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + LottoService lottoService = new LottoService(); + lottoService.run(); } } From 3c03b63b17bd294cede3f9ae4dbd8698a06d11fa Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 22:52:30 +0900 Subject: [PATCH 12/22] feat : add PurchaseService --- src/main/java/lotto/purchase/PurchaseService.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/purchase/PurchaseService.java b/src/main/java/lotto/purchase/PurchaseService.java index 811436d000..6ba7b62d6f 100644 --- a/src/main/java/lotto/purchase/PurchaseService.java +++ b/src/main/java/lotto/purchase/PurchaseService.java @@ -11,7 +11,17 @@ private PurchaseService() { * 텍스트 입력을 lotto 수로 변환 */ public static int getLottoNum(int cost) { - return 0; + if (cost <=0 ) + throw new IllegalArgumentException("[ERROR] 1 이상의 양수를 입력해주세요"); + if (cost % PRICE_PER_LOTTO != 0) + throw new IllegalArgumentException("[ERROR] 가격의 배수에 해당하는 가격을 입력해주세요"); + + return cost / PRICE_PER_LOTTO; + } + + public static double getRewardPercent(int num, int reward){ + return (double) reward / (num * PRICE_PER_LOTTO) * 100; } + } From d878bb01e4ecd200a7e67f569ae3c8de38d890fc Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 22:52:42 +0900 Subject: [PATCH 13/22] feat : add LottoBundle --- src/main/java/lotto/lotto/LottoBundle.java | 68 ++++++++++++++++------ 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/src/main/java/lotto/lotto/LottoBundle.java b/src/main/java/lotto/lotto/LottoBundle.java index 374f676b51..ff6f1c649d 100644 --- a/src/main/java/lotto/lotto/LottoBundle.java +++ b/src/main/java/lotto/lotto/LottoBundle.java @@ -1,14 +1,17 @@ package lotto.lotto; +import javafx.scene.input.DataFormat; +import lotto.purchase.PurchaseService; import lotto.util.LottoUtil; import lotto.util.UserOutput; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; public class LottoBundle { private List lottos = new ArrayList<>(); - private Lotto winningLotto ; + private Lotto winningLotto; private int bonus; @@ -22,43 +25,74 @@ public void createLottos(int lottoNum) { } } - // 당첨번호 입력받기 - public void setWinningLotto(List winningNumList){ + /** + * 당첨번호 입력받기 + */ + public void setWinningLotto(List winningNumList) { Lotto lotto = new Lotto(winningNumList); this.winningLotto = lotto; } - // 보너스번호 입력받기 - public void setBonus(int bonus){ + /** + * 보너스번호 입력받기 + */ + public void setBonus(int bonus) { this.bonus = bonus; } - // 로또 출력하기 + /** + * 로또 출력하기 + */ public void printLottos() { StringBuilder sb = new StringBuilder(); - for (Lotto lotto : lottos){ + for (Lotto lotto : lottos) sb.append(lotto).append("\n"); - } - UserOutput.printLottos(0, sb.toString()); + UserOutput.printLottos(lottos.size(), sb.toString()); } - // 당첨 통계 출력하기 + /** + * 당첨 통계 출력하기 + */ public void printResult() { - String str = ""; - int[] prizeStat = getPrizeStat(); int totalreward = getTotalReward(prizeStat); + double rewardPercent = PurchaseService.getRewardPercent(lottos.size(), totalreward); + + StringBuilder sb = new StringBuilder(); + for (Prize prize : Prize.values()){ + if (prize == Prize.NONE) continue; + sb.append(prize.getToString()); + sb.append( + String.format(" (%,d원) - %d개", + prize.getReward(), + prizeStat[prize.ordinal()] + )); + sb.append("\n"); + } + sb.append(String.format("총 수익률은 %.1f%%입니다.", rewardPercent)); - UserOutput.printResult(str); + UserOutput.printResult(sb.toString()); } public int[] getPrizeStat() { - return new int[Prize.values().length]; + int[] prizeStat = new int[Prize.values().length]; + for (Lotto lotto : lottos) { + Prize prize = lotto.comparePrize(winningLotto, bonus); + if (prize != Prize.NONE) + prizeStat[prize.ordinal()]++; + } + return prizeStat; } - public int getTotalReward(int[] prizeStat){ - return 0; + + public int getTotalReward(int[] prizeStat) { + int totalReward = 0; + for (Prize prize : Prize.values()){ + if (prizeStat[prize.ordinal()] != 0) + totalReward += prize.getReward() * prizeStat[prize.ordinal()]; + } + return totalReward; } - + } From b4bb8e74b1db0dbbc1cde6c60fcf6cbe7553552d Mon Sep 17 00:00:00 2001 From: raycho Date: Wed, 29 Mar 2023 22:52:56 +0900 Subject: [PATCH 14/22] feat : add Lotto --- src/main/java/lotto/lotto/Lotto.java | 39 +++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main/java/lotto/lotto/Lotto.java b/src/main/java/lotto/lotto/Lotto.java index dc8542186e..fa0e52e7f9 100644 --- a/src/main/java/lotto/lotto/Lotto.java +++ b/src/main/java/lotto/lotto/Lotto.java @@ -1,33 +1,58 @@ package lotto.lotto; +import lotto.config.LottoConfig; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; public class Lotto { private final List numbers; - private static final int LENGTH = 6; public Lotto(List numbers) { validate(numbers); + numbers.sort(Comparator.naturalOrder()); this.numbers = numbers; } private void validate(List numbers) { - if (numbers.size() != LENGTH) { - throw new IllegalArgumentException(); - } + if (numbers.size() != LottoConfig.LOTTO_NUM_LENGTH) + throw new IllegalArgumentException("[ERROR] 숫자의 개수가 올바르지 않습니다."); + if (numbers.size() != (new HashSet<>(numbers)).size()) + throw new IllegalArgumentException("[ERROR] 숫자에 중복이 없어야 합니다."); } - // TODO: 추가 기능 구현 public Prize comparePrize(Lotto winningLotto, int bonus) { - return null; + List list = new ArrayList<>(); + list.addAll(numbers); + list.addAll(winningLotto.numbers); + int matches = list.size() - (new HashSet<>(list)).size(); + boolean isBonus = numbers.contains(bonus); + + Prize prize = Prize.NONE; + for (Prize p : Prize.values()) { + if ( + p != Prize.NONE && + p.getMatchNum() <= matches && + p.getGrade() <= prize.getGrade() + ) { + if (p.isBonus() && !isBonus) + continue; + prize = p; + } + } + + return prize; } @Override public String toString() { return "[" + - numbers.stream().map(String::valueOf).collect(Collectors.joining(",")) + + numbers.stream().map(String::valueOf).collect(Collectors.joining(", ")) + "]"; } + } From 8099c5c6c55b4e9ef08ce94ce364ba3fabfae793 Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:26:12 +0900 Subject: [PATCH 15/22] chore : edit output format --- src/main/java/lotto/util/UserOutput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/lotto/util/UserOutput.java b/src/main/java/lotto/util/UserOutput.java index f7e1c63491..e75a8a749a 100644 --- a/src/main/java/lotto/util/UserOutput.java +++ b/src/main/java/lotto/util/UserOutput.java @@ -13,7 +13,7 @@ public static void printLottos(int num, String lottoStr) { public static void printResult(String resultStr){ System.out.println( "당첨 통계\n" + - "---\n"); + "---"); System.out.println(resultStr); } From fde7c092976124ab1d9876b434abde769f5b59a3 Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:26:37 +0900 Subject: [PATCH 16/22] chore : edit comments --- src/main/java/lotto/purchase/PurchaseService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/lotto/purchase/PurchaseService.java b/src/main/java/lotto/purchase/PurchaseService.java index 6ba7b62d6f..8aaf074500 100644 --- a/src/main/java/lotto/purchase/PurchaseService.java +++ b/src/main/java/lotto/purchase/PurchaseService.java @@ -19,6 +19,9 @@ public static int getLottoNum(int cost) { return cost / PRICE_PER_LOTTO; } + /** + * 총 로또 수익률을 퍼센트 단위로 반환 + */ public static double getRewardPercent(int num, int reward){ return (double) reward / (num * PRICE_PER_LOTTO) * 100; } From 184b14e28cf8dd3ccd23f840b1cf311afe601408 Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:27:06 +0900 Subject: [PATCH 17/22] test : fix error for CsvSource --- src/test/java/lotto/lotto/LottoServiceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/lotto/lotto/LottoServiceTest.java b/src/test/java/lotto/lotto/LottoServiceTest.java index 342eed0129..45d86d53d0 100644 --- a/src/test/java/lotto/lotto/LottoServiceTest.java +++ b/src/test/java/lotto/lotto/LottoServiceTest.java @@ -14,7 +14,7 @@ class LottoServiceTest { @ParameterizedTest @DisplayName("getNumList 동작 테스트") - @CsvSource(value = {"1,1","2,2","3,3","4,4"}, delimiter = ':') + @CsvSource(value = {"1,1","2,2","3,3","4,4"}, delimiter = ',') void getNum_동작(String input, int expected) { // given LottoService lottoService = new LottoService(); @@ -43,7 +43,7 @@ class LottoServiceTest { // given LottoService lottoService = new LottoService(); // when & then - assertThatThrownBy(()->lottoService.getNumList(input)) + assertThatCode(()->lottoService.getNumList(input)) .doesNotThrowAnyException(); } From 51e4d73561785930b79d416421c644895520eca0 Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:28:21 +0900 Subject: [PATCH 18/22] feat : add lotto sort --- src/main/java/lotto/lotto/Lotto.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/lotto/lotto/Lotto.java b/src/main/java/lotto/lotto/Lotto.java index fa0e52e7f9..82f6997268 100644 --- a/src/main/java/lotto/lotto/Lotto.java +++ b/src/main/java/lotto/lotto/Lotto.java @@ -13,7 +13,11 @@ public class Lotto { public Lotto(List numbers) { validate(numbers); - numbers.sort(Comparator.naturalOrder()); + + try { + numbers.sort(Comparator.naturalOrder()); + } catch (UnsupportedOperationException ignored) {} + this.numbers = numbers; } @@ -35,16 +39,15 @@ public Prize comparePrize(Lotto winningLotto, int bonus) { Prize prize = Prize.NONE; for (Prize p : Prize.values()) { if ( - p != Prize.NONE && + p.isPrized() && p.getMatchNum() <= matches && p.getGrade() <= prize.getGrade() ) { - if (p.isBonus() && !isBonus) + if (p.isBonus() && !isBonus) // 보너스 true인 경우 isBonus 확인한다. continue; prize = p; } } - return prize; } From 14407eb921be5a28da71aaa4e8f82331ca41f29b Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:28:50 +0900 Subject: [PATCH 19/22] feat : add validation code for getNumList --- src/main/java/lotto/lotto/LottoService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/lotto/LottoService.java b/src/main/java/lotto/lotto/LottoService.java index 7517770ab9..74c331edd0 100644 --- a/src/main/java/lotto/lotto/LottoService.java +++ b/src/main/java/lotto/lotto/LottoService.java @@ -48,13 +48,17 @@ public int getNum (String input) { } public List getNumList(String input) { - List strList = new ArrayList<>( Arrays.asList( input.split(",") ) ); + // "," 개수를 이용해서 배열의 길이가 올바르게 입력되었는지 확인한다. + int commas = input.length() - input.replace(String.valueOf(","), "").length(); + if (commas+1 != strList.size()) + throw new IllegalArgumentException("[ERROR] 정수와 ,로 이루어진 배열을 입력해주세요."); + List numList = strList.stream() .map(s -> { try { From 44e98a1b4b9a993d5b24890d7bd3555d6115366d Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:29:54 +0900 Subject: [PATCH 20/22] feat : add pried field for Prize --- src/main/java/lotto/lotto/Prize.java | 43 +++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/main/java/lotto/lotto/Prize.java b/src/main/java/lotto/lotto/Prize.java index 1e7cc6d3be..762425e7ee 100644 --- a/src/main/java/lotto/lotto/Prize.java +++ b/src/main/java/lotto/lotto/Prize.java @@ -1,22 +1,51 @@ package lotto.lotto; public enum Prize { - FIFTH(3, false, 5000, "3개 일치"), - FOURTH(4, false, 50000, "4개 일치"), - THIRD(5, false, 1500000, "5개 일치"), - SECOND(5, true, 30000000, "5개 일치, 보너스 볼 일치"), - FIRST(6, false, 2000000000, "6개 일치"); - + FIFTH(true, 5, 3, false, 5000, "3개 일치"), + FOURTH(true, 4, 4, false, 50000, "4개 일치"), + THIRD(true, 3, 5, false, 1500000, "5개 일치"), + SECOND(true, 2, 5, true, 30000000, "5개 일치, 보너스 볼 일치"), + FIRST(true, 1, 6, false, 2000000000, "6개 일치"), + NONE(false, 99999, 0, false, 0, ""); + private final boolean prized; + private final int grade; private final int matchNum; private final boolean bonus; private final int reward; private final String toString; - Prize(int matchNum, boolean bonus, int reward, String toString) { + Prize(boolean prized, int grade, int matchNum, boolean bonus, int reward, String toString) { + this.prized = prized; + this.grade = grade; this.matchNum = matchNum; this.bonus = bonus; this.reward = reward; this.toString = toString; } + + public boolean isPrized() { + return prized; + } + + public int getGrade() { + return grade; + } + + public int getMatchNum() { + return matchNum; + } + + public boolean isBonus() { + return bonus; + } + + public int getReward() { + return reward; + } + + public String getToString() { + return toString; + } + } From 47cd5d9808076c265521fc23f2a00b7fe8bf7af5 Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:31:14 +0900 Subject: [PATCH 21/22] chore : remove unused imports --- src/main/java/lotto/lotto/LottoBundle.java | 11 +++++------ src/main/java/lotto/util/UserInput.java | 2 -- src/test/java/lotto/lotto/LottoServiceTest.java | 3 --- src/test/java/lotto/lotto/LottoTest.java | 3 --- src/test/java/lotto/purchase/PurchaseServiceTest.java | 2 -- 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/main/java/lotto/lotto/LottoBundle.java b/src/main/java/lotto/lotto/LottoBundle.java index ff6f1c649d..318f886c95 100644 --- a/src/main/java/lotto/lotto/LottoBundle.java +++ b/src/main/java/lotto/lotto/LottoBundle.java @@ -1,11 +1,9 @@ package lotto.lotto; -import javafx.scene.input.DataFormat; import lotto.purchase.PurchaseService; import lotto.util.LottoUtil; import lotto.util.UserOutput; -import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -26,7 +24,7 @@ public void createLottos(int lottoNum) { } /** - * 당첨번호 입력받기 + * 당첨번호 저장하기 */ public void setWinningLotto(List winningNumList) { Lotto lotto = new Lotto(winningNumList); @@ -34,9 +32,10 @@ public void setWinningLotto(List winningNumList) { } /** - * 보너스번호 입력받기 + * 보너스번호 저장하기 */ public void setBonus(int bonus) { + //todo: 보너스랑 당첨번호 겹치면 안됨!! this.bonus = bonus; } @@ -62,7 +61,7 @@ public void printResult() { StringBuilder sb = new StringBuilder(); for (Prize prize : Prize.values()){ - if (prize == Prize.NONE) continue; + if (!prize.isPrized()) continue; sb.append(prize.getToString()); sb.append( String.format(" (%,d원) - %d개", @@ -80,7 +79,7 @@ public int[] getPrizeStat() { int[] prizeStat = new int[Prize.values().length]; for (Lotto lotto : lottos) { Prize prize = lotto.comparePrize(winningLotto, bonus); - if (prize != Prize.NONE) + if (prize.isPrized()) prizeStat[prize.ordinal()]++; } return prizeStat; diff --git a/src/main/java/lotto/util/UserInput.java b/src/main/java/lotto/util/UserInput.java index a7f06eb0a6..6874eeccc2 100644 --- a/src/main/java/lotto/util/UserInput.java +++ b/src/main/java/lotto/util/UserInput.java @@ -2,8 +2,6 @@ import camp.nextstep.edu.missionutils.Console; -import java.util.Scanner; - public class UserInput { private UserInput() { diff --git a/src/test/java/lotto/lotto/LottoServiceTest.java b/src/test/java/lotto/lotto/LottoServiceTest.java index 45d86d53d0..9d2c55b756 100644 --- a/src/test/java/lotto/lotto/LottoServiceTest.java +++ b/src/test/java/lotto/lotto/LottoServiceTest.java @@ -1,14 +1,11 @@ package lotto.lotto; -import lotto.purchase.PurchaseService; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; class LottoServiceTest { diff --git a/src/test/java/lotto/lotto/LottoTest.java b/src/test/java/lotto/lotto/LottoTest.java index 078f0704ca..05b4f0ee32 100644 --- a/src/test/java/lotto/lotto/LottoTest.java +++ b/src/test/java/lotto/lotto/LottoTest.java @@ -1,12 +1,9 @@ package lotto.lotto; -import lotto.lotto.Lotto; -import lotto.util.LottoUtil; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.ValueSource; import java.util.ArrayList; import java.util.List; diff --git a/src/test/java/lotto/purchase/PurchaseServiceTest.java b/src/test/java/lotto/purchase/PurchaseServiceTest.java index 9299aad4e7..929cf4f2eb 100644 --- a/src/test/java/lotto/purchase/PurchaseServiceTest.java +++ b/src/test/java/lotto/purchase/PurchaseServiceTest.java @@ -1,14 +1,12 @@ package lotto.purchase; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; class PurchaseServiceTest { From f1da751ae3d5e16582dfd284862a76c45068b7b5 Mon Sep 17 00:00:00 2001 From: raycho Date: Thu, 30 Mar 2023 10:38:40 +0900 Subject: [PATCH 22/22] fix : add validation that bonus does not duplicate with the number in the list --- src/main/java/lotto/lotto/Lotto.java | 4 ++++ src/main/java/lotto/lotto/LottoBundle.java | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/lotto/lotto/Lotto.java b/src/main/java/lotto/lotto/Lotto.java index 82f6997268..b1b6ee1db4 100644 --- a/src/main/java/lotto/lotto/Lotto.java +++ b/src/main/java/lotto/lotto/Lotto.java @@ -51,6 +51,10 @@ public Prize comparePrize(Lotto winningLotto, int bonus) { return prize; } + public boolean contains(int num) { + return numbers.contains(num); + } + @Override public String toString() { return "[" + diff --git a/src/main/java/lotto/lotto/LottoBundle.java b/src/main/java/lotto/lotto/LottoBundle.java index 318f886c95..adc973364f 100644 --- a/src/main/java/lotto/lotto/LottoBundle.java +++ b/src/main/java/lotto/lotto/LottoBundle.java @@ -35,7 +35,9 @@ public void setWinningLotto(List winningNumList) { * 보너스번호 저장하기 */ public void setBonus(int bonus) { - //todo: 보너스랑 당첨번호 겹치면 안됨!! + if (winningLotto.contains(bonus)) { + throw new IllegalArgumentException("[ERROR] 보너스 번호와 당첨 번호에 중복이 있습니다."); + } this.bonus = bonus; }