Skip to content

Commit 89190a4

Browse files
authored
Step4 - 로또(수동) (#4234)
* refactor: 4단계 로또(수동) - LottoNum의 명확한 사용제한을 위해 싱글톤 패턴으로 구현 - LottoNum 싱글톤 패턴으로 변경을 위해 로또번호 풀을 LottoNum 내부로 이관 - LottoMachine의 인스턴스 메서드 -> 클래스 메서드화 - 총 상금 계산로직 캡슐화를 위해 WinStandard로 일부 이관 * refactor: 4단계 로또(수동) - 네이밍 개선 및 고민사항 의식의 흐름 작성 * refactor: 4단계 로또(수동) - 수동 요구사항 도입을 위해 유저 입력정보 클래스 생성 - LottoMachine 에 수동/자동 로또 생성 메서드 추가 * refactor: 4단계 로또(수동) - 메세지 출력 부분 개선 - 자동갯수 잘못 노출되는 부분 개선 * refactor: 4단계 로또(수동) - getInstance 네이밍 컨벤션에 맞게 수정 - ManualLottos 제거 - LottoMachine 자동/수동 생성 행위 추가. * refactor: 4단계 로또(수동) - 자동, 수동 로또 생성방식을 인터페이스 기반으로 변경 - LottoStore에서 자동, 수동 따로 생성해서 조합하는 방식에서 조합한 결과를 응답하는 행위를 LottoMachine으로 이관 * refactor: 4단계 로또(수동) - 자동, 수동 로또 생성 인터페이스 구현채로 생성하게 변경 * refactor: 4단계 로또(수동) - 질문사항 주석추가.
1 parent 471668e commit 89190a4

31 files changed

+634
-237
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package lottogame.controller;
2+
3+
import java.util.List;
4+
import lottogame.model.price.LottoPurchasePrice;
5+
import lottogame.model.winner.WinnerResult;
6+
7+
public record LottoPurchaseRequest(
8+
LottoPurchasePrice lottoPurchasePrice,
9+
List<String> manualLottos
10+
) {
11+
12+
public int calculateAutoLottoCount(int perLottoPrice) {
13+
int totalLottoCount = this.lottoPurchasePrice.calculateLottoCount(perLottoPrice);
14+
int manualLottoCount = this.manualLottos.size();
15+
16+
return totalLottoCount - manualLottoCount;
17+
}
18+
19+
public double getRateOfReturn(WinnerResult winnerResult) {
20+
return this.lottoPurchasePrice.calculateRateOfReturn(winnerResult.sumTotalWinReturn());
21+
}
22+
}

src/main/java/lottogame/controller/LottoStore.java

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,64 @@
11
package lottogame.controller;
22

3-
import static lottogame.model.lotto.LottoMachine.PER_LOTTO_PRICE;
4-
import static lottogame.view.Casher.askBeforeWinNums;
3+
import static lottogame.model.lotto.LottoNum.of;
54
import static lottogame.view.Casher.askBonusNum;
65
import static lottogame.view.Casher.askBuyPrice;
6+
import static lottogame.view.Casher.askLottoNums;
7+
import static lottogame.view.Casher.askManualLottos;
78
import static lottogame.view.Casher.informBuyCount;
89
import static lottogame.view.Casher.informPublishedLottos;
910
import static lottogame.view.Casher.informWinResult;
1011

12+
import java.util.List;
1113
import java.util.Set;
12-
import lottogame.model.lotto.Lotto;
1314
import lottogame.model.lotto.LottoMachine;
1415
import lottogame.model.lotto.LottoNum;
1516
import lottogame.model.lotto.Lottos;
1617
import lottogame.model.lotto.WinningLottoNums;
18+
import lottogame.model.lotto.generator.TotallyLottosGenerator;
1719
import lottogame.model.price.LottoPurchasePrice;
1820
import lottogame.model.winner.WinnerResult;
1921

2022
public class LottoStore {
2123

24+
public static final int PER_LOTTO_PRICE = 1_000;
25+
2226
public void start() {
23-
LottoPurchasePrice lottoPurchasePrice = getLottoPurchasePrice();
24-
LottoMachine lottoMachine = new LottoMachine();
27+
LottoPurchaseRequest lottoPurchaseRequest = getPurchaseInfosFromUser();
2528

26-
Lottos lottos = buyLottos(lottoMachine, lottoPurchasePrice);
29+
Lottos lottos = buyLottos(lottoPurchaseRequest);
2730

28-
WinnerResult winnerResult = lottos.compareAndElectWinResult(
29-
getWinningLottoNums(lottoMachine));
31+
WinnerResult winnerResult = lottos.compareAndElectWinResult(getWinningLottoNums());
3032

31-
informWinResult(winnerResult, lottoPurchasePrice);
33+
informWinResult(winnerResult, lottoPurchaseRequest.getRateOfReturn(winnerResult));
3234
}
3335

34-
private LottoPurchasePrice getLottoPurchasePrice() {
36+
private LottoPurchaseRequest getPurchaseInfosFromUser() {
3537
LottoPurchasePrice lottoPurchasePrice = new LottoPurchasePrice(askBuyPrice());
36-
informBuyCount(lottoPurchasePrice.calculateLottoCount(PER_LOTTO_PRICE));
38+
List<String> manualLottos = askManualLottos();
39+
40+
informBuyCount(
41+
lottoPurchasePrice.calculateLottoCount(PER_LOTTO_PRICE),
42+
manualLottos.size()
43+
);
3744

38-
return lottoPurchasePrice;
45+
return new LottoPurchaseRequest(lottoPurchasePrice, manualLottos);
3946
}
4047

41-
private Lottos buyLottos(LottoMachine lottoMachine, LottoPurchasePrice lottoPurchasePrice) {
42-
Lottos lottos = lottoMachine.publish(lottoPurchasePrice);
48+
private Lottos buyLottos(LottoPurchaseRequest lottoPurchaseRequest) {
49+
Lottos lottos = new TotallyLottosGenerator(
50+
lottoPurchaseRequest.lottoPurchasePrice(),
51+
lottoPurchaseRequest.manualLottos()
52+
).generateLottos();
53+
4354
informPublishedLottos(lottos.convertRawString());
55+
4456
return lottos;
4557
}
4658

47-
private WinningLottoNums getWinningLottoNums(LottoMachine lottoMachine) {
48-
Set<LottoNum> lottoByNums = lottoMachine.createLottoByNums(askBeforeWinNums());
49-
LottoNum bonusNum = lottoMachine.getLottoNum(askBonusNum());
59+
private WinningLottoNums getWinningLottoNums() {
60+
Set<LottoNum> lottoByNums = LottoMachine.createLottoNums(askLottoNums());
61+
LottoNum bonusNum = of(askBonusNum());
5062

5163
return new WinningLottoNums(lottoByNums, bonusNum);
5264
}
Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,32 @@
11
package lottogame.model.lotto;
22

3-
import static java.util.stream.IntStream.range;
4-
import static lottogame.model.lotto.LottoNum.MAX_NUM;
5-
import static lottogame.model.lotto.LottoNum.MIN_NUM;
3+
import static lottogame.model.util.StringUtils.splitAndParseToInt;
64

7-
import java.util.ArrayList;
8-
import java.util.HashMap;
9-
import java.util.HashSet;
10-
import java.util.List;
11-
import java.util.Map;
12-
import java.util.Random;
135
import java.util.Set;
146
import java.util.stream.Collectors;
15-
import lottogame.model.price.LottoPurchasePrice;
167

178
public class LottoMachine {
189

19-
public static final int MIN_NUM = 1;
20-
public static final int MAX_NUM = 45;
2110
public static final int LOTTO_NUM_COUNT = 6;
22-
public static final int PER_LOTTO_PRICE = 1_000;
11+
public static final String DELIMITER = ", ";
2312

24-
private static final Random RANDOM = new Random();
25-
26-
private static final Map<Integer, LottoNum> LOTTO_NUM_POOL = new HashMap<>();
27-
28-
static {
29-
range(MIN_NUM, MAX_NUM + 1).forEach(
30-
num -> LOTTO_NUM_POOL.put(num, new LottoNum(num))
31-
);
32-
}
33-
34-
public Lottos publish(LottoPurchasePrice lottoPurchasePrice) {
35-
List<Lotto> lottos = range(0, lottoPurchasePrice.calculateLottoCount(PER_LOTTO_PRICE))
36-
.mapToObj(idx ->
37-
new Lotto(
38-
createLottoByCount(LOTTO_NUM_COUNT)
39-
)
40-
).toList();
41-
42-
return new Lottos(lottos);
43-
}
44-
45-
public LottoNum getLottoNum(int num) {
46-
return LOTTO_NUM_POOL.get(num);
47-
}
48-
49-
private Set<LottoNum> createLottoByCount(int numCount) {
50-
if (numCount <= 0) {
51-
throw new IllegalArgumentException("생성할 로또의 로또번호 갯수를 입력해 주세요.");
52-
}
53-
54-
Set<LottoNum> lottoNums = new HashSet<>();
55-
while (lottoNums.size() < numCount) {
56-
LottoNum lottoNum = getLottoNum(RANDOM.nextInt(MIN_NUM, MAX_NUM));
57-
lottoNums.add(lottoNum);
13+
public static Set<LottoNum> createLottoNums(Set<Integer> rawNums) {
14+
if (rawNums.isEmpty() || rawNums.size() != LOTTO_NUM_COUNT) {
15+
throw new IllegalArgumentException("생성할 로또의 로또번호 갯수를 정확히 입력해 주세요.");
5816
}
5917

60-
return lottoNums;
18+
return rawNums.stream()
19+
.map(LottoNum::of)
20+
.collect(Collectors.toSet());
6121
}
6222

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

68-
return rawNums.stream()
69-
.map(LOTTO_NUM_POOL::get)
70-
.collect(Collectors.toSet());
28+
return createLottoNums(splitAndParseToInt(rawNums, DELIMITER));
7129
}
30+
31+
7232
}

src/main/java/lottogame/model/lotto/LottoNum.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,67 @@
11
package lottogame.model.lotto;
22

3+
import static java.util.stream.IntStream.range;
4+
5+
import java.util.HashMap;
6+
import java.util.Map;
37
import java.util.Objects;
8+
import java.util.Set;
9+
import java.util.stream.Collectors;
10+
11+
public class LottoNum implements Comparable<LottoNum> {
412

5-
public class LottoNum implements Comparable<LottoNum>{
613
public static final int MIN_NUM = 1;
714
public static final int MAX_NUM = 45;
815

16+
private static final Map<Integer, LottoNum> CACHE = new HashMap<>();
17+
918
private final int num;
1019

11-
public LottoNum(int num) {
20+
static {
21+
range(MIN_NUM, MAX_NUM + 1).forEach(
22+
num -> CACHE.put(num, new LottoNum(num))
23+
);
24+
}
25+
26+
private LottoNum(int num) {
1227
if (isOutOfLottoRange(num)) {
1328
throw new IllegalArgumentException("1부터 45사이의 숫자만 입력해주세요.");
1429
}
1530

1631
this.num = num;
1732
}
1833

19-
private boolean isOutOfLottoRange(int num) {
20-
return num < MIN_NUM || num > MAX_NUM;
34+
public static LottoNum of(int num) {
35+
if (isOutOfLottoRange(num)) {
36+
throw new IllegalArgumentException("1부터 45사이의 숫자만 입력해주세요.");
37+
}
38+
39+
return CACHE.get(num);
2140
}
2241

23-
@Override
24-
public int compareTo(LottoNum o) {
25-
return Integer.compare(this.num, o.num);
42+
public static Set<LottoNum> convertToBundle(Set<Integer> lottoNums) {
43+
if (Objects.isNull(lottoNums) || lottoNums.isEmpty()) {
44+
throw new IllegalArgumentException("비정상적인 파라미터 입니다.");
45+
}
46+
47+
return lottoNums.stream()
48+
.map(LottoNum::of)
49+
.collect(Collectors.toSet());
50+
}
51+
52+
private static boolean isOutOfLottoRange(int num) {
53+
return num < MIN_NUM || num > MAX_NUM;
2654
}
2755

2856
public String toString() {
2957
return String.valueOf(num);
3058
}
3159

60+
@Override
61+
public int compareTo(LottoNum o) {
62+
return Integer.compare(num, o.num);
63+
}
64+
3265
@Override
3366
public boolean equals(Object o) {
3467
if (o == null || getClass() != o.getClass()) {

src/main/java/lottogame/model/lotto/Lottos.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package lottogame.model.lotto;
22

3+
import java.util.ArrayList;
34
import java.util.List;
4-
import lottogame.model.winner.WinStandard;
5+
import lottogame.model.winner.Rank;
56
import lottogame.model.winner.WinnerResult;
67

78
public class Lottos {
@@ -15,8 +16,8 @@ public Lottos(List<Lotto> lottos) {
1516
public WinnerResult compareAndElectWinResult(final WinningLottoNums winningLottoNums) {
1617
WinnerResult winnerResult = new WinnerResult();
1718
for (Lotto lotto : lottos) {
18-
WinStandard winStandard = winningLottoNums.checkIfWin(lotto);
19-
winnerResult.addWinResult(winStandard);
19+
Rank RANK = winningLottoNums.checkIfWin(lotto);
20+
winnerResult.addWinResult(RANK);
2021
}
2122

2223
return winnerResult;
@@ -31,4 +32,11 @@ public List<String> convertRawString() {
3132
.map(Lotto::toString)
3233
.toList();
3334
}
35+
36+
public Lottos merge(Lottos additionalLottos) {
37+
List<Lotto> mergedLottos = new ArrayList<>(this.lottos);
38+
mergedLottos.addAll(additionalLottos.lottos);
39+
40+
return new Lottos(mergedLottos);
41+
}
3442
}

src/main/java/lottogame/model/lotto/WinningLottoNums.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package lottogame.model.lotto;
22

33
import java.util.Set;
4-
import lottogame.model.winner.WinStandard;
4+
import lottogame.model.winner.Rank;
55

66
public class WinningLottoNums {
77
private final Lotto winLotto;
@@ -20,10 +20,10 @@ public WinningLottoNums(Lotto winLotto, LottoNum bonusNums) {
2020
this.bonusNums = bonusNums;
2121
}
2222

23-
public WinStandard checkIfWin(Lotto otherLotto) {
23+
public Rank checkIfWin(Lotto otherLotto) {
2424
int matchCount = this.winLotto.findMatchCountBy(otherLotto);
2525
boolean isMatchBonus = otherLotto.isContain(bonusNums);
2626

27-
return WinStandard.findBy(matchCount, isMatchBonus);
27+
return Rank.findBy(matchCount, isMatchBonus);
2828
}
2929
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package lottogame.model.lotto.generator;
2+
3+
import static java.util.stream.IntStream.*;
4+
import static lottogame.model.lotto.LottoMachine.LOTTO_NUM_COUNT;
5+
import static lottogame.model.lotto.LottoNum.of;
6+
7+
import java.util.HashSet;
8+
import java.util.List;
9+
import java.util.Random;
10+
import java.util.Set;
11+
import lottogame.model.lotto.Lotto;
12+
import lottogame.model.lotto.LottoNum;
13+
import lottogame.model.lotto.Lottos;
14+
15+
public class AutoLottoGenerator implements LottosGenerator{
16+
public static final int MIN_NUM = 1;
17+
public static final int MAX_NUM = 45;
18+
19+
private static final Random RANDOM = new Random();
20+
21+
private final int autoLottoCount;
22+
23+
public AutoLottoGenerator(int autoLottoCount) {
24+
this.autoLottoCount = autoLottoCount;
25+
}
26+
27+
@Override
28+
public Lottos generateLottos() {
29+
List<Lotto> lottos = range(0, autoLottoCount)
30+
.mapToObj(idx -> createLottoByCount())
31+
.map(Lotto::new)
32+
.toList();
33+
34+
return new Lottos(lottos);
35+
}
36+
37+
private Set<LottoNum> createLottoByCount() {
38+
Set<LottoNum> lottoNums = new HashSet<>();
39+
while (lottoNums.size() < LOTTO_NUM_COUNT) {
40+
LottoNum lottoNum = of(getRandomNum());
41+
lottoNums.add(lottoNum);
42+
}
43+
44+
return lottoNums;
45+
}
46+
47+
private int getRandomNum() {
48+
return RANDOM.nextInt(MIN_NUM, MAX_NUM);
49+
}
50+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package lottogame.model.lotto.generator;
2+
3+
import lottogame.model.lotto.Lottos;
4+
5+
public interface LottosGenerator {
6+
7+
Lottos generateLottos();
8+
9+
}

0 commit comments

Comments
 (0)