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

[Step4] 로또(2등) #1676

Merged
merged 6 commits into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,33 @@ LotteryTicket - 로또


# [4단계] 로또(2등)

// TODO
```text
[... 생략 ...]

지난 주 당첨 번호를 입력해 주세요.
1, 2, 3, 4, 5, 6
보너스 볼을 입력해 주세요.
7

당첨 통계
---------
3개 일치 (5000원)- 1개
4개 일치 (50000원)- 0개
5개 일치 (1500000원)- 0개
5개 일치, 보너스 볼 일치(30000000원) - 0개
6개 일치 (2000000000원)- 0개
총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
```

- [x] 보너스볼 변수 생성
- [x] 보너스볼 체크 로직 추가
- [x] 보너스볼 당첨시 전체 금액 확인
- [x] 보너스볼을 물어보는 메세지 출력
- [x] 보너스볼이 포함된 메세지 출력

--- 그외 고려해볼만한 리팩토링
- [x] matchCount 의 integer을 통해 matchType 개선
- [x] infoCenter 테스트 코드 리팩토링

# [5단계] 로또(수동)

Expand Down
21 changes: 20 additions & 1 deletion src/main/java/lottery/Buyer.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package lottery;

import static java.util.Objects.*;
import static lottery.Money.*;

import java.util.Objects;

public final class Buyer {

private Money money = Money.ZERO;
private Tickets tickets = Tickets.EMPTY_TICKETS;

Expand Down Expand Up @@ -34,8 +38,23 @@ public Result checkTicket(InfoCenter infoCenter) {

public void setMoney(Money money) {
if (isNull(money) || money.amount() < 0) {
throw new IllegalArgumentException("유효하지 않은 값입니다.");
throw new IllegalArgumentException(NOT_VALID_MONEY_EXCEPTION_MESSAGE);
}
this.money = money;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Buyer))
return false;
Buyer buyer = (Buyer)o;
return Objects.equals(money, buyer.money) && Objects.equals(tickets, buyer.tickets);
}

@Override
public int hashCode() {
return hash(money, tickets);
}
}
15 changes: 6 additions & 9 deletions src/main/java/lottery/InfoCenter.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@

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

import java.util.stream.Collectors;

public class InfoCenter {

private final int MATCH_THREE_NUMBER = 3;
private Ticket lastWeekWinningTicket;
private WinningTicket lastWeekWinningTicket;

public void setLastWeekWinningTicket(Ticket lastWeekWinningTicket) {
public void setLastWeekWinningTicket(WinningTicket lastWeekWinningTicket) {
this.lastWeekWinningTicket = lastWeekWinningTicket;
}

public Result confirmTicket(Tickets buyerTickets) {
return new Result(LotteryMatchTypeMap.of(buyerTickets.getValues().stream()
.map(ticket -> ticket.numbers().matchCountWith(lastWeekWinningTicket.numbers()))
.filter(matchCount -> matchCount >= MATCH_THREE_NUMBER)
.collect(Collectors.groupingBy(LotteryMatchType::fromInteger, summingInt(a -> 1)))));
.map(ticket -> lastWeekWinningTicket.getMatchTypeWith(ticket))
.filter(matchType -> LotteryMatchType.MISS_MATCH != matchType)
.collect(groupingBy(a -> a, summingInt(a -> 1)))));
}

public Ticket lastWeekWinningNumbers() {
public WinningTicket lastWeekWinningNumbers() {
return lastWeekWinningTicket;
}
}
5 changes: 3 additions & 2 deletions src/main/java/lottery/LotteryMatchType.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum LotteryMatchType {
THREE_MATCH(3, Money.won(5_000L)),
FOUR_MATCH(4, Money.won(50_000L)),
FIVE_MATCH(5, Money.won(1_500_000L)),
FIVE_MATCH_WITH_BONUS(5, Money.won(30_000_000L)),
SIX_MATCH(6, Money.won(2_000_000_000L));

private final int matchCount;
Expand All @@ -25,9 +26,9 @@ public int matchCount() {
return matchCount;
}

public static LotteryMatchType fromInteger(int matchCount) {
public static LotteryMatchType byMatchCount(int matchCount) {
return Arrays.stream(LotteryMatchType.values())
.filter(a -> a.matchCount == matchCount)
.filter(matchType -> matchType.matchCount == matchCount)
.findFirst()
.orElse(MISS_MATCH);
}
Expand Down
21 changes: 14 additions & 7 deletions src/main/java/lottery/LotteryMatchTypeMap.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
package lottery;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

public class LotteryMatchTypeMap {

public static final LotteryMatchTypeMap EMPTY = new LotteryMatchTypeMap(new LinkedHashMap<>());
private static final String NOT_FOUND_LOTTERY_MATCH_TYPE = "LotteryMatchTypeMap 정보가 없습니다";

private final Map<LotteryMatchType, Integer> matchTypeMap;
private Map<LotteryMatchType, Integer> matchTypeMap;

public static LotteryMatchTypeMap of(Map<LotteryMatchType, Integer> map) {
return new LotteryMatchTypeMap(map);
}

private LotteryMatchTypeMap(Map<LotteryMatchType, Integer> matchTypeMap) {
this.matchTypeMap = matchTypeMap;
setMatchTypeMap(matchTypeMap);
}

public static LotteryMatchTypeMap of(Map<LotteryMatchType, Integer> map) {
return new LotteryMatchTypeMap(map);
private void setMatchTypeMap(Map<LotteryMatchType, Integer> matchTypeMap) {
if (Objects.isNull(matchTypeMap) || matchTypeMap.isEmpty()){
throw new IllegalArgumentException(NOT_FOUND_LOTTERY_MATCH_TYPE);
}
this.matchTypeMap = matchTypeMap;
}

public Map<LotteryMatchType, Integer> getMatchTypeMap() {
public Map<LotteryMatchType, Integer> matchTypeMap() {
return Collections.unmodifiableMap(matchTypeMap);
}

Expand Down
18 changes: 11 additions & 7 deletions src/main/java/lottery/LottoNumbers.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

public class LottoNumbers {

private final Set<Integer> numbers;
private static final String NOT_FOUND_LOTTO_NUMBERS_EXCEPTION_MESSAGE = "로또 번호에 대한 정보가 없습니다";

private Set<Integer> numbers;

public static LottoNumbers from(Set<Integer> numbers) {
if (numbers.size() != SIZE_OF_TICKET) {
Expand All @@ -20,16 +22,18 @@ public static LottoNumbers from(Set<Integer> numbers) {
}

private LottoNumbers(Set<Integer> numbers) {
this.numbers = numbers;
setNumbers(numbers);
}

public Set<Integer> getValues() {
return Collections.unmodifiableSet(numbers);
private void setNumbers(Set<Integer> numbers) {
if (Objects.isNull(numbers) || numbers.isEmpty()){
throw new IllegalArgumentException(NOT_FOUND_LOTTO_NUMBERS_EXCEPTION_MESSAGE);
}
this.numbers = numbers;
}

public int matchCountWith(LottoNumbers numbers){
this.numbers.removeAll(numbers.getValues());
return SIZE_OF_TICKET - this.numbers.size();
public Set<Integer> values() {
return Collections.unmodifiableSet(numbers);
}

@Override
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/lottery/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ public static void main(String[] args) {
.map(a -> Integer.parseInt(a.trim()))
.sorted()
.collect(Collectors.toCollection(LinkedHashSet::new));
infoCenter.setLastWeekWinningTicket(Ticket.of(LottoNumbers.from(ints)));
Ticket lastWeekTicket = Ticket.of(LottoNumbers.from(ints));

inputView.askForBonusNumber();
int bonus = Integer.parseInt(sc.nextLine().trim());
infoCenter.setLastWeekWinningTicket(new WinningTicket(lastWeekTicket, bonus));

Result result = buyer.checkTicket(infoCenter);
float totalYield = result.getTotalYield(initialMoney);
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/lottery/Money.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

public final class Money {
public static final Money ZERO = new Money(0L);
public static final String NOT_VALID_MONEY_EXCEPTION_MESSAGE = "유효하지 않은 로또 금액입니다.";
private Long amount;

public static Money won(Long amount) {
Expand All @@ -19,8 +20,8 @@ public Long amount() {
}

private void setAmount(Long amount) {
if (amount < 0) {
throw new IllegalArgumentException("유효하지 않는 금액입니다");
if (Objects.isNull(amount) || amount < 0) {
throw new IllegalArgumentException(NOT_VALID_MONEY_EXCEPTION_MESSAGE);
}
this.amount = amount;
}
Expand Down Expand Up @@ -48,7 +49,7 @@ public Money add(Money target) {
public float divideWithFloating(Money result) {
float v = (float)this.amount / result.amount;
if (Float.isInfinite(v) || Float.isNaN(v)) {
throw new IllegalArgumentException("유효하지 않는 값입니다.");
throw new IllegalArgumentException(NOT_VALID_MONEY_EXCEPTION_MESSAGE);
}
return v;
}
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/lottery/Result.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@

import java.util.Collections;
import java.util.Map;
import java.util.Objects;

public class Result {

private final LotteryMatchTypeMap resultMap;
private LotteryMatchTypeMap resultMap;
private static final String NOT_FOUND_RESULTMAP_EXCEPTION_MESSAGE = "당첨을 확인할 수 있는 정보가 없습니다.";

public Result(LotteryMatchTypeMap resultMap) {
setResultMap(resultMap);
}

private void setResultMap(LotteryMatchTypeMap resultMap) {
if (Objects.isNull(resultMap)) {
throw new IllegalArgumentException(NOT_FOUND_RESULTMAP_EXCEPTION_MESSAGE);
}
this.resultMap = resultMap;
}

public Map<LotteryMatchType, Integer> getResultMap() {
return Collections.unmodifiableMap(resultMap.getMatchTypeMap());
return Collections.unmodifiableMap(resultMap.matchTypeMap());
}

public float getTotalYield(Money buyerMoney) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/lottery/Store.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class Store {

private final TicketMachine machine;

private static final Money TICKET_PRICE = Money.won(1000L);
public static final Money TICKET_PRICE = Money.won(1000L);

public Store() {
machine = new TicketMachine();
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/lottery/Ticket.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lottery;

import java.util.Objects;
import java.util.Set;

public final class Ticket {

Expand All @@ -19,8 +20,8 @@ private void setNumbers(LottoNumbers lottoNumbers) {
this.lottoNumbers = lottoNumbers;
}

public LottoNumbers numbers() {
return lottoNumbers;
public Set<Integer> numbers() {
return lottoNumbers.values();
}

@Override
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/lottery/Tickets.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,27 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class Tickets {

public static final Tickets EMPTY_TICKETS = new Tickets(new ArrayList<>());

private final List<Ticket> value;
private List<Ticket> value;
private String NOT_FOUND_TICKETS_EXCEPTION_MESSAGE = "Ticket 정보가 없습니다";

public static Tickets of(List<Ticket> ticketList) {
return new Tickets(ticketList);
}

private Tickets(List<Ticket> value) {
setValue(value);
}

private void setValue(List<Ticket> value) {
if (Objects.isNull(value)){
throw new IllegalArgumentException(NOT_FOUND_TICKETS_EXCEPTION_MESSAGE);
}
this.value = value;
}

Expand Down
62 changes: 62 additions & 0 deletions src/main/java/lottery/WinningTicket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package lottery;

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

public class WinningTicket {

private Ticket ticket;
private int bonus;
private static final String NOT_VALID_WINNING_TICKET_NUMBERS_EXCEPTION_MESSAGE = "잘못된 당첨 정보 입니다";
private static final String NOT_VALID_BONUS_EXCEPTION_MESSAGE = "잘못된 보너스 번호 입니다";

public WinningTicket(Ticket ticket, int bonus) {
setTicket(ticket);
setBonus(bonus);
}

private void setTicket(Ticket ticket) {
if (Objects.isNull(ticket)) {
throw new IllegalArgumentException(NOT_VALID_WINNING_TICKET_NUMBERS_EXCEPTION_MESSAGE);
}
this.ticket = ticket;
}

private void setBonus(int bonus) {
if (bonus <= 0 || bonus > 45) {
throw new IllegalArgumentException(NOT_VALID_BONUS_EXCEPTION_MESSAGE);
}
this.bonus = bonus;
}

public LotteryMatchType getMatchTypeWith(Ticket targetTicket) {
LinkedHashSet<Integer> targetNumbers = new LinkedHashSet<>(targetTicket.numbers());
targetNumbers.removeAll(this.ticket.numbers());

LotteryMatchType matchType = LotteryMatchType.byMatchCount(Ticket.SIZE_OF_TICKET - targetNumbers.size());
if (isBonusMatchCount(bonus, matchType, targetNumbers)) {
return LotteryMatchType.FIVE_MATCH_WITH_BONUS;
}
return matchType;
}

private boolean isBonusMatchCount(int bonus, LotteryMatchType matchType, Set<Integer> winningTicketNumbers) {
return matchType == LotteryMatchType.FIVE_MATCH && winningTicketNumbers.contains(bonus);
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof WinningTicket))
return false;
WinningTicket that = (WinningTicket)o;
return bonus == that.bonus && Objects.equals(ticket, that.ticket);
}

@Override
public int hashCode() {
return Objects.hash(ticket, bonus);
}
}