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

[로또 미션] 김성재 미션 제출합니다. #47

Open
wants to merge 6 commits into
base: seongjae6751
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
Empty file removed src/main/java/.gitkeep
Empty file.
36 changes: 36 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import java.util.ArrayList;
import java.util.List;

import domain.Lotto;
import domain.LottoGameResult;
import domain.LottoMachine;
import domain.WinningNumbers;

public class Application {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개인적으로 실행시키는 클래스는 깔끔해야 한다고 생각해서 동작들을 클래스로 빼면 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

타당한 말씀이십니다! 👍

public static void main(String[] args) {
InputHandler inputHandler = new InputHandler();
LottoMachine lottoMachine = new LottoMachine();

int purchaseAmount = inputHandler.getPurchaseAmount();
int totalLottos = lottoMachine.calculateNumberOfLottos(purchaseAmount);

int manualLottoCount = inputHandler.getManualLottoCount();
List<Lotto> manualLottos = inputHandler.getManualLottos(manualLottoCount);

int automaticLottoCount = totalLottos - manualLottoCount;
List<Lotto> automaticLottos = lottoMachine.generateAutomaticLottos(automaticLottoCount);

List<Lotto> allLottos = new ArrayList<>();
allLottos.addAll(manualLottos);
allLottos.addAll(automaticLottos);

System.out.println("수동으로 " + manualLottoCount + "장, 자동으로 " + automaticLottoCount + "개를 구매했습니다.");
for (Lotto lotto : allLottos) {
System.out.println(lotto);
}

WinningNumbers winningNumbers = inputHandler.getWinningNumbers();
LottoGameResult gameResult = new LottoGameResult(allLottos, winningNumbers);
gameResult.printWinningStatistics();
}
}
50 changes: 50 additions & 0 deletions src/main/java/InputHandler.java

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InputHandler 클래스인만큼 입력값만 받아주고 처리는 해당 입력을 사용하는 클래스에서 하는게 좋다고 생각하는데 어떻게 생각하시나요?

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import domain.Lotto;
import domain.WinningNumbers;

public class InputHandler {
private final Scanner scanner = new Scanner(System.in);

public int getPurchaseAmount() {
System.out.println("구입금액을 입력해 주세요.");
return scanner.nextInt();
}

public int getManualLottoCount() {
System.out.println("수동으로 구매할 로또 수를 입력해 주세요.");
int manualCount = scanner.nextInt();
scanner.nextLine();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int manualCount = Integer.parseInt(scanner.nextLine);
으로 한번에 하는건 어떤가요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼼꼼하시네요

return manualCount;
}

public List<Lotto> getManualLottos(int manualCount) {
List<Lotto> manualLottos = new ArrayList<>();
System.out.println("수동으로 구매할 번호를 입력해 주세요.");
for (int i = 0; i < manualCount; i++) {
String input = scanner.nextLine();
String[] inputs = input.split(", ");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이러면 공백이 없을 경우에 오류가 날수도 있을 것 같아요

List<Integer> numbers = new ArrayList<>();
for (String number : inputs) {
numbers.add(Integer.parseInt(number));
}
manualLottos.add(new Lotto(numbers));
}
return manualLottos;
}

public WinningNumbers getWinningNumbers() {
System.out.println("지난 주 당첨 번호를 입력해 주세요. (예: 1, 2, 3, 4, 5, 6)");
String input = scanner.nextLine();
String[] inputs = input.split(", ");
List<Integer> winningNumbers = new ArrayList<>();
for (String number : inputs) {
winningNumbers.add(Integer.parseInt(number));
}
System.out.println("보너스 볼을 입력해 주세요.");
int bonusNumber = scanner.nextInt();
return new WinningNumbers(winningNumbers, bonusNumber);
}
}
31 changes: 31 additions & 0 deletions src/main/java/domain/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package domain;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Lotto {
private final Set<LottoNumber> numbers;

public Lotto(List<Integer> numbers) {
if (numbers.size() != 6) {
throw new IllegalArgumentException("로또 번호는 정확히 6개여야 합니다.");
}
this.numbers = numbers.stream()
.map(LottoNumber::new)
.collect(Collectors.toSet());
if (this.numbers.size() != 6) {
throw new IllegalArgumentException("로또 번호는 중복되지 않아야 합니다.");
}
Comment on lines +18 to +20

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로또 번호를 만들때 중복검사하는건 어떤가요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 set으로 중복 검사하고 있습니다!

}

public Set<LottoNumber> getNumbers() {
return Collections.unmodifiableSet(numbers);
}

@Override
public String toString() {
return numbers.toString();
}
}
71 changes: 71 additions & 0 deletions src/main/java/domain/LottoGameResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package domain;

import java.util.EnumMap;
import java.util.List;
import java.util.Map;

public class LottoGameResult {
private static final int LOTTO_PRICE = 1000;

private final List<Lotto> lottos;
private final WinningNumbers winningNumbers;

public LottoGameResult(List<Lotto> lottos, WinningNumbers winningNumbers) {
this.lottos = lottos;
this.winningNumbers = winningNumbers;
}

public void printWinningStatistics() {
Map<WinningRank, Integer> matchCount = new EnumMap<>(WinningRank.class);
for (WinningRank rank : WinningRank.values()) {
matchCount.put(rank, 0);
}

for (Lotto lotto : lottos) {
WinningRank rank = determineRank(lotto);
matchCount.put(rank, matchCount.get(rank) + 1);
}
printStatistics(matchCount);
}

private WinningRank determineRank(Lotto lotto) {
int match = winningNumbers.countMatchingNumbers(lotto);
if (match == 6) {
return WinningRank.SIX;
}
if (match == 5 && winningNumbers.containsBonusNumber(lotto)) {
return WinningRank.FIVE_WITH_BONUS;
}
if (match == 5) {
return WinningRank.FIVE;
}
if (match == 4) {
return WinningRank.FOUR;
}
if (match == 3) {
return WinningRank.THREE;
}
return WinningRank.NONE;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WinningRank 클래스에 bonusNumber 여부도 추가해서 관리하는것도 괜찮을 것 같아요


private void printStatistics(Map<WinningRank, Integer> matchCount) {
System.out.println("당첨 통계");
System.out.println("---------");
System.out.println("3개 일치 (5000원) - " + matchCount.get(WinningRank.THREE) + "개");
System.out.println("4개 일치 (50000원) - " + matchCount.get(WinningRank.FOUR) + "개");
System.out.println("5개 일치 (1500000원) - " + matchCount.get(WinningRank.FIVE) + "개");
System.out.println("5개 일치, 보너스 볼 일치 (30000000원) - " + matchCount.get(WinningRank.FIVE_WITH_BONUS) + "개");
System.out.println("6개 일치 (2000000000원) - " + matchCount.get(WinningRank.SIX) + "개");
double profitRate = calculateProfitRate(matchCount);
System.out.printf("총 수익률은 %.4f입니다.%n", profitRate);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 하면 변경이 일어날경우 고치기 힘들 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 말씀이네용 👍

}

private double calculateProfitRate(Map<WinningRank, Integer> matchCount) {
int totalPrize = 0;
for (WinningRank rank : WinningRank.values()) {
totalPrize += matchCount.get(rank) * rank.getPrize();
}
int totalSpent = LOTTO_PRICE * lottos.size();
return (double) totalPrize / totalSpent;
}
}
41 changes: 41 additions & 0 deletions src/main/java/domain/LottoMachine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class LottoMachine {
private static final int LOTTO_PRICE = 1000;
private static final int LOTTO_NUMBER_COUNT = 6;
private static final int LOTTO_MAX_NUMBER = 45;

public int calculateNumberOfLottos(int purchaseAmount) {
return purchaseAmount / LOTTO_PRICE;
}

public List<Lotto> generateLottos(int numberOfLottos) {
List<Lotto> lottos = new ArrayList<>();
for (int i = 0; i < numberOfLottos; i++) {
lottos.add(generateLotto());
}
return lottos;
}

private Lotto generateLotto() {
List<Integer> numbers = IntStream.rangeClosed(1, LOTTO_MAX_NUMBER)
.boxed()
.collect(Collectors.toList());
Collections.shuffle(numbers);
return new Lotto(numbers.subList(0, LOTTO_NUMBER_COUNT));
}

public List<Lotto> generateAutomaticLottos(int automaticCount) {
List<Lotto> lottos = new ArrayList<>();
for (int i = 0; i < automaticCount; i++) {
lottos.add(generateLotto());
}
return lottos;
}
}
34 changes: 34 additions & 0 deletions src/main/java/domain/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package domain;

public class LottoNumber {
private final int number;

public LottoNumber(int number) {
if (number < 1 || number > 45) {
throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}
this.number = number;
}

public int getNumber() {
return 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 Integer.hashCode(number);
}

@Override
public String toString() {
return String.valueOf(number);
}
}
33 changes: 33 additions & 0 deletions src/main/java/domain/WinningNumbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package domain;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class WinningNumbers {
private final Set<LottoNumber> numbers;
private final LottoNumber bonusNumber;

public WinningNumbers(List<Integer> numbers, int bonusNumber) {
if (numbers.size() != 6) {
throw new IllegalArgumentException("당첨 번호는 정확히 6개여야 합니다.");
}
this.numbers = numbers.stream()
.map(LottoNumber::new)
.collect(Collectors.toSet());
if (this.numbers.size() != 6) {
throw new IllegalArgumentException("당첨 번호는 중복되지 않아야 합니다.");
}
this.bonusNumber = new LottoNumber(bonusNumber);
}

public int countMatchingNumbers(Lotto lotto) {
return (int) lotto.getNumbers().stream()
.filter(numbers::contains)
.count();
}

public boolean containsBonusNumber(Lotto lotto) {
return lotto.getNumbers().contains(bonusNumber);
}
}
26 changes: 26 additions & 0 deletions src/main/java/domain/WinningRank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package domain;

public enum WinningRank {
THREE(3, 5000),
FOUR(4, 50000),
FIVE(5, 1500000),
FIVE_WITH_BONUS(5, 30000000),
SIX(6, 2000000000),
NONE(0, 0);

private final int matchCount;
private final int prize;

WinningRank(int matchCount, int prize) {
this.matchCount = matchCount;
this.prize = prize;
}

public int getMatchCount() {
return matchCount;
}

public int getPrize() {
return prize;
}
}