Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[로또 main2] 박성우 제출합니다 #5

Open
wants to merge 12 commits into
base: main2
Choose a base branch
from
50 changes: 49 additions & 1 deletion src/main/java/lotto/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,55 @@
package lotto;

import java.util.List;
import java.util.stream.Collectors;
import lotto.domain.Lotto;
import lotto.domain.LottoNumber;
import lotto.domain.LottoRank;
import lotto.domain.LottoRanks;
import lotto.domain.Money;
import lotto.domain.Ticket;
import lotto.domain.WinningLotto;
import lotto.domain.lottocreator.AutoLottoCreator;
import lotto.domain.lottocreator.ManualLottoCreator;
import lotto.domain.picker.RandomPicker;
import lotto.ui.Input;
import lotto.ui.Output;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
final Money money = new Money(Input.getMoneyValue());
final int manualLottoCount = Input.getManualLottoCount();
validateLottoCount(money, manualLottoCount);

final List<List<Integer>> manualLottos = Input.getManualLottos(manualLottoCount);
Copy link
Member

Choose a reason for hiding this comment

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

LottoNumber를 구현하셨는데, 여기서는 그냥 Integer를 사용하신 이유가 있으신가요??

Copy link
Member

Choose a reason for hiding this comment

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

24라인과 25라인을 묶어서 manualTicket을 생성하는 메소드를 따로 빼서 만드는게 가독성이 더 좋을 것 같습니다! manualLottos는 getManualTicket에서만 사용되기도 하구요

Copy link

Choose a reason for hiding this comment

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

image

manualLottoCount = 0인 경우에도 "수동으로 구매할 번호를 입력해 주세요."가 출력됩니다!

final Ticket manualTicket = getManualTicket(manualLottos);
final int autoLottoCount = money.remainCount(manualLottoCount);
final Ticket autoTicket = Ticket.of(new AutoLottoCreator(new RandomPicker()), autoLottoCount);
Comment on lines +25 to +27
Copy link

Choose a reason for hiding this comment

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

manualTicket은 Lotto.create(...)를 사용하고, autoTicket은 Ticket.of(...) 를 사용하네요. 티켓의 생성방식이 다를 뿐이지, 같은 역할을 하는 메소드이니 같은 객체 내에서 처리되도록 하면 어떨까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

맞네요 이 부분이 조금 부자연스럽네요


Output.printTicket(manualLottoCount, manualTicket, autoLottoCount, autoTicket);

final Lotto lotto = Lotto.create(new ManualLottoCreator(Input.getWinningLotto()));
final LottoNumber bonusBall = LottoNumber.from(Input.getBonusBall());
WinningLotto winningLotto = new WinningLotto(lotto, bonusBall);

final List<LottoRank> ticketResults = manualTicket.getResults(winningLotto);
ticketResults.addAll(autoTicket.getResults(winningLotto));
LottoRanks ranks = LottoRanks.from(ticketResults);

Output.printResult(money, ranks);
}

private static void validateLottoCount(Money money, int manualLottoCount) {
if (!money.canBuy(manualLottoCount)) {
throw new IllegalArgumentException(String.format("[ERROR] 로또를 %d개 구매할 수 없습니다.", manualLottoCount));
}
}

private static Ticket getManualTicket(List<List<Integer>> manualLottos) {
return new Ticket(
manualLottos.stream()
.map(lotto -> Lotto.create(new ManualLottoCreator(lotto)))
.collect(Collectors.toList())
);
}
}
45 changes: 45 additions & 0 deletions src/main/java/lotto/domain/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package lotto.domain;

import java.util.Set;
import java.util.stream.Collectors;
import lotto.domain.lottocreator.LottoCreator;

public class Lotto {

private static final int LOTTO_SIZE = 6;

private final Set<LottoNumber> numbers;

private Lotto(Set<LottoNumber> numbers) {
validateLength(numbers);
this.numbers = numbers;
}

public static Lotto create(LottoCreator creator) {
return new Lotto(creator.create(LOTTO_SIZE));
}

private void validateLength(Set<LottoNumber> numbers) {
if (numbers.size() != LOTTO_SIZE) {
throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자 개수는 %d일 수 없습니다.", numbers.size()));
}
}

public int calculateSameLottoNumber(Lotto other) {
return (int) other.numbers.stream()
.filter(this::contains)
.count();
}

public boolean contains(LottoNumber bonusBall) {
return this.numbers.contains(bonusBall);
}

@Override
public String toString() {
return this.numbers.stream()
.sorted()
.collect(Collectors.toList())
.toString();
}
}
67 changes: 67 additions & 0 deletions src/main/java/lotto/domain/LottoNumber.java
Copy link

Choose a reason for hiding this comment

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

LottoNumber 클래스를 만들 생각은 못했네요! 좋은 아이디어인 것 같습니다

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package lotto.domain;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lotto.domain.picker.Picker;

public class LottoNumber implements Comparable<LottoNumber> {
private static final int MIN_VALUE = 1;
private static final int MAX_VALUE = 45;
private static final List<LottoNumber> VALUES;

static {
VALUES = IntStream.rangeClosed(MIN_VALUE, MAX_VALUE)
Copy link
Member

Choose a reason for hiding this comment

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

옹,, 그러면 VALUES는 1부터 45까지 LottoNumber 객체들이 들어있는 리스트가 되는건가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

네 맞습니다. 캐싱을 해놓은 겁니다.
로또 숫자가 들어올때마다 매번 로또 숫자 객체를 만들면 불필요한 객체 생성이 많아지기 떄문입니다.

.mapToObj(LottoNumber::new)
.collect(Collectors.toList());
}

private final int value;

private LottoNumber(int value) {
this.value = value;
}

public static LottoNumber pick(Picker picker) {
return LottoNumber.from(picker.pick(MIN_VALUE, MAX_VALUE));
}

public static LottoNumber from(int value) {
validateRange(value);
return VALUES.get(value - 1);
}

private static void validateRange(int value) {
if (value < MIN_VALUE || value > MAX_VALUE) {
throw new IllegalArgumentException(String.format("[ERROR] 로또 숫자는 %d일 수 없습니다.", value));
}
}

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

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

@Override
public int compareTo(LottoNumber o) {
return this.value - o.value;
}

@Override
public String toString() {
return String.valueOf(value);
}
}
48 changes: 48 additions & 0 deletions src/main/java/lotto/domain/LottoRank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package lotto.domain;

import java.util.Arrays;

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


private final int prize;
private final int count;
private final boolean bonus;

LottoRank(int prize, int count, boolean bonus) {
this.prize = prize;
this.count = count;
this.bonus = bonus;
}

public static LottoRank calculateRank(WinningLotto winningLotto, Lotto lotto) {
return Arrays.stream(LottoRank.values())
.filter(rank -> rank.count == winningLotto.calculateSameLottoNumber(lotto))
.filter(rank -> !rank.bonus || winningLotto.matchBonus(lotto))
.findAny()
.orElse(LottoRank.OTHER);
}


public int getPrize() {
return prize;
}

@Override
public String toString() {
if (this.bonus) {
return String.format("%d개 일치, 보너스 볼 일치 (%,d원)", this.count, this.prize);
}
return String.format("%d개 일치 (%,d원)", this.count, this.prize);
}

public boolean isNotOtherRank() {
return this != OTHER;
}
}
44 changes: 44 additions & 0 deletions src/main/java/lotto/domain/LottoRanks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package lotto.domain;

import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;

public class LottoRanks {
private final Map<LottoRank, Integer> ranks;

private LottoRanks(Map<LottoRank, Integer> ranks) {
this.ranks = ranks;
}

public static LottoRanks from(List<LottoRank> ranks) {
return new LottoRanks(
ranks.stream().collect(Collectors.toMap(Function.identity(), rank -> 1, Integer::sum))
);
}

public int getProfit() {
return this.ranks.entrySet()
.stream()
.mapToInt(entry -> entry.getKey().getPrize() * entry.getValue())
.sum();
}

@Override
public String toString() {
Arrays.stream(LottoRank.values())
.forEach(rank -> this.ranks.computeIfAbsent(rank, value -> 0));

return ranks.entrySet()
.stream()
.filter(entry -> entry.getKey().isNotOtherRank())
.sorted(Entry.comparingByKey())
Copy link

Choose a reason for hiding this comment

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

image

순서가 요구사항과 맞지 않네요!

.map(entry -> String.format("%s - %d개", entry.getKey(), entry.getValue()))
.collect(Collectors.joining("\n"));
}
}
30 changes: 30 additions & 0 deletions src/main/java/lotto/domain/Money.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package lotto.domain;

public class Money {
private static final int LOTTO_AMOUNT = 1000;

private final int value;

public Money(int value) {
validate(value);
this.value = value;
}

private void validate(int value) {
if (value <= 0 || value % LOTTO_AMOUNT != 0) {
throw new IllegalArgumentException(String.format("[ERROR] 금액은 %d일 수 없습니다.", value));
}
}

public boolean canBuy(int lottoCount) {
return this.value / LOTTO_AMOUNT >= lottoCount;
}

public int remainCount(int lottoCount) {
return this.value / LOTTO_AMOUNT - lottoCount;
}

public double getProfitRate(int profit) {
return (double) profit / this.value;
}
}
35 changes: 35 additions & 0 deletions src/main/java/lotto/domain/Ticket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package lotto.domain;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lotto.domain.lottocreator.LottoCreator;

public class Ticket {
private final List<Lotto> lottos;

public Ticket(List<Lotto> lottos) {
this.lottos = lottos;
}

public static Ticket of(LottoCreator creator, int count) {
final List<Lotto> lottos = Stream.generate(() -> Lotto.create(creator))
.limit(count)
.collect(Collectors.toList());

return new Ticket(lottos);
}

public List<LottoRank> getResults(WinningLotto winningLotto) {
return this.lottos.stream()
.map(lotto -> LottoRank.calculateRank(winningLotto, lotto))
.collect(Collectors.toList());
}

@Override
public String toString() {
return this.lottos.stream()
.map(Lotto::toString)
.collect(Collectors.joining("\n"));
}
}
28 changes: 28 additions & 0 deletions src/main/java/lotto/domain/WinningLotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package lotto.domain;

public class WinningLotto {

public final Lotto lotto;
private final LottoNumber bonusBall;

public WinningLotto(Lotto lotto, LottoNumber bonusBall) {
validateBonusBall(lotto, bonusBall);

this.lotto = lotto;
this.bonusBall = bonusBall;
}

private static void validateBonusBall(Lotto winningLotto, LottoNumber bonusBall) {
if (winningLotto.contains(bonusBall)) {
throw new IllegalArgumentException(String.format("[ERROR] 로또에 이미 %s가 존재합니다.", bonusBall));
}
}

public int calculateSameLottoNumber(Lotto lotto) {
return this.lotto.calculateSameLottoNumber(lotto);
}

public boolean matchBonus(Lotto lotto) {
return lotto.contains(this.bonusBall);
}
}
24 changes: 24 additions & 0 deletions src/main/java/lotto/domain/lottocreator/AutoLottoCreator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package lotto.domain.lottocreator;

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lotto.domain.LottoNumber;
import lotto.domain.picker.Picker;

public class AutoLottoCreator implements LottoCreator {

private final Picker picker;

public AutoLottoCreator(Picker picker) {
this.picker = picker;
}

@Override
public Set<LottoNumber> create(int lottoSize) {
return Stream.generate(() -> LottoNumber.pick(this.picker))
.distinct()
.limit(lottoSize)
.collect(Collectors.toSet());
}
}
8 changes: 8 additions & 0 deletions src/main/java/lotto/domain/lottocreator/LottoCreator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package lotto.domain.lottocreator;

import java.util.Set;
import lotto.domain.LottoNumber;

public interface LottoCreator {
Set<LottoNumber> create(int lottoSize);
}
Loading