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 #3258

Open
wants to merge 3 commits into
base: joooahn
Choose a base branch
from
Open

step4 #3258

Show file tree
Hide file tree
Changes from all 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
12 changes: 7 additions & 5 deletions src/main/java/lotto/domain/BonusBall.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package lotto.domain;

import lotto.exception.TicketNumberOutOfBoundException;

public class BonusBall {
private final Integer bonusBall;
private final LottoNo bonusBall;

private BonusBall(Integer bonusBall) {
private BonusBall(LottoNo bonusBall) {
this.bonusBall = bonusBall;
}

public static BonusBall from(String bonusBall) {
return new BonusBall(Integer.valueOf(bonusBall));
public static BonusBall from(String bonusBall) throws TicketNumberOutOfBoundException {
return new BonusBall(LottoNo.from(Integer.valueOf(bonusBall)));
}

public Integer getBonusBall() {
public LottoNo getBonusBall() {
return bonusBall;
}
}
11 changes: 7 additions & 4 deletions src/main/java/lotto/domain/LottoGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

public class LottoGenerator {

public static LottoTickets generateTickets(long money) {
public static LottoTickets generateAutoTickets(long numberOfTicket) {
List<Ticket> tickets = new ArrayList<>();
long numberOfTickets = money / LOTTO_PRICE;
long numberOfTickets = numberOfTicket;

for (int i = 0; i < numberOfTickets; i++) {
List<Integer> candidateNumbers = makeCandidateNumbers();
Expand All @@ -24,10 +24,13 @@ public static LottoTickets generateTickets(long money) {
return LottoTickets.from(tickets);
}

public static LottoTickets generateManualTickets(List<Ticket> tickets) {
return LottoTickets.from(tickets);
}

private static List<Integer> makeCandidateNumbers() {
List<Integer> candidateNumbers = IntStream.rangeClosed(MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER)
return IntStream.rangeClosed(MIN_LOTTO_NUMBER, MAX_LOTTO_NUMBER)
.boxed()
.collect(Collectors.toList());
return candidateNumbers;
}
}
36 changes: 36 additions & 0 deletions src/main/java/lotto/domain/LottoNo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package lotto.domain;

import lotto.exception.TicketNumberOutOfBoundException;

public class LottoNo {
int number;

private LottoNo(int number) throws TicketNumberOutOfBoundException {
if (checkValid(number)) {
this.number = number;
}
}

public static LottoNo from(int number) throws TicketNumberOutOfBoundException {
return new LottoNo(number);
}

public static LottoNo from(String string) throws TicketNumberOutOfBoundException {
return new LottoNo(Integer.parseInt(string.trim()));
}

private boolean checkValid(int number) throws TicketNumberOutOfBoundException {
if (number < 0 || number > 45) {
throw new TicketNumberOutOfBoundException("1 ~ 45 범위만 입력 가능합니다.");
}
return true;
}

public int number() {
return this.number;
}

public boolean equals(LottoNo lottoNo) {
return this.number == lottoNo.number();
}
}
85 changes: 57 additions & 28 deletions src/main/java/lotto/domain/LottoTickets.java
Original file line number Diff line number Diff line change
@@ -1,61 +1,84 @@
package lotto.domain;

import lotto.exception.TicketNumberOutOfBoundException;
import lotto.exception.TicketPriceOutOfBoundException;

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

import static lotto.domain.Ticket.LOTTO_PRICE;

public class LottoTickets {
Copy link

Choose a reason for hiding this comment

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

LottoTickets 의 책임이 점점 많아지고 있어요.
다른 객체로 책임을 분산 할 수 없나 고민해볼까요? 🤔

private final List<Ticket> tickets;
private final Integer numberOfManualTickets;
private final Integer numberOfAutoTickets;

private LottoTickets(List<Ticket> tickets) {
private LottoTickets(List<Ticket> tickets, int numberOfManualTickets, int numberOfAutoTickets) {
this.tickets = tickets;
this.numberOfManualTickets = numberOfManualTickets;
this.numberOfAutoTickets = numberOfAutoTickets;
}

public static LottoTickets from(List<Ticket> tickets) {
return new LottoTickets(tickets);
return new LottoTickets(tickets, 0, 0);
}

public static LottoTickets of(LottoTickets manualTickets, LottoTickets autoTickets) {
return new LottoTickets(manualTickets.merge(autoTickets), manualTickets.numberOfTickets(), autoTickets.numberOfTickets());
}

private List<Ticket> merge(LottoTickets tickets) {
List<Ticket> mergedTickets = new ArrayList<>();
mergedTickets.addAll(this.tickets);
mergedTickets.addAll(tickets.getTickets());
return mergedTickets;
}

public int numberOfTickets() {
return tickets.size();
}

public int totalPrice() {
return tickets.size() * 1000;
return tickets.size() * LOTTO_PRICE;
}

public boolean checkValidTickets() {
return tickets.stream().allMatch(Ticket::checkValidTickets);
public static LottoTickets buyTickets(long money, List<Ticket> manualTickets) throws TicketNumberOutOfBoundException, TicketPriceOutOfBoundException {
if (money < 0) {
throw new TicketPriceOutOfBoundException("가격은 음수가 불가능합니다.");
}
int numberOfManualTicket = manualTickets.size();
int numberOfAutoTicket = (int) (money / LOTTO_PRICE) - numberOfManualTicket;
return LottoTickets.of(buyManualTickets(manualTickets), buyAutoTickets(numberOfAutoTicket));
}

public static LottoTickets buyTickets(long money) {
return LottoGenerator.generateTickets(money);
public static LottoTickets buyManualTickets(List<Ticket> tickets) {
return LottoGenerator.generateManualTickets(tickets);
}

public static LottoTickets buyAutoTickets(long numberOfTicket) throws TicketNumberOutOfBoundException {
if (numberOfTicket < 0) {
throw new TicketNumberOutOfBoundException("티켓 개수는 음수가 불가능합니다.");
}
return LottoGenerator.generateAutoTickets(numberOfTicket);
}

public List<Ticket> getTickets() {
return tickets;
}

public WinningStatus winningStatus(WinningNumber winningNumber) {
List<PrizeType> prizeTypes = listOfPrize(winningNumber);
return makeWinningStatus(prizeTypes);
List<Prize> prizeTypesOfTickets = listOfPrize(winningNumber);
return makeWinningStatus(prizeTypesOfTickets);
}

public List<PrizeType> listOfPrize(WinningNumber winningNumber) {
public List<Prize> listOfPrize(WinningNumber winningNumber) {
return tickets.stream()
.map(ticket -> ticket.checkLotteryWinningStatus(winningNumber))
.collect(Collectors.toList());
}

private WinningStatus makeWinningStatus(List<PrizeType> prizeTypes) {
Map<PrizeType, Integer> winningStatus = new HashMap<>();
Arrays.stream(PrizeType.values())
.forEach(prizeType -> winningStatus.put(prizeType, countPrizeType(prizeTypes, prizeType)));
return WinningStatus.from(winningStatus);
}

public int countPrizeType(List<PrizeType> prizeTypes, PrizeType prizeType) {
return (int) prizeTypes.stream()
.filter(t -> t == prizeType)
.count();
private WinningStatus makeWinningStatus(List<Prize> prizeTypesOfTickets) {
return WinningStatus.from(prizeTypesOfTickets);
}

public double returnRate(WinningNumber winningNumber) {
Copy link

Choose a reason for hiding this comment

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

지금 listOfPrize를 두번 만들고 있는데요, WinningStatus 만들때 totalPrice 만 같이 넘겨주면
WinningStatus 안에 있는 정보들로 returnRate도 만들어 줄 수 있을 것 같아요.

Copy link
Author

Choose a reason for hiding this comment

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

winningStatus(당첨 통계), returnRate(수익를)을 구할 땐 LottoTickets에게 WinningNumber만 주고 계산하도록 구현했어요
의미상 LottoTickets에게 당첨 번호를 주고 결과를 물어보는게 맞다고 생각해서입니다.

listOfPrice를 2번 사용한다면 listOfPrice가 수정될 경우 2군데 수정해야 한다는 단점이 있지만,
WinningStatus의 정보들로 returnRate를 만드려면 다음과 같이 파라미터를 통해 WinningStatus를 넘겨줘야 해 lottoTickets와 WinningStatus간의 새로운 의존관계가 생겨서 좋지 않다고 생각하는데 어떻게 생각하시나요?
lottoTickets.returnRate(winningStatus)

Copy link

Choose a reason for hiding this comment

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

returnRate 메소드에서 winningNumberList<Prize> types = listOfPrize(winningNumber); 를 구할때 사용 하고 있는것으로 보이는데요. WinningStatus 를 만들때 동일하게 listOfPrize(winningNumber); 의 결과를 이용 하는것으로 보여요.
그래서 WinningStatus의 필드인 winningStatus를 이용해서 충분히 같은 값을 구할 수 있다고 생각했습니다.

아래 LottoTickets 의 returnRate 메소드는

public double returnRate(WinningNumber winningNumber) {
        double result = (double) sumOfPrize(winningNumber) / totalPrice();
        return Math.floor(result * 100) / 100;
    }

    private long sumOfPrize(WinningNumber winningNumber) {
        List<Prize> types = listOfPrize(winningNumber);
        return types.stream()
                .mapToLong(Prize::prize)
                .sum();
    }

WinningStatus 에서는 아래 로직으로 대체 할 수 있을 것 같습니다.

public double returnRate() {
        double result = (double) sumOfPrize() / price;
        return Math.floor(result * 100) / 100;
    }

    private long sumOfPrize() {
        return winningStatus.entrySet().stream()
                .mapToLong(it -> it.getKey().prize() * it.getValue())
                .sum();
    }

Expand All @@ -64,11 +87,17 @@ public double returnRate(WinningNumber winningNumber) {
}

private long sumOfPrize(WinningNumber winningNumber) {
long sum = 0;
List<PrizeType> types = listOfPrize(winningNumber);
for (PrizeType type : types) {
sum += type.prize();
}
return sum;
List<Prize> types = listOfPrize(winningNumber);
return types.stream()
.mapToLong(Prize::prize)
.sum();
}

public int getNumberOfManualTickets() {
return numberOfManualTickets;
}

public int getNumberOfAutoTickets() {
return numberOfAutoTickets;
}
}
}
58 changes: 58 additions & 0 deletions src/main/java/lotto/domain/Prize.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package lotto.domain;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public enum Prize {
FIRST_PRIZE(6, false, 2_000_000_000),

SECOND_PRIZE(5, true, 300_000_000),

THIRD_PRIZE(5, false, 1_500_000),

FOURTH_PRIZE(4, false, 50_000),

FIFTH_PRIZE(3, false, 5_000),

NOT_MATCHING(0, false, 0);

private final Integer numberOfMatching;
private final Boolean bonusMatching;
private final Long prize;

Prize(int numberOfMatching, boolean bonusMatching, long prize) {
this.numberOfMatching = numberOfMatching;
this.bonusMatching = bonusMatching;
this.prize = prize;
}

public int numberOfMatching() {
return numberOfMatching;
}

public static Prize create(int numberOfMatching, boolean bonusMatching) {
return Arrays.stream(Prize.values())
.filter(p -> p.numberOfMatching == numberOfMatching && p.bonusMatching == bonusMatching)
.findFirst()
.orElse(NOT_MATCHING);
}

public static Map<Prize, Long> winningStatus(List<Prize> prizeTypesOfTickets) {
return prizeTypesOfTickets.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}

private static int countPrizeType(List<Prize> prizeTypesOfTickets, Prize prize) {
return (int) prizeTypesOfTickets.stream()
.filter(t -> t == prize)
.count();
}

public long prize() {
return prize;
}
}
42 changes: 0 additions & 42 deletions src/main/java/lotto/domain/PrizeType.java

This file was deleted.

15 changes: 15 additions & 0 deletions src/main/java/lotto/domain/ThrowableFunctionWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package lotto.domain;
import java.util.function.Function;

class ThrowableFunctionWrapper {
Copy link

Choose a reason for hiding this comment

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

👍

public static Function wrapper(ThrowableFunctionalInterface function) {
return t -> {
try {
return function.apply(t);
} catch (Exception e) {
throw new RuntimeException();
}
};
}
Comment on lines +5 to +13
Copy link

Choose a reason for hiding this comment

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

wrapper 에서도 제네릭 타입을 표시해주어야 할 것 같아요 :)
안그러면 경고가 뜨네요.

Suggested change
public static Function wrapper(ThrowableFunctionalInterface function) {
return t -> {
try {
return function.apply(t);
} catch (Exception e) {
throw new RuntimeException();
}
};
}
public static <T, R, E extends Exception> Function<T, R> wrapper(ThrowableFunctionalInterface<T, R, E> function) {
return t -> {
try {
return function.apply(t);
} catch (Exception e) {
throw new RuntimeException();
}
};
}

}

6 changes: 6 additions & 0 deletions src/main/java/lotto/domain/ThrowableFunctionalInterface.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package lotto.domain;

@FunctionalInterface
interface ThrowableFunctionalInterface<T, R, E extends Exception> {
R apply(T t) throws E;
}
Loading