diff --git a/src/main/java/com/javabom/lotto/LottoApplication.java b/src/main/java/com/javabom/lotto/LottoApplication.java index 13f852e..9588963 100644 --- a/src/main/java/com/javabom/lotto/LottoApplication.java +++ b/src/main/java/com/javabom/lotto/LottoApplication.java @@ -1,7 +1,33 @@ package com.javabom.lotto; +import com.javabom.lotto.domain.results.LottoLuckyNumbers; +import com.javabom.lotto.domain.results.LottoResults; +import com.javabom.lotto.domain.ticket.*; +import com.javabom.lotto.view.InputView; +import com.javabom.lotto.view.OutputView; + +import java.util.List; + public class LottoApplication { public static void main(String[] args) { + Money inputMoney = new Money(InputView.getMoneyToBuyTicket()); + + int manualLottoAmount = InputView.getManualLottoAmount(); + List manualLottoNumbers = InputView.getManualLottoNumbers(manualLottoAmount); + + LottoTicketDispenser lottoTicketDispenser = new LottoTicketDispenser(new RandomLottoTicketGenerator()); + LottoTickets manualLottoTickets = lottoTicketDispenser.getManualTickets(inputMoney, manualLottoNumbers); + Money restMoney = inputMoney.spend(LottoTicketDispenser.getTotalTicketPrice(manualLottoAmount)); + LottoTickets autoLottoTickets = lottoTicketDispenser.getAutoTickets(restMoney); + OutputView.printLottoTickets(manualLottoTickets, autoLottoTickets); + + LottoTicket basicLuckyTicket = new LottoTicket(LottoNumberConverter.convert(InputView.getLottoBasicLuckyNumbers())); + LottoNumber bonusNumber = new LottoNumber(InputView.getBonusNumber()); + LottoLuckyNumbers luckyNumbers = new LottoLuckyNumbers(basicLuckyTicket, bonusNumber); + LottoTickets wholeLottoTickets = autoLottoTickets.add(manualLottoTickets); + LottoResults lottoResults = wholeLottoTickets.getLottoResults(luckyNumbers); + OutputView.printLottoResults(lottoResults); + OutputView.printEarningRate(inputMoney, lottoResults.getTotalPrizeMoney()); } } diff --git a/src/main/java/com/javabom/lotto/domain/results/LottoLuckyNumbers.java b/src/main/java/com/javabom/lotto/domain/results/LottoLuckyNumbers.java new file mode 100644 index 0000000..6e5cfe2 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/results/LottoLuckyNumbers.java @@ -0,0 +1,31 @@ +package com.javabom.lotto.domain.results; + +import com.javabom.lotto.domain.ticket.LottoNumber; +import com.javabom.lotto.domain.ticket.LottoTicket; + +public class LottoLuckyNumbers { + + private final LottoTicket basicLuckyTicket; + private final LottoNumber bonusNumber; + + public LottoLuckyNumbers(LottoTicket basicLuckyTicket, LottoNumber bonusNumber) { + this.basicLuckyTicket = basicLuckyTicket; + this.bonusNumber = bonusNumber; + validateDuplicatedBonusNumber(); + } + + private void validateDuplicatedBonusNumber() { + if (this.basicLuckyTicket.isContain(bonusNumber)) { + throw new IllegalStateException( + String.format("보너스 숫자 %s는 기본 당첨번호와 중복 될 수 없습니다.", bonusNumber.toString()) + ); + } + } + + public LottoResult getLottoResult(LottoTicket lottoTicket) { + int matchCounts = lottoTicket.countMatchingNumbers(basicLuckyTicket); + boolean isBonusMatched = lottoTicket.isContain(bonusNumber); + return LottoResult.find(matchCounts, isBonusMatched); + } + +} diff --git a/src/main/java/com/javabom/lotto/domain/results/LottoResult.java b/src/main/java/com/javabom/lotto/domain/results/LottoResult.java new file mode 100644 index 0000000..759e1ac --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/results/LottoResult.java @@ -0,0 +1,54 @@ +package com.javabom.lotto.domain.results; + +import java.util.Arrays; + +public enum LottoResult { + + FIRST_PRIZE(6, 2_000_000_000), + SECOND_PRIZE(5, 30_000_000), + THIRD_PRIZE(5, 1_500_000), + FOURTH_PRIZE(4, 50_000), + FIFTH_PRIZE(3, 5_000), + LOSE(-1, 0); + + private final int matchCount; + private final long prize; + + LottoResult(int matchCount, long prize) { + this.matchCount = matchCount; + this.prize = prize; + } + + public static LottoResult find(final int matchCount, final boolean isBonusMatched) { + validateMatchCount(matchCount); + if (matchCount == SECOND_PRIZE.matchCount) { + return findByBonus(isBonusMatched); + } + return Arrays.stream(values()) + .filter(result -> result.matchCount == matchCount) + .findFirst() + .orElse(LOSE); + } + + private static void validateMatchCount(final int matchCount) { + if (matchCount < 0 || matchCount > 6) { + throw new IllegalArgumentException("로또번호 매치 수는 0~6 이외일 수 없습니다."); + } + } + + private static LottoResult findByBonus(final boolean isBonusMatched) { + if (isBonusMatched) { + return SECOND_PRIZE; + } + return THIRD_PRIZE; + } + + public long getPrize() { + return prize; + } + + public int getMatchCount() { + return matchCount; + } + +} diff --git a/src/main/java/com/javabom/lotto/domain/results/LottoResults.java b/src/main/java/com/javabom/lotto/domain/results/LottoResults.java new file mode 100644 index 0000000..d758d60 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/results/LottoResults.java @@ -0,0 +1,42 @@ +package com.javabom.lotto.domain.results; + +import com.javabom.lotto.domain.ticket.Money; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class LottoResults { + + private final List lottoResults; + + public LottoResults(List lottoResults) { + this.lottoResults = lottoResults; + } + + public List findResultsOf(LottoResult lottoResult) { + return lottoResults.stream() + .filter(result -> result == lottoResult) + .collect(Collectors.toList()); + } + + public Money getTotalPrizeMoney() { + long sum = lottoResults.stream() + .mapToLong(LottoResult::getPrize) + .sum(); + return new Money(sum); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LottoResults that = (LottoResults) o; + return Objects.equals(lottoResults, that.lottoResults); + } + + @Override + public int hashCode() { + return Objects.hash(lottoResults); + } +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoNumber.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoNumber.java new file mode 100644 index 0000000..c7e4bcf --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoNumber.java @@ -0,0 +1,40 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.Objects; + +public class LottoNumber { + public static final int MIN_LOTTO_NUM = 1; + public static final int MAX_LOTTO_NUM = 45; + + private final int number; + + public LottoNumber(int number) { + validateNumber(number); + this.number = number; + } + + private void validateNumber(int number) { + if (number < MIN_LOTTO_NUM || number > MAX_LOTTO_NUM) { + throw new IllegalArgumentException("로또 번호는 1~45이외 일 수 없습니다. 입력 값 : " + number); + } + } + + @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); + } + + @Override + public String toString() { + return String.valueOf(number); + } + +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoNumberConverter.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoNumberConverter.java new file mode 100644 index 0000000..8daabb3 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoNumberConverter.java @@ -0,0 +1,17 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.List; +import java.util.stream.Collectors; + +public class LottoNumberConverter { + + private LottoNumberConverter() { + } + + public static List convert(List lottoNumbers) { + return lottoNumbers.stream() + .map(LottoNumber::new) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoTicket.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicket.java new file mode 100644 index 0000000..8964179 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicket.java @@ -0,0 +1,52 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.List; +import java.util.Objects; + +public class LottoTicket { + + private static final int LOTTO_NUM_PICK_SIZE = 6; + + private final List numbers; + + public LottoTicket(List numbers) { + validateLottoNumbers(numbers); + this.numbers = numbers; + } + + private void validateLottoNumbers(List numbers) { + if (numbers.size() != LOTTO_NUM_PICK_SIZE) { + throw new IllegalArgumentException(String.format("로또 티켓에 6개 숫자를 넣어야 합니다. 입력 size : %d", numbers.size())); + } + } + + public int countMatchingNumbers(LottoTicket lottoTicket) { + int count = 0; + for (int i = 0; i < LOTTO_NUM_PICK_SIZE; i++) { + if (this.numbers.get(i).equals(lottoTicket.numbers.get(i))) count++; + } + return count; + } + + public boolean isContain(LottoNumber number) { + return numbers.contains(number); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LottoTicket ticket = (LottoTicket) o; + return Objects.equals(numbers, ticket.numbers); + } + + @Override + public int hashCode() { + return Objects.hash(numbers); + } + + @Override + public String toString() { + return String.valueOf(numbers); + } +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoTicketDispenser.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicketDispenser.java new file mode 100644 index 0000000..db0bfcf --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicketDispenser.java @@ -0,0 +1,47 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class LottoTicketDispenser { + + private static final Money LOTTO_TICKET_PRICE = new Money(1_000); + + private final LottoTicketGenerator lottoTicketGenerator; + + public LottoTicketDispenser(LottoTicketGenerator lottoTicketGenerator) { + this.lottoTicketGenerator = lottoTicketGenerator; + } + + static public Money getTotalTicketPrice(int amount) { + return LOTTO_TICKET_PRICE.multiply(amount); + } + + public LottoTickets getAutoTickets(Money inputMoney) { + int quantity = inputMoney.calculateQuantityPer(LOTTO_TICKET_PRICE); + List tickets = new ArrayList<>(); + for (int i = 0; i < quantity; i++) { + LottoTicket lottoTicket = lottoTicketGenerator.getLottoTicket(); + tickets.add(lottoTicket); + } + return new LottoTickets(tickets); + } + + public LottoTickets getManualTickets(Money inputMoney, List manualNumbers) { + validateEnoughMoney(inputMoney, manualNumbers.size()); + return new LottoTickets(manualNumbers.stream() + .map(ManualLottoNumbers::toLottoTicket) + .collect(Collectors.toList())); + } + + private void validateEnoughMoney(Money inputMoney, int quantity) { + Money totalPrice = LOTTO_TICKET_PRICE.multiply(quantity); + if (totalPrice.isBiggerThan(inputMoney)) { + throw new IllegalStateException(String.format("%d개의 티켓을 사기에 돈이 모자랍니다. 넣은 금액 : %s", quantity, inputMoney.toString())); + } + } + // 여기서 그냥 inputMoney.spend(totalPrice); 한줄만 때리려했는데, (spend 내부에 금액 검사 로직이 있어서) + // 다른사람이 볼 때 이게뭐야? 할거같고, inputMoney내부의 상태값이 바뀌는듯한 인상을 주어 + // 이렇게 바꿨는데.. 어떻게 생각하시나요? +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoTicketGenerator.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicketGenerator.java new file mode 100644 index 0000000..4b615be --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoTicketGenerator.java @@ -0,0 +1,7 @@ +package com.javabom.lotto.domain.ticket; + +public interface LottoTicketGenerator { + + LottoTicket getLottoTicket(); + +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/LottoTickets.java b/src/main/java/com/javabom/lotto/domain/ticket/LottoTickets.java new file mode 100644 index 0000000..d732069 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/LottoTickets.java @@ -0,0 +1,50 @@ +package com.javabom.lotto.domain.ticket; + +import com.javabom.lotto.domain.results.LottoLuckyNumbers; +import com.javabom.lotto.domain.results.LottoResult; +import com.javabom.lotto.domain.results.LottoResults; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class LottoTickets { + + private final List tickets; + + public LottoTickets(List tickets) { + this.tickets = tickets; + } + + public List get() { + return Collections.unmodifiableList(tickets); + } + + public LottoTickets add(LottoTickets lottoTickets) { + List newTickets = new ArrayList<>(); + newTickets.addAll(this.tickets); + newTickets.addAll(lottoTickets.tickets); + return new LottoTickets(newTickets); + } + + public LottoResults getLottoResults(LottoLuckyNumbers lottoLuckyNumbers) { + return new LottoResults(tickets.stream() + .map(lottoLuckyNumbers::getLottoResult) + .collect(Collectors.toList())); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LottoTickets that = (LottoTickets) o; + return Objects.equals(tickets, that.tickets); + } + + @Override + public int hashCode() { + return Objects.hash(tickets); + } +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/ManualLottoNumbers.java b/src/main/java/com/javabom/lotto/domain/ticket/ManualLottoNumbers.java new file mode 100644 index 0000000..a982664 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/ManualLottoNumbers.java @@ -0,0 +1,20 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.List; +import java.util.stream.Collectors; + +public class ManualLottoNumbers { + + private final List numbers; + + public ManualLottoNumbers(List numbers) { + this.numbers = numbers; + } + + public LottoTicket toLottoTicket() { + return new LottoTicket(numbers.stream() + .map(LottoNumber::new) + .collect(Collectors.toList()) + ); + } +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/Money.java b/src/main/java/com/javabom/lotto/domain/ticket/Money.java new file mode 100644 index 0000000..4c7549d --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/Money.java @@ -0,0 +1,64 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.Objects; + +public class Money { + + private final long value; + + public Money(long money) { + validateMoney(money); + value = money; + } + + private void validateMoney(long money) { + if (money < 0) { + throw new IllegalArgumentException("돈은 음수일 수 없습니다. 입력값 : " + money); + } + } + + public Money multiply(int value) { + return new Money(this.value * value); + } + + public boolean isBiggerThan(Money money) { + return this.value > money.value; + } + + public Money spend(Money money) { + validateCanSpendMoney(money); + return new Money(this.value - money.value); + } + + private void validateCanSpendMoney(Money money) { + if (money.value > this.value) { + throw new IllegalArgumentException(String.format("현재 값 (%d) 보다 사용하려는 금액 (%d) 이 더 많습니다.", value, money.value)); + } + } + + public int calculateQuantityPer(Money price) { + return (int) (value / price.value); + } + + public double calculateRatioOf(Money input) { + return (double) input.value / this.value * 100; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Money money1 = (Money) o; + return value == money1.value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/com/javabom/lotto/domain/ticket/RandomLottoTicketGenerator.java b/src/main/java/com/javabom/lotto/domain/ticket/RandomLottoTicketGenerator.java new file mode 100644 index 0000000..d6d2385 --- /dev/null +++ b/src/main/java/com/javabom/lotto/domain/ticket/RandomLottoTicketGenerator.java @@ -0,0 +1,31 @@ +package com.javabom.lotto.domain.ticket; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class RandomLottoTicketGenerator implements LottoTicketGenerator { + + private static final int LOTTO_NUM_PICK_SIZE = 6; + + private final List sortedLottoNumbers; + + public RandomLottoTicketGenerator() { + sortedLottoNumbers = createSortedLottoNumbers(); + } + + private List createSortedLottoNumbers() { + return IntStream.rangeClosed(LottoNumber.MIN_LOTTO_NUM, LottoNumber.MAX_LOTTO_NUM) + .mapToObj(LottoNumber::new) + .collect(Collectors.toList()); + } + + @Override + public LottoTicket getLottoTicket() { + List numbers = new ArrayList<>(sortedLottoNumbers); + Collections.shuffle(numbers); + return new LottoTicket(numbers.subList(0, LOTTO_NUM_PICK_SIZE)); + } +} diff --git a/src/main/java/com/javabom/lotto/view/InputView.java b/src/main/java/com/javabom/lotto/view/InputView.java new file mode 100644 index 0000000..3a67d58 --- /dev/null +++ b/src/main/java/com/javabom/lotto/view/InputView.java @@ -0,0 +1,63 @@ +package com.javabom.lotto.view; + +import com.javabom.lotto.domain.ticket.ManualLottoNumbers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +public class InputView { + + private static final String DELIMITER_COMMA = ","; + private static final String NOTICE_INPUT_MONEY = "구입 금액을 입력해 주세요. 잔돈은 없습니다 ^^"; + private static final String NOTICE_INPUT_BASIC_LUCKY_NUMBER = "지난 주 당첨 번호를 입력해 주세요. (,로 나눠서 입력)"; + private static final String NOTICE_INPUT_BONUS_NUMBER = "보너스 볼을 입력해 주세요."; + private static final String NOTICE_INPUT_MANUAL_LOTTO_AMOUNT = "수동으로 구매할 로또 수를 입력해 주세요."; + private static final String NOTICE_INPUT_MANUAL_LOTTO_NUMBER = "수동으로 구매할 번호를 입력해 주세요."; + + private static final Scanner scanner = new Scanner(System.in); + + public static int getMoneyToBuyTicket() { + printLineOf(NOTICE_INPUT_MONEY); + return Integer.parseInt(scanner.nextLine()); + } + + public static List getLottoBasicLuckyNumbers() { + printLineOf(NOTICE_INPUT_BASIC_LUCKY_NUMBER); + return Arrays.stream(scanner.nextLine().split(DELIMITER_COMMA)) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } + + public static int getBonusNumber() { + printLineOf(NOTICE_INPUT_BONUS_NUMBER); + return scanner.nextInt(); + } + + public static int getManualLottoAmount() { + printLineOf(NOTICE_INPUT_MANUAL_LOTTO_AMOUNT); + return Integer.parseInt(scanner.nextLine()); + } + + public static List getManualLottoNumbers(int amount) { + printLineOf(NOTICE_INPUT_MANUAL_LOTTO_NUMBER); + List manualLottoNumbers = new ArrayList<>(); + for (int i = 0; i < amount; i++) { + manualLottoNumbers.add(new ManualLottoNumbers(getManualLottoNumber())); + } + return manualLottoNumbers; + } + + public static List getManualLottoNumber() { + return Arrays.stream(scanner.nextLine().split(DELIMITER_COMMA)) + .map(Integer::parseInt) + .collect(Collectors.toList()); + } + + private static void printLineOf(String string) { + System.out.println(string); + } + +} diff --git a/src/main/java/com/javabom/lotto/view/OutputView.java b/src/main/java/com/javabom/lotto/view/OutputView.java new file mode 100644 index 0000000..aff7cb6 --- /dev/null +++ b/src/main/java/com/javabom/lotto/view/OutputView.java @@ -0,0 +1,58 @@ +package com.javabom.lotto.view; + +import com.javabom.lotto.domain.results.LottoResult; +import com.javabom.lotto.domain.results.LottoResults; +import com.javabom.lotto.domain.ticket.LottoTicket; +import com.javabom.lotto.domain.ticket.LottoTickets; +import com.javabom.lotto.domain.ticket.Money; + +public class OutputView { + + private static final String NOTICE_BUY_COMPLETE = "수동으로 %d장, 자동으로 %d개를 구매했습니다."; + private static final String NOTICE_WINNING_STATISTICS = "당첨 통계"; + private static final String NOTICE_MATCH_QUANTITY = "%d개 일치, "; + private static final String NOTICE_PRIZE_MONEY = "(%d원)"; + private static final String NOTICE_MATCH_RESULT_QUANTITY = " - %d개"; + private static final String NOTICE_MATCH_BONUS = "보너스 볼 일치"; + private static final String NOTICE_EARNING_RATE = "총 수익률은 %.2f%% 입니다."; + + public static void printLottoTickets(LottoTickets manualLottoTickets, LottoTickets autoLottoTickets) { + printLineOf(String.format(NOTICE_BUY_COMPLETE, manualLottoTickets.get().size(), autoLottoTickets.get().size())); + for (LottoTicket lottoTicket : manualLottoTickets.get()) { + printLineOf(lottoTicket.toString()); + } + for (LottoTicket lottoTicket : autoLottoTickets.get()) { + printLineOf(lottoTicket.toString()); + } + } + + public static void printLottoResults(LottoResults lottoResults) { + printLineOf(NOTICE_WINNING_STATISTICS); + for (LottoResult resultKind : LottoResult.values()) { + long resultSize = lottoResults.findResultsOf(resultKind).size(); + printLottoResult(resultKind, resultSize); + } + } + + private static void printLottoResult(LottoResult result, long resultSize) { + if (result == LottoResult.LOSE) return; + StringBuilder stringBuilder = new StringBuilder() + .append(String.format(NOTICE_MATCH_QUANTITY, result.getMatchCount())); + if (result == LottoResult.SECOND_PRIZE) { + stringBuilder.append(NOTICE_MATCH_BONUS); + } + stringBuilder + .append(String.format(NOTICE_PRIZE_MONEY, result.getPrize())) + .append(String.format(NOTICE_MATCH_RESULT_QUANTITY, resultSize)); + printLineOf(stringBuilder.toString()); + } + + public static void printEarningRate(Money spendMoney, Money earnMoney) { + double rate = spendMoney.calculateRatioOf(earnMoney); + printLineOf(String.format(NOTICE_EARNING_RATE, rate)); + } + + private static void printLineOf(String string) { + System.out.println(string); + } +} diff --git a/src/test/java/com/javabom/lotto/domain/results/LottoLuckyNumbersTest.java b/src/test/java/com/javabom/lotto/domain/results/LottoLuckyNumbersTest.java new file mode 100644 index 0000000..4ee31ab --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/results/LottoLuckyNumbersTest.java @@ -0,0 +1,44 @@ +package com.javabom.lotto.domain.results; + +import com.javabom.lotto.domain.ticket.LottoNumber; +import com.javabom.lotto.domain.ticket.LottoTicket; +import com.javabom.lotto.domain.ticket.LottoTickets; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static com.javabom.lotto.domain.results.LottoResult.FIRST_PRIZE; +import static org.assertj.core.api.Assertions.assertThat; + +class LottoLuckyNumbersTest { + + @DisplayName("로또 결과를 잘 계산해 내는지 확인") + @Test + void getLottoResults() { + // given + List stubLottoNumbers = Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + ); + + LottoNumber bonusNumber = new LottoNumber(7); + LottoTicket basicLuckyTicket = new LottoTicket(stubLottoNumbers); + + LottoLuckyNumbers lottoLuckyNumbers = new LottoLuckyNumbers(basicLuckyTicket, bonusNumber); + + // when + LottoTickets allMatchLottoTicket = new LottoTickets(Arrays.asList(new LottoTicket(stubLottoNumbers))); + LottoResults lottoResults = allMatchLottoTicket.getLottoResults(lottoLuckyNumbers); + LottoResults expectedLottoResults = new LottoResults(Arrays.asList(FIRST_PRIZE)); + + // then + assertThat(lottoResults).isEqualTo(expectedLottoResults); + } +} diff --git a/src/test/java/com/javabom/lotto/domain/results/LottoResultTest.java b/src/test/java/com/javabom/lotto/domain/results/LottoResultTest.java new file mode 100644 index 0000000..7ec1b34 --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/results/LottoResultTest.java @@ -0,0 +1,40 @@ +package com.javabom.lotto.domain.results; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoResultTest { + + @DisplayName("로또 번호 매치 가능 수는 0~6 사이임.") + @CsvSource({"-1", "7"}) + @ParameterizedTest + void validateMatchCount(int matchCount) { + // then + assertThatThrownBy(() -> LottoResult.find(matchCount, true)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또번호 매치 수는 0~6 이외일 수 없습니다."); + } + + @DisplayName("로또 번호 매치수와 보너스 매치여부에 따른 로또 결과 확인") + @CsvSource({ + "6,false,FIRST_PRIZE", + "5,true,SECOND_PRIZE", + "5,false,THIRD_PRIZE", + "4,false,FOURTH_PRIZE", + "3,false,FIFTH_PRIZE", + "2,false,LOSE", + "1,false,LOSE", + "0,false,LOSE",}) + @ParameterizedTest + void find(int matchCount, boolean isBonusMatched, LottoResult expectedLottoResult) { + // given + LottoResult findLottoResult = LottoResult.find(matchCount, isBonusMatched); + + // then + assertThat(findLottoResult).isEqualTo(expectedLottoResult); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/results/LottoResultsTest.java b/src/test/java/com/javabom/lotto/domain/results/LottoResultsTest.java new file mode 100644 index 0000000..ea7eead --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/results/LottoResultsTest.java @@ -0,0 +1,45 @@ +package com.javabom.lotto.domain.results; + +import com.javabom.lotto.domain.ticket.Money; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static com.javabom.lotto.domain.results.LottoResult.FIFTH_PRIZE; +import static com.javabom.lotto.domain.results.LottoResult.FOURTH_PRIZE; +import static org.assertj.core.api.Assertions.assertThat; + +class LottoResultsTest { + + @DisplayName("원하는 로또 결과만을 담은 List를 반환하는지 확인") + @Test + void findResultsOf() { + // given + List lottoResultList = Arrays.asList( + FOURTH_PRIZE, + FOURTH_PRIZE, + FIFTH_PRIZE); + LottoResults lottoResults = new LottoResults(lottoResultList); + List expectedLottoResultList = Arrays.asList( + FOURTH_PRIZE, + FOURTH_PRIZE); + + // then + assertThat(lottoResults.findResultsOf(FOURTH_PRIZE)) + .isEqualTo(expectedLottoResultList); + } + + @Test + void getTotalPrizeMoney() { + // given + List lottoResultList = Arrays.asList(FOURTH_PRIZE, FIFTH_PRIZE); + LottoResults lottoResults = new LottoResults(lottoResultList); + Money expectedTotalPrizeMoney = new Money(FOURTH_PRIZE.getPrize() + FIFTH_PRIZE.getPrize()); + + // then + assertThat(lottoResults.getTotalPrizeMoney()) + .isEqualTo(expectedTotalPrizeMoney); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoMoneyTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoMoneyTest.java new file mode 100644 index 0000000..029e8c4 --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoMoneyTest.java @@ -0,0 +1,56 @@ +package com.javabom.lotto.domain.ticket; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoMoneyTest { + + @DisplayName("돈에 음수가 들어가면 Exception") + @Test + void validateMoney() { + assertThatThrownBy(() -> new Money(-1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("돈은 음수일 수 없습니다. 입력값 : -1"); + } + + @DisplayName("인풋값에 대한 수량 가져오기") + @Test + void calculateQuantityPer() { + // given + Money money = new Money(10_000); + Money price = new Money(1_000); + int expectedQuantity = 10; + + // then + assertThat(money.calculateQuantityPer(price)).isEqualTo(expectedQuantity); + } + + @DisplayName("돈 소비할 때 제대로 남는 돈이 제대로 계산 되는지 확인") + @Test + void spend() { + // given + Money money = new Money(5_000); + Money spendMoney = new Money(2_000); + Money expectedMoney = new Money(3_000); + + // then + assertThat(money.spend(spendMoney)).isEqualTo(expectedMoney); + } + + @DisplayName("남은 돈 보다 더 많은 돈을 사용할 수는 없음.") + @Test + void validateCanSpendMoney() { + // given + Money bigMoney = new Money(5_000); + Money smallMoney = new Money(3_000); + // then + assertThatThrownBy(() ->smallMoney.spend(bigMoney)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("현재 값 (3000) 보다 사용하려는 금액 (5000) 이 더 많습니다."); + + + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberConverterTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberConverterTest.java new file mode 100644 index 0000000..b8b438e --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberConverterTest.java @@ -0,0 +1,31 @@ +package com.javabom.lotto.domain.ticket; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class LottoNumberConverterTest { + + @DisplayName("정수 리스트를 로또 넘버 리스트로 제대로 변환하는 지 검사") + @Test + void convert() { + // given + List stubNumbers = Arrays.asList(1, 2, 3, 4, 5, 6); + List expectedLottoNumbers = Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + ); + + // then + assertThat(LottoNumberConverter.convert(stubNumbers)) + .isEqualTo(expectedLottoNumbers); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberTest.java new file mode 100644 index 0000000..db736fe --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoNumberTest.java @@ -0,0 +1,22 @@ +package com.javabom.lotto.domain.ticket; + + +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 static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoNumberTest { + + @DisplayName("로또번호가 아닌 1~45 이외의 수 입력못함.") + @CsvSource({"0", "46"}) + @ParameterizedTest + void name(int number) { + assertThatThrownBy(() -> new LottoNumber(number)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 번호는 1~45이외 일 수 없습니다. 입력 값 : " + number); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketDispenserTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketDispenserTest.java new file mode 100644 index 0000000..cb61ee2 --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketDispenserTest.java @@ -0,0 +1,96 @@ +package com.javabom.lotto.domain.ticket; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoTicketDispenserTest { + + @DisplayName("로또 발급기가 원하는대로 로또 티켓을 발급하는지 확인") + @Test + void getAutoTickets() { + // given + List stubLottoNumbers = Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + ); + LottoTicket stubLottoTicket = new LottoTicket(stubLottoNumbers); + LottoTicketDispenser lottoTicketDispenser = new LottoTicketDispenser(() -> stubLottoTicket); + LottoTickets expectedLottoTickets = new LottoTickets(Arrays.asList(stubLottoTicket)); + + // when + Money money = new Money(1_000); + LottoTickets receivedLottoTicket = lottoTicketDispenser.getAutoTickets(money); + + // then + assertThat(receivedLottoTicket).isEqualTo(expectedLottoTickets); + } + + @DisplayName("로또 발급기가 원하는 개수의 티켓을 뽑아내는지 확인") + @Test + void name() { + // given + LottoTicketDispenser lottoTicketDispenser = new LottoTicketDispenser(new RandomLottoTicketGenerator()); + + // when + int expectedTicketQuantity = 1; + Money money = new Money(1_000 * expectedTicketQuantity); + LottoTickets lottoTickets = lottoTicketDispenser.getAutoTickets(money); + + // then + assertThat(lottoTickets.get()).hasSize(expectedTicketQuantity); + } + + @DisplayName("돈이 발급 해야할 티켓보다 적을 경우") + @Test + void validateEnoughMoney() { + // given + Money money = new Money(1_000); + List stubManualNumbers = Arrays.asList( + new ManualLottoNumbers(Arrays.asList(1, 2, 3, 4, 5, 6)), + new ManualLottoNumbers(Arrays.asList(1, 2, 3, 4, 5, 6)) + ); + LottoTicketDispenser dispenser = new LottoTicketDispenser(new RandomLottoTicketGenerator()); + + // then + assertThatThrownBy(() -> dispenser.getManualTickets(money, stubManualNumbers)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("2개의 티켓을 사기에 돈이 모자랍니다. 넣은 금액 : 1000"); + } + + @DisplayName("수동 티켓 발급 테스트") + @Test + void getManualTickets() { + // given + Money money = new Money(1_000); + List stubManualNumbers = Arrays.asList( + new ManualLottoNumbers(Arrays.asList(1, 2, 3, 4, 5, 6)) + ); + LottoTicket stubTicket = new LottoTicket(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + )); + LottoTickets expectedTickets = new LottoTickets(Arrays.asList(stubTicket)); + LottoTicketDispenser dispenser = new LottoTicketDispenser(new RandomLottoTicketGenerator()); + + // when + LottoTickets manualTickets = dispenser.getManualTickets(money, stubManualNumbers); + + // then + assertThat(manualTickets).isEqualTo(expectedTickets); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketTest.java new file mode 100644 index 0000000..efcbc60 --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketTest.java @@ -0,0 +1,78 @@ +package com.javabom.lotto.domain.ticket; + +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LottoTicketTest { + + @DisplayName("티켓내에 특정 번호가 들어있는지 확인") + @CsvSource({"1,true", "7,false"}) + @ParameterizedTest + void isContain(int matchNumber, boolean isNumberContain) { + // given + List stubLottoNumbers = Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + ); + + LottoTicket lottoTicket = new LottoTicket(stubLottoNumbers); + LottoNumber matchLottoNumber = new LottoNumber(matchNumber); + // then + assertThat(lottoTicket.isContain(matchLottoNumber)).isEqualTo(isNumberContain); + } + + @DisplayName("로또 티켓생성시 로또번호의 개수는 6개이여야 함.") + @CsvSource({"5", "7"}) + @ParameterizedTest + void validateLottoNumbersSize(int size) { + // given + List stubLottoNumbers = IntStream.rangeClosed(1, size) + .boxed() + .map(LottoNumber::new) + .collect(Collectors.toList()); + // then + assertThatThrownBy(() -> new LottoTicket(stubLottoNumbers)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("로또 티켓에 6개 숫자를 넣어야 합니다. 입력 size : " + size); + } + + @DisplayName("로또 번호 매치 수를 잘 구하는지 확인") + @Test + void countMatchingNumbers() { + // given + LottoTicket ticket1 = new LottoTicket(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + )); + LottoTicket ticket2 = new LottoTicket(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(7), + new LottoNumber(8) + )); + + // then + assertThat(ticket1.countMatchingNumbers(ticket2)).isEqualTo(4); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketsTest.java b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketsTest.java new file mode 100644 index 0000000..8d24a31 --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/LottoTicketsTest.java @@ -0,0 +1,42 @@ +package com.javabom.lotto.domain.ticket; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +class LottoTicketsTest { + + @DisplayName("두 일급 컬렉션 합치기") + @Test + void add() { + // given + LottoTicket ticket1 = new LottoTicket(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + )); + LottoTicket ticket2 = new LottoTicket(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(7), + new LottoNumber(8) + )); + LottoTickets lottoTickets1 = new LottoTickets(Arrays.asList(ticket1)); + LottoTickets lottoTickets2 = new LottoTickets(Arrays.asList(ticket2)); + + // when + LottoTickets addedLottoTickets = lottoTickets1.add(lottoTickets2); + + // then + assertThat(addedLottoTickets.get()).isEqualTo(Arrays.asList(ticket1, ticket2)); + + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/domain/ticket/ManualLottoNumbersTest.java b/src/test/java/com/javabom/lotto/domain/ticket/ManualLottoNumbersTest.java new file mode 100644 index 0000000..be53934 --- /dev/null +++ b/src/test/java/com/javabom/lotto/domain/ticket/ManualLottoNumbersTest.java @@ -0,0 +1,29 @@ +package com.javabom.lotto.domain.ticket; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +class ManualLottoNumbersTest { + + @DisplayName("수동 입력 정수가 로또티켓으로 변환되는지 확인") + @Test + void toLottoTicket() { + // given + ManualLottoNumbers manualLottoNumbers = new ManualLottoNumbers(Arrays.asList(1, 2, 3, 4, 5, 6)); + LottoTicket expectedLottoTicket = new LottoTicket(Arrays.asList( + new LottoNumber(1), + new LottoNumber(2), + new LottoNumber(3), + new LottoNumber(4), + new LottoNumber(5), + new LottoNumber(6) + )); + + // then + assertThat(manualLottoNumbers.toLottoTicket()).isEqualTo(expectedLottoTicket); + } +} \ No newline at end of file diff --git a/src/test/java/com/javabom/lotto/empty.txt b/src/test/java/com/javabom/lotto/empty.txt deleted file mode 100644 index e69de29..0000000