Skip to content

Step4 #4156

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

Open
wants to merge 7 commits into
base: youlalala
Choose a base branch
from
Open

Step4 #4156

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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@
### 3단계 - 로또(2등)
- [X] 보너스볼 입력
- [X] rank 2등 추가

### 4단계 - 로또(수동)
- [X] 수동으로 구매할 로또 수 입력
- [X] 수동으로 구매할 로또 번호 입력
28 changes: 17 additions & 11 deletions src/main/java/lotto/Lotto.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,39 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Lotto {
public static final int LOTTO_PRICE = 1000;
public static final long LOTTO_NUM_COUNT = 6;

private final List<Integer> lottoNumbers;
private final Set<LottoNumber> lottoNumbers;

public Lotto(List<Integer> lottoNumbers) {
validateLottoNumbers(lottoNumbers);
this.lottoNumbers = lottoNumbers;
public Lotto(List<Integer> numbers) {
this(new HashSet<>(numbers));
}

public List<Integer> getLottoNumbers() {
public Lotto(Set<Integer> numbers) {
this.lottoNumbers = numbers.stream().map(LottoNumber::of).collect(Collectors.toSet());
validateLottoNumbers();
}

public Set<LottoNumber> getLottoNumbers() {
return lottoNumbers;
}

public LottoRank getLottoRank(List<Integer> winningNumbers, Integer bonusNumber) {
return LottoRank.fromMatchCount((int) this.lottoNumbers.stream().filter(winningNumbers::contains).count(), lottoNumbers.contains(bonusNumber));
public LottoRank getLottoRank(Lotto winningNumbers, int bonusNumber) {
int matchCount = (int) this.lottoNumbers.stream().filter(winningNumbers.getLottoNumbers()::contains).count();
boolean isBonusNumber = lottoNumbers.contains(LottoNumber.of(bonusNumber));
return LottoRank.fromMatchCount(matchCount, isBonusNumber);
}

private void validateLottoNumbers(List<Integer> numbers) {
if (numbers.size() != LOTTO_NUM_COUNT) {
private void validateLottoNumbers() {
if (lottoNumbers.size() > LOTTO_NUM_COUNT) {
throw new IllegalArgumentException("로또 번호는 6개여야 합니다.");
}
Comment on lines +33 to 36
Copy link
Member

Choose a reason for hiding this comment

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

별건 아니지만! 이런 경우엔 lottoNumber.size() != LOTTO_NUM_COUNT 가 그대로 유지되어도 괜찮을거 같아요 😄


Set<Integer> uniqueNumbers = new HashSet<>(numbers);
if (uniqueNumbers.size() != LOTTO_NUM_COUNT) {
if (lottoNumbers.size() < LOTTO_NUM_COUNT) {
throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다.");
Comment on lines -32 to 39
Copy link
Member

Choose a reason for hiding this comment

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

여기서는 요 표현식이 가장 정확하겠네요 👍

}
}
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/lotto/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package lotto;

import calculator.Operator;
import view.LottoNumbersParser;
import view.InputView;
import view.OutputView;

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

import static lotto.Lotto.LOTTO_PRICE;
Expand All @@ -13,14 +13,18 @@ public class LottoApplication {

public static void main(String[] args) {

Integer lottoPurchaseAmount = InputView.showLottoPurchaseAmountInput();
Integer lottoQuantity = Operator.DIVIDE.formula.apply(lottoPurchaseAmount, LOTTO_PRICE);
OutputView.showLottoQuantity(lottoQuantity);
int lottoPurchaseAmount = InputView.showLottoPurchaseAmountInput();
int totalLottoCount = Operator.DIVIDE.formula.apply(lottoPurchaseAmount, LOTTO_PRICE);

List<Lotto> lottos = LottoNumberGenerator.generateLottoNumbers(lottoQuantity);
int manualLottoCount = InputView.showManualLottoCountInput();
List<Lotto> lottos = new ArrayList<>(InputView.showManualLottoNumbersInput(manualLottoCount));

int autoLottoCount = totalLottoCount - manualLottoCount;
lottos.addAll(LottoNumberGenerator.generateLottoNumbers(autoLottoCount));
OutputView.showTotalLottoCount(manualLottoCount, autoLottoCount);
OutputView.showGeneratedLottoNumber(lottos);
List<Integer> winningLotto = LottoNumbersParser.parse(InputView.showWinningLottoNumbersInput());

Lotto winningLotto = InputView.showWinningLottoNumbersInput();
Integer bonusNumber = InputView.showLottoBonusNumberInput();

LottosResult lottosResult = new LottosResult(lottos, winningLotto, bonusNumber);
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/lotto/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package lotto;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

public class LottoNumber {

static final int LOTTO_MIN_NUM = 1;
static final int LOTTO_MAX_NUM = 45;
Comment on lines +9 to +10
Copy link
Member

Choose a reason for hiding this comment

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

접근 제한자를 default(package private) 을 선택해주셨네요!
요렇게 접근제한자를 선택하신 이유가 궁금해요!


public static final Map<Integer, LottoNumber> lottoNumberMap = IntStream.rangeClosed(LOTTO_MIN_NUM, LOTTO_MAX_NUM)
.boxed()
.collect(HashMap::new, (map, number) -> map.put(number, new LottoNumber(number)), HashMap::putAll);

private final int number;

private LottoNumber(int number) {
this.number = number;
}
Comment on lines +6 to +20
Copy link
Member

Choose a reason for hiding this comment

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

LottoNumber vo 가 생겼고, 이에 대해 캐싱해주셨군요 👍
보통 LottoNumber 에 대한 캐싱 값이 어딨는지 알고 싶을 땐 LottoNumber 클래스파일을 먼저 열어볼테니, 좋은 코드 배치라고 생각합니다 😄 👍


private static void validateLottoNumber(Integer number) {
if (number == null) {
throw new IllegalArgumentException("로또 번호는 null일 수 없습니다.");
}
if (number < LOTTO_MIN_NUM || number > LOTTO_MAX_NUM) {
throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}
}

public static LottoNumber of(Integer number) {
validateLottoNumber(number);
return lottoNumberMap.get(number);
}

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

}
10 changes: 3 additions & 7 deletions src/main/java/lotto/LottoNumberGenerator.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package lotto;

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

import static lotto.Lotto.LOTTO_NUM_COUNT;
import static lotto.LottoNumber.*;

public class LottoNumberGenerator {

private static final int LOTTO_MIN_NUM = 1;
private static final int LOTTO_MAX_NUM = 45;

private static List<Integer> numbersPool = IntStream.rangeClosed(LOTTO_MIN_NUM, LOTTO_MAX_NUM)
.boxed()
.collect(Collectors.toList());
private static final List<Integer> numbersPool = new ArrayList<>(lottoNumberMap.keySet());

public static List<Lotto> generateLottoNumbers(int lottoQuantity) {
return IntStream.range(0, lottoQuantity)
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/lotto/LottoRank.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public static LottoRank fromMatchCount(int matchCount, boolean isBonusMatch) {

@Override
public String toString() {
return String.format("%d개 일치 (%,d원)", matchCount, prize);
String bonusText = isBonusMatch ? ", 보너스 볼 일치" : "";
return String.format("%d개 일치%s (%,d원)", matchCount, bonusText, prize);
}
}
8 changes: 4 additions & 4 deletions src/main/java/lotto/LottosResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
public class LottosResult {

private List<Lotto> lottos;
private List<Integer> winningNumbers;
private Lotto winningLotto;
private final EnumMap<LottoRank, Integer> lottoRankMap = new EnumMap<>(LottoRank.class);

public LottosResult(List<Lotto> lottos, List<Integer> winningNumbers, int bonusNumber) {
public LottosResult(List<Lotto> lottos, Lotto winningLotto, int bonusNumber) {
this.lottos = lottos;
this.winningNumbers = winningNumbers;
this.winningLotto = winningLotto;

for (Lotto lotto : lottos) {
LottoRank lottoRank = lotto.getLottoRank(winningNumbers, bonusNumber);
LottoRank lottoRank = lotto.getLottoRank(winningLotto, bonusNumber);
lottoRankMap.put(
lottoRank,
lottoRankMap.getOrDefault(lottoRank, 0) + 1
Expand Down
47 changes: 37 additions & 10 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
package view;

import lotto.Lotto;

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

public class InputView {

private static final Scanner scanner = new Scanner(System.in);
public static String showExpressionInput() {
System.out.println("수식 입력 > ");
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}

public static Integer showLottoPurchaseAmountInput() {
public static int showLottoPurchaseAmountInput() {
System.out.println("구입금액을 입력해 주세요.");
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
return readInt();
}

public static String showWinningLottoNumbersInput() {
public static Lotto showWinningLottoNumbersInput() {
System.out.println("\n지난 주 당첨 번호를 입력해 주세요.");
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
String input = scanner.nextLine();
return new Lotto(LottoNumbersParser.parse(input));
}

public static Integer showLottoBonusNumberInput() {
public static int showLottoBonusNumberInput() {
System.out.println("보너스 볼을 입력해 주세요.");
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
return readInt();
}

public static int showManualLottoCountInput() {
System.out.println("\n수동으로 구매할 로또 수를 입력해 주세요.");
return readInt();
}

public static List<Lotto> showManualLottoNumbersInput(int manualLottoCount) {
System.out.println("\n수동으로 구매할 번호를 입력해 주세요.");
List<Lotto> manualLottoNumbers = new ArrayList<>();
for (int i = 0; i < manualLottoCount; i++) {
String input = scanner.nextLine();
manualLottoNumbers.add(new Lotto(LottoNumbersParser.parse(input)));
}
return manualLottoNumbers;
}

private static int readInt() {
String input = scanner.nextLine();
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
System.out.println("잘못된 입력입니다. 다시 시도하세요.");
return readInt();
}
}
}
9 changes: 6 additions & 3 deletions src/main/java/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
package view;

import lotto.Lotto;
import lotto.LottoNumber;
import lotto.LottoRank;
import lotto.LottosResult;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

public class OutputView {

public static void showResult(int result) {
System.out.println("result = " + result);
}

public static void showLottoQuantity(int lottoQuantity) {
System.out.println(lottoQuantity + "개를 구매했습니다.");
public static void showTotalLottoCount(int manualLottoCount, int autoLottoCount) {
System.out.println("\n수동으로 " + manualLottoCount + "장, 자동으로 " + autoLottoCount + "개를 구매했습니다.");
}

public static void showLottoNumbers(List<Integer> numbers) {
public static void showLottoNumbers(Set<LottoNumber> numbers) {
System.out.println(numbers);
}

Expand All @@ -40,3 +42,4 @@ public static void showGeneratedLottoNumber(List<Lotto> lottos) {
lottos.forEach(lotto -> showLottoNumbers(lotto.getLottoNumbers()));
}
}

11 changes: 0 additions & 11 deletions src/test/java/lotto/LottoNumberGeneratorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

import org.junit.jupiter.api.Test;

import java.util.HashSet;
import java.util.List;

import static lotto.Lotto.LOTTO_NUM_COUNT;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class LottoNumberGeneratorTest {
Expand All @@ -17,13 +15,4 @@ public class LottoNumberGeneratorTest {
assertThat(lottos.size()).isEqualTo(quantity);
}

@Test
void 각_Lotto는_6개의_서로_다른_숫자를_가진다() {
List<Lotto> lottos = LottoNumberGenerator.generateLottoNumbers(1);
List<Integer> numbers = lottos.get(0).getLottoNumbers();

assertThat(numbers.size()).isEqualTo(LOTTO_NUM_COUNT);
assertThat(new HashSet<>(numbers).size()).isEqualTo(numbers.size());
}

}
26 changes: 26 additions & 0 deletions src/test/java/lotto/LottoNumberTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package lotto;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class LottoNumberTest {

@Test
void of_1에서_45사이_숫자면_같은_객체_반환한다() {
assertThat(LottoNumber.of(2)).isEqualTo(LottoNumber.of(2));
}

@Test
void of_1미만일_경우_예외를_던진다() {
assertThatThrownBy(() -> LottoNumber.of(0))
.isInstanceOf(IllegalArgumentException.class);
}

@Test
void of_45초과일_경우_예외를_던진다() {
assertThatThrownBy(() -> LottoNumber.of(46))
.isInstanceOf(IllegalArgumentException.class);
}
Comment on lines +9 to +25
Copy link
Member

Choose a reason for hiding this comment

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

경계값을 이용한 꼼꼼한 테스트 💯

}
Loading