Skip to content
Open
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
22 changes: 22 additions & 0 deletions src/main/java/lottogame/controller/LottoPurchaseRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package lottogame.controller;

import java.util.Set;
import lottogame.model.lotto.ManualLottos;
import lottogame.model.price.LottoPurchasePrice;
import lottogame.model.winner.WinnerResult;

public record LottoPurchaseRequest(
LottoPurchasePrice lottoPurchasePrice,
ManualLottos manualLottos
) {
public int calculateAutoLottoCount(int perLottoPrice) {
int totalLottoCount = this.lottoPurchasePrice.calculateLottoCount(perLottoPrice);
int manualLottoCount = this.manualLottos.size();

return totalLottoCount - manualLottoCount;
}

public double getRateOfReturn(WinnerResult winnerResult) {
return this.lottoPurchasePrice.calculateRateOfReturn(winnerResult.sumTotalWinReturn());
}
}
41 changes: 23 additions & 18 deletions src/main/java/lottogame/controller/LottoStore.java
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
package lottogame.controller;

import static lottogame.model.lotto.LottoMachine.PER_LOTTO_PRICE;
import static lottogame.view.Casher.askBeforeWinNums;
import static lottogame.view.Casher.askBonusNum;
import static lottogame.view.Casher.askBuyPrice;
import static lottogame.view.Casher.askLottoNums;
import static lottogame.view.Casher.askManualLottos;
import static lottogame.view.Casher.informBuyCount;
import static lottogame.view.Casher.informPublishedLottos;
import static lottogame.view.Casher.informWinResult;

import java.util.Set;
import lottogame.model.lotto.Lotto;
import lottogame.model.lotto.LottoMachine;
import lottogame.model.lotto.LottoNum;
import lottogame.model.lotto.Lottos;
import lottogame.model.lotto.ManualLottos;
import lottogame.model.lotto.WinningLottoNums;
import lottogame.model.price.LottoPurchasePrice;
import lottogame.model.winner.WinnerResult;

public class LottoStore {
Copy link
Contributor

Choose a reason for hiding this comment

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

이 객체의 책임 중 로또를 생성하는 책임을 다음과 같은 인터페이스를 추가한 후 분리해 보는 도전을 해보면 어떨까?
코드를 보면 로또를 생성하는 부분이 여러 객체에 분산되어 있는 느낌이 든다.
인터페이스를 추가하고 자동/수동에 대한 구현체를 만들어 로또 생성 부분을 합쳐보면 어떨까?

3단계에서 4단계로 요구사항이 변경될 때 로또를 생성하는 부분의 요구사항만 변경됐다.
로또를 생성하는 부분을 다음과 같은 구조의 인터페이스로 분리해 보는 연습을 해보면 어떨까?
이와 같이 인터페이스로 구현했을 때의 잇점에 대해 고민해 보는 시간을 가져본다.

public interface LottosGenerator {
    Lottos generate();
}


public void start() {
LottoPurchasePrice lottoPurchasePrice = getLottoPurchasePrice();
LottoMachine lottoMachine = new LottoMachine();
LottoPurchaseRequest lottoPurchaseRequest = getPurchaseInfosFromUser();

Lottos lottos = buyLottos(lottoMachine, lottoPurchasePrice);
Lottos lottos = buyLottos(lottoPurchaseRequest);

WinnerResult winnerResult = lottos.compareAndElectWinResult(
getWinningLottoNums(lottoMachine));
WinnerResult winnerResult = lottos.compareAndElectWinResult(getWinningLottoNums());

informWinResult(winnerResult, lottoPurchasePrice);
informWinResult(winnerResult, lottoPurchaseRequest.getRateOfReturn(winnerResult));
}

private LottoPurchasePrice getLottoPurchasePrice() {
private LottoPurchaseRequest getPurchaseInfosFromUser() {
LottoPurchasePrice lottoPurchasePrice = new LottoPurchasePrice(askBuyPrice());
informBuyCount(lottoPurchasePrice.calculateLottoCount(PER_LOTTO_PRICE));
ManualLottos manualLottos = new ManualLottos(askManualLottos());

return lottoPurchasePrice;
return new LottoPurchaseRequest(lottoPurchasePrice, manualLottos);
}

private Lottos buyLottos(LottoMachine lottoMachine, LottoPurchasePrice lottoPurchasePrice) {
Lottos lottos = lottoMachine.publish(lottoPurchasePrice);
informPublishedLottos(lottos.convertRawString());
return lottos;
private Lottos buyLottos(LottoPurchaseRequest lottoPurchaseRequest) {
Lottos autoLottos = LottoMachine.createAutoLotto(lottoPurchaseRequest.calculateAutoLottoCount(PER_LOTTO_PRICE));
Lottos manualLottos = LottoMachine.createManualLotto(lottoPurchaseRequest.manualLottos());

Lottos mergedLottos = autoLottos.merge(manualLottos);

informBuyCount(autoLottos.size(), manualLottos.size());
informPublishedLottos(mergedLottos.convertRawString());

return mergedLottos;
}

private WinningLottoNums getWinningLottoNums(LottoMachine lottoMachine) {
Set<LottoNum> lottoByNums = lottoMachine.createLottoByNums(askBeforeWinNums());
LottoNum bonusNum = lottoMachine.getLottoNum(askBonusNum());
private WinningLottoNums getWinningLottoNums() {
Set<LottoNum> lottoByNums = LottoMachine.createLottoNums(askLottoNums());
LottoNum bonusNum = LottoMachine.getLottoNum(askBonusNum());

return new WinningLottoNums(lottoByNums, bonusNum);
}
Expand Down
32 changes: 12 additions & 20 deletions src/main/java/lottogame/model/lotto/LottoMachine.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package lottogame.model.lotto;

import static java.util.stream.IntStream.range;
import static lottogame.model.lotto.LottoNum.MAX_NUM;
import static lottogame.model.lotto.LottoNum.MIN_NUM;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -23,16 +18,8 @@ public class LottoMachine {

private static final Random RANDOM = new Random();

private static final Map<Integer, LottoNum> LOTTO_NUM_POOL = new HashMap<>();

static {
range(MIN_NUM, MAX_NUM + 1).forEach(
num -> LOTTO_NUM_POOL.put(num, new LottoNum(num))
);
}

public Lottos publish(LottoPurchasePrice lottoPurchasePrice) {
List<Lotto> lottos = range(0, lottoPurchasePrice.calculateLottoCount(PER_LOTTO_PRICE))
public static Lottos createAutoLotto(int autoLottoCount) {
List<Lotto> lottos = range(0, autoLottoCount)
.mapToObj(idx ->
new Lotto(
createLottoByCount(LOTTO_NUM_COUNT)
Expand All @@ -42,11 +29,16 @@ public Lottos publish(LottoPurchasePrice lottoPurchasePrice) {
return new Lottos(lottos);
}

public LottoNum getLottoNum(int num) {
return LOTTO_NUM_POOL.get(num);
public static Lottos createManualLotto(ManualLottos manualLottos) {
return manualLottos.convertToLottos();
}


public static LottoNum getLottoNum(int num) {
return LottoNum.getInstance(num);
}

private Set<LottoNum> createLottoByCount(int numCount) {
private static Set<LottoNum> createLottoByCount(int numCount) {
if (numCount <= 0) {
throw new IllegalArgumentException("생성할 로또의 로또번호 갯수를 입력해 주세요.");
}
Expand All @@ -60,13 +52,13 @@ private Set<LottoNum> createLottoByCount(int numCount) {
return lottoNums;
}

public Set<LottoNum> createLottoByNums(Set<Integer> rawNums) {
public static Set<LottoNum> createLottoNums(Set<Integer> rawNums) {
if (rawNums.isEmpty() || rawNums.size() != LOTTO_NUM_COUNT) {
throw new IllegalArgumentException("생성할 로또의 로또번호 갯수를 정확히 입력해 주세요.");
}

return rawNums.stream()
.map(LOTTO_NUM_POOL::get)
.map(LottoNum::getInstance)
.collect(Collectors.toSet());
}
}
35 changes: 28 additions & 7 deletions src/main/java/lottogame/model/lotto/LottoNum.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,55 @@
package lottogame.model.lotto;

import static java.util.stream.IntStream.range;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class LottoNum implements Comparable<LottoNum>{
public class LottoNum implements Comparable<LottoNum> {

public static final int MIN_NUM = 1;
public static final int MAX_NUM = 45;

private static final Map<Integer, LottoNum> CACHE = new HashMap<>();

private final int num;

public LottoNum(int num) {
static {
range(MIN_NUM, MAX_NUM + 1).forEach(
num -> CACHE.put(num, new LottoNum(num))
);
}

private LottoNum(int num) {
if (isOutOfLottoRange(num)) {
throw new IllegalArgumentException("1부터 45사이의 숫자만 입력해주세요.");
}

this.num = num;
}

private boolean isOutOfLottoRange(int num) {
return num < MIN_NUM || num > MAX_NUM;
public static LottoNum getInstance(int num) {
Copy link
Contributor

Choose a reason for hiding this comment

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

effective java 책을 보면 정적 팩터리 메서드 이름에 대한 컨벤션 제안을 하고 있다.
이 컨벤션을 찾아 리팩터링 해보면 어떨까?

if (isOutOfLottoRange(num)) {
throw new IllegalArgumentException("1부터 45사이의 숫자만 입력해주세요.");
}

return CACHE.get(num);
}

@Override
public int compareTo(LottoNum o) {
return Integer.compare(this.num, o.num);
private static boolean isOutOfLottoRange(int num) {
return num < MIN_NUM || num > MAX_NUM;
}

public String toString() {
return String.valueOf(num);
}

@Override
public int compareTo(LottoNum o) {
return Integer.compare(num, o.num);
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/lottogame/model/lotto/Lottos.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package lottogame.model.lotto;

import java.util.ArrayList;
import java.util.List;
import lottogame.model.winner.WinStandard;
import lottogame.model.winner.WinnerResult;
Expand Down Expand Up @@ -31,4 +32,11 @@ public List<String> convertRawString() {
.map(Lotto::toString)
.toList();
}

public Lottos merge(Lottos additionalLottos) {
List<Lotto> mergedLottos = new ArrayList<>(this.lottos);
mergedLottos.addAll(additionalLottos.lottos);

return new Lottos(mergedLottos);
}
}
35 changes: 35 additions & 0 deletions src/main/java/lottogame/model/lotto/ManualLottos.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package lottogame.model.lotto;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class ManualLottos {
private final List<Set<Integer>> manualLottos;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
private final List<Set<Integer>> manualLottos;
private final List<Lotto> manualLottos;

Lottos와 다른 점이 있나?
굳이 분리할 필요가 있을까?


public ManualLottos(List<Set<Integer>> ManualLottos) {
this.manualLottos = ManualLottos;
}

public int size() {
return manualLottos.size();
}

public Set<Integer> findManualLottoByIdx(int idx) {
if (idx < 0 || idx >= this.manualLottos.size()) {
return Set.of();
}

return manualLottos.get(idx);
}

public Lottos convertToLottos() {
List<Lotto> tempLottos = new ArrayList<>(size());
for (int i = 0; i < size(); i++) {
Set<LottoNum> lottoNums = LottoMachine.createLottoNums(findManualLottoByIdx(i));
tempLottos.add(new Lotto(lottoNums));
}

return new Lottos(tempLottos);
}
}
14 changes: 10 additions & 4 deletions src/main/java/lottogame/model/price/LottoPurchasePrice.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package lottogame.model.price;

import static java.lang.Math.floor;

import lottogame.model.winner.WinnerResult;

public class LottoPurchasePrice {
private static final int UP_TWO_DECIMAL_PLACE = 100;
private static final double DOWN_TWO_DECIMAL_PLACE = 100.0;

private final int price;

public LottoPurchasePrice(int price) {
Expand All @@ -19,15 +26,14 @@ public int calculateLottoCount(int perLottoPrice) {
return price / perLottoPrice;
}


public double calculateRateOfReturn(int totalWinReturn) {
if (totalWinReturn < 0) {
throw new IllegalArgumentException("잘못된 값입니다.");
}

return (double) totalWinReturn / this.price;
}
double rateOfReturn = (double) totalWinReturn / this.price * UP_TWO_DECIMAL_PLACE;

public int price() {
return this.price;
return floor(rateOfReturn) / DOWN_TWO_DECIMAL_PLACE;
}
}
8 changes: 4 additions & 4 deletions src/main/java/lottogame/model/winner/WinStandard.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ public boolean isNothing() {
return this == NOTHING;
}

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

public static Map<WinStandard, Integer> getInitWinStandardMap() {
return Arrays.stream(WinStandard.values())
.filter(winStandard -> !winStandard.isNothing())
Expand All @@ -53,4 +49,8 @@ public static Map<WinStandard, Integer> getInitWinStandardMap() {
public int value() {
return this.value;
}

public int calculateWinReturn(int winCount) {
return this.returnOfWin * winCount;
}
}
2 changes: 1 addition & 1 deletion src/main/java/lottogame/model/winner/WinnerResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ public int sumTotalWinReturn() {
}

private int calculateWinReturnBy(WinStandard winStandard) {
return winStandard.returnOfWin() * this.winStandardToWinCount.get(winStandard);
return winStandard.calculateWinReturn(this.findWinCount(winStandard));
}
}
Loading