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
32 changes: 32 additions & 0 deletions src/main/java/com/javabom/lotto/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
package com.javabom.lotto;

import com.javabom.lotto.domain.Customer;
import com.javabom.lotto.domain.shop.AutoLottoNumberGenerator;
import com.javabom.lotto.domain.shop.LottoShop;
import com.javabom.lotto.domain.shop.LottoMachine;
import com.javabom.lotto.domain.number.PrizeNumbersBundle;
import com.javabom.lotto.domain.result.LottoResultBundle;
import com.javabom.lotto.domain.ticket.LottoTicketBundle;
import com.javabom.lotto.view.InputView;
import com.javabom.lotto.view.OutputView;

import java.util.List;
import java.util.Scanner;

public class LottoApplication {
Copy link

Choose a reason for hiding this comment

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

스크린샷 2020-06-12 오후 4 15 41

구입 금액이 수동으로 구매할 로또 금액보다 적은데, 수동 번호를 입력 받아요!

수동 번호 입력 전에 구입 금액이랑 수동 번호 구매 금액을 검증하는 부분이 추가되면 좋을 거 같습니다!

private static final InputView inputView = new InputView(new Scanner(System.in));

public static void main(String[] args) {

Choose a reason for hiding this comment

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

지금 메인 로직을 보면 전체 비지니스 플로우의 흐름을 알기 어렵습니다.

내부로 숨겨야할 구현들이 main에 너무 노출되어있어요

예를들어 MyLottoBundle은 LottoFactory의 createLotto를 호출해 로또를 주입받아 생성되는데,
이걸 LottoFactory안쪽으로 감추면 어떨까요

LottoShop lottoShop = new LottoShop(new RandomMachine());
MyLottoBundle bundle = lottoShop.buyLotto(money);

랜덤 로또 머신을 가진 로또가게에 돈을 주면 로또를 살 수 있다.
이 문맥흐름이 더 자연스럽지 않나요?

굳이 money.getLottoCount()가 외부에 노출될 필요가 있을까요?

기본 문맥에 방해되는 세부 구현내용은 안쪽으로 감추는 연습을 하는게 좋을거같아요

밑에 내용들도 좀더 자연스러운 문맥으로 바꿔보세요

Copy link
Author

Choose a reason for hiding this comment

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

오 맞습니다. 자연스러운 문맥흐름과 세부 구현내용을 안쪽으로 감춘다에 초점을 맞춰서 바꿔보겠습니다! 감사합니다!


int amount = inputView.inputMoney();
int manualLottoTicketCount = inputView.inputManualLottoTicketCount();
List<List<String>> manualLottoNumbers = inputView.inputManualLottoNumbers(manualLottoTicketCount);
Customer customer = new Customer(amount, manualLottoNumbers);

LottoShop lottoShop = new LottoShop(new LottoMachine(new AutoLottoNumberGenerator()));
LottoTicketBundle lottoTicketBundle = lottoShop.buy(customer);

OutputView.printLottoCount(manualLottoNumbers.size(), customer.getAutoLottoTicketCount());
OutputView.printLottoBundle(lottoTicketBundle);

PrizeNumbersBundle prizeNumberBundle = new PrizeNumbersBundle(
inputView.inputPrizeNumbers(), inputView.inputBonusNumber());

LottoResultBundle lottoResultBundle = lottoTicketBundle.getLottoResults(prizeNumberBundle);

OutputView.printResults(lottoResultBundle, amount);
Copy link

Choose a reason for hiding this comment

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

구입 금액을 그대로 수익률 계산에서 사용하시는 거 같은데, 투입금액이 6500 이렇게 들어가면 수익률 계산이 올바르게 되지 않습니다!

그래서 LottoResultBundle에서 amount 값을 입력 받지 않고(입력을 받는다면 구매한 금액을 받아야합니다!), 구입한 티켓 개수로 수익률을 계산하면 올바르게 계산이 될 거 같습니다:)

}
}
72 changes: 72 additions & 0 deletions src/main/java/com/javabom/lotto/domain/Customer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.javabom.lotto.domain;

import com.javabom.lotto.domain.ticket.LottoTicket;
import com.javabom.lotto.domain.number.OrderGameNumber;
import com.javabom.lotto.domain.utils.GameNumberConverter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Customer {
private final int amount;
private final List<List<OrderGameNumber>> manualLottoNumbers;

public Customer(int amount, List<List<String>> strManualLottoNumbers) {
checkPositive(amount);
checkBuyManualLottoTicket(amount, strManualLottoNumbers.size());
this.amount = amount;
this.manualLottoNumbers = collet(strManualLottoNumbers);
}

private void checkPositive(int amount) {
if (amount <= 0) {
throw new IllegalArgumentException(String.format("%d, 0원 이상의 돈을 입력해 주세요.", amount));
}
}

private void checkBuyManualLottoTicket(int amount, int ticketCount) {
int requiredAmount = ticketCount * LottoTicket.PRICE;
if (amount < requiredAmount) {
throw new IllegalArgumentException(String.format("현재 보유 금액:%d, 필요한 금액:%d, 금액이 부족합니다.", amount, requiredAmount));
}
}

private List<List<OrderGameNumber>> collet(List<List<String>> strManualLottoNumbers) {
List<List<OrderGameNumber>> manualLottoNumbers = new ArrayList<>();
for (List<String> eachManualLottoNumbers : strManualLottoNumbers) {
checkCount(eachManualLottoNumbers.size());

List<OrderGameNumber> orderGameNumbers = GameNumberConverter.convert(eachManualLottoNumbers);
checkDuplicate(orderGameNumbers.size());

manualLottoNumbers.add(GameNumberConverter.convert(eachManualLottoNumbers));

}
return manualLottoNumbers;
}

private void checkCount(int numberCount) {
if (numberCount != LottoTicket.COUNT) {
throw new IllegalArgumentException(String.format("%d개의 수동 로또 번호를 입력하셨습니다. 수동 로또 번호는 총 6개여야 합니다.", numberCount));
}
}

private void checkDuplicate(int gameNumbersSize) {
if (gameNumbersSize != LottoTicket.COUNT) {
throw new IllegalArgumentException("수동 로또 번호는 모두 달라야 합니다.");
}
}

public int getAutoLottoTicketCount() {
int curAmount = amount - (manualLottoNumbers.size() * LottoTicket.PRICE);
if (curAmount < LottoTicket.PRICE) {
return 0;
}
return curAmount / LottoTicket.PRICE;
}

public List<List<OrderGameNumber>> getManualLottoNumbers() {
return Collections.unmodifiableList(this.manualLottoNumbers);
}
}
60 changes: 60 additions & 0 deletions src/main/java/com/javabom/lotto/domain/number/GameNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.javabom.lotto.domain.number;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class GameNumber {
public static final int MIN_NUMBER = 1;
public static final int MAX_NUMBER = 45;

private final int gameNumber;

private GameNumber(int gameNumber) {
this.gameNumber = gameNumber;
}

public static GameNumber valueOf(int number) {
checkRange(number);
return GameNumberCache.cache.get(number);
}

public static GameNumber valueOf(String strNumber) {
return GameNumber.valueOf(Integer.parseInt(strNumber));
}

private static void checkRange(int number) {
if (number < MIN_NUMBER || number > MAX_NUMBER) {
throw new IllegalArgumentException(String.format("입력값: %d, 당첨 번호는 1-45 숫자만 가능합니다.", number));
}
}

public int value() {
return this.gameNumber;
}

private static class GameNumberCache {
static final List<GameNumber> cache;

static {
cache = new ArrayList<>();

for (int idx = MIN_NUMBER - 1; idx <= MAX_NUMBER; idx++) {
cache.add(new GameNumber(idx));
}
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GameNumber)) return false;
GameNumber that = (GameNumber) o;
return gameNumber == that.gameNumber;
}

@Override
public int hashCode() {
return Objects.hash(gameNumber);
}
}
53 changes: 53 additions & 0 deletions src/main/java/com/javabom/lotto/domain/number/OrderGameNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.javabom.lotto.domain.number;

import java.util.Objects;

public class OrderGameNumber {
private static final int MIN_ORDER_NUMBER = 1;
private static final int MAX_ORDER_NUMBER = 7;

private final int order;
private final GameNumber gameNumber;

private OrderGameNumber(final int order, final GameNumber gameNumber) {
this.order = order;
this.gameNumber = gameNumber;
}

public static OrderGameNumber of(int order, final GameNumber gameNumber) {
checkOrderRange(order);
return new OrderGameNumber(order, gameNumber);
}

public static OrderGameNumber of(int order, final String strGameNumber) {
return OrderGameNumber.of(order, GameNumber.valueOf(strGameNumber));
}

private static void checkOrderRange(final int order) {
if (order < MIN_ORDER_NUMBER || order > MAX_ORDER_NUMBER) {
throw new IllegalArgumentException(String.format("%d, 게임 숫자의 인덱스 범위는 1-6 이어야 합니다.", order));
}
}

public boolean equalsOfNumber(final OrderGameNumber orderGameNumber) {
return this.gameNumber.equals(orderGameNumber.gameNumber);
}

public GameNumber numberValue() {
return this.gameNumber;
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (!(o instanceof OrderGameNumber)) return false;
final OrderGameNumber that = (OrderGameNumber) o;
return order == that.order &&
Objects.equals(gameNumber, that.gameNumber);
}

@Override
public int hashCode() {
return Objects.hash(order, gameNumber);
}
}
45 changes: 45 additions & 0 deletions src/main/java/com/javabom/lotto/domain/number/PrizeNumbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.javabom.lotto.domain.number;

import com.javabom.lotto.domain.ticket.LottoTicket;
import com.javabom.lotto.domain.utils.GameNumberConverter;

import java.util.List;

public class PrizeNumbers {

private final List<OrderGameNumber> prizeNumbers;

public PrizeNumbers(List<String> strPrizeNumbers) {
this.prizeNumbers = collect(strPrizeNumbers);
}

private List<OrderGameNumber> collect(final List<String> strPrizeNumbers) {
checkCount(strPrizeNumbers.size());
List<OrderGameNumber> prizeNumbers = GameNumberConverter.convert(strPrizeNumbers);
checkDuplicate(prizeNumbers.size());
return prizeNumbers;
}

private static void checkCount(int numberCount) {
if (numberCount != LottoTicket.COUNT) {
throw new IllegalArgumentException(String.format("%d개의 당첨 번호를 입력하셨습니다. 당첨 번호는 총 6개여야 합니다.", numberCount));
}
}

private static void checkDuplicate(int gameNumbersSize) {
if (gameNumbersSize != LottoTicket.COUNT) {
throw new IllegalArgumentException("당첨 번호는 모두 달라야 합니다.");
}
}

public boolean contains(OrderGameNumber orderGameNumber) {
return prizeNumbers.stream()
.anyMatch(number -> number.equalsOfNumber(orderGameNumber));
}

public int getMatchedCount(final LottoTicket lottoTicket) {
return (int) prizeNumbers.stream()
.filter(lottoTicket::contains)
.count();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.javabom.lotto.domain.number;

import com.javabom.lotto.domain.result.LottoResult;
import com.javabom.lotto.domain.ticket.LottoTicket;

import java.util.List;

public class PrizeNumbersBundle {
private static final int BONUS_ORDER = 7;

private final PrizeNumbers prizeNumbers;
private final OrderGameNumber bonusNumber;

public PrizeNumbersBundle(List<String> prizeNumbers, String bonusNumber) {
this.prizeNumbers = new PrizeNumbers(prizeNumbers);
this.bonusNumber = OrderGameNumber.of(BONUS_ORDER, bonusNumber);
checkDuplicate();
}

private void checkDuplicate() {
if (prizeNumbers.contains(bonusNumber)) {
throw new IllegalArgumentException("입력하신 보너스 번호는 당첨 번호와 겹칩니다.");
}
}

public LottoResult getLottoResult(LottoTicket lottoTicket) {
int matchedCount = prizeNumbers.getMatchedCount(lottoTicket);
boolean bonusStatus = lottoTicket.containsBonus(bonusNumber);
return LottoResult.findLottoResult(matchedCount, bonusStatus);
}
}
50 changes: 50 additions & 0 deletions src/main/java/com/javabom/lotto/domain/result/LottoResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.javabom.lotto.domain.result;

import java.util.Arrays;

public enum LottoResult {
FIRST(6, 2_000_000_000),
SECOND(5, 30_000_000),
THIRD(5, 1_500_000),
FOURTH(4, 50_000),
FIFTH(3, 5_000),
FAIL(0, 0);

LottoResult(int matchedCount, int prize) {
this.matchedCount = matchedCount;
this.prize = prize;
}

public final int matchedCount;
public final int prize;

public static LottoResult findLottoResult(int matchedCount, boolean bonusStatus) {
if (matchedCount == 5) {
return findBonus(bonusStatus);
}
return valueOf(matchedCount);
}

private static LottoResult findBonus(boolean bonusStatus) {
if (bonusStatus) {
return SECOND;
}
return THIRD;
}

public static LottoResult valueOf(int matchedCount){
return Arrays.stream(LottoResult.values())
.filter(lottoResult -> lottoResult.getMatchedCount() == matchedCount)
.filter(lottoResult -> !lottoResult.equals(SECOND))
.findFirst()
.orElse(FAIL);
}

private int getMatchedCount(){
return this.matchedCount;
}

public int getPrize() {
return this.prize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.javabom.lotto.domain.result;

import java.util.List;

public class LottoResultBundle {
private final int PERCENT = 100;

private final List<LottoResult> lottoResultBundle;

public LottoResultBundle(List<LottoResult> lottoResultBundle) {
this.lottoResultBundle = lottoResultBundle;
}

public long calculatePrize() {
long prize = 0;
for (LottoResult lottoResult : lottoResultBundle) {
prize += lottoResult.getPrize();
}
return prize;
}

public long getRateOfProfit(int amount) {
long profit = calculatePrize() - amount;
if (profit < 0) {
return 0;
}
return (profit / amount) * PERCENT;
}

public int getCountOfPrize(LottoResult lottoResult) {
return (int) lottoResultBundle.stream()
.filter(result -> result.equals(lottoResult))
.count();
}

public LottoResult valueOf(int idx){
return lottoResultBundle.get(idx);
}
}
Loading