-
Notifications
You must be signed in to change notification settings - Fork 0
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
base: main2
Are you sure you want to change the base?
Changes from all commits
0608052
82fd9de
ad212c5
f08f8b8
4ad0cb2
9675356
4851fab
596ebb9
af74f66
bbaf058
3010836
030ea77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. manualTicket은 Lotto.create(...)를 사용하고, autoTicket은 Ticket.of(...) 를 사용하네요. 티켓의 생성방식이 다를 뿐이지, 같은 역할을 하는 메소드이니 같은 객체 내에서 처리되도록 하면 어떨까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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()) | ||
); | ||
} | ||
} |
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(); | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 옹,, 그러면 VALUES는 1부터 45까지 LottoNumber 객체들이 들어있는 리스트가 되는건가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
} | ||
} |
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; | ||
} | ||
} |
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()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
.map(entry -> String.format("%s - %d개", entry.getKey(), entry.getValue())) | ||
.collect(Collectors.joining("\n")); | ||
} | ||
} |
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; | ||
} | ||
} |
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")); | ||
} | ||
} |
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); | ||
} | ||
} |
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()); | ||
} | ||
} |
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); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LottoNumber를 구현하셨는데, 여기서는 그냥 Integer를 사용하신 이유가 있으신가요??
There was a problem hiding this comment.
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에서만 사용되기도 하구요