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

[로또 미션] 최규원 미션 제출합니다. #8

Open
wants to merge 5 commits into
base: kyuwon-choi
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
57 changes: 57 additions & 0 deletions src/main/java/Constant.java
Copy link

Choose a reason for hiding this comment

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

constant class를 통해 상수를 정리하셨는데 이 덕분에 코드가 깔끔해진 것 같아요 👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
public class Constant {

public static final int LOTTO_PRICE = 1000;
public static final int LOTTO_SIZE = 6;
public static final int MAX_LOTTO_NUMBER = 45;
public static final int MIN_LOTTO_NUMBER = 1;
public static final int THREE_COUNT = 3;
public static final int FOUR_COUNT = 4;
public static final int FIVE_COUNT = 5;
public static final int SIX_COUNT = 6;
public static final int ZERO_COUNT = 0;

public static final int FIFTH_PRICE = 5000;
public static final int FOURTH_PRICE = 50000;
public static final int THIRD_PRICE = 1500000;
public static final int SECOND_PRICE = 30000000;
public static final int FIRST_PRICE = 2000000000;

public static final String SEPARATOR = ",";

// InputView

public static final String PRICE_QUERY = "구입금액을 입력해 주세요.";
public static final String WIN_LOTTO_QUERY = "지난 주 당첨 번호를 입력해 주세요.";
public static final String BONUS_QUERY = "보너스 볼을 입력해 주세요";
public static final String MANUAL_COUNT_QUERY = "수동으로 구매할 로또 수를 입력해 주세요.";
public static final String MANUAL_LOTTO_QUERY = "수동으로 구매할 번호를 입력해 주세요.";


// ResultView
public static final String WIN_RESULT = "당첨 통계";
public static final String LINES = "---------";
public static final String LOTTO_BUY_RESULT_1 = "수동으로 ";
public static final String LOTTO_BUY_RESULT_2 = "장 자동으로";
public static final String LOTTO_BUY_RESULT_3 = "개를 구매했습니다.";
public static final String PROFIT_RESULT_1 = "총 수익률은 ";
public static final String PROFIT_RESULT_2 = "입니다.";
public static final String STATICS_RESULT_1 = "개 일치";
public static final String STATICS_RESULT_2 = " 보너스볼 일치";
public static final String STATICS_RESULT_3 = "원";
public static final String STATICS_RESULT_4 = "개";
public static final String OPEN_PARENTHESES = "(";
public static final String CLOSE_PARENTHESES = ")";
public static final String DASH = "-";
public static final String BLANK = " ";

//exceptions
public static final String RANGE_EXCEPTION = "로또 번호는 1부터 45 사이여야 합니다.";
public static final String SIZE_EXCEPTION = "로또 번호는 6개입니다.";
public static final String DUPLICATE_EXCEPTION = "로또 번호는 중복이 불가합니다.";
public static final String VALUE_EXCEPTION = "로또 번호는 숫자여야 합니다.";
public static final String PRICE_VALUE_EXCEPTION = "가격은 숫자여야 합니다.";
public static final String BONUS_DUPLICATE_EXCEPTION = "보너스 볼은 중복이 불가합니다.";
public static final String LOTTO_PRICE_EXCEPTION = "로또는 천원 단위로만 구입이 가능합니다.";


}
8 changes: 8 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import controller.LottoController;
public class Main {
public static void main(String[] args) {
LottoController lottoController = new LottoController();
lottoController.lottoStart();

}
}
34 changes: 34 additions & 0 deletions src/main/java/controller/LottoController.java
Copy link

Choose a reason for hiding this comment

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

controller에선 int price같은 변수 선언을 아예 하지 않는 게 좋은 지에 대해서 질문 주셨는데요.
저도 이 부분을 고민하였지만, 기능 구현에 한계가 있어 결국 작성할 때는 변수 선언을 진행 하였습니다ㅠㅠ.
저의 생각으론 최대한 지양하는 것이 좋을 것 같다고 생각합니다! 컨트롤러는 최대한 가볍게 작성하는 것이 좋다고 생각하기 때문이에요.
아래 MVC 패턴에 관한 글인데 한번 보시면 좋을 것 같아요. 규원님도 이부분을 어떻게 생각하지는지도 궁금합니다!

https://newwisdom.tistory.com/58

Copy link
Author

Choose a reason for hiding this comment

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

넵 반영해서 수정해보겠습니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package controller;

import model.BuyLotto;
import model.Lotto;
import model.ProfitCalculator;
import model.WinLotto;
import view.InputView;
import view.ResultView;

import java.util.List;

public class LottoController {

public void lottoStart() {

int price = InputView.getPrice();
int manualCount = InputView.getManualCount();
BuyLotto buyLotto = new BuyLotto(price, manualCount, InputView.getManualLottos(manualCount));
List<Lotto> lottos = buyLotto
.generateLotto();

ResultView.printLottos(manualCount, lottos);

WinLotto winLotto = new WinLotto(InputView.getWinLotto(), lottos, InputView.getBonusBall());
winLotto.updateWinningStates(lottos);
ResultView.printStatics(winLotto.getWinningStates());

ProfitCalculator profitCalculator = new ProfitCalculator();
ResultView.printProfit(profitCalculator.calculateProfit(winLotto.getWinPrize(), price));

}


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

import java.util.*;
import java.util.stream.Collectors;

public class BuyLotto {
private LottoMoney totalPrice;
private int lottoCount;
private int manualLottoCount;
private List<String> manualLottoList;
private List<Integer> numberList;

public BuyLotto(int totalPrice, int manualLottoCount, List<String> manualLottoList) {
numberList = new ArrayList<>();

for (int i = Constant.MIN_LOTTO_NUMBER; i <= Constant.MAX_LOTTO_NUMBER; i++) {
numberList.add(i);
}
this.manualLottoCount = manualLottoCount;
this.manualLottoList = manualLottoList;
this.totalPrice = new LottoMoney(String.valueOf(totalPrice));
this.lottoCount = totalPrice / Constant.LOTTO_PRICE - manualLottoCount;
}

private List<Lotto> convertManualLottoList(List<String> manualLottoList) {
return manualLottoList.stream()
.map(this::parseLottoNumbers)
.collect(Collectors.toList());
}

private Lotto parseLottoNumbers(String lotto) {
List<LottoNumber> numbers = Arrays.stream(lotto.split(Constant.SEPARATOR))
.map(String::trim)
.map(s -> new LottoNumber(s))
.collect(Collectors.toList());
return new Lotto(numbers);
}

public List<Lotto> generateLotto() {
List<Lotto> lottos = convertManualLottoList(manualLottoList);

for (int i = 0; i < lottoCount; i++) {
lottos.add(new Lotto(generateRandomNumbers()));
}

return lottos;
}

private List<LottoNumber> generateRandomNumbers() {
Collections.shuffle(numberList);
return numberList.subList(Constant.ZERO_COUNT, Constant.LOTTO_SIZE)
.stream()
.map(n -> new LottoNumber(String.valueOf(n)))
.sorted(Comparator.comparingInt(LottoNumber::getNumber)) // 정렬
.collect(Collectors.toList());
}
}
Copy link

Choose a reason for hiding this comment

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

BuyLotto에서 로또 구매와 생성이 모두 이루어지고 있는데요 두가지를 분리해보는것은 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

반영하여 수정하였습니다!

41 changes: 41 additions & 0 deletions src/main/java/model/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package model;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Lotto {
private List<LottoNumber> numbers = new ArrayList<>();

public Lotto(List<LottoNumber> numbers) {
validateSize(numbers);
validateDuplicate(numbers);
this.numbers = new ArrayList<>(numbers);
}

@Override
public String toString() {
return numbers.toString();
}

public List<LottoNumber> getNumbers() {
return new ArrayList<>(numbers);
}

private void validateSize(List<LottoNumber> numbers) {
if (numbers.size() != Constant.SIX_COUNT) {
throw new IllegalArgumentException(Constant.SIZE_EXCEPTION);
}
}

private void validateDuplicate(List<LottoNumber> numbers) {
Set<Integer> numberSet = new HashSet<>();
for (LottoNumber number : numbers) {
numberSet.add(number.getNumber());
}
if (numberSet.size() != Constant.SIX_COUNT) {
throw new IllegalArgumentException(Constant.DUPLICATE_EXCEPTION);
}
}
}
25 changes: 25 additions & 0 deletions src/main/java/model/LottoMoney.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package model;

public class LottoMoney {
private final int amount;

public LottoMoney(String inputAmount) {
try {
int amount = Integer.parseInt(inputAmount);
validateAmount(amount);
this.amount = amount;
} catch (NumberFormatException e) {
throw new IllegalArgumentException(Constant.PRICE_VALUE_EXCEPTION, e);
}
}

private void validateAmount(int amount) {
if (amount % Constant.LOTTO_PRICE != 0 || amount < Constant.LOTTO_PRICE) {
throw new IllegalArgumentException(Constant.LOTTO_PRICE_EXCEPTION);
}
}
Comment on lines +6 to +20
Copy link

Choose a reason for hiding this comment

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

각각의 예외처리가 잘들어간 것 같아요!


public int getAmount() {
return amount;
}
}
30 changes: 30 additions & 0 deletions src/main/java/model/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package model;

public class LottoNumber {
private final int number;

public LottoNumber(String number) {
try {
int parsedNumber = Integer.parseInt(number);
validateRange(parsedNumber);
this.number = parsedNumber;
} catch (NumberFormatException e) {
throw new IllegalArgumentException(Constant.VALUE_EXCEPTION, e);
}
}

private void validateRange(int number) {
if (number < Constant.MIN_LOTTO_NUMBER || number > Constant.MAX_LOTTO_NUMBER) {
throw new IllegalArgumentException(Constant.RANGE_EXCEPTION);
}
}

public int getNumber() {
return number;
}

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

public enum LottoPrize {
FIFTH(Constant.THREE_COUNT, Constant.FIFTH_PRICE, false),
FOURTH(Constant.FOUR_COUNT, Constant.FOURTH_PRICE, false),
THIRD(Constant.FIVE_COUNT, Constant.THIRD_PRICE, false),
SECOND(Constant.FIVE_COUNT, Constant.SECOND_PRICE, true),
FIRST(Constant.SIX_COUNT, Constant.FIRST_PRICE, false);

private final int matchCount;
private final int prizeAmount;
private final boolean hasBonus;

LottoPrize(int matchCount, int prizeAmount, boolean hasBonus) {
this.matchCount = matchCount;
this.prizeAmount = prizeAmount;
this.hasBonus = hasBonus;
}

public int getMatchCount() {
return matchCount;
}

public int getPrizeAmount() {
return prizeAmount;
}

public boolean hasBonus() {
return hasBonus;
}

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

public class ProfitCalculator {

public double calculateProfit(int winPrice, int totalPrice) {
return (double) winPrice / totalPrice;
}

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

import java.util.*;

public class WinLotto {
private List<LottoNumber> winnerLotto = new ArrayList<>();
private List<Lotto> userLottos;
private Map<LottoPrize, Integer> winningStates = new LinkedHashMap<>();
private int winPrize;
private LottoNumber bonusBall;

public WinLotto(String inputWinnerLotto, List<Lotto> userLottos, String bonusBall) {
Arrays.stream(inputWinnerLotto.split(Constant.SEPARATOR))
.forEach(e -> winnerLotto.add(new LottoNumber(e.trim())));
this.userLottos = userLottos;
this.winPrize = Constant.ZERO_COUNT;
LottoNumber tempBonusBall = new LottoNumber(bonusBall);
if (winnerLotto.stream().anyMatch(winnerNumber -> winnerNumber.getNumber() == tempBonusBall.getNumber())) {
throw new IllegalArgumentException(Constant.BONUS_DUPLICATE_EXCEPTION);
}
this.bonusBall = new LottoNumber(bonusBall);
for (LottoPrize prize : LottoPrize.values()) {
winningStates.put(prize, Constant.ZERO_COUNT);
}
}

private int compareHowManyNumberSame(Lotto lotto) {
return (int) lotto.getNumbers().stream()
.filter(number -> winnerLotto.stream().anyMatch(winnerNumber -> winnerNumber.getNumber() == number.getNumber()))
.count();
}

public int getWinPrize() {
return winPrize;
}

public Map<LottoPrize, Integer> getWinningStates() {
return winningStates;
}

public void updateWinningStates(List<Lotto> userLottos) {
userLottos.forEach(userLotto -> {
int matchedNumbers = compareHowManyNumberSame(userLotto);
boolean containsBonus = userLotto.getNumbers().stream().anyMatch(number -> number.getNumber() == bonusBall.getNumber());

if (matchedNumbers == Constant.SIX_COUNT) {
updateWinningState(LottoPrize.FIRST);
}
if (matchedNumbers == Constant.FIVE_COUNT && containsBonus) {
updateWinningState(LottoPrize.SECOND);
}
if (matchedNumbers == Constant.FIVE_COUNT && !containsBonus) {
updateWinningState(LottoPrize.THIRD);
}
if (matchedNumbers == Constant.FOUR_COUNT) {
updateWinningState(LottoPrize.FOURTH);
}
if (matchedNumbers == Constant.THREE_COUNT) {
updateWinningState(LottoPrize.FIFTH);
}
});
}
Comment on lines +41 to +62
Copy link

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 void updateWinningState(LottoPrize prize) {
winningStates.put(prize, winningStates.get(prize) + 1);
winPrize += prize.getPrizeAmount();
}
}
Loading