-
Notifications
You must be signed in to change notification settings - Fork 39
스프링 월요일 [B팀] (김재현) 미션 제출합니다. #13
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
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 |
|---|---|---|
|
|
@@ -25,4 +25,4 @@ java { | |
|
|
||
| test { | ||
| useJUnitPlatform() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # java-blackjack | ||
|
|
||
| 로또 미션 저장소 | ||
|
|
||
| <!-- | ||
| ## 도메인 다이어그램 | ||
| --> | ||
|
|
||
| [//]: # (```mermaid) | ||
|
|
||
| [//]: # (graph TD) | ||
|
|
||
| [//]: # ( LottoController --> InputView) | ||
|
|
||
| [//]: # ( LottoController --> OutputView) | ||
|
|
||
| [//]: # ( LottoController --> LottoGame) | ||
|
|
||
| [//]: # () | ||
| [//]: # ( LottoGame --> Lotto) | ||
|
|
||
| [//]: # ( LottoGame --> WinningNumbers) | ||
|
|
||
| [//]: # ( LottoGame --> LottoMachine) | ||
|
|
||
| [//]: # () | ||
| [//]: # (```) | ||
|
|
||
|
|
||
| ## 기능 구현 목록 | ||
|
|
||
| ### Lotto | ||
|
|
||
| - [x] 로또 번호를 저장한다 | ||
|
|
||
| ### WinningNumbers | ||
|
|
||
| - [x] 당첨 번호를 저장한다 | ||
| - [x] 보너스 번호를 저장한다 | ||
|
|
||
| ### LottoMachine | ||
|
|
||
| - [x] 숫자를 무작위 생성한다 | ||
| - [x] 숫자를 정렬한다 | ||
|
|
||
| ### 입력 | ||
|
|
||
| - [x] 로또 구입 금액을 입력 받는다 | ||
| - [x] 금액이 1,000원으로 나누어 떨어지지 않는지 확인한다 | ||
| - [x] 금액이 1,000원으로 나누어 떨어지지 않으면 예외 처리한다 | ||
| - [x] 당첨 번호를 입력 받는다 | ||
| - [x] 보너스 번호를 입력 받는다 | ||
|
|
||
| ### 출력 | ||
|
|
||
| - [x] 발행한 로또 수량을 출력한다 | ||
| - [x] 발행한 로또 번호를 출력한다 | ||
| - [x] 당첨 통계를 출력한다 | ||
| - [x] 수익률을 출력한다 (소수점 둘째 자리에서 반올림) | ||
| - [x] 예외 상황 시 에러 문구를 출력한다 (단, 에러 문구는 "[ERROR]"로 시작) |
| 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: 프로그램 구현 | ||
| final LottoController lottoController = new LottoController(); | ||
| lottoController.run(); | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package lotto.controller; | ||
|
|
||
| import lotto.domain.betting.Betting; | ||
| import lotto.domain.number.LottoArray; | ||
| import lotto.domain.number.LottoMachine; | ||
| import lotto.domain.number.WinningNumbers; | ||
| import lotto.domain.result.EarningsRate; | ||
| import lotto.domain.result.MatchedPlace; | ||
| import lotto.domain.result.Result; | ||
| import lotto.view.InputView; | ||
| import lotto.view.OutputView; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public class LottoController { | ||
| public void run() { | ||
| try{ | ||
| final Betting betting = new Betting(getBetting()); | ||
| final int amount = betting.getAmount(); | ||
| LottoMachine lottoMachine = new LottoMachine(amount); | ||
| LottoArray lottoArray = new LottoArray(lottoMachine.createLottoArray()); | ||
| printLotto(lottoMachine, lottoArray); | ||
|
|
||
| final WinningNumbers winningNumbers = | ||
| new WinningNumbers(getWinningArray(),getBonusNumber()); | ||
| Map<MatchedPlace, Integer> matchedDetails = Result.getMatchedDetails(lottoArray, winningNumbers); | ||
| printResult(matchedDetails,amount); | ||
| }catch(IllegalArgumentException e) { | ||
| System.out.println((e.getMessage())); | ||
| } | ||
|
|
||
| } | ||
| private String getBetting() { | ||
| return InputView.readMoney(); | ||
| } | ||
| private List<Integer> getWinningArray() { | ||
| return InputView.readWinningArray(); | ||
| } | ||
| private String getBonusNumber() { | ||
| return InputView.readBonusNumber(); | ||
| } | ||
| private void printLotto(LottoMachine lottoMachine,LottoArray lottoArray) { | ||
| OutputView.printLottoTicketNumber(lottoMachine.getTicketNumber()); | ||
| OutputView.printLotto(lottoArray); | ||
| } | ||
|
|
||
| private void printResult(Map<MatchedPlace, Integer> matchedDetails, int amount) { | ||
| OutputView.printStatistics(); | ||
| OutputView.printMatchedDetails(matchedDetails); | ||
| long winningAmount = EarningsRate.getEarning(matchedDetails); | ||
| OutputView.printEarningsRate(EarningsRate.getEarningsRate(winningAmount, amount)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package lotto.domain.betting; | ||
|
|
||
| public class Betting { | ||
| private static final String NOT_A_NUMBER = "[ERROR] 정수가 아닙니다."; | ||
| private static final String LESS_THAN_0 = "[ERROR] 금액이 0보다 작습니다"; | ||
|
|
||
| private final int amount; | ||
| public Betting(final String amount) { | ||
| validate(amount); | ||
| this.amount = Integer.parseInt(amount); | ||
| } | ||
|
|
||
| private void validate(final String input) { | ||
| validateInteger(input); | ||
| validateBiggerThan0(Integer.parseInt(input)); | ||
| } | ||
| private void validateInteger(final String input) { | ||
| if (!(input.matches("[+-]?\\d*(\\.\\d+)?"))) { | ||
| throw new IllegalArgumentException(NOT_A_NUMBER); | ||
| } | ||
| } | ||
| private void validateBiggerThan0(final int amount) { | ||
|
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.
|
||
| if (amount<=0) { | ||
| throw new IllegalArgumentException(LESS_THAN_0); | ||
| } | ||
| } | ||
|
|
||
| public int getAmount() { | ||
| return amount; | ||
| } | ||
|
|
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package lotto.domain.number; | ||
|
|
||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| public class Lotto { | ||
| private final List<Integer> numbers; | ||
|
|
||
| public Lotto(List<Integer> numbers) { | ||
| validate(numbers); | ||
| this.numbers = numbers; | ||
| } | ||
|
|
||
| private void validate(List<Integer> numbers) { | ||
| validateSix(numbers); | ||
| validateDuplicatedNumber(numbers); | ||
| } | ||
| private void validateSix(List<Integer> numbers) { | ||
|
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. 로또 개수가 만약 변경되면 해당 메소드명도 변경되어야 하지 않을까요? 이는 리팩토링 내성을 잃는 것을 의미합니다. |
||
| if (numbers.size() != 6) { | ||
| throw new IllegalArgumentException("[ERROR] 원소의 개수가 6개가 아닙니다."); | ||
| } | ||
| } | ||
| private void validateDuplicatedNumber(List<Integer> numbers) { | ||
| Set<Integer> numbersSet = new HashSet<>(numbers); | ||
| if(numbersSet.size()!= numbers.size()){ | ||
| throw new IllegalArgumentException("[ERROR] 중복된 원소가 있습니다"); | ||
| } | ||
| } | ||
|
|
||
| public List<Integer> getNumbers() { | ||
| return numbers; | ||
| // TODO: 추가 기능 구현 | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package lotto.domain.number; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class LottoArray { | ||
| private List<Lotto> lottoArray; | ||
|
|
||
| public LottoArray(List<Lotto> lottoArray) { | ||
| this.lottoArray = lottoArray; | ||
| } | ||
|
|
||
| public List<Lotto> getLottoArray() { | ||
| return lottoArray; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package lotto.domain.number; | ||
|
|
||
| import org.kokodak.Randoms; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Comparator; | ||
| import java.util.List; | ||
|
|
||
| public class LottoMachine { | ||
| private static final int LOTTO_PRICE = 1_000; | ||
|
|
||
| private final List<Lotto> lottoArray = new ArrayList<>(); | ||
|
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. 클래스명만 본다면 발권된 로또들은 해당 클래스는 단순히 로또만을 발권해주는 클래스로 변경하는게 좋을 것 같습니다. 연장선으로 해당 메소드들도 |
||
| private final int ticketNumber; | ||
|
|
||
| public LottoMachine(int amount) { | ||
| validateDivisibleBy1000(amount); | ||
| this.ticketNumber = amount / LOTTO_PRICE; | ||
| } | ||
|
|
||
| private void validateDivisibleBy1000(final int input) { | ||
|
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.
|
||
| if ((input % LOTTO_PRICE) !=0) { | ||
| throw new IllegalArgumentException("[ERROR] " + input + "이 1,000으로 나누어 떨어지지 않습니다."); | ||
| } | ||
| } | ||
| public List<Lotto> createLottoArray() { | ||
| for (int i = 0; i < ticketNumber; i++) { | ||
| Lotto lotto = createNumbers(); | ||
| lottoArray.add(lotto); | ||
| } | ||
| return lottoArray; | ||
| } | ||
| public Lotto createNumbers() { | ||
| List<Integer> randomNumbers = new ArrayList<>( | ||
| Randoms.pickUniqueNumbersInRange(1, 45, | ||
| 6)); | ||
| randomNumbers.sort(Comparator.naturalOrder()); | ||
| return new Lotto(randomNumbers); | ||
| } | ||
|
Comment on lines
+32
to
+38
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 getTicketNumber() { | ||
| return ticketNumber; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| package lotto.domain.number; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class WinningNumbers { | ||
| private final List<Integer> array; | ||
| private final int bonusNumber; | ||
|
|
||
| public WinningNumbers(List<Integer> array, String bonusNumber) { | ||
| validate(array,bonusNumber); | ||
| this.array = array; | ||
| this.bonusNumber=Integer.parseInt(bonusNumber); | ||
| } | ||
|
Comment on lines
+9
to
+13
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.
|
||
|
|
||
| private void validate(List<Integer> array, String bonusNumber) { | ||
| validateArraySize(array); | ||
| validateInteger(bonusNumber); | ||
| validateIntegerBetween1And45(Integer.parseInt(bonusNumber)); | ||
| validateArrayContainsBonusNumber(array,Integer.parseInt(bonusNumber)); | ||
| } | ||
| private void validateArraySize(List<Integer> array) { | ||
| if (array.size() != 6) { | ||
| throw new IllegalArgumentException("[ERROR] 원소의 개수가 6개가 아닙니다."); | ||
| } | ||
| } | ||
| private void validateInteger(final String input) { | ||
| if (!input.matches("[+-]?\\d*(\\.\\d+)?")) { | ||
| throw new IllegalArgumentException("[ERROR] " + input + "이 정수가 아닙니다."); | ||
| } | ||
| } | ||
| private void validateIntegerBetween1And45(final int input) { | ||
| if (input<1||input>45) { | ||
| throw new IllegalArgumentException("[ERROR] " + input + " 1과 45 사이의 정수가 아닙니다."); | ||
| } | ||
| } | ||
| private void validateArrayContainsBonusNumber(final List<Integer> array ,final int number) { | ||
| if (array.contains(number)) { | ||
| throw new IllegalArgumentException("[ERROR] 보너스 숫자가 이미 당첨 번호에 있습니다."); | ||
| } | ||
| } | ||
|
|
||
| public List<Integer> getArray() { | ||
| return array; | ||
| } | ||
|
|
||
| public int getBonusNumber() { | ||
| return bonusNumber; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package lotto.domain.result; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| public class EarningsRate { | ||
|
|
||
| public static long getEarning(Map<MatchedPlace, Integer> winningDetails) { | ||
| return winningDetails.entrySet().stream() | ||
| .mapToLong(entry -> (long) entry.getKey().getPrize() * entry.getValue()) | ||
| .sum(); | ||
| } | ||
|
|
||
| public static double getEarningsRate(long winningAmount, int money) { | ||
| double lottoYield = 100 + (double) (winningAmount - money) / money * 100; | ||
| return Math.round(lottoYield * 10) / 10.0; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package lotto.domain.result; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public enum MatchedPlace { | ||
| ELSE(0,false,0), | ||
|
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.
|
||
| FIFTH(3,false , 5_000), | ||
| FOURTH(4, false, 50_000), | ||
| THIRD(5, false, 1_500_000), | ||
| SECOND(5, true, 30_000_000), | ||
| FIRST(6,false , 2_000_000_000); | ||
| private final int matchedCount; | ||
|
|
||
| private final boolean matchedBonusNumber; | ||
| private final int prize; | ||
|
|
||
| public static MatchedPlace findPlace(int matchedCount, boolean matchedBonusNumber) { | ||
| return Arrays.stream(values()) | ||
| .filter(place -> place.matchedCount == matchedCount) | ||
| .filter(place -> place.matchedBonusNumber == matchedBonusNumber) | ||
| .findFirst() | ||
| .orElse(MatchedPlace.ELSE); | ||
| } | ||
| MatchedPlace(int matchedCount, boolean matchedBonusNumber, final int prize) { | ||
| this.matchedCount = matchedCount; | ||
| this.matchedBonusNumber = matchedBonusNumber; | ||
| this.prize = prize; | ||
| } | ||
| public int getMatchedCount() { | ||
| return matchedCount; | ||
| } | ||
|
|
||
| public int getPrize() { | ||
| return prize; | ||
| } | ||
| } | ||
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.
숫자인지 검증하는 정규식으로 보이는데, 정규식을 하드코딩하기보다
NUMBER_REGEX상수로 저장해서 사용하는 것이 좋을 것 같습니다