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

[로또 미션] 오지현 미션 제출합니다. #20

Open
wants to merge 7 commits into
base: zhy2on
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions src/main/java/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import controller.LottoController;

public class LottoApplication {
public static void main(String[] args) {
LottoController controller = new LottoController();
controller.run();
}
}
40 changes: 27 additions & 13 deletions src/main/java/controller/LottoController.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
package controller;

import domain.Lotto;
import domain.LottoNumber;
import domain.LottoStatistics;
import domain.*;
import view.InputView;
import view.OutputView;

import java.util.List;

public class LottoController {
public static void main(String[] args) {
LottoController controller = new LottoController();
controller.run();
}

private void run() {
public void run() {
int purchaseAmount = InputView.getPurchaseAmount();
List<Lotto> lottos = Lotto.purchaseLottos(purchaseAmount);
List<Lotto> lottos = LottoMachine.generateLottos(purchaseAmount / Lotto.LOTTO_PRICE);
OutputView.printLottos(lottos);

List<LottoNumber> winningNumbers = InputView.getWinningNumbers();
LottoStatistics statistics = Lotto.getStatistics(lottos, winningNumbers);
OutputView.printStatistics(statistics);
Lotto winningLotto = InputView.getWinningLotto();
LottoNumber bonusNumber = InputView.getBonusNumber();

LottoResult result = getLottoResult(lottos, winningLotto, bonusNumber);
OutputView.printResult(result, purchaseAmount);
}

private LottoResult getLottoResult(List<Lotto> lottos, Lotto winningLotto, LottoNumber bonusNumber) {
List<LottoPrize> prizes = lottos.stream()
.map(lotto -> getLottoPrize(lotto, winningLotto, bonusNumber))
.toList();
return new LottoResult(prizes);
}

private LottoPrize getLottoPrize(Lotto lotto, Lotto winningLotto, LottoNumber bonusNumber) {
int matchCount = countMatchingNumbers(lotto, winningLotto);
boolean isMatchBonus = lotto.contains(bonusNumber);
return LottoPrize.matchPrize(matchCount, isMatchBonus);
}

private int countMatchingNumbers(Lotto lotto, Lotto winningLotto) {
return (int) lotto.numbers().stream()
.filter(winningLotto.numbers()::contains)
.count();
}
}
45 changes: 18 additions & 27 deletions src/main/java/domain/Lotto.java
Copy link

Choose a reason for hiding this comment

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

원시 값 포장을 잘 사용하셨네요! 저는 그냥 1000으로 나눠버렸는데 하나 배워갑니다 :-)

Copy link
Author

Choose a reason for hiding this comment

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

아하 감사합니다! 그런데 저 부분은 매직넘버를 상수로 선언해서 제거한 부분이고 이번 과제에서 말한 원시값 포장이랑은 다른 개념인 것 같아요..!!

저도 잘은 모르지만
int money; 로 바로 사용하는 게 아니라
Money 클래스를 따로 구현하고 Money money = new Money(int amount);
이런식으로 원시 값을 객체로 포장해서 사용하는 게 원시값 포장인 것 같습니다..!!

돈에 대해선 제가 원시값 포장을 못 했어요🥲 이 부분은 추가로 더 고민해보고 수정하겠습니다!

Copy link

Choose a reason for hiding this comment

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

죄송해요 저도 어제 스터디에서 설명해주시는 거 듣고 제가 틀렸단 걸 깨달았습니다..전 단순히 포장(감싼다)인 줄 알았어요ㅠㅠ저도 아직 배워야할 게 많은 것 같습니다..ㅠㅠ

Original file line number Diff line number Diff line change
@@ -1,47 +1,38 @@
package domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public record Lotto(List<LottoNumber> numbers) {
public static final int LOTTO_NUMBER_COUNT = 6;
public static final int LOTTO_PRICE = 1000;

public static List<Lotto> purchaseLottos(int purchaseAmount) {
int lottoCount = purchaseAmount / LOTTO_PRICE;
return IntStream.range(0, lottoCount)
.mapToObj(i -> generateLotto())
.collect(Collectors.toList());
public Lotto {
validateNumbers(numbers);
Collections.sort(numbers);
}

private static Lotto generateLotto() {
List<LottoNumber> numbers = new ArrayList<>();
while (numbers.size() < LOTTO_NUMBER_COUNT) {
LottoNumber number = LottoNumber.generate();
if (!numbers.contains(number)) {
numbers.add(number);
}
private void validateNumbers(List<LottoNumber> numbers) {
if (numbers.size() != LOTTO_NUMBER_COUNT) {
throw new IllegalArgumentException("로또 숫자는 6개여야 합니다.");
}
if (numbers.stream().distinct().count() != LOTTO_NUMBER_COUNT) {
throw new IllegalArgumentException("로또 숫자는 중복 되지 않아야 합니다.");
}
Copy link

Choose a reason for hiding this comment

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

예외 처리도 잘 하신 것 같아요.

Collections.sort(numbers);
return new Lotto(numbers);
}

public static LottoStatistics getStatistics(List<Lotto> lottos, List<LottoNumber> winningNumbers) {
LottoStatistics statistics = new LottoStatistics();
for (Lotto lotto : lottos) {
int matchCount = getMatchCount(lotto, winningNumbers);
statistics.addCount(matchCount);
}
return statistics;
public static Lotto generate() {
List<LottoNumber> numbers = Stream.generate(LottoNumber::generate)
.distinct()
.limit(LOTTO_NUMBER_COUNT)
.collect(Collectors.toList());
return new Lotto(numbers);
}

private static int getMatchCount(Lotto lotto, List<LottoNumber> winningNumbers) {
return (int) lotto.numbers.stream()
.filter(winningNumbers::contains)
.count();
public boolean contains(LottoNumber number) {
return numbers.contains(number);
}

@Override
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/domain/LottoMachine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package domain;

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

public class LottoMachine {
public static List<Lotto> generateLottos(int count) {
return Stream.generate(Lotto::generate)
.limit(count)
.collect(Collectors.toList());
}
}
20 changes: 10 additions & 10 deletions src/main/java/domain/LottoNumber.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,32 @@

import java.util.Random;

public record LottoNumber(int value) implements Comparable<LottoNumber> {
private static final int MIN_VALUE = 1;
private static final int MAX_VALUE = 45;
public record LottoNumber(int number) implements Comparable<LottoNumber> {
private static final int MIN_NUMBER = 1;
private static final int MAX_NUMBER = 45;
private static final Random random = new Random();

public LottoNumber {
validateValue(value);
valdateNumber(number);
}

private void validateValue(int value) {
if (value < MIN_VALUE || value > MAX_VALUE) {
private void valdateNumber(final int number) {
if (number < MIN_NUMBER || number > MAX_NUMBER) {
throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 값이어야 합니다.");
}
}

public static LottoNumber generate() {
Random random = new Random();
return new LottoNumber(random.nextInt(MAX_VALUE - MIN_VALUE + 1) + MIN_VALUE);
return new LottoNumber(random.nextInt(MAX_NUMBER - MIN_NUMBER + 1) + MIN_NUMBER);
}

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

@Override
public int compareTo(LottoNumber other) {
return Integer.compare(this.value, other.value);
return Integer.compare(this.number, other.number);
}
}
43 changes: 43 additions & 0 deletions src/main/java/domain/LottoPrize.java
Copy link

Choose a reason for hiding this comment

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

enum을 잘 활용하신 것 같습니다. 저는 enum을 활용할 때 많이 헤맸는데 또 하나 배워갑니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package domain;

import java.util.Arrays;

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

private final int matchCount;
private final int prize;
private final boolean isMatchBonus;

LottoPrize(final int matchCount, final int prize, final boolean isMatchBonus) {
this.matchCount = matchCount;
this.prize = prize;
this.isMatchBonus = isMatchBonus;
}

public static LottoPrize matchPrize(final int matchCount, final boolean isWithBonus) {
return Arrays.stream(LottoPrize.values())
.filter(prize -> prize.matchCount == matchCount)
.filter(prize -> prize.isMatchBonus == isWithBonus)
.findFirst()
.orElse(MISS);
}

public int getMatchCount() {
return matchCount;
}

public int getPrize() {
return prize;
}

public boolean isMatchBonus() {
return isMatchBonus;
}
}

27 changes: 27 additions & 0 deletions src/main/java/domain/LottoResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package domain;

import java.util.List;

public class LottoResult {
private final List<LottoPrize> prizes;

public LottoResult(List<LottoPrize> prizes) {
this.prizes = prizes;
}

public int getTotalPrize() {
return prizes.stream()
.mapToInt(LottoPrize::getPrize)
.sum();
}

public double getEarningRate(int purchaseAmount) {
return (double) getTotalPrize() / purchaseAmount;
}

public int getCountByPrize(LottoPrize prize) {
return (int) prizes.stream()
.filter(p -> p == prize)
.count();
}
}
26 changes: 0 additions & 26 deletions src/main/java/domain/LottoStatistics.java
Copy link

Choose a reason for hiding this comment

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

잘 하신 것 같습니다. PRIZES를 배열로 선언하지 않고 따로 클래스를 생성해서 관리하고(Map을 사용한다던지) 로또 수익 계산을 해도 괜찮을 것 같습니다!

This file was deleted.

20 changes: 15 additions & 5 deletions src/main/java/view/InputView.java
Copy link

Choose a reason for hiding this comment

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

문자열도 포장을 하시면 좋을 것 같아요. 위에서 원시 값을 포장하신 것처럼요!

Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
package view;

import domain.Lotto;
import domain.LottoNumber;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class InputView {
private static final Scanner scanner = new Scanner(System.in);

public static int getPurchaseAmount() {
System.out.print("구입금액을 입력해 주세요.\n");
System.out.println("구입 금액을 입력해 주세요.");
return Integer.parseInt(scanner.nextLine());
}

public static List<LottoNumber> getWinningNumbers() {
System.out.print("지난 주 당첨 번호를 입력해 주세요.\n");
return Stream.of(scanner.nextLine().split(","))
public static Lotto getWinningLotto() {
System.out.println("지난 주 당첨 번호를 입력해 주세요.");
String input = scanner.nextLine();
List<LottoNumber> numbers = Arrays.stream(input.split(","))
.map(String::trim)
.map(Integer::parseInt)
.map(LottoNumber::new)
.collect(Collectors.toList());
return new Lotto(numbers);
}

public static LottoNumber getBonusNumber() {
System.out.println("보너스 볼을 입력해 주세요.");
int number = Integer.parseInt(scanner.nextLine());
return new LottoNumber(number);
}
}
35 changes: 23 additions & 12 deletions src/main/java/view/OutputView.java
Copy link

Choose a reason for hiding this comment

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

문자열을 포장하시고 반복문으로 출력하시면 코드가 훨씬 더 간결해질 것 같습니다.

Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
package view;

import domain.Lotto;
import domain.LottoStatistics;
import domain.LottoPrize;
import domain.LottoResult;

import java.util.List;

public class OutputView {
public static void printLottos(List<Lotto> lottos) {
System.out.printf("%d개를 구매했습니다.\n", lottos.size());
for (Lotto lotto : lottos) {
System.out.println(lotto);
lottos.forEach(System.out::println);
System.out.println();
}

public static void printResult(LottoResult result, int purchaseAmount) {
System.out.println("당첨 통계");
System.out.println("---------");
for (LottoPrize prize : LottoPrize.values()) {
int count = result.getCountByPrize(prize);
printPrizeStatics(prize, count);
}
double earningRate = result.getEarningRate(purchaseAmount);
System.out.printf("총 수익률은 %.2f입니다.%n", earningRate);
}

public static void printStatistics(LottoStatistics statistics) {
System.out.println("\n당첨 통계\n---------");
System.out.printf("3개 일치 (%d원)- %d개\n", statistics.getPrizeFor(3), statistics.getCountFor(3));
System.out.printf("4개 일치 (%d원)- %d개\n", statistics.getPrizeFor(4), statistics.getCountFor(4));
System.out.printf("5개 일치 (%d원)- %d개\n", statistics.getPrizeFor(5), statistics.getCountFor(5));
System.out.printf("6개 일치 (%d원)- %d개\n", statistics.getPrizeFor(6), statistics.getCountFor(6));
System.out.printf("총 수익률은 %.2f입니다.(기준이 1이기 때문에 결과적으로 %s라는 의미임)\n",
statistics.getProfitRatio(),
statistics.getProfitRatio() < 1 ? "손해" : "이익");
private static void printPrizeStatics(LottoPrize prize, int statics) {
if (prize == LottoPrize.MISS) {
return;
}
if (prize.isMatchBonus()) {
System.out.printf("%d개 일치, 보너스 볼 일치(%d원) - %d개%n", prize.getMatchCount(), prize.getPrize(), statics);
return;
}
System.out.printf("%d개 일치 (%d원)- %d개%n", prize.getMatchCount(), prize.getPrize(), statics);
}
}