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

import com.javabom.lotto.domain.results.LottoLuckyNumbers;
import com.javabom.lotto.domain.results.LottoResults;
import com.javabom.lotto.domain.ticket.*;
import com.javabom.lotto.view.InputView;
import com.javabom.lotto.view.OutputView;

import java.util.List;

public class LottoApplication {
public static void main(String[] args) {
Money inputMoney = new Money(InputView.getMoneyToBuyTicket());

int manualLottoAmount = InputView.getManualLottoAmount();
List<ManualLottoNumbers> manualLottoNumbers = InputView.getManualLottoNumbers(manualLottoAmount);

LottoTicketDispenser lottoTicketDispenser = new LottoTicketDispenser(new RandomLottoTicketGenerator());
LottoTickets manualLottoTickets = lottoTicketDispenser.getManualTickets(inputMoney, manualLottoNumbers);
Money restMoney = inputMoney.spend(LottoTicketDispenser.getTotalTicketPrice(manualLottoAmount));
LottoTickets autoLottoTickets = lottoTicketDispenser.getAutoTickets(restMoney);
OutputView.printLottoTickets(manualLottoTickets, autoLottoTickets);

LottoTicket basicLuckyTicket = new LottoTicket(LottoNumberConverter.convert(InputView.getLottoBasicLuckyNumbers()));
LottoNumber bonusNumber = new LottoNumber(InputView.getBonusNumber());
LottoLuckyNumbers luckyNumbers = new LottoLuckyNumbers(basicLuckyTicket, bonusNumber);

LottoTickets wholeLottoTickets = autoLottoTickets.add(manualLottoTickets);
LottoResults lottoResults = wholeLottoTickets.getLottoResults(luckyNumbers);
OutputView.printLottoResults(lottoResults);
OutputView.printEarningRate(inputMoney, lottoResults.getTotalPrizeMoney());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.javabom.lotto.domain.results;

import com.javabom.lotto.domain.ticket.LottoNumber;
import com.javabom.lotto.domain.ticket.LottoTicket;

public class LottoLuckyNumbers {

private final LottoTicket basicLuckyTicket;
private final LottoNumber bonusNumber;

public LottoLuckyNumbers(LottoTicket basicLuckyTicket, LottoNumber bonusNumber) {
this.basicLuckyTicket = basicLuckyTicket;
this.bonusNumber = bonusNumber;
validateDuplicatedBonusNumber();
}

private void validateDuplicatedBonusNumber() {
if (this.basicLuckyTicket.isContain(bonusNumber)) {
throw new IllegalStateException(
String.format("보너스 숫자 %s는 기본 당첨번호와 중복 될 수 없습니다.", bonusNumber.toString())
);
}
}

public LottoResult getLottoResult(LottoTicket lottoTicket) {
int matchCounts = lottoTicket.countMatchingNumbers(basicLuckyTicket);
boolean isBonusMatched = lottoTicket.isContain(bonusNumber);
return LottoResult.find(matchCounts, isBonusMatched);
}

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

import java.util.Arrays;

public enum LottoResult {

FIRST_PRIZE(6, 2_000_000_000),
SECOND_PRIZE(5, 30_000_000),
THIRD_PRIZE(5, 1_500_000),
FOURTH_PRIZE(4, 50_000),
FIFTH_PRIZE(3, 5_000),
LOSE(-1, 0);

private final int matchCount;
private final long prize;

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

public static LottoResult find(final int matchCount, final boolean isBonusMatched) {
validateMatchCount(matchCount);
if (matchCount == SECOND_PRIZE.matchCount) {
return findByBonus(isBonusMatched);
}
return Arrays.stream(values())
.filter(result -> result.matchCount == matchCount)
.findFirst()
.orElse(LOSE);
}

private static void validateMatchCount(final int matchCount) {
if (matchCount < 0 || matchCount > 6) {
throw new IllegalArgumentException("로또번호 매치 수는 0~6 이외일 수 없습니다.");
}
}

private static LottoResult findByBonus(final boolean isBonusMatched) {
if (isBonusMatched) {
return SECOND_PRIZE;
}
return THIRD_PRIZE;
}

public long getPrize() {
return prize;
}

public int getMatchCount() {
return matchCount;
}

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

import com.javabom.lotto.domain.ticket.Money;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class LottoResults {

private final List<LottoResult> lottoResults;

public LottoResults(List<LottoResult> lottoResults) {
this.lottoResults = lottoResults;
}

public List<LottoResult> findResultsOf(LottoResult lottoResult) {
return lottoResults.stream()
.filter(result -> result == lottoResult)
.collect(Collectors.toList());
}

public Money getTotalPrizeMoney() {
long sum = lottoResults.stream()
.mapToLong(LottoResult::getPrize)
.sum();
return new Money(sum);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LottoResults that = (LottoResults) o;
return Objects.equals(lottoResults, that.lottoResults);
}

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

import java.util.Objects;

public class LottoNumber {
Copy link
Contributor

Choose a reason for hiding this comment

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

감싼거 아주 좋습니다b

public static final int MIN_LOTTO_NUM = 1;
public static final int MAX_LOTTO_NUM = 45;

private final int number;

public LottoNumber(int number) {
validateNumber(number);
this.number = number;
}

private void validateNumber(int number) {
if (number < MIN_LOTTO_NUM || number > MAX_LOTTO_NUM) {
throw new IllegalArgumentException("로또 번호는 1~45이외 일 수 없습니다. 입력 값 : " + number);
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LottoNumber that = (LottoNumber) o;
return number == that.number;
}

@Override
public int hashCode() {
return Objects.hash(number);
}

@Override
public String toString() {
return String.valueOf(number);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.javabom.lotto.domain.ticket;

import java.util.List;
import java.util.stream.Collectors;

public class LottoNumberConverter {

private LottoNumberConverter() {
}

public static List<LottoNumber> convert(List<Integer> lottoNumbers) {
return lottoNumbers.stream()
.map(LottoNumber::new)
.collect(Collectors.toList());
}

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

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

public class LottoTicket {

private static final int LOTTO_NUM_PICK_SIZE = 6;

private final List<LottoNumber> numbers;

public LottoTicket(List<LottoNumber> numbers) {
validateLottoNumbers(numbers);
this.numbers = numbers;
}

private void validateLottoNumbers(List<LottoNumber> numbers) {
if (numbers.size() != LOTTO_NUM_PICK_SIZE) {
throw new IllegalArgumentException(String.format("로또 티켓에 6개 숫자를 넣어야 합니다. 입력 size : %d", numbers.size()));
}
}

public int countMatchingNumbers(LottoTicket lottoTicket) {
int count = 0;
for (int i = 0; i < LOTTO_NUM_PICK_SIZE; i++) {
if (this.numbers.get(i).equals(lottoTicket.numbers.get(i))) count++;

Choose a reason for hiding this comment

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

인덴트 규칙! stream 을 써서 해결하는 방법은 없을까??

Copy link
Member Author

Choose a reason for hiding this comment

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

내머리로는 스트림으로 도저히 안돼던데... 대체 어케하는거야..?

}
return count;
}

public boolean isContain(LottoNumber number) {
return numbers.contains(number);
}

@Override
public boolean equals(Object o) {
Copy link

Choose a reason for hiding this comment

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

이 LottoTicket의 equals는 어디에서 사용하는 거야?? 일단 실제 코드에는 사용하지않는 것 같고 사용한다면 테스트 코드에서 사용할 것 같은데 내 생각은 equals는 조심해서 사용해야 한다고 생각해.

LottoTicket이 같은 경우가 코드대로라면은 티켓이 들고있는 LottoNumber들이 같을 때 같다고 하게 되는데, 그렇게 되면 똑같은 번호로 산 로또 2개는 같은 Ticket 이라는 의미가 될것같아.

Set은 중복을 허용하지 않는데, Ticket을 Set에 넣는다고 가정했을때 같은 번호를 가지고있는 Ticket 2개를 넣게되면 Set에는 1개만 들어가게 될것같아.

Copy link
Member Author

Choose a reason for hiding this comment

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

내생각에는 같은 번호의 로또 티켓이라면 같은 티켓이 맞다고 봐.
Set은 형말대로 "중복"으로 같은 숫자들을 가진 티켓들을 제거 하려고 쓰일텐데, 그렇다면 오히려 Equals를 상속받아서 중복을 제거하는게 맞다고봐. 그러니 같은 숫자들을 가지고있는 티켓을 2개 넣는다면 1개가 들어가는게 맞는거지.
같은 번호들을 갖는 티켓을 서로 다르게 취급할거면 애초에 List로 들고있는게 맞다고봐.

if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LottoTicket ticket = (LottoTicket) o;
return Objects.equals(numbers, ticket.numbers);
}

@Override
public int hashCode() {
return Objects.hash(numbers);
}

@Override
public String toString() {
return String.valueOf(numbers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.javabom.lotto.domain.ticket;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class LottoTicketDispenser {

private static final Money LOTTO_TICKET_PRICE = new Money(1_000);

private final LottoTicketGenerator lottoTicketGenerator;

public LottoTicketDispenser(LottoTicketGenerator lottoTicketGenerator) {
this.lottoTicketGenerator = lottoTicketGenerator;
}

static public Money getTotalTicketPrice(int amount) {
return LOTTO_TICKET_PRICE.multiply(amount);
}

public LottoTickets getAutoTickets(Money inputMoney) {
int quantity = inputMoney.calculateQuantityPer(LOTTO_TICKET_PRICE);
List<LottoTicket> tickets = new ArrayList<>();
for (int i = 0; i < quantity; i++) {
LottoTicket lottoTicket = lottoTicketGenerator.getLottoTicket();
tickets.add(lottoTicket);
}
return new LottoTickets(tickets);
}

public LottoTickets getManualTickets(Money inputMoney, List<ManualLottoNumbers> manualNumbers) {
validateEnoughMoney(inputMoney, manualNumbers.size());
return new LottoTickets(manualNumbers.stream()
.map(ManualLottoNumbers::toLottoTicket)
.collect(Collectors.toList()));
}

private void validateEnoughMoney(Money inputMoney, int quantity) {
Money totalPrice = LOTTO_TICKET_PRICE.multiply(quantity);
if (totalPrice.isBiggerThan(inputMoney)) {
throw new IllegalStateException(String.format("%d개의 티켓을 사기에 돈이 모자랍니다. 넣은 금액 : %s", quantity, inputMoney.toString()));
}
}
// 여기서 그냥 inputMoney.spend(totalPrice); 한줄만 때리려했는데, (spend 내부에 금액 검사 로직이 있어서)
// 다른사람이 볼 때 이게뭐야? 할거같고, inputMoney내부의 상태값이 바뀌는듯한 인상을 주어
// 이렇게 바꿨는데.. 어떻게 생각하시나요?

Choose a reason for hiding this comment

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

내 개인적인 생각인데 Money의

private void validateCanSpendMoney(Money money)

메소드를 public 으로 바꿔서 사용하는건 어떨까?? 검증로직이 곂치니까 public으로 열어두고 사용해도 괜찮을거 같아서

Copy link
Member Author

Choose a reason for hiding this comment

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

흠 이거 public으로 해도 괜찮은거야? 뭔가 validation 로직을 private으로밖에 안만들어봐서
이생각을 하긴햇는데 뭔가 석연치 않아서 private으로 놔둔거였거든...

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.javabom.lotto.domain.ticket;

public interface LottoTicketGenerator {

LottoTicket getLottoTicket();

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

import com.javabom.lotto.domain.results.LottoLuckyNumbers;
import com.javabom.lotto.domain.results.LottoResult;
import com.javabom.lotto.domain.results.LottoResults;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class LottoTickets {

private final List<LottoTicket> tickets;

public LottoTickets(List<LottoTicket> tickets) {
this.tickets = tickets;
}

public List<LottoTicket> get() {
return Collections.unmodifiableList(tickets);
}

public LottoTickets add(LottoTickets lottoTickets) {
List<LottoTicket> newTickets = new ArrayList<>();
newTickets.addAll(this.tickets);
newTickets.addAll(lottoTickets.tickets);
return new LottoTickets(newTickets);
}

public LottoResults getLottoResults(LottoLuckyNumbers lottoLuckyNumbers) {
return new LottoResults(tickets.stream()
.map(lottoLuckyNumbers::getLottoResult)
.collect(Collectors.toList()));
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LottoTickets that = (LottoTickets) o;
return Objects.equals(tickets, that.tickets);
}

@Override
public int hashCode() {
return Objects.hash(tickets);
}
}
Loading