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

[로또 미션] 방지원 미션 제출합니다. #16

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
93 changes: 93 additions & 0 deletions docs/README.md
Copy link

Choose a reason for hiding this comment

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

README가 매우 깔끔하게 작성되어 있어서 보기 좋았습니다!
어떻게 설계하시면서 코딩을 하셨는지 잘 보여진 것 같아요.
제가 배워야될 것 같습니다. 감사합니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
## 게임 설명
1. 범위가 1~45인 6개의 숫자를 가진 로또를 뽑는다. 한 장 당 1000원
2. 로또를 사기 위한 입력값은 1000에 맞게 떨어져야한다 (아닐시 예외 발생)
3. 로또를 구매한 개수에 맞게 오름차순으로 나열되게 출력한다
```
8개를 구매했습니다.
[8, 21, 23, 41, 42, 43]
[3, 5, 11, 16, 32, 38]
[7, 11, 16, 35, 36, 44]
[1, 8, 11, 31, 41, 42]
[13, 14, 16, 38, 42, 45]
[7, 11, 30, 40, 42, 43]
[2, 13, 22, 32, 38, 45]
[1, 3, 5, 14, 22, 45]
```
4. 당첨 번호 6개를 입력 받는다 이때 번호는 쉼표로 구분되어 았어야한다
5. 보너스 번호를 입력 받는다
6. 당첨 내역을 출력한다
```
3개 일치 (5,000원) - 개
4개 일치 (50,000원) - 개
5개 일치 (1,500,000원) - 개
5개 일치, 보너스 볼 일치 (30,000,000원) - 개
6개 일치 (2,000,000,000원) - 개
```
7. 소수점 둘째 자리에서 반올림한 수익률을 출력한다
```
총 수익률은 62.5%입니다.
```

### 입력값
```
- 로또 구입 금액
- 당첨 번호 6개 ( ,를 기준으로 구분)
- 보너스 번호
```

---
## 주요 요구사항
- 클래스(객체)를 분리
- 도메인 로직에 대한 단위 테스트를 작성
- 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다.
- else 예약어를 쓰지 않는다. (switch/case 도 당연히 안됨)
- depth는 2까지만 허용
- 도메인 로직에 단위 테스트를 구현해야 한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다.
- Lotto 클래스를 활용해야한다 -> 사용자가 지정한 로또 혹은 구매한 로또의 객체
- 기본 메서드
- 생성자
- 입력 받은 리스트의 길이가 6이 아닌 경우 예외를 발생시키는 메서드
- enum 사용

---
## 기능 구현 목록
### 사용 DTO
- `Money`, `Lotto`, `Lottos`, `Bingo`
```
Money : 사용자가 입력한 구매 금액
Lotto : 사용자의 로또 및 사용자가 구매한 개수(ticket)만큼의 로또 객체. 총 6개의 숫자가 중복 없이 존재해야한다.
Lottos : 사용자가 구매한 개수만큼의 로또를 List<>로 묶은 객체
Bingo : 사용자의 당첨번호와 3~6개의 숫자가 일치하는 로또 개수 객체. 당첨 기준이 동일하기 때문에 싱글톤으로 생성 (3,4,5,5+보너스,6)
```
### 1. 사용자 입력 (inputView.Input*)
- 로또 구매 금액 입력 `InputUserMoney`
- 입력 처리 되자마자 정수형이 아닌 다른 자료형으로 입력되었는지 확인
- 입력 처리 후 올바른 정수값인지 확인
- 오류 확인은 Money 객체에서 실행한다
- Lotto 클래스를 활용하여 로또 번호 6개 입력 `InputNumber`
- 보너스 번호 입력 `InputBonusNumber`
### 2. 로또 게임 구현 (domain)
- ticket(로또 구매 금액 / 1000)에 맞는 개수의 로또 객체를 가진 로또 리스트 객체 만들기 `CreateLotto`, `CreateLottoList`
- 랜덤으로 숫자들이 지정되어야한다 ( 중복x )
- 오름차순으로 출력되도록 재배치 필요
- Bingo 클래스를 통해 당첨 통계 만들기 `FindBingo`
- 여기서 빙고 클래스 객체가 어떤것인지 정해져있으므로는 싱클톤패턴으로 고유 클래스를 가지도록 구현 ( bingo3, bingo4, bingo5, bingo5wB, bingo6 )
- 결과에 따른 수익률 계산하기 `CalculateProfit`
- 소수점 두번째 자리에서 반올림 하도록 구현
### 3. 출력 (outputView.Output*)
- 구매 개수 출력 `OutputTicketNum.printTicketNum()`
- 뽑은 로또 리스트 출력 `OutputLottos.printLottos()`
- 당첨 통계 출력 `OutputResult.printResult()`
- 수익률 출력 `OutputPercent.printPercent()`
### 4. 테스트 코드 (LottoTest, InputTest)
- LottoTest
- 랜덤으로 부여된 로또에 1~45 사이가 아닌 숫자가 있으면 예외가 발생한다. `checkOutOfRangeNum()`
- 로또번호가 오름차순으로 정렬되는지 확인한다. `checkLottoNumArray()`
- InputTest
- 입력한 보너스 번호가 정수가 아닌 경우 예외가 발생한다. `checkBonusNumberValidate()`
- 입력한 보너스 번호가 범위를 벗어나면 예외가 발생한다. `checkBonusNumberRange()`
- 입력한 로또 번호가 올바른 구분자로 구분이 안되어 있으면 예외가 발생한다. `checkInputNumberValidate()`
- 입력한 구매 금액이 정수가 아닌 경우 예외가 발생한다. `checkInputUserMoneyValidate()`
- 구매 금액이 1000 단위가 아닌 경우 예외가 발생한다. `checkInputUserMoneyDigit()`
- 구매 금액이 양수가 아닌 경우 예외가 발생한다. `checkInputUserMoneyPositive()`

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

import lotto.controller.LottoController;

public class Application {

public static void main(String[] args) {
try {
LottoController lottoController = new LottoController();
lottoController.start();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

71 changes: 71 additions & 0 deletions src/main/java/lotto/controller/LottoController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package lotto.controller;

import lotto.domain.CalculateProfit;
import lotto.domain.CreateLottoList;
import lotto.domain.FindBingo;
import lotto.dto.Lotto;
import lotto.dto.Lottos;
import lotto.dto.Money;
import lotto.inputView.InputBonusNumber;
import lotto.inputView.InputNumber;
import lotto.inputView.InputUserMoney;

import java.util.List;

import static lotto.outputView.OutputLottos.printLottos;
import static lotto.outputView.OutputPercent.printPercent;
import static lotto.outputView.OutputResult.printResult;
import static lotto.outputView.OutputTicketNum.printTicketNum;

public class LottoController {

public void start(){
Money money = getUserMoney();
int ticket = money.ticket();

Lottos lottos = makeLottoList(ticket);
printTicketNum(ticket);
printLottos(lottos);

Lotto userLotto = getUserNumber();
int bonusNum = getBonusNumber();

makeBingo(lottos, userLotto, bonusNum);
printResult();
printPercent(calculate(ticket));
}

public Money getUserMoney(){
InputUserMoney inputUserMoney = new InputUserMoney();
Integer money = inputUserMoney.getInput();
return new Money(money);
}

public Lotto getUserNumber(){
InputNumber inputUserNumber = new InputNumber();
List<Integer> userNumber = inputUserNumber.getInput();
return new Lotto(userNumber);
}

public int getBonusNumber(){
InputBonusNumber inputBonusNumber = new InputBonusNumber();
return inputBonusNumber.getInput();
}

public Lottos makeLottoList(int ticket) {
CreateLottoList lottoList = new CreateLottoList();
return new Lottos(lottoList.createLottoList(ticket));
}

public void makeBingo(Lottos lottos, Lotto userLotto, int bonusNum){
FindBingo findBingo = new FindBingo();
findBingo.findBingos(lottos,userLotto,bonusNum);
}

private double calculate(int ticket) {
CalculateProfit calculateProfit = new CalculateProfit();
calculateProfit.calcProfit();
return calculateProfit.calcProfitPercent(ticket*1000);
}

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

import lotto.dto.Bingo;

public class CalculateProfit {
double profit = 0;

public void calcProfit(){
Copy link

Choose a reason for hiding this comment

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

여기도 calc를 calculate으로 표현되면 좋을 것 같습니다!

profit += 5000* Bingo.getBingo3().correctLotto;
profit += 50000*Bingo.getBingo4().correctLotto;
profit += 1500000*Bingo.getBingo5().correctLotto;
profit += 30000000*Bingo.getBingo5wB().correctLotto;
Copy link

Choose a reason for hiding this comment

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

"줄여 쓰지 않는다(축약 금지)"의 요구사항에 맞지 않는 것 같습니다.
w와 B가 with와 bonus를 의미한다면 풀어쓰는게 좋을 것 같습니다!

profit += 2000000000*Bingo.getBingo6().correctLotto;
}

public double calcProfitPercent(int money){
double percent = (profit/(double)money)*100;
return Math.round(percent*100)/100.0;
}

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

import lotto.dto.Lotto;

import java.util.*;

public class CreateLotto {
public Lotto createLotto() {
Random rand = new Random();
List<Integer> randomNumbers = new ArrayList<>();

// 한 로또 내에 난수가 중복되지 않도록 HashSet을 사용한다
Set<Integer> uniqueNumbers = new HashSet<>();

while (uniqueNumbers.size() < 6) {
int randomNumber = rand.nextInt(45) + 1;
uniqueNumbers.add(randomNumber);
}

randomNumbers.addAll(uniqueNumbers);

return new Lotto(randomNumbers);
}
}
24 changes: 24 additions & 0 deletions src/main/java/lotto/domain/CreateLottoList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package lotto.domain;

import lotto.dto.Lotto;

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

public class CreateLottoList {

public List<Lotto> createLottoList(int ticket){
List<Lotto> lottoList = new ArrayList<>();
for ( int i = 0 ; i < ticket ; i++ ){
lottoList.add(createLotto());
}

return lottoList;
}

public Lotto createLotto(){
CreateLotto lotto = new CreateLotto();
return lotto.createLotto();
}

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

import lotto.dto.Bingo;
import lotto.dto.Lotto;
import lotto.dto.Lottos;

public class FindBingo {
int correctNum = 0;
int bonusFlag = 0;

public void findBingos(Lottos lottos, Lotto userLotto, int bonusNum){

for ( Lotto lotto : lottos.getLottos() ){
correctNum = 0;
bonusFlag = 0;
compareUserLotto(lotto, userLotto, bonusNum);

checkBingoList(correctNum, bonusFlag);
}
}

public void compareUserLotto(Lotto lotto, Lotto userLotto, int bonusNum){
for ( int i : userLotto.getNumbers() ){
for ( int j : lotto.getNumbers()){
compareNumber(i,j,bonusNum);
}
}
}

public void compareNumber(int i, int j, int bonusNum ){
if ( i == j ) correctNum++;
if ( bonusNum == j ) bonusFlag = 1;
}

public void checkBingoList(int correctNum, int bonusFlag){
findBingo3(correctNum);
findBingo4(correctNum);
findBingo5(correctNum, bonusFlag);
findBingo5wB(correctNum, bonusFlag);
findBingo6(correctNum);
}

public void findBingo3( int correctNum ){
if ( correctNum == 3 ) Bingo.getBingo3().correctLotto++;
}

public void findBingo4( int correctNum ){
if ( correctNum == 4 ) Bingo.getBingo4().correctLotto++;
}

public void findBingo5( int correctNum, int bonusFlag ){
if ( correctNum == 5 && bonusFlag == 0 ) Bingo.getBingo5().correctLotto++;
}

public void findBingo5wB( int correctNum, int bonusFlag ){
if ( correctNum == 5 && bonusFlag == 1 ) Bingo.getBingo5wB().correctLotto++;
}

public void findBingo6( int correctNum ){
if ( correctNum == 6 ) Bingo.getBingo6().correctLotto++;
}
}
25 changes: 25 additions & 0 deletions src/main/java/lotto/dto/Bingo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package lotto.dto;

public class Bingo {
int bingoNum;
boolean checkBonus;
public int correctLotto = 0;

private Bingo(int bingoNum, boolean checkBonus){
this.bingoNum = bingoNum;
this.checkBonus = checkBonus;
}

private static Bingo bingo3 = new Bingo(3,false);
private static Bingo bingo4 = new Bingo(4,false);
private static Bingo bingo5 = new Bingo(5,false);
private static Bingo bingo5wB = new Bingo(5,true);
private static Bingo bingo6 = new Bingo(6,false);

public static Bingo getBingo3() { return bingo3; }
public static Bingo getBingo4() { return bingo4; }
public static Bingo getBingo5() { return bingo5; }
public static Bingo getBingo5wB() { return bingo5wB; }
public static Bingo getBingo6() { return bingo6; }

}
53 changes: 53 additions & 0 deletions src/main/java/lotto/dto/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package lotto.dto;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Lotto {
private final List<Integer> numbers;

public Lotto(List<Integer> numbers) {
checkValidateCnt(numbers);
Copy link

Choose a reason for hiding this comment

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

Cnt가 Count로 바뀌면 좋을 것 같습니다!

checkValidateRange(numbers);
checkDuplicatedNum(numbers);
numbers = sorted(numbers);
this.numbers = numbers;
}

private void checkDuplicatedNum(List<Integer> numbers) {
Set<Integer> nonDuplicateNumbers = new HashSet<>(numbers);
if (nonDuplicateNumbers.size() != 6) {
throw new IllegalArgumentException("[ERROR] 중복된 숫자가 존재하는 로또입니다. ");
}
}

private void checkValidateRange(List<Integer> numbers) {
for ( int num : numbers){
if ( num < 1 || num > 45 ){
throw new IllegalArgumentException("[ERROR] 지정된 범위에 벗어나는 숫자입니다.");
}
}
}

private void checkValidateCnt(List<Integer> numbers) {
Copy link

Choose a reason for hiding this comment

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

마찬가지로 Cnt가 Count로 바뀌면 좋을 것 같습니다!

if (numbers.size() != 6) {
throw new IllegalArgumentException("[ERROR] 로또 번호 개수는 6개여야 합니다.");
}
}

public List<Integer> getNumbers() {
return numbers;
}

public List<Integer> sorted(List<Integer> numbers) {
return numbers.stream().sorted().collect(Collectors.toList());
}

@Override
public String toString() {
return numbers + "";
}

}
Loading