-
Notifications
You must be signed in to change notification settings - Fork 39
[스프링 목요일 4팀] (김하연) 미션 제출합니다 #39
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
base: main
Are you sure you want to change the base?
Changes from all commits
6601d44
2c29892
a8539a1
aec5282
ab9b65a
96f930d
e5251b8
e00e160
c3e7230
ff8b2f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| - 로또 구매 (구매 금액 입력) | ||
| PurchasedLotto: 구매 개수, 발행된 로또 | ||
|
|
||
| - 로또 발행 (구매한 로또 출력) | ||
|
|
||
| - 당첨 로또 (당첨 번호 입력) | ||
| WinningLotto: 당첨 번호, 보너스 번호 | ||
|
|
||
| - 당첨 통계 출력 | ||
| WinningRank: 등수와 당첨금, enum 사용 | ||
|
|
||
| - Exception 처리 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| package lotto; | ||
|
|
||
| import lotto.controller.LottoController; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| LottoController lottoController = new LottoController(); | ||
| lottoController.run(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package lotto.controller; | ||
|
|
||
| import lotto.domain.Lotto; | ||
| import lotto.domain.PurchasedLotto; | ||
| import lotto.domain.WinningLotto; | ||
| import lotto.domain.WinningRank; | ||
| import lotto.view.InputView; | ||
| import lotto.view.OutputView; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.EnumMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public class LottoController { | ||
| public void run() { | ||
| PurchasedLotto purchasedLotto = new PurchasedLotto(purchaseLotto()); | ||
| publishLotto(purchasedLotto); | ||
| WinningLotto winningLotto = getLottoNumbers(); | ||
| printLottoResult(purchasedLotto, winningLotto); | ||
| } | ||
|
|
||
| // 구매 금액 입력 | ||
| private int purchaseLotto() { | ||
| return InputView.getPurchaseAmount(); | ||
| } | ||
|
|
||
| // 구매한 로또 출력 | ||
| private void publishLotto(PurchasedLotto purchasedLotto) { | ||
| OutputView.printLottoCount(purchasedLotto.getLottoCount()); | ||
| OutputView.printPublishedLotto(purchasedLotto.getLottoSet()); | ||
| } | ||
|
|
||
| // 당첨 번호와 보너스 번호 입력 | ||
| private WinningLotto getLottoNumbers() { | ||
| WinningLotto winningLotto = new WinningLotto(InputView.getLottoNumbers()); | ||
| winningLotto.setBonusNumber(InputView.getBonusNumber()); | ||
| return winningLotto; | ||
| } | ||
|
|
||
| // 당첨 통계 출력 | ||
| private void printLottoResult(PurchasedLotto purchasedLotto, WinningLotto winningLotto) { | ||
| Map<WinningRank, Integer> winningResult = calculateResult(purchasedLotto.getLottoSet(), winningLotto); | ||
| double returnRate = calculateReturnRate(purchasedLotto.getPurchaseAmount(), winningResult); | ||
| OutputView.printWinningResult(winningResult, returnRate); | ||
| } | ||
|
|
||
| // 당첨 통계 계산 | ||
| private Map<WinningRank, Integer> calculateResult(List<Lotto> lottoSet, WinningLotto winningLotto) { | ||
| Map<WinningRank, Integer> winningResult = new EnumMap<>(WinningRank.class); | ||
| Arrays.stream(WinningRank.values()).forEach(winningRank -> winningResult.put(winningRank, 0)); | ||
|
|
||
| for (Lotto lotto : lottoSet) { | ||
| int match = compareNumbers(lotto.getNumbers(), winningLotto.getWinningNumber()); | ||
| boolean containBonus = isContainBonus(lotto.getNumbers(), winningLotto.getBonusNumber(), match); | ||
| WinningRank winningRank = WinningRank.findWinningRank(match, containBonus); | ||
| winningResult.replace(winningRank, winningResult.get(winningRank) + 1); | ||
| } | ||
|
Comment on lines
+53
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 계산하는 역할의 클래스를 분리하거나 메서드 분리가 좋아보입니다. |
||
|
|
||
| return winningResult; | ||
| } | ||
|
|
||
| // 로또 하나의 당첨 결과 계산 | ||
| private int compareNumbers(List<Integer> lottoNumber, List<Integer> winningLotto) { | ||
| return (int) lottoNumber.stream().filter(winningLotto::contains).count(); | ||
| } | ||
|
|
||
| // 보너스 번호 포함 여부 확인 | ||
| private boolean isContainBonus(List<Integer> lottoNumber, int bonus, int match) { | ||
| if (match != 5) return false; | ||
| return lottoNumber.contains(bonus); | ||
| } | ||
|
Comment on lines
+68
to
+72
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validation 클래스에 있어야할 메서드 같습니다 |
||
|
|
||
| // 수익률 계산 | ||
| private double calculateReturnRate(int purchaseAmount, Map<WinningRank, Integer> winningResult) { | ||
| long winningAmount = winningResult.entrySet().stream() | ||
| .mapToLong(entry -> (long) entry.getKey().getReword() * entry.getValue()) | ||
| .sum(); | ||
| return (double) winningAmount / purchaseAmount * 100.0f; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package lotto.domain; | ||
|
|
||
| import lotto.util.Validation; | ||
| import org.kokodak.Randoms; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| // 구매한 로또 | ||
| public class PurchasedLotto { | ||
| public static final int LOTTO_PRICE = 1000; | ||
|
|
||
| private final int lottoCount; | ||
| private final List<Lotto> lottoSet = new ArrayList<>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. List 는 Lottos 나 LottoList로 표현하는게 알맞는 명명법 같습니다. |
||
|
|
||
| public PurchasedLotto(int purchasedAmount) { | ||
| Validation.validateMoneyRange(purchasedAmount); | ||
| this.lottoCount = purchasedAmount / LOTTO_PRICE; | ||
| generatedLotto(); | ||
| } | ||
|
|
||
| // 구매한 로또 생성 | ||
| private void generatedLotto() { | ||
| for (int i=0; i<lottoCount; i++) { | ||
| List<Integer> numbers = new ArrayList<>( | ||
| Randoms.pickUniqueNumbersInRange(1, 45, 6)); | ||
| Collections.sort(numbers); | ||
| lottoSet.add(new Lotto(numbers)); | ||
| } | ||
| } | ||
|
Comment on lines
+24
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 역할 분리를 위해 메서드를 더 쪼개주시면 좋을 것 같습니다. |
||
|
|
||
| // 구매한 로또 개수 반환 | ||
| public int getLottoCount() { | ||
| return lottoCount; | ||
| } | ||
|
|
||
| // 구매한 로또 반환 | ||
| public List<Lotto> getLottoSet() { | ||
| return lottoSet; | ||
| } | ||
|
|
||
| // 구매 금액 반환 | ||
| public int getPurchaseAmount() { | ||
| return lottoCount * LOTTO_PRICE; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package lotto.domain; | ||
|
|
||
| import lotto.util.Validation; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| // 당첨 번호 | ||
| public class WinningLotto { | ||
| private final Lotto winningNumber; | ||
| private int bonusNumber; | ||
|
|
||
| public WinningLotto(List<Integer> winningNumber) { | ||
| Validation.validateLotto(winningNumber); | ||
| this.winningNumber = new Lotto(winningNumber); | ||
| } | ||
|
|
||
| // 당첨 번호 반환 | ||
| public List<Integer> getWinningNumber() { | ||
| return winningNumber.getNumbers(); | ||
| } | ||
|
|
||
| // 보너스 번호 반환 | ||
| public int getBonusNumber() { | ||
| return bonusNumber; | ||
| } | ||
|
|
||
| // 보너스 번호 설정 | ||
| public void setBonusNumber(int bonusNumber) { | ||
| Validation.validateBonus(winningNumber.getNumbers(), bonusNumber); | ||
| this.bonusNumber = bonusNumber; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package lotto.domain; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| // 당첨 등수 | ||
| public enum WinningRank { | ||
| LAST_RANK(0, 0, false), | ||
| FORTH_RANK(3, 5_000, false), | ||
| THIRD_RANK(4, 50_000, false), | ||
| SECOND_RANK(5, 1_500_000, false), | ||
| SECOND_BONUS_RANK(5, 30000000, true), | ||
| FIRST_RANK(6, 2_000_000_000, false); | ||
|
|
||
| private final int match; | ||
| private final int reword; | ||
| private final boolean bonus; | ||
|
|
||
| WinningRank(int match, int reword, boolean bonus) { | ||
| this.match = match; | ||
| this.reword = reword; | ||
| this.bonus = bonus; | ||
| } | ||
|
|
||
| // 맞힌 번호 개수 반환 | ||
| public int getMatch() { | ||
| return match; | ||
| } | ||
|
|
||
| // 당첨금 반환 | ||
| public int getReword() { | ||
| return reword; | ||
| } | ||
|
Comment on lines
+30
to
+32
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오타가있네요~! |
||
|
|
||
| // 해당 조건 등수 반환 | ||
| public static WinningRank findWinningRank(int match, boolean bonus) { | ||
| return Arrays.stream(values()) | ||
| .filter(winningRank -> winningRank.match == match) | ||
| .filter(winningRank -> winningRank.bonus == bonus) | ||
| .findFirst() | ||
| .orElse(LAST_RANK); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| package lotto.util; | ||
|
|
||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| public class Validation { | ||
| private static final String INPUT_LOTTO_PRICE_ERROR = "[ERROR] 구입 금액은 1,000원 단위로 입력해주세요."; | ||
| private static final String INPUT_TYPE_ERROR = "[ERROR] 숫자를 입력해주세요."; | ||
| private static final String INPUT_NUMBER_RANGE_ERROR = "[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."; | ||
| private static final String INPUT_LOTTO_SIZE_ERROR = "[ERROR] 당첨 번호는 서로 다른 6개의 수로 입력해주세요."; | ||
| private static final String LOTTO_NUMBER_DUPLICATED_ERROR = "[ERROR] 당첨 번호 중 중복되는 번호가 있습니다."; | ||
| private static final String INPUT_BONUS_RANGE_ERROR = "[ERROR] 보너스 번호는 1부터 45 사이의 숫자여야 합니다."; | ||
| private static final String LOTTO_BONUS_DUPLICATED_ERROR = "[ERROR] 당첨 번호 중 보너스 번호와 중복되는 번호가 존재합니다."; | ||
|
Comment on lines
+8
to
+14
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ErrorCode를 따로 enum으로 나누는것이 깔끔할것같습니다. |
||
|
|
||
| private static final int ZERO = 0; | ||
| private static final int LOTTO_PRICE = 1_000; | ||
| private static final int LOTTO_MIN_NUMBER = 1; | ||
| private static final int LOTTO_MAX_NUMBER = 45; | ||
| private static final int LOTTO_NUMBER_SIZE = 6; | ||
|
|
||
| // 입력된 타입 확인 | ||
| public static Integer parseInteger(String input) { | ||
| try { | ||
| return Integer.parseInt(input); | ||
| } catch (NumberFormatException e) { | ||
| throw new IllegalArgumentException(INPUT_TYPE_ERROR); | ||
| } | ||
| } | ||
|
|
||
| // 구매 금액은 0이상, 1000원 단위 | ||
| public static void validateMoneyRange(int purchasedAmount) { | ||
| if (purchasedAmount <= ZERO || purchasedAmount % LOTTO_PRICE != 0) { | ||
| throw new IllegalArgumentException(INPUT_LOTTO_PRICE_ERROR); | ||
| } | ||
| } | ||
|
|
||
| // 로또 번호 적합성 | ||
| public static void validateLotto(List<Integer> lotto) { | ||
| validateLottoNumber(lotto); | ||
| validateLottoNumberSize(lotto); | ||
| validateDuplicateLottoNumber(lotto); | ||
| } | ||
|
|
||
| // 로또 번호는 1~45 | ||
| private static void validateLottoNumber(List<Integer> lotto) { | ||
| for (Integer l : lotto) { | ||
| if (l < LOTTO_MIN_NUMBER || l > LOTTO_MAX_NUMBER) { | ||
| throw new IllegalArgumentException(INPUT_NUMBER_RANGE_ERROR); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // 로또는 6개의 숫자 | ||
| private static void validateLottoNumberSize(List<Integer> lotto) { | ||
| if (lotto.size() != LOTTO_NUMBER_SIZE) { | ||
| throw new IllegalArgumentException(INPUT_LOTTO_SIZE_ERROR); | ||
| } | ||
| } | ||
|
|
||
| // 로또 번호는 중복 없음 | ||
| public static void validateDuplicateLottoNumber(List<Integer> lotto) { | ||
| Set<Integer> deduplicate = new HashSet<>(lotto); | ||
| if (deduplicate.size() != lotto.size()) { | ||
| throw new IllegalArgumentException(LOTTO_NUMBER_DUPLICATED_ERROR); | ||
| } | ||
| } | ||
|
|
||
| // 보너스 번호 적합성 | ||
| public static void validateBonus(List<Integer> lotto, int bonus) { | ||
| validateBonusNumber(bonus); | ||
| validateDuplicateLottoBonus(lotto, bonus); | ||
| } | ||
|
|
||
| // 보너스 번호는 1~45 | ||
| private static void validateBonusNumber(int bonus) { | ||
| if (bonus < LOTTO_MIN_NUMBER || bonus > LOTTO_MAX_NUMBER) { | ||
| throw new IllegalArgumentException(INPUT_BONUS_RANGE_ERROR); | ||
| } | ||
| } | ||
|
|
||
| // 보너스 번호는 당첨 번호와 중복 없음 | ||
| private static void validateDuplicateLottoBonus(List<Integer> lotto, int bonus) { | ||
| if (lotto.contains(bonus)) { | ||
| throw new IllegalArgumentException(LOTTO_BONUS_DUPLICATED_ERROR); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package lotto.view; | ||
|
|
||
| import lotto.util.Validation; | ||
| import org.kokodak.Console; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class InputView { | ||
| private static final String PURCHASE_AMOUNT_MESSAGE = "구입 금액을 입력해 주세요."; | ||
| private static final String WINNING_NUMBER_MESSAGE = "\n당첨 번호를 입력해 주세요."; | ||
| private static final String BONUS_NUMBER_MESSAGE = "\n보너스 번호를 입력해 주세요."; | ||
| private static final String SEPARATOR_VALUE = ","; | ||
|
|
||
| // 구매 금액 입력 | ||
| public static int getPurchaseAmount() { | ||
| System.out.println(PURCHASE_AMOUNT_MESSAGE); | ||
| return Validation.parseInteger(Console.readLine()); | ||
| } | ||
|
|
||
| // 당첨 번호 입력 | ||
| public static List<Integer> getLottoNumbers() { | ||
| System.out.println(WINNING_NUMBER_MESSAGE); | ||
| return Arrays.stream(Console.readLine().split(SEPARATOR_VALUE)) | ||
| .map(Validation::parseInteger) | ||
| .collect(Collectors.toList()); | ||
| } | ||
|
|
||
| // 보너스 번호 입력 | ||
| public static int getBonusNumber() { | ||
| System.out.println(BONUS_NUMBER_MESSAGE); | ||
| return Validation.parseInteger(Console.readLine()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
printLottoResult 과 printWinningResult 으로 메소드를 나눈 이유가 뭔가요??