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

[디디] 로또 수동 입력 #168

Merged
merged 8 commits into from
Mar 4, 2020
Merged
Show file tree
Hide file tree
Changes from 3 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
39 changes: 16 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
## 로또 미션을 위한 저장소

---

## 게임 순서

- 구입 금액을 입력 받는다.

- 1000단위가 아닌 경우는 예외처리
- 문자열이 포함되는 경우 예외처리
- 공백 및 NULL 예외처리
- 1000원 ~ 100,000원까지만 가능
- 구입 금액 또한 클래스로 분리하고
- 기능은 생성자를 통한 검증
- 장수를 계산해서 보내는 부분도

- 금액 / 1000 의 갯수만큼 로또를 자동으로 생성 및 출력한다.

- Number : 각각의 수
- 1~45 사이의 값인지
- 문자열이 포함되는 경우 예외처리
Expand All @@ -27,7 +21,6 @@
- Lotto를 구매한 만큼 가지고 있는 Lottos 객체를 생성한다.
- 금액 / 1000 == Lottos.size()
- 이렇게 생성된 Lottos 를 출력한다.

- 당첨번호(보너스 번호 제외) 6자리를 `,` 를 기준으로 분리한다.
- 싱글톤 ?
- 당첨번호를 담당하는 WinningLotto 객체를 생성한다.
Expand All @@ -36,23 +29,18 @@
- 갯수 6개
- 번호의 범위
- 각각 다른 번호인지

- 보너스 볼 하나를 입력한다
- 보너스 볼 객체 Bonus
- Number 하나를 갖는 객체

- 당첨 통계를 출력한다
- LottoModel ← Lottos , Winning
- OutputView
- Enum 에서 맞힌 갯수, 금액, 몇장인지를 가지는 Enum에서 처리

- 참고
- 숫자를 생성할 때 그리고 보너스 넘버를 생성할 때 로직이 겹치니까 해결책으로
- Validator를 따로 둔다.
- Number를 상속받는다.

### 구현 순서

- 구입 금액 테스트
- [x] 1000단위가 아닌 경우는 예외처리
- [x] 문자열이 포함되는 경우 예외처리
Expand All @@ -62,48 +50,53 @@
- Utility 클래스 검증
- [x] 공백 제거
- [x] `,` Parsing 검증

- Number
- [x] 1~45 사이의 값인지
- [x] 문자열이 포함되는 경우 예외처리
- [x] 공백 및 NULL 예외처리
- Enum을 통해서 Number 기능을 같이 하는 방안 고려 (현재 static 부분)

- LottoFactory

- Lotto
- [x] `Lotto.size()` = 6
- [x] 중복된 수가 있으면 안된다.

- Lottos
- [x] Lotto를 구매한 만큼 가지고 있는 Lottos 객체를 생성한다
- [x] 금액 / 1000 == Lottos.size()

- WinningLotto
- [x] 보너스넘버와 WinningNumbers의 값이 겹치지 않아야 한다.
- [x] BonusNumber (상속 : Number)
- [x] WinningNumbers
- [x] 상속받고 있고 (Lotto) : 로직이 같고, 로또와 의미를 구분하기 위함

- [x] Result
- 인자 : WinningLotto, Lottos
- 기능
- [x] 맞힌 갯수별로 장수 + 수익금 계산
- [x] 수익률
- [x] OutputView 보내기

- 추가 요구사항(수동)
- [x] 수동으로 구매할 로또의 개수를 입력 받는다.
- [x] 개수라는 클래스를 두고
- [x] 음수 예외처리
- [x] 금액을 초과하는 경우
- [x] 문자열
- [x] Null & 공백
- [x] 금액이랑 비교
- [x] 수동으로 구매할 로또의 번호를 개수만큼 입력받는다.
- [x] 기존의 LottoFactory 를 재활용한다.
### 프로그래밍 요구사항

- indent(인덴트, 들여쓰기) depth를 2단계에서 1단계로 줄여라.
- depth의 경우 if문을 사용하는 경우 1단계의 depth가 증가한다. if문 안에 while문을 사용한다면 depth가 2단계가 된다.
- else를 사용하지 마라.
- 메소드의 크기가 최대 10라인을 넘지 않도록 구현한다.
- method가 한 가지 일만 하도록 최대한 작게 만들어라.
- **배열 대신 ArrayList를 사용한다.**
- enum을 적용해 프로그래밍을 구현한다.

- 예외가 발생하는 부분에 대해 자바 Exception을 적용해 예외처리한다.
- 사용자가 입력한 값에 대한 예외 처리를 철저히 한다.
### 힌트

- 로또 자동 생성은 Collections.shuffle() 메소드 활용한다.
- Collections.sort() 메소드를 활용해 정렬 가능하다.
- ArrayList의 contains() 메소드를 활용하면 어떤 값이 존재하는지 유무를 판단할 수 있다.
- ArrayList의 contains() 메소드를 활용하면 어떤 값이 존재하는지 유무를 판단할 수 있다.
## 추가 요구 사항
- 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다.
- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다.
37 changes: 37 additions & 0 deletions src/main/java/lotto/domain/LottoCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package lotto.domain;

import lotto.exception.ExceedMoneyException;
import lotto.util.StringUtil;

public class LottoCount {
private final int manualLotto;
private final int autoLotto;

public LottoCount(String manualLotto, int totalLotto) {
validate(manualLotto);
validateMoney(manualLotto, totalLotto);
this.manualLotto = Integer.parseInt(manualLotto);
this.autoLotto = totalLotto - this.manualLotto;
}

private void validate(String input) {
StringUtil.checkNull(input);
StringUtil.checkBlank(input);
StringUtil.checkNumberFormat(input);
StringUtil.checkRange(input);
}

private void validateMoney(String input, int totalLotto) {
Copy link

Choose a reason for hiding this comment

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

input 을 더 의미있는 이름으로 바꿔보면 좋을 듯 합니다.

if (totalLotto < Integer.parseInt(input)) {
throw new ExceedMoneyException(totalLotto + "장 이하만 구매가 가능합니다.");
}
}

public int getManualLotto() {
return manualLotto;
}

public int getAutoLottoCount() {
return autoLotto;
}
Copy link

Choose a reason for hiding this comment

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

해당 메서드는 자동/수동의 개수를 반환하는 getter인데 서로 네이밍 형식이 다르네요!

}
11 changes: 11 additions & 0 deletions src/main/java/lotto/domain/LottoFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,15 @@ public static Lottos create(int count) {
}
return new Lottos(lottos);
}

public static Lottos create(List<String> list, int autoCount){
Copy link

Choose a reason for hiding this comment

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

list 라는 이름만 보고 어떤 파라미터인지 유추하기 힘들지 않을까요?

List<Lotto> lottos = new ArrayList<>();
for (String input : list) {
lottos.add(create(input));
}
for(int i =0; i< autoCount;i++) {
Copy link

Choose a reason for hiding this comment

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

띄어쓰기 컨벤션 위반입니다.

lottos.add(create());
}
Copy link

Choose a reason for hiding this comment

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

메서드를 추출해 가독성을 높여보면 어떨까요?

return new Lottos(lottos);
}
}
27 changes: 4 additions & 23 deletions src/main/java/lotto/domain/Number.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Objects;

import lotto.exception.InvalidNumberException;
import lotto.util.StringUtil;

import static javax.management.Query.value;

Expand All @@ -26,39 +27,19 @@ public Number(int number) {
}

public static void validate(String value) {
checkNull(value);
checkBlank(value);
checkNumberFormat(value);
StringUtil.checkNull(value);
StringUtil.checkBlank(value);
StringUtil.checkNumberFormat(value);
checkRange(value);
}

private static void checkNumberFormat(String value) {
try {
Integer.parseInt(value);
} catch (NumberFormatException e) {
throw new InvalidNumberException("문자는 사용이 불가능합니다.");
}
}

private static void checkRange(String value) {
int number = Integer.parseInt(value);
if (number > MAX_LOTTO_NUMBER || number < MIN_LOTTO_NUMBER) {
throw new InvalidNumberException("로또 번호는 1에서 45까지만 가능합니다");
}
}

private static void checkBlank(String value) {
if (value.trim().isEmpty()) {
throw new InvalidNumberException("공백은 사용이 불가능합니다.");
}
}

private static void checkNull(String value) {
if (Objects.isNull(value)) {
throw new InvalidNumberException("Null문자열은 사용이 불가능합니다.");
}
}

@Override
public String toString() {
return Integer.toString(number);
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/lotto/domain/controller/LottoController.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package lotto.domain.controller;

import lotto.domain.Lotto;
import lotto.domain.LottoFactory;
import lotto.domain.Lottos;
import lotto.domain.*;
import lotto.domain.Number;
import lotto.domain.PurchaseMoney;
import lotto.domain.WinningLotto;
import lotto.domain.model.LottoGame;
import lotto.domain.result.GameResult;
import lotto.view.InputView;
import lotto.view.OutputView;

import java.util.List;

public class LottoController {
public void run() {
PurchaseMoney money = new PurchaseMoney(InputView.getMoney());
Lottos lottos = LottoFactory.create(money.parseToPiece());
OutputView.printPieces(money.parseToPiece());
LottoCount count = new LottoCount(InputView.getCount(), money.parseToPiece());
List<String> manual = InputView.getManualLottosNumber(count.getManualLotto());
Lottos lottos = LottoFactory.create(manual, count.getAutoLottoCount());

OutputView.printPieces(count.getManualLotto(), count.getAutoLottoCount());
OutputView.printLottos(lottos);

createResult(money, lottos, createWinningLotto());
}

Expand Down
7 changes: 7 additions & 0 deletions src/main/java/lotto/exception/EmptyInputException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lotto.exception;

public class EmptyInputException extends RuntimeException {
public EmptyInputException(String message) {
super(message);
}
}
7 changes: 7 additions & 0 deletions src/main/java/lotto/exception/ExceedMoneyException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lotto.exception;

public class ExceedMoneyException extends RuntimeException {
public ExceedMoneyException(String message) {
super(message);
}
}
7 changes: 7 additions & 0 deletions src/main/java/lotto/exception/InvalidRangeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lotto.exception;

public class InvalidRangeException extends RuntimeException {
public InvalidRangeException(String message) {
super(message);
}
}
29 changes: 29 additions & 0 deletions src/main/java/lotto/util/StringUtil.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package lotto.util;

import lotto.exception.EmptyInputException;
import lotto.exception.InvalidRangeException;

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

public class StringUtil {
public static final String BLANK = " ";
Expand All @@ -15,4 +19,29 @@ public static String removeBlank(String value) {
public static List<String> parseByComma(String value) {
return Arrays.asList(value.split(DELIMITER));
}

public static void checkBlank(String input) {
if(input.trim().isEmpty()){
throw new EmptyInputException("공백은 사용할 수 없습니다.");
}
}

public static void checkNull(Object o) {
if(Objects.isNull(o)){
throw new NullPointerException("널문자는 사용할 수 없습니다.");
}
}

public static void checkNumberFormat(String input) {
try{
Integer.parseInt(input);
} catch(NumberFormatException e){
throw new NumberFormatException("문자열은 사용할 수 없습니다.");
}
}

public static void checkRange(String input) {
if(Integer.parseInt(input) < 0)
Copy link

Choose a reason for hiding this comment

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

여기만 괄호가 없는 이유가 무엇일까요? 일관된 포맷을 가져가면 좋을 것 같습니다~

throw new InvalidRangeException("음수는 입력할 수 없습니다.");
}
}
16 changes: 16 additions & 0 deletions src/main/java/lotto/view/InputView.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package lotto.view;

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

public class InputView {
Expand All @@ -19,4 +21,18 @@ public static String getBonusNumber() {
System.out.println("보너스 번호를 입력해 주세요.");
return scanner.nextLine();
}

public static String getCount() {
Copy link

Choose a reason for hiding this comment

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

getCount() 는 모호한 네이밍입니다. 적절한 네이밍으로 바꿔보면 어떨까요?

System.out.println("수동으로 구매할 로또 수를 입력해 주세요.");
return scanner.nextLine();
}

public static List<String> getManualLottosNumber(int manualLottoCount) {
List<String> input = new ArrayList<>();
System.out.println("수동으로 구매할 번호를 입력해 주세요.");
for(int i=0;i<manualLottoCount;i++){
Copy link

Choose a reason for hiding this comment

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

컨벤션 위반입니다.

input.add(scanner.nextLine());
}
return input;
}
}
4 changes: 2 additions & 2 deletions src/main/java/lotto/view/OutputView.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import lotto.domain.result.Rank;

public class OutputView {
public static void printPieces(int parseToPiece) {
System.out.println(parseToPiece + "개를 구매했습니다.");
public static void printPieces(int manualCount, int autoCount) {
System.out.println("수동으로 " +manualCount+ "장, 자동으로 "+autoCount+"개를 구매했습니다.");
}

public static void printLottos(Lottos lottos) {
Expand Down
Loading