Skip to content

Commit de169d7

Browse files
authored
Step2 - 로또(자동) (#4207)
* feat: 2단계 로또(자동) - 요구사항 추출 및 객체설계 * feat: 2단계 로또(자동) - 요구사항에 맞게 각 객체별 기능 TDD로 구현 시도 * feat: 2단계 로또(자동) - TDD로 작성한 로직 컨트롤러 클래스에서 조립 - 뷰 관련 기능 구현
1 parent 5290a8b commit de169d7

24 files changed

+840
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package lottoGame;
2+
3+
import lottoGame.controller.LottoStore;
4+
5+
public class Application {
6+
7+
public static void main(String[] args) {
8+
new LottoStore().start();
9+
}
10+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package lottoGame.controller;
2+
3+
import static lottoGame.view.Casher.askBeforeWinNums;
4+
import static lottoGame.view.Casher.askBuyPrice;
5+
import static lottoGame.view.Casher.informBuyCount;
6+
import static lottoGame.view.Casher.informPublishedLottos;
7+
import static lottoGame.view.Casher.informWinningLottoNums;
8+
9+
import lottoGame.model.lotto.LottoMachine;
10+
import lottoGame.model.lotto.Lottos;
11+
import lottoGame.model.price.BuyPrice;
12+
import lottoGame.model.winner.BeforeWinNums;
13+
import lottoGame.model.winner.WinnerResult;
14+
import lottoGame.view.WinResultDto;
15+
16+
public class LottoStore {
17+
public static final int PER_LOTTO_PRICE = 1000;
18+
19+
public void start() {
20+
BuyPrice buyPrice = getBuyPrice();
21+
22+
Lottos lottos = buyLottos(buyPrice);
23+
24+
totalWinResult(
25+
new BeforeWinNums(askBeforeWinNums()),
26+
lottos,
27+
buyPrice.price()
28+
);
29+
}
30+
31+
private Lottos buyLottos(BuyPrice buyPrice) {
32+
Lottos lottos = publishLottos(buyPrice);
33+
informPublishedLottos(lottos.convertRawString());
34+
return lottos;
35+
}
36+
37+
private BuyPrice getBuyPrice() {
38+
BuyPrice buyPrice = new BuyPrice(askBuyPrice());
39+
informBuyCount(buyPrice.calculateLottoCount(PER_LOTTO_PRICE));
40+
41+
return buyPrice;
42+
}
43+
44+
private Lottos publishLottos(BuyPrice buyPrice) {
45+
LottoMachine lottoMachine = new LottoMachine(PER_LOTTO_PRICE);
46+
47+
return lottoMachine.publish(buyPrice);
48+
}
49+
50+
private void totalWinResult(BeforeWinNums beforeWinNums, Lottos lottos, int price) {
51+
WinnerResult winnerResult = lottos.compareAndElectWinResult(beforeWinNums);
52+
53+
informWinningLottoNums(
54+
new WinResultDto(
55+
winnerResult,
56+
price
57+
)
58+
);
59+
}
60+
61+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package lottoGame.model.lotto;
2+
3+
import static java.lang.String.join;
4+
5+
import java.util.Collections;
6+
import java.util.List;
7+
import lottoGame.model.winner.BeforeWinNums;
8+
import lottoGame.model.winner.WinStandard;
9+
10+
public class Lotto {
11+
12+
public static final int LOTTO_NUM_COUNT = 6;
13+
14+
private final List<LottoNum> lottoNums;
15+
16+
public Lotto(List<LottoNum> lottoNums) {
17+
if (lottoNums.size() != LOTTO_NUM_COUNT) {
18+
throw new IllegalArgumentException("로또 갯수가 유효하지 않습니다");
19+
}
20+
21+
Collections.sort(lottoNums);
22+
23+
this.lottoNums = lottoNums;
24+
}
25+
26+
public WinStandard checkIfWin(BeforeWinNums beforeWinNums) {
27+
long result = this.lottoNums.stream()
28+
.mapToInt(LottoNum::value)
29+
.filter(beforeWinNums::isContain)
30+
.count();
31+
32+
return WinStandard.findByValue(
33+
Long.valueOf(result).intValue()
34+
);
35+
}
36+
37+
public String toString() {
38+
return "[" + join(", ", convertString()) + "]";
39+
}
40+
41+
private List<String> convertString() {
42+
return this.lottoNums.stream()
43+
.map(LottoNum::toString)
44+
.toList();
45+
}
46+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package lottoGame.model.lotto;
2+
3+
import static java.util.stream.IntStream.range;
4+
import static lottoGame.model.lotto.LottoNumFactory.createLotto;
5+
6+
import java.util.List;
7+
import lottoGame.model.price.BuyPrice;
8+
9+
public class LottoMachine {
10+
11+
public static final int LOTTO_NUM_COUNT = 6;
12+
13+
private final int perLottoPrice;
14+
15+
public LottoMachine(int perLottoPrice) {
16+
this.perLottoPrice = perLottoPrice;
17+
}
18+
19+
public Lottos publish(BuyPrice buyPrice) {
20+
List<Lotto> lottos = range(0, buyPrice.calculateLottoCount(perLottoPrice))
21+
.mapToObj(idx ->
22+
new Lotto(
23+
createLotto(LOTTO_NUM_COUNT)
24+
)
25+
).toList();
26+
27+
return new Lottos(lottos);
28+
}
29+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package lottoGame.model.lotto;
2+
3+
import java.util.Objects;
4+
5+
public class LottoNum implements Comparable<LottoNum>{
6+
public static final int MIN_NUM = 1;
7+
public static final int MAX_NUM = 45;
8+
9+
private final int num;
10+
11+
public LottoNum(int num) {
12+
if (isOutOfLottoRange(num)) {
13+
throw new IllegalArgumentException("1부터 45사이의 숫자만 입력해주세요.");
14+
}
15+
16+
this.num = num;
17+
}
18+
19+
private boolean isOutOfLottoRange(int num) {
20+
return num < MIN_NUM || num > MAX_NUM;
21+
}
22+
23+
public int value() {
24+
return num;
25+
}
26+
27+
@Override
28+
public int compareTo(LottoNum o) {
29+
return Integer.compare(this.num, o.num);
30+
}
31+
32+
public String toString() {
33+
return String.valueOf(num);
34+
}
35+
36+
@Override
37+
public boolean equals(Object o) {
38+
if (o == null || getClass() != o.getClass()) {
39+
return false;
40+
}
41+
LottoNum lottoNum = (LottoNum) o;
42+
return num == lottoNum.num;
43+
}
44+
45+
@Override
46+
public int hashCode() {
47+
return Objects.hashCode(num);
48+
}
49+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package lottoGame.model.lotto;
2+
3+
import static lottoGame.model.lotto.LottoNum.MAX_NUM;
4+
import static lottoGame.model.lotto.LottoNum.MIN_NUM;
5+
6+
import java.util.ArrayList;
7+
import java.util.HashSet;
8+
import java.util.List;
9+
import java.util.Random;
10+
import java.util.Set;
11+
12+
public class LottoNumFactory {
13+
14+
public static LottoNum createLottoNum() {
15+
return new LottoNum(
16+
new Random().nextInt(MIN_NUM, MAX_NUM)
17+
);
18+
}
19+
20+
public static List<LottoNum> createLotto(int numCount) {
21+
if (numCount <= 0) {
22+
throw new IllegalArgumentException("생성할 로또의 로또번호 갯수를 입력해 주세요.");
23+
}
24+
25+
Set<LottoNum> lottoNums = new HashSet<>();
26+
while (lottoNums.size() < numCount) {
27+
lottoNums.add(createLottoNum());
28+
}
29+
30+
return new ArrayList<>(lottoNums);
31+
}
32+
33+
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package lottoGame.model.lotto;
2+
3+
import java.util.List;
4+
import lottoGame.model.winner.BeforeWinNums;
5+
import lottoGame.model.winner.WinnerResult;
6+
7+
public class Lottos {
8+
9+
private final List<Lotto> lottos;
10+
11+
public Lottos(List<Lotto> lottos) {
12+
this.lottos = lottos;
13+
}
14+
15+
public WinnerResult compareAndElectWinResult(BeforeWinNums beforeWinNums) {
16+
WinnerResult winnerResult = new WinnerResult();
17+
for (Lotto lotto : lottos) {
18+
winnerResult.addWinResult(lotto.checkIfWin(beforeWinNums));
19+
}
20+
21+
return winnerResult;
22+
}
23+
24+
public int size() {
25+
return this.lottos.size();
26+
}
27+
28+
public List<String> convertRawString() {
29+
return this.lottos.stream()
30+
.map(Lotto::toString)
31+
.toList();
32+
}
33+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package lottoGame.model.price;
2+
3+
public class BuyPrice {
4+
private final int price;
5+
6+
public BuyPrice(int price) {
7+
if (price <= 0) {
8+
throw new IllegalArgumentException("로또가격은 0보다 커야 합니다.");
9+
}
10+
11+
this.price = price;
12+
}
13+
14+
public int calculateLottoCount(int perLottoPrice) {
15+
if (perLottoPrice < 0) {
16+
throw new IllegalArgumentException("잘못된 값입니다.");
17+
}
18+
19+
return price / perLottoPrice;
20+
}
21+
22+
public int price() {
23+
return this.price;
24+
}
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package lottoGame.model.winner;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
public class BeforeWinNums {
7+
private final List<Integer> winNums;
8+
9+
public BeforeWinNums(List<Integer> winNums) {
10+
this.winNums = winNums;
11+
}
12+
13+
public boolean isContain(int num) {
14+
return winNums.contains(num);
15+
}
16+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package lottoGame.model.winner;
2+
3+
import java.util.Arrays;
4+
5+
public enum WinStandard {
6+
FIRST("6개 일치 (2000000000원)-", 6, 2000000000),
7+
SECOND("5개 일치 (1500000원)-", 5, 1500000),
8+
THIRD("4개 일치 (50000원)-", 4, 50000),
9+
FOURTH("3개 일치 (5000원)-", 3, 5000),
10+
11+
NOTHING("x", -1, 0),
12+
;
13+
14+
private final String desc;
15+
private final int value;
16+
private final int returnOfWin;
17+
18+
WinStandard(String desc, int value, int returnOfWin) {
19+
this.desc = desc;
20+
this.value = value;
21+
this.returnOfWin = returnOfWin;
22+
}
23+
24+
public static WinStandard findByValue(int value) {
25+
return Arrays.stream(WinStandard.values())
26+
.filter(winStandard -> winStandard.value == value)
27+
.findFirst().orElse(NOTHING);
28+
}
29+
30+
public boolean isNothing() {
31+
return this == NOTHING;
32+
}
33+
34+
public String desc() {
35+
return this.desc;
36+
}
37+
38+
public int returnOfWin() {
39+
return this.returnOfWin;
40+
}
41+
}

0 commit comments

Comments
 (0)