Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[로또] 이동준 제출합니다. #1361

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# java-lotto-precourse

validate
* purchase amount
- ensure it only composed of digits
- ensure it's int range
- ensure % 1000 == 0


* lotto numbers
- ensure each numbers are in range(1, 45)
- ensure number of lotto numbers are 6
- ensure numbers are not duplicate
- ensure it's delimited by ','


* bonus number
- ensure each numbers are in range(1, 45)
- ensure it's not in lotto number

generate numbers
- generate 6 numbers and return the numbers

calculate result
- see how many numbers match with lotto numbers

calculate RoR
- profit : prize / money spent
- return profit
34 changes: 33 additions & 1 deletion src/main/java/lotto/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
package lotto;

import camp.nextstep.edu.missionutils.Console;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
List<Integer> winningNumber;
String purchaseAmount;
while (true) {
try {
purchaseAmount = PurchaseAmountValidator.validate(Console.readLine());
winningNumber = stringToList(Console.readLine());
Lotto lotto = new Lotto(winningNumber);
String bonusNumber = Console.readLine();
BonusNumberValidator.validate(bonusNumber, winningNumber);
break;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
LottoGenerator lottoGenerator = new LottoGenerator(Integer.parseInt(purchaseAmount) / 1000);
LottoCalculator lottoCalculator = new LottoCalculator(LottoGenerator.getGeneratedTickets(), winningNumber,
BonusNumberValidator.getBonusNumber(), Integer.parseInt(purchaseAmount));

lottoCalculator.displayResults();



}

static List<Integer> stringToList(String str) {
return Arrays.stream(str.split(","))
.map(Integer::parseInt)
.collect(Collectors.toList());
}
}
31 changes: 31 additions & 0 deletions src/main/java/lotto/BonusNumberValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package lotto;

import java.util.List;

public class BonusNumberValidator extends LottoNumber {
private static int parsedBonusNumber;

BonusNumberValidator(String bonusNumber, List<Integer> winningNumbers) {
validate(bonusNumber, winningNumbers);
}

public static void validate(String bonusNumber, List<Integer> winningNumbers) {
int parsedBonusNumber;
try {
parsedBonusNumber = Integer.parseInt(bonusNumber);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("[ERROR] int 범위 숫자만 입력해 주세요.(원 단위)");
}
validateNumberRange(parsedBonusNumber);
for (int num : winningNumbers) {
if (parsedBonusNumber == num) {
throw new IllegalArgumentException("[ERROR] bonus 숫자는 당첨 번호와 달라야합니다.");
}
}
}

public static int getBonusNumber() {
return parsedBonusNumber;
}

}
21 changes: 18 additions & 3 deletions src/main/java/lotto/Lotto.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;

public class Lotto {
public class Lotto extends LottoNumber{
private final List<Integer> numbers;

public Lotto(List<Integer> numbers) {
Expand All @@ -11,10 +11,25 @@ public Lotto(List<Integer> numbers) {
}

private void validate(List<Integer> numbers) {
if (numbers.size() != 6) {
validateNumberSize(numbers);
validateDuplicate(numbers);
for (int number : numbers)
validateNumberRange(number);
}

private void validateNumberSize(List<Integer> numbers) {
if (numbers.size() != NUMBERS_SIZE) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 6개여야 합니다.");
}
}

// TODO: 추가 기능 구현
private void validateDuplicate(List<Integer> numbers) {
if (numbers.size() != numbers.stream().distinct().count()) {
throw new IllegalArgumentException("[ERROR] 중복된 번호가 있습니다.");
}
}

public List<Integer> getNumbers() {
return this.numbers;
}
}
109 changes: 109 additions & 0 deletions src/main/java/lotto/LottoCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package lotto;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LottoCalculator {
private final List<List<Integer>> generatedTickets;
private final List<Integer> winningNumbers;
private final int bonusNumber;
private final int totalSpent;
private long totalPrizeAmount = 0;
private final Map<Prize, Integer> prizeCount = new HashMap<>();

private enum Prize {
FIRST(6, 2_000_000_000, false),
SECOND(5, 30_000_000, true),
THIRD(5, 1_500_000, false),
FOURTH(4, 50_000, false),
FIFTH(3, 5_000, false);

private final int matchCount;
private final int prizeAmount;
private final boolean requiresBonus;

Prize(int matchCount, int prizeAmount, boolean requiresBonus) {
this.matchCount = matchCount;
this.prizeAmount = prizeAmount;
this.requiresBonus = requiresBonus;
}

public boolean matches(int matchCount, boolean bonusMatch) {
return this.matchCount == matchCount && (!requiresBonus || bonusMatch);
}

public int getPrizeAmount() {
return prizeAmount;
}

public String getDescription() {
return matchCount + "개 일치" + (requiresBonus ? ", 보너스 번호 일치" : "") + " (" + prizeAmount + "원)";
}
}

public LottoCalculator(List<List<Integer>> generatedTickets, List<Integer> winningNumbers, int bonusNumber, int totalSpent) {
this.generatedTickets = generatedTickets;
this.winningNumbers = winningNumbers;
this.bonusNumber = bonusNumber;
this.totalSpent = totalSpent;
initializePrizeCount();
}

public void calculateResults() {
for (List<Integer> ticket : generatedTickets) {
int matchCount = countMatches(ticket, winningNumbers);
boolean bonusMatch = ticket.contains(bonusNumber);
allocatePrize(matchCount, bonusMatch);
}
}

private void allocatePrize(int matchCount, boolean bonusMatch) {
for (Prize prize : Prize.values()) {
if (prize.matches(matchCount, bonusMatch)) {
prizeCount.put(prize, prizeCount.get(prize) + 1);
totalPrizeAmount += prize.getPrizeAmount();
break;
}
}
}

private int countMatches(List<Integer> ticket, List<Integer> winningNumbers) {
int matches = 0;
for (int number : ticket) {
if (winningNumbers.contains(number)) {
matches++;
}
}
return matches;
}

private void initializePrizeCount() {
for (Prize prize : Prize.values()) {
prizeCount.put(prize, 0);
}
}

public double calculateReturnRate() {
return ((double) totalPrizeAmount / totalSpent) * 100;
}

public Map<Prize, Integer> getPrizeCount() {
return prizeCount;
}

public long getTotalPrizeAmount() {
return totalPrizeAmount;
}

public void displayResults() {
System.out.println("당첨 내역을 출력한다.");
System.out.println("\n");
for (Prize prize : Prize.values()) {
int count = prizeCount.get(prize);
System.out.println(prize.getDescription() + " - " + count + "개");
}
System.out.printf("총 수익률은 %.1f%%입니다.\n", calculateReturnRate());
}

}
34 changes: 34 additions & 0 deletions src/main/java/lotto/LottoGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package lotto;

import camp.nextstep.edu.missionutils.Randoms;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class LottoGenerator extends LottoNumber {
private static final List<List<Integer>> generatedTickets = new ArrayList<>();

public LottoGenerator(int numberOfTickets) {
generateAndStoreTickets(numberOfTickets);
displayTickets();
}

public static void generateAndStoreTickets(int numberOfTickets) {
for (int i = 0; i < numberOfTickets; i++) {
List<Integer> ticket = Randoms.pickUniqueNumbersInRange(MIN_NUMBER, MAX_NUMBER, NUMBERS_SIZE);
Collections.sort(ticket);
generatedTickets.add(ticket);
}
}

public static List<List<Integer>> getGeneratedTickets() {
return generatedTickets;
}

public static void displayTickets() {
System.out.println(generatedTickets.size() + "개를 구매했습니다.");
for (List<Integer> ticket : generatedTickets) {
System.out.println(ticket);
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/lotto/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package lotto;

public class LottoNumber {
protected static final int NUMBERS_SIZE = 6;
protected static final int MIN_NUMBER = 1;
protected static final int MAX_NUMBER = 45;

protected static void validateNumberRange(int number) {
if (number < MIN_NUMBER || MAX_NUMBER < number) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 1에서 45 사이입니다.");
}
}
}
21 changes: 21 additions & 0 deletions src/main/java/lotto/PurchaseAmountValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package lotto;

public class PurchaseAmountValidator {
private static final int UNIT = 1000;

public static String validate(String purchaseAmount) {
int amount;
try {
amount = Integer.parseInt(purchaseAmount);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("[ERROR] int 범위 숫자만 입력해 주세요.(원 단위)");
}
if (amount < UNIT) {
throw new IllegalArgumentException("[ERROR] 금액은 1000 이상입니다.");
}
if (amount % UNIT != 0) {
throw new IllegalArgumentException("[ERROR] 금액은 1000원 단위입니다.");
}
return purchaseAmount;
}
}
55 changes: 55 additions & 0 deletions src/test/java/lotto/BonusNumberValidatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package lotto;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.List;
public class BonusNumberValidatorTest {
@Test
public void testValidBonusNumber() {
String bonusNumber = "7";
List<Integer> winningNumbers = List.of(1, 2, 3, 4, 5, 6);

assertDoesNotThrow(() -> BonusNumberValidator.validate(bonusNumber, winningNumbers));
}
@Test
public void testBonusNumberMatchingWinningNumber() {
String bonusNumber = "5";
List<Integer> winningNumbers = List.of(1, 2, 3, 4, 5, 6);

Exception exception = assertThrows(IllegalArgumentException.class, () ->
BonusNumberValidator.validate(bonusNumber, winningNumbers)
);
assertEquals("[ERROR] bonus 숫자는 당첨 번호와 달라야합니다.", exception.getMessage());
}
@Test
public void testInvalidBonusNumber() {
String bonusNumber = "-5";
List<Integer> winningNumbers = List.of(1, 2, 3, 4, 5, 6);

Exception exception = assertThrows(IllegalArgumentException.class, () ->
BonusNumberValidator.validate(bonusNumber, winningNumbers)
);
assertEquals("[ERROR] 로또 번호는 1에서 45 사이입니다.", exception.getMessage());
}
@Test
public void testInvalidBonusNumberFormat() {
String bonusNumber = "abc";
List<Integer> winningNumbers = List.of(1, 2, 3, 4, 5, 6);

Exception exception = assertThrows(IllegalArgumentException.class, () ->
BonusNumberValidator.validate(bonusNumber, winningNumbers)
);
assertEquals("[ERROR] int 범위 숫자만 입력해 주세요.(원 단위)", exception.getMessage());
}

}

Loading