diff --git a/docs/README.md b/docs/README.md index e69de29..2318055 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,50 @@ +# 요구사항 명세서 +## [카테고리] +1. 사용자 +2. 로또 발행기 +3. 결과 비교기 +4. 시스템 + +## [카테고리 별 요구사항 내용] +### 1. 사용자 + - 로또 구입 금액을 입력한다. + - 당첨 번호 추첨 시 중복되지 않는 6개의 숫자와 보너스 번호를 1개를 입력한다. + + +### 2. 로또 발행기 + - 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. + - 로또 구입 금액에 해당하는 만큼 로또를 발행한다. + + +### 3. 결과 비교기 + - 당첨 번호를 입력 받아 발행한 로또와 비교한다. + + +### 4. 시스템 + - 당첨 내역과 수익률을 출력하고 로또 게임을 종료한다. + - 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고 "[ERROR]"로 시작하는 에러 메세지를 출력 후 종료한다. + +# 기능 목록 +### 1. 입력 기능 + - 사용자가 입력하는 금액을 입력 받는 기능 + - 사용자가 입력하는 당첨 번호, 보너스 번호를 입력 받는 기능 + + +### 2. 출력 기능 + - 발행한 로또 내역 출력 기능 + - 당첨 통계와 수익률 출력 기능 + + +### 3. 게임 로직 기능 + - 로또 발행 기능 + - 당첨 통계 기능 + - 수익률 계산 기능 + + +### 4. 검증 기능 + - 입력 검증 + - 사용자가 입력한 금액이 1000원 단위로 1000의 배수인지 검증 + - 사용자가 입력한 당첨 번호가 정수 1 ~ 45인지 검증 + - 사용자가 입력한 당첨 번호가 숫자 6개인지 검증 + - 사용자가 입력한 보너스 번호가 정수 1 ~ 45인지 검증 + - 사용자가 입력한 보너스 번호가 숫자 1개인지 검증 \ No newline at end of file diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922..2d864fb 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,10 @@ package lotto; +import lotto.controller.Controller; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + new Controller().run(); } } diff --git a/src/main/java/lotto/controller/Controller.java b/src/main/java/lotto/controller/Controller.java new file mode 100644 index 0000000..f5edf18 --- /dev/null +++ b/src/main/java/lotto/controller/Controller.java @@ -0,0 +1,61 @@ +package lotto.controller; + +import lotto.domain.Lotto.AnswerLotto; +import lotto.domain.Lotto.Lotto; +import lotto.domain.user.User; +import lotto.service.ResultService; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static camp.nextstep.edu.missionutils.Console.readLine; +import static lotto.domain.Lotto.LottoGenerator.generateLottos; +import static lotto.domain.Lotto.MoneyGenerator.generateMoney; + +public class Controller { + private User user; + private ResultService resultService; + + public Controller() { + this.resultService = new ResultService(); + } + + public void run() { + System.out.println("구입금액을 입력해 주세요."); + int money = generateMoney(); + + buyLotto(money); + + List lottos = user.getLottos(); + System.out.println(lottos.size() + "개를 구매했습니다."); + for (Lotto lotto : lottos) { + System.out.println(lotto); + } + + System.out.println("당첨 번호를 입력해 주세요."); + String answerNumbers = readLine(); + System.out.println("보너스 번호를 입력해 주세요."); + int bonusLottoNumber = Integer.parseInt(readLine()); + List answerLottoNumbers = Stream.of(answerNumbers.split(",")) + .map(Integer::valueOf).collect(Collectors.toList()); + AnswerLotto answerLotto = new AnswerLotto(answerLottoNumbers, bonusLottoNumber); + + Map statistics = resultService.getStatistics(lottos, answerLotto.getAnswerNumbers(), answerLotto.getBonusNumber()); + double returnRate = resultService.getReturnRate(money); + + System.out.println("당첨 통계"); + System.out.println("---"); + System.out.println("3개 일치 (5,000원)" + "-" + statistics.get("THREE") + "개"); + System.out.println("4개 일치 (50,000원)" + "-" + statistics.get("FOUR") + "개"); + System.out.println("5개 일치 (1,500,000원)" + "-" + statistics.get("FIVE") + "개"); + System.out.println("5개 일치, 보너스 볼 일치 (30,000,000원)" + "-" + statistics.get("FIVEPLUSBONUS") + "개"); + System.out.println("6개 일치 (2,000,000,000원)" + "-" + statistics.get("SIX") + "개"); + System.out.println(String.format("총 수익률은 %.1f입니다.", returnRate)); + } + + private void buyLotto(int money) { + user = new User(generateLottos(money)); + } +} diff --git a/src/main/java/lotto/domain/Lotto/AnswerLotto.java b/src/main/java/lotto/domain/Lotto/AnswerLotto.java new file mode 100644 index 0000000..cc3abc6 --- /dev/null +++ b/src/main/java/lotto/domain/Lotto/AnswerLotto.java @@ -0,0 +1,50 @@ +package lotto.domain.Lotto; + +import java.util.List; + +public class AnswerLotto { + private List answerNumbers; + private int bonusNumber; + + public AnswerLotto(List answerNumbers, Integer bonusNumber) { + validateLottoSize(answerNumbers); + validateLottoHasDuplicate(answerNumbers); + validateLottoNumbersRange(answerNumbers); + this.answerNumbers = answerNumbers; + this.bonusNumber = bonusNumber; + } + + private void validateLottoSize(List numbers) { + if (numbers.size() != 6) { + throw new IllegalArgumentException("정답 로또 번호가 6자리가 아닙니다."); + } + } + + private void validateLottoHasDuplicate(List numbers) { + if (hasDuplicate(numbers)) { + throw new IllegalArgumentException("로또 번호에 중복된 번호가 있습니다."); + } + } + + private boolean hasDuplicate(List numbers) { + return numbers.stream().distinct().count() != 6; + } + + private void validateLottoNumbersRange(List numbers) { + if (isNotInRange(numbers)) { + throw new IllegalArgumentException("로또 번호 중에 1 ~ 45가 아닌 것이 있습니다."); + } + } + + private boolean isNotInRange(List numbers) { + return numbers.stream().anyMatch(number -> number < 1 || number > 45); + } + + public List getAnswerNumbers() { + return answerNumbers; + } + + public int getBonusNumber() { + return bonusNumber; + } +} diff --git a/src/main/java/lotto/domain/Lotto/Lotto.java b/src/main/java/lotto/domain/Lotto/Lotto.java new file mode 100644 index 0000000..3cf1cc9 --- /dev/null +++ b/src/main/java/lotto/domain/Lotto/Lotto.java @@ -0,0 +1,49 @@ +package lotto.domain.Lotto; + +import java.util.List; + +public class Lotto { + private final List numbers; + + public Lotto(List numbers) { + validateLottoSize(numbers); + validateLottoHasDuplicate(numbers); + validateLottoNumbersRange(numbers); + this.numbers = numbers; + } + + private void validateLottoSize(List numbers) { + if (numbers.size() != 6) { + throw new IllegalArgumentException("로또 번호가 6자리가 아닙니다."); + } + } + + private void validateLottoHasDuplicate(List numbers) { + if (hasDuplicate(numbers)) { + throw new IllegalArgumentException("로또 번호에 중복된 번호가 있습니다."); + } + } + + private boolean hasDuplicate(List numbers) { + return numbers.stream().distinct().count() != 6; + } + + private void validateLottoNumbersRange(List numbers) { + if (isNotInRange(numbers)) { + throw new IllegalArgumentException("로또 번호 중에 1 ~ 45가 아닌 것이 있습니다."); + } + } + + private boolean isNotInRange(List numbers) { + return numbers.stream().anyMatch(number -> number < 1 || number > 45); + } + + public List getNumbers() { + return numbers; + } + + @Override + public String toString() { + return numbers.toString(); + } +} diff --git a/src/main/java/lotto/domain/Lotto/LottoGenerator.java b/src/main/java/lotto/domain/Lotto/LottoGenerator.java new file mode 100644 index 0000000..d33a4ae --- /dev/null +++ b/src/main/java/lotto/domain/Lotto/LottoGenerator.java @@ -0,0 +1,30 @@ +package lotto.domain.Lotto; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.List; + +public class LottoGenerator { + private LottoGenerator() { + } + + public static List generateLottos(int money) { + List lottos = new ArrayList<>(); + final int quantity = money / 1000; + + for (int i = 0; i < quantity; i++) { + lottos.add(generateLotto()); + } + + return lottos; + } + + private static Lotto generateLotto() { + return new Lotto(getLottoNumbers()); + } + + private static List getLottoNumbers() { + return Randoms.pickUniqueNumbersInRange(1, 45, 6); + } +} diff --git a/src/main/java/lotto/domain/Lotto/MoneyGenerator.java b/src/main/java/lotto/domain/Lotto/MoneyGenerator.java new file mode 100644 index 0000000..ecce5b6 --- /dev/null +++ b/src/main/java/lotto/domain/Lotto/MoneyGenerator.java @@ -0,0 +1,43 @@ +package lotto.domain.Lotto; + +import static camp.nextstep.edu.missionutils.Console.readLine; + +public class MoneyGenerator { + private MoneyGenerator() { + } + + public static int generateMoney() { + int money = inputMoney(); + validateMoney(money); + return money; + } + + private static int inputMoney() { + String inputMoney = readLine(); + return convertMoneyTypeStringToInt(inputMoney); + } + + private static int convertMoneyTypeStringToInt(String inputMoney) { + return Integer.parseInt(inputMoney); + } + private static void validateMoney(int money) { + validateMoneyIsPositive(money); + validateMoneyIsMultiplesOfPrice(money); + } + + private static void validateMoneyIsPositive(int money) { + if (money < 0) { + throw new IllegalArgumentException("구입금액은 음수를 입력할 수 없습니다."); + } + } + + private static void validateMoneyIsMultiplesOfPrice(int money) { + if (isNotMultiplesOfPrice(money)) { + throw new IllegalArgumentException("구입금액은 1000의 배수여야 합니다."); + } + } + + private static boolean isNotMultiplesOfPrice(int money) { + return (money / 1000) < 0 || (money % 1000) > 0; + } +} diff --git a/src/main/java/lotto/domain/user/User.java b/src/main/java/lotto/domain/user/User.java new file mode 100644 index 0000000..e999cea --- /dev/null +++ b/src/main/java/lotto/domain/user/User.java @@ -0,0 +1,17 @@ +package lotto.domain.user; + +import lotto.domain.Lotto.Lotto; + +import java.util.List; + +public class User { + private List lottos; + + public User(List lottos) { + this.lottos = lottos; + } + + public List getLottos() { + return lottos; + } +} diff --git a/src/main/java/lotto/service/ResultService.java b/src/main/java/lotto/service/ResultService.java new file mode 100644 index 0000000..43e02ed --- /dev/null +++ b/src/main/java/lotto/service/ResultService.java @@ -0,0 +1,68 @@ +package lotto.service; + +import lotto.domain.Lotto.Lotto; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ResultService { + private Map collectMap = new HashMap<>(){{ + put(3, "THREE"); + put(4, "FOUR"); + put(5, "FIVE"); + put(6, "SIX"); + }}; + private Map statisticCollectCntMap = new HashMap<>(){{ + put("THREE", 0); + put("FOUR", 0); + put("FIVE", 0); + put("FIVEPLUSBONUS", 0); + put("SIX", 0); + }}; + + public Map getStatistics(List userLottos, List answerNumbers, int bonusNumber) { + int bonusCnt; + int collectCnt; + + for (Lotto userLotto : userLottos) { + List eachLottoNumbers = userLotto.getNumbers(); + bonusCnt = isContainsBonusNumber(eachLottoNumbers, bonusNumber); + collectCnt = getCollectCnt(eachLottoNumbers, answerNumbers); + + try { + if (bonusCnt == 1 && collectCnt == 5) { + statisticCollectCntMap.compute("FIVEPLUSBONUS", (k, v) -> Integer.valueOf(v + 1)); + } else { + statisticCollectCntMap.compute(collectMap.get(collectCnt), (k, v) -> Integer.valueOf(v + 1)); + } + } catch (NullPointerException e) { + + } + } + + return statisticCollectCntMap; + } + + private int isContainsBonusNumber(List eachLottoNumbers, Integer bonusNumber) { + if (eachLottoNumbers.contains(bonusNumber)) { + return 1; + } + return 0; + } + + private int getCollectCnt(List eachLottoNumbers, List answerNumbers) { + eachLottoNumbers.retainAll(answerNumbers); + return eachLottoNumbers.size(); + } + + public double getReturnRate(int money) { + return (double) 100 * ( + statisticCollectCntMap.get("THREE") * 5000 + + statisticCollectCntMap.get("FOUR") * 50000 + + statisticCollectCntMap.get("FIVE") * 1500000 + + statisticCollectCntMap.get("FIVEPLUSBONUS") * 30000000 + + statisticCollectCntMap.get("SIX") * 2000000000 + ) / money; + } +} diff --git a/src/test/java/lotto/LottoTest.java b/src/test/java/lotto/LottoTest.java index 0f3af0f..231ba81 100644 --- a/src/test/java/lotto/LottoTest.java +++ b/src/test/java/lotto/LottoTest.java @@ -1,5 +1,6 @@ package lotto; +import lotto.domain.Lotto.Lotto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -22,6 +23,12 @@ void createLottoByDuplicatedNumber() { assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5))) .isInstanceOf(IllegalArgumentException.class); } - - // 아래에 추가 테스트 작성 가능 + + @Test + @DisplayName("로또 번호에 1 ~ 45 외 범위의 숫자가 있으면 예외가 발생한다.") + void lottoNumberIsNotInRange() { + // then + assertThatThrownBy(() -> new Lotto(List.of(66, 1, 2))) + .isInstanceOf(IllegalArgumentException.class); + } } diff --git a/src/test/java/lotto/domain/Lotto/AnswerLottoTest.java b/src/test/java/lotto/domain/Lotto/AnswerLottoTest.java new file mode 100644 index 0000000..82dbaac --- /dev/null +++ b/src/test/java/lotto/domain/Lotto/AnswerLottoTest.java @@ -0,0 +1,56 @@ +package lotto.domain.Lotto; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class AnswerLottoTest { + @Test + @DisplayName("당첨 번호 6자리와 보너스 번호 1자리를 입력하면 당첨 로또를 선언할 수 있다.") + void canCreateAnswerLotto() { + // given + List answerNumberList = List.of(1, 2, 3, 4, 5, 6); + Integer bonusNumber = 1; + AnswerLotto answerLotto = new AnswerLotto(answerNumberList, bonusNumber); + + // then + assertThat(answerLotto.getAnswerNumbers()).isEqualTo(answerNumberList); + } + + @Test + @DisplayName("당첨 로또 번호가 6개가 아니면 예외가 발생한다.") + void throwException_wrongSize() { + // given + List answerNumberList = List.of(1, 2, 3, 4, 5); + + // then + assertThatThrownBy(() -> new AnswerLotto(answerNumberList, 0)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("당첨 로또 번호에 중복이 있으면 예외가 발생한다.") + void throwException_hasDuplicate() { + // given + List answerNumberList = List.of(1, 2, 5, 4, 5, 6); + + // then + assertThatThrownBy(() -> new AnswerLotto(answerNumberList, 0)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("당첨 로또 번호가 범위를 넘어가면 예외가 발생한다.") + void throwException_invalidRange() { + // given + List answerNumberList = List.of(1, 2, 5, 4, 5, 6); + + // then + assertThatThrownBy(() -> new AnswerLotto(answerNumberList, 0)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/Lotto/MoneyGeneratorTest.java b/src/test/java/lotto/domain/Lotto/MoneyGeneratorTest.java new file mode 100644 index 0000000..7ec3e76 --- /dev/null +++ b/src/test/java/lotto/domain/Lotto/MoneyGeneratorTest.java @@ -0,0 +1,63 @@ +package lotto.domain.Lotto; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.stream.Stream; + +import static lotto.domain.Lotto.MoneyGenerator.generateMoney; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class MoneyGeneratorTest { + private InputStream in; + + @AfterEach + void afterEach() throws IOException { + in.close(); + } + + @Test + @DisplayName("올바른 구입 금액(1000원 단위로 1000의 배수 구입 금액)은 입력할 수 있다.") + void createMoneyValidFormat() { + // given + String money = "5000"; + in = new ByteArrayInputStream(money.getBytes()); + + // when + System.setIn(in); + + // then + assertThat(5000).isEqualTo(generateMoney()); + } + + @ParameterizedTest + @MethodSource("invalidMoney") + @DisplayName("올바른 구입 금액(1000원 단위로 1000의 배수 구입 금액)이 아니면 예외가 발생한다.") + void createMoneyInvalidFormat(String money) { + // given + in = new ByteArrayInputStream(money.getBytes()); + + // when + System.setIn(in); + + // then + assertThatThrownBy(() -> generateMoney()) + .isInstanceOf(IllegalArgumentException.class); + } + + private static Stream invalidMoney() { + return Stream.of( + Arguments.of("5001"), + Arguments.of("500"), + Arguments.of("-1000") + ); + } +} \ No newline at end of file diff --git a/src/test/java/lotto/domain/user/LottoGeneratorTest.java b/src/test/java/lotto/domain/user/LottoGeneratorTest.java new file mode 100644 index 0000000..8476ae4 --- /dev/null +++ b/src/test/java/lotto/domain/user/LottoGeneratorTest.java @@ -0,0 +1,26 @@ +package lotto.domain.user; + +import lotto.domain.Lotto.Lotto; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static lotto.domain.Lotto.LottoGenerator.generateLottos; +import static org.assertj.core.api.Assertions.assertThat; + +class LottoGeneratorTest { + @Test + @DisplayName("입력한 돈에 따른 갯수의 로또를 발행한다.") + void generateLotto() { + // given + int money = 8000; + int quantity = money / 1000; + + // when + List lottos = generateLottos(money); + + // then + assertThat(lottos.size()).isEqualTo(quantity); + } +} diff --git a/src/test/java/lotto/service/ResultServiceTest.java b/src/test/java/lotto/service/ResultServiceTest.java new file mode 100644 index 0000000..9637926 --- /dev/null +++ b/src/test/java/lotto/service/ResultServiceTest.java @@ -0,0 +1,282 @@ +package lotto.service; + +import lotto.domain.Lotto.Lotto; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +class ResultServiceTest { + private ResultService resultService; + + @BeforeEach + void beforeEach() { + resultService = new ResultService(); + } + + @Test + @DisplayName("3개 일치 1개 당첨 통계를 구한다.") + void getStatisticsOneThreeCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 11, 12, 13))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + Map statistics = resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(statistics.get("THREE")).isEqualTo(1), + () -> assertThat(statistics.get("FOUR")).isEqualTo(0), + () -> assertThat(statistics.get("FIVE")).isEqualTo(0), + () -> assertThat(statistics.get("FIVEPLUSBONUS")).isEqualTo(0), + () -> assertThat(statistics.get("SIX")).isEqualTo(0) + ); + } + + @Test + @DisplayName("4개 일치 1개 당첨 통계를 구한다.") + void getStatisticsOneFourCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 11, 12))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + Map statistics = resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(statistics.get("THREE")).isEqualTo(0), + () -> assertThat(statistics.get("FOUR")).isEqualTo(1), + () -> assertThat(statistics.get("FIVE")).isEqualTo(0), + () -> assertThat(statistics.get("FIVEPLUSBONUS")).isEqualTo(0), + () -> assertThat(statistics.get("SIX")).isEqualTo(0) + ); + } + + @Test + @DisplayName("5개 일치 1개 당첨 통계를 구한다.") + void getStatisticsOneFiveCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 11))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + Map statistics = resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(statistics.get("THREE")).isEqualTo(0), + () -> assertThat(statistics.get("FOUR")).isEqualTo(0), + () -> assertThat(statistics.get("FIVE")).isEqualTo(1), + () -> assertThat(statistics.get("FIVEPLUSBONUS")).isEqualTo(0), + () -> assertThat(statistics.get("SIX")).isEqualTo(0) + ); + } + + @Test + @DisplayName("5개 일치, 보너스 볼 일치 1개 당첨 통계를 구한다.") + void getStatisticsBonusCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 7))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + Map statistics = resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(statistics.get("THREE")).isEqualTo(0), + () -> assertThat(statistics.get("FOUR")).isEqualTo(0), + () -> assertThat(statistics.get("FIVE")).isEqualTo(0), + () -> assertThat(statistics.get("FIVEPLUSBONUS")).isEqualTo(1), + () -> assertThat(statistics.get("SIX")).isEqualTo(0) + ); + } + + @Test + @DisplayName("6개 일치 1개 당첨 통계를 구한다.") + void getStatisticsOneSixCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 6))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + Map statistics = resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(statistics.get("THREE")).isEqualTo(0), + () -> assertThat(statistics.get("FOUR")).isEqualTo(0), + () -> assertThat(statistics.get("FIVE")).isEqualTo(0), + () -> assertThat(statistics.get("FIVEPLUSBONUS")).isEqualTo(0), + () -> assertThat(statistics.get("SIX")).isEqualTo(1) + ); + } + + @Test + @DisplayName("6개 일치 2개 당첨 통계를 구한다.") + void getStatisticsTwoSixCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 6))), + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 6))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + Map statistics = resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + + // then + assertAll( + () -> assertThat(statistics.get("THREE")).isEqualTo(0), + () -> assertThat(statistics.get("FOUR")).isEqualTo(0), + () -> assertThat(statistics.get("FIVE")).isEqualTo(0), + () -> assertThat(statistics.get("FIVEPLUSBONUS")).isEqualTo(0), + () -> assertThat(statistics.get("SIX")).isEqualTo(2) + ); + } + + + @Test + @DisplayName("3개 일치 총 수익률을 계산한다.") + void getReturnRateThreeCollecth() { + } + + @Test + @DisplayName("3개 일치 총 수익률을 계산한다.") + void getReturnRateThreeCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 11, 12, 13))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + int money = 1000; + double returnRate = resultService.getReturnRate(money); + + // then + assertThat(returnRate).isEqualTo(100 * 5000 / money); + } + + @Test + @DisplayName("4개 일치 총 수익률을 계산한다.") + void getReturnRateFourCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 11, 12))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + int money = 1000; + double returnRate = resultService.getReturnRate(money); + + // then + assertThat(returnRate).isEqualTo(100 * 50000 / money); + } + + @Test + @DisplayName("5개 일치 총 수익률을 계산한다.") + void getReturnRateFiveCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 11))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + int money = 1000; + double returnRate = resultService.getReturnRate(money); + + // then + assertThat(returnRate).isEqualTo(100d * 1500000 / money); + } + + @Test + @DisplayName("5개 일치, 보너스 일치 총 수익률을 계산한다.") + void getReturnRateBonusCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 7))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + int money = 1000; + double returnRate = resultService.getReturnRate(money); + + // then + assertThat(returnRate).isEqualTo(100d * 30000000 / money); + } + + @Test + @DisplayName("6개 일치 총 수익률을 계산한다.") + void getReturnRateSixCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 6))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + int money = 1000; + double returnRate = resultService.getReturnRate(money); + + // then + assertThat(returnRate).isEqualTo(100d * 2000000000 / money); + } + + @Test + @DisplayName("6개 일치 2개 총 수익률을 계산한다.") + void getReturnRateTwoSixCollect() { + // given + List userLottos = List.of( + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 6))), + new Lotto(new ArrayList<>(List.of(1, 2, 3, 4, 5, 6))) + ); + List answerNumbers = List.of(1, 2, 3, 4, 5, 6); + int bonusNumber = 7; + + // when + resultService.getStatistics(userLottos, answerNumbers, bonusNumber); + int money = 2000; + double returnRate = resultService.getReturnRate(money); + + // then + assertThat(returnRate).isEqualTo((double) 100 * (2 * 2000000000) / money); + } +}