-
Notifications
You must be signed in to change notification settings - Fork 3
로또(순서보장) #11
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: master
Are you sure you want to change the base?
로또(순서보장) #11
Changes from 9 commits
eb48727
ca50eee
4fd9cd8
dfee2bd
816f30f
ad70aa7
9044919
15e115d
bed1357
51a3697
d44524b
5eee3e2
3b5feca
6282d30
2ef0714
efeb456
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,38 @@ | ||
| 1. 로또 번호를 발급한다 ---> LotteNumberGenerator - o | ||
| - input: 구입금액 | ||
|
|
||
| 2. 지난주 로또 번호와 비교하여 3-6개 사이 일치하는 개수를 반환한다. | ||
|
|
||
| 3. 총 수익률을 계산한다. | ||
|
|
||
|
|
||
|
|
||
| **view** | ||
| - 구입금액을 입력받는다 (1) - o | ||
| - 지난주 당첨번호를 입력받는다 (4) - o | ||
| - 보너스 번호를 입력받는다 (5) - o | ||
|
|
||
|
|
||
| - 구매 갯수를 출력한다. (2) | ||
| - 로또 랜덤을 출력한다(3) | ||
| - 3-6개까지 일치하는 개수를 출력한다 (6) | ||
| - 수익률을 출한다 (7) | ||
|
|
||
|
|
||
|
|
||
| 질문) | ||
| 1. LottoTicket은 AutoLottoNumberGenerator에 의해서만 발행된다. | ||
| 하지만 생성잔느 public하게 열려있다. 그래서 사이즈 체크 검증을 추가했고 그 결과 | ||
| private static final int COUNT_OF_LOTTO_NUMBER = 6; | ||
|
|
||
| 가 중복된다. | ||
|
|
||
|
|
||
| 2. this.lottoNumbers = Collections.unmodifiableList(lottoNumbers); | ||
|
|
||
| add시 발생하는 UnsupportedOperationException 는 그냥 던지게 남겨두면 되는건가 | ||
|
|
||
| 3. LottoTicket 일급컬렉션의 검증은 어디까지? | ||
|
|
||
|
|
||
| 4. 객체의 상태와 역할을 생각하면 가격은 티켓이 가지고 있어야 할 것 같은데, 계속 Getter로 가져오자니 비횰 ㅠ,,ㅇ? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,31 @@ | ||
| package com.javabom.lotto; | ||
|
|
||
| import com.javabom.lotto.domain.AutoLottoNumberGenerator; | ||
| import com.javabom.lotto.domain.LottoStore; | ||
| import com.javabom.lotto.domain.result.BonusNumber; | ||
| import com.javabom.lotto.domain.result.LottoResult; | ||
| import com.javabom.lotto.domain.result.WinningTicket; | ||
| import com.javabom.lotto.domain.ticket.LottoTicket; | ||
| import com.javabom.lotto.domain.ticket.LottoTickets; | ||
| import com.javabom.lotto.view.InputView; | ||
| import com.javabom.lotto.view.OutputView; | ||
| import com.javabom.lotto.vo.Money; | ||
|
|
||
| public class LottoApplication { | ||
|
|
||
| public static void main(String[] args) { | ||
| LottoStore lottoStore = new LottoStore(new AutoLottoNumberGenerator()); | ||
|
|
||
| Money totalMoney = new Money(InputView.askTotalMoney()); | ||
| LottoTickets lottoTickets = lottoStore.buy(totalMoney); | ||
|
|
||
| OutputView.printLottoTicketNumbers(lottoTickets); | ||
|
|
||
| LottoTicket winningLottoTicket = new LottoTicket(InputView.askLastWeekWinningNumbers()); | ||
| BonusNumber bonusNumber = new BonusNumber(InputView.askBonusNumber()); | ||
| WinningTicket winningTicket = new WinningTicket(winningLottoTicket, bonusNumber); | ||
| LottoResult lottoResult = lottoTickets.getLottoResult(winningTicket); | ||
|
|
||
| OutputView.printResult(lottoResult, totalMoney); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.javabom.lotto.domain; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| import static com.javabom.lotto.domain.LottoNumberSetting.*; | ||
| import static java.util.stream.Collectors.toList; | ||
|
|
||
| public class AutoLottoNumberGenerator implements LottoNumberGenerator { | ||
| private final List<Integer> lottoBalls; | ||
|
|
||
| public AutoLottoNumberGenerator() { | ||
| this.lottoBalls = IntStream.rangeClosed(NUMBER_BEGIN_BOUND, NUMBER_END_BOUND) | ||
| .boxed() | ||
| .collect(toList()); | ||
| } | ||
|
|
||
| @Override | ||
| public Set<Integer> generate() { | ||
| Collections.shuffle(lottoBalls); | ||
| return Collections.unmodifiableSet(new HashSet<>(pickLottoBalls())); | ||
| } | ||
|
|
||
| private List<Integer> pickLottoBalls() { | ||
| return lottoBalls.subList(0, COUNT_OF_NUMBER); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.javabom.lotto.domain; | ||
|
|
||
| import java.util.Set; | ||
|
|
||
| public interface LottoNumberGenerator { | ||
| Set<Integer> generate(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.javabom.lotto.domain; | ||
|
|
||
| public class LottoNumberSetting { | ||
| public static final int NUMBER_BEGIN_BOUND = 1; | ||
| public static final int NUMBER_END_BOUND = 45; | ||
| public static final int COUNT_OF_NUMBER = 6; | ||
|
|
||
| private LottoNumberSetting() { | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.javabom.lotto.domain; | ||
|
|
||
| import com.javabom.lotto.domain.ticket.LottoTicket; | ||
| import com.javabom.lotto.domain.ticket.LottoTickets; | ||
| import com.javabom.lotto.vo.Money; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class LottoStore { | ||
| private static final Money LOTTO_TICKET_PRICE = new Money(1000); | ||
| private final LottoNumberGenerator lottoNumberGenerator; | ||
|
|
||
| public LottoStore(LottoNumberGenerator lottoNumberGenerator) { | ||
| this.lottoNumberGenerator = lottoNumberGenerator; | ||
| } | ||
|
|
||
| public LottoTickets buy(final Money totalMoney) { | ||
| Money currentChange = totalMoney; | ||
| List<LottoTicket> lottoTickets = new ArrayList<>(); | ||
|
|
||
| while (isEnoughChange(currentChange)) { | ||
| lottoTickets.add(new LottoTicket(lottoNumberGenerator.generate())); | ||
| currentChange = currentChange.spend(LOTTO_TICKET_PRICE); | ||
| } | ||
|
|
||
| return new LottoTickets(lottoTickets); | ||
| } | ||
|
|
||
| private boolean isEnoughChange(Money currentChange) { | ||
| return currentChange.isEnoughToBuy(LOTTO_TICKET_PRICE); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.javabom.lotto.domain.result; | ||
|
|
||
| import static com.javabom.lotto.domain.LottoNumberSetting.NUMBER_BEGIN_BOUND; | ||
| import static com.javabom.lotto.domain.LottoNumberSetting.NUMBER_END_BOUND; | ||
|
|
||
| public class BonusNumber { | ||
| private final int number; | ||
|
|
||
| public BonusNumber(int number) { | ||
|
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. 저도 찬인님 말씀대로 BonusNumber와 WinningTicket 모두 number(integer)값에 대한 유효성 검사가 들어가서 한번 더 객체로 감싸서 하면 좋다고 생각합니다! ㅎㅎ
Author
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(matchCount == THIRD.hitCount && matchBonus){
return SECOND;
}
if(matchCount == THIRD.hitCount && !matchBonus){
return THRID;
}보다는 위의 방식이 더 가독성있어보인다고 생각했어요!
Author
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. BonusNumber는 지금은 없는 클래스예요! LottoNumber로 대체하고있어용 |
||
| if (isValidNumber(number)) { | ||
| throw new IllegalArgumentException("보너스번호는 1이상 45이하여야합니다"); | ||
| } | ||
| this.number = number; | ||
| } | ||
|
|
||
| private boolean isValidNumber(int number) { | ||
| return number < NUMBER_BEGIN_BOUND || number > NUMBER_END_BOUND; | ||
| } | ||
|
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. 저는 개인적으로 if 문에다가 조건을 전부 쓰고,
Author
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문이 조금 더 판단하기 쉽다고 생각했는데 이 경우는 딱히 그래보이지 않네용 ㅎㅅㅎ 반영했습니다! |
||
|
|
||
| public int getNumber() { | ||
| return this.number; | ||
| } | ||
|
|
||
| public boolean isSameNumber(final int number) { | ||
| return this.number == number; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package com.javabom.lotto.domain.result; | ||
|
|
||
| import com.javabom.lotto.vo.Money; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| public enum LottoPrize { | ||
| FIRST(6, 2_000_000_000), | ||
| SECOND(5, 30_000_000), | ||
| THIRD(5, 1_500_000), | ||
| FOURTH(4, 50_000), | ||
| FIFTH(3, 5_000), | ||
| MISS(0, 0); | ||
|
|
||
| private final int hitCount; | ||
| private final long reward; | ||
|
|
||
| LottoPrize(int hitCount, long reward) { | ||
| this.hitCount = hitCount; | ||
| this.reward = reward; | ||
| } | ||
|
|
||
| public static Money calculateTotalReword(List<LottoPrize> statistics) { | ||
| Long totalMoney = statistics.stream() | ||
| .map(LottoPrize::getReward) | ||
| .reduce(0L, Long::sum); | ||
| return new Money(totalMoney); | ||
| } | ||
|
|
||
| public static LottoPrize findByMathCount(int matchCount, boolean matchBonus) { | ||
|
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. Match의 오타..인가요?
Author
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 (matchCount == THIRD.hitCount) { | ||
| return findByBonus(matchBonus); | ||
| } | ||
| return Arrays.stream(LottoPrize.values()) | ||
| .filter(lottoPrize -> lottoPrize.hitCount == matchCount) | ||
| .findAny() | ||
| .orElse(MISS); | ||
| } | ||
|
|
||
| private static LottoPrize findByBonus(boolean matchBonus) { | ||
| if (matchBonus) { | ||
| return SECOND; | ||
| } | ||
| return THIRD; | ||
| } | ||
|
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. 아 요런방법이... 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. matchBonus 변수 자체가 보너스 번호 유무를 넘겨주는 건데, matchCount == THIRD.hitCount && matchBonus말고 한번 더 findByBonus로 빼신 이유가 있을까요?? |
||
|
|
||
| public long getReward() { | ||
| return reward; | ||
| } | ||
|
|
||
| public int getHitCount() { | ||
| return hitCount; | ||
| } | ||
| } | ||
|
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. 이건 안쓰는메소드라 없애도 될거같아요 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.javabom.lotto.domain.result; | ||
|
|
||
| import com.javabom.lotto.vo.Money; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| public class LottoResult { | ||
| private static final int PERCENTAGE = 100; | ||
| private final List<LottoPrize> lottoStatistics; | ||
|
|
||
| public LottoResult(List<LottoPrize> lottoPrizes) { | ||
| this.lottoStatistics = lottoPrizes; | ||
| } | ||
|
|
||
| public int getNumberOfHitTickets(final LottoPrize lottoPrize) { | ||
| return Math.toIntExact(lottoStatistics.stream() | ||
| .filter(lottoStatistic -> lottoStatistic.equals(lottoPrize)) | ||
| .count()); | ||
| } | ||
|
|
||
| public double getRateOfProfit(final Money spentMoney) { | ||
| Money totalProfit = LottoPrize.calculateTotalReword(lottoStatistics); | ||
| return (double) totalProfit.getValue() / spentMoney.getValue() * PERCENTAGE; | ||
|
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. 이 로직 Money 쪽에서 해줄수 있지않을까? |
||
| } | ||
|
|
||
| public List<LottoPrize> getLottoStatistics() { | ||
| return Collections.unmodifiableList(lottoStatistics); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.javabom.lotto.domain.result; | ||
|
|
||
| import com.javabom.lotto.domain.ticket.LottoTicket; | ||
|
|
||
| public class WinningTicket { | ||
| private final LottoTicket lottoTicket; | ||
| private final BonusNumber bonusNumber; | ||
|
|
||
| public WinningTicket(LottoTicket lottoTicket, BonusNumber bonusNumber) { | ||
| if (lottoTicket.contains(bonusNumber.getNumber())) { | ||
| throw new IllegalArgumentException("보너스번호와 당첨번호는 중복될 수 없습니다"); | ||
| } | ||
| this.lottoTicket = lottoTicket; | ||
| this.bonusNumber = bonusNumber; | ||
| } | ||
|
|
||
| public boolean contains(final int lottoNumber) { | ||
| return lottoTicket.contains(lottoNumber); | ||
| } | ||
|
|
||
| public boolean matchBonus(final int lottoNumber) { | ||
| return bonusNumber.isSameNumber(lottoNumber); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package com.javabom.lotto.domain.ticket; | ||
|
|
||
| import com.javabom.lotto.domain.result.LottoPrize; | ||
| import com.javabom.lotto.domain.result.WinningTicket; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import static com.javabom.lotto.domain.LottoNumberSetting.*; | ||
|
|
||
| public class LottoTicket { | ||
| private final Set<Integer> lottoNumbers; | ||
|
|
||
| public LottoTicket(Set<Integer> lottoNumbers) { | ||
| validate(lottoNumbers); | ||
| this.lottoNumbers = lottoNumbers; | ||
| } | ||
|
|
||
| private static boolean isValidNumber(Integer number) { | ||
| return number >= NUMBER_BEGIN_BOUND && number <= NUMBER_END_BOUND; | ||
| } | ||
|
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. LottoTicket이 들고 있는 Integer에 대해 개별적으로 검증해야 할 로직이 있다는건 |
||
|
|
||
| private void validate(Set<Integer> lottoNumbers) { | ||
| Set<Integer> validLottoNumbers = lottoNumbers.stream() | ||
| .filter(LottoTicket::isValidNumber) | ||
| .collect(Collectors.toSet()); | ||
| if (validLottoNumbers.size() != COUNT_OF_NUMBER) { | ||
| throw new IllegalArgumentException("로또번호는 중복이 없는 6개의 1과 45사이의 숫자여야 합니다"); | ||
| } | ||
| } | ||
|
|
||
| public LottoPrize calculateLottoPrize(WinningTicket winningTicket) { | ||
|
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.
Author
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. ㅋㅋㅋㅋㅋㅋㅋ 나 안그래도 이거 질문남겼어 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 해결하겠읍니다 ,,! |
||
| int matchCount = Math.toIntExact(lottoNumbers.stream() | ||
| .filter(winningTicket::contains) | ||
| .count()); | ||
| boolean matchBonus = lottoNumbers.stream() | ||
| .anyMatch(winningTicket::matchBonus); | ||
|
|
||
| return LottoPrize.findByMathCount(matchCount, matchBonus); | ||
| } | ||
|
|
||
| public boolean contains(int number) { | ||
| return lottoNumbers.contains(number); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| List<Integer> sortedLottoNumbers = new ArrayList<>(lottoNumbers); | ||
| Collections.sort(sortedLottoNumbers); | ||
| return String.valueOf(sortedLottoNumbers); | ||
|
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. 헉 나는 toString의 본래 용도대로 사용되는게 아닌거같아 보여
Author
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. :( 마쟈요 동의합니다 ,, |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package com.javabom.lotto.domain.ticket; | ||
|
|
||
| import com.javabom.lotto.domain.result.LottoPrize; | ||
| import com.javabom.lotto.domain.result.LottoResult; | ||
| import com.javabom.lotto.domain.result.WinningTicket; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| import static java.util.stream.Collectors.toList; | ||
|
|
||
| public class LottoTickets { | ||
| private final List<LottoTicket> lottoTickets; | ||
|
|
||
| public LottoTickets(List<LottoTicket> lottoTickets) { | ||
| this.lottoTickets = lottoTickets; | ||
| } | ||
|
|
||
| public LottoResult getLottoResult(WinningTicket winningTicket) { | ||
| List<LottoPrize> lottoPrizes = lottoTickets.stream() | ||
| .map(lottoTicket -> lottoTicket.calculateLottoPrize(winningTicket)) | ||
| .collect(toList()); | ||
| return new LottoResult(lottoPrizes); | ||
| } | ||
|
|
||
| public List<LottoTicket> getLottoTickets() { | ||
| return Collections.unmodifiableList(lottoTickets); | ||
| } | ||
|
|
||
| public int count() { | ||
| return lottoTickets.size(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return String.valueOf(lottoTickets); | ||
| } | ||
| } |

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.
Money에서 isEnougToBuy랑 같은 행위를 하는데, 한번 더 메소드로 빼신 이유가 있으신가요?! 궁금합니다!
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.
이것도 지금 없어짐 메서드일거예여!