Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5f0e0d6
docs: 입출력 기능 목록 작성
Nov 3, 2024
7738ae1
feat: 입력&유효성 검사 기능 구현
Nov 4, 2024
64b273e
test: 로또 입력 테스트 작성
Nov 4, 2024
607165b
feat: 로또 번호 리스트 생성 기능 구현
Nov 4, 2024
e3d9b70
test: 로또 숫자 파싱 테스트 작성
Nov 4, 2024
28bbfa2
docs: Domain, Service, Controller 기능 목록 작성
Nov 4, 2024
fef6d87
feat: Lotto domain 기능 구현
Nov 4, 2024
392caa4
test: Lotto 클래스 테스트 코드 작성
Nov 4, 2024
fe052f4
feat: bonusNumber Domain 기능 구현
Nov 4, 2024
aa686ed
test: bonusNumber test 코드 작성
Nov 4, 2024
48b9473
feat: PurchaseAmount Domain 기능 구현
Nov 4, 2024
2193dc5
test: purchaseAmount test 코드 작성
Nov 4, 2024
75be103
feat: LottoRank enum 기능 구현
Nov 4, 2024
3818ef8
feat: LottoRank Enum 기능 구현
Nov 4, 2024
a6064d3
feat: Lotto 입출력 기능 구현
Nov 4, 2024
c9fe7c4
feat: 무작위 로또 번호 생성 기능 구현
Nov 4, 2024
21b70d2
feat: random 로또 번호 오름차순 정렬 기능 구현
Nov 4, 2024
923bd9a
feat: 로또 결과를 구하는 기능 구현
Nov 4, 2024
c8b2836
fix: 랜덤 로또 생성 로직 수정
Nov 4, 2024
c1b5fce
fix: enum count값 수정
Nov 4, 2024
269e05e
feat: input 타입 변환 기능 구현
Nov 4, 2024
1cc8dbb
feat: 수익률 계산 기능 구현
Nov 4, 2024
4c4f1c2
fix: 수익률 출력 방식 수정
Nov 4, 2024
2dcd6db
feat: lottoController 기능 구현
Nov 4, 2024
c64958f
fix: 정렬 오류 수정
Nov 4, 2024
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
118 changes: 118 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,119 @@
# java-lotto-precourse

## 입출력 기능

### 입력 기능

- 구입 금액 입력 기능
- 로또 구입 금액을 1,000원 단위로 입력 받는다.
- 유효성 검증
- 숫자가 아닌 문자(공백, 특수기호)를 입력받으면 예외 처리
- 1,000원으로 나누어 떨어지지 않는 경우 예외 처리
- 0을 입력받으면 예외 처리
- 구입 금액이 0으로 시작하면 예외 처리 (01000원)

- 당첨 번호 입력 기능
- `,`를 기준으로 6개의 당첨 번호를 입력 받는다.
- 유효성 검증
- 당첨 번호가 6개가 아닌 경우 예외 처리
- 중복된 당첨 번호가 있다면 예외 처리
- 당첨 번호가 숫자가 아닌 경우 예외 처리
- 당첨 번호가 0으로 시작하면 예외 처리
- 당첨 번호가 1 ~ 45의 범위에 해당하지 않으면 예외 처리

- 보너스 번호 입력 기능
- 보너스 번호를 입력 받는다.
- 유효성 검증
- 보너스 번호가 숫자가 아닌 경우 예외 처리
- 보너스 번호가 당첨 번호와 중복된다면 예외 처리
- 보너스 번호가 1 ~45의 범위에 해당하지 않으면 예외 처리
- 보너스 번호가 0으로 시작하면 예외 처리

- 예외 처리
- 오입력에대한 예외 처리는 `IllegalArgumentException`을 발생 후 에러 메시지 출력 후 입력을 다시 받는다.
- 에러메시지의 형식은 `[ERROR]`로 시작한다.

### 출력 기능

- 발행한 로또 수량 및 번호 출력 기능
- 발행한 로또 수량 및 번호 출력
- 로또 번호는 오름차순으로 정렬
```text
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]
```

- 당첨 내역 출력 기능
- 발행한 로또의 당첨 내역(당첨 개수)을 출력
```text
3개 일치 (5,000원) - 1개
4개 일치 (50,000원) - 0개
5개 일치 (1,500,000원) - 0개
5개 일치, 보너스 볼 일치 (30,000,000원) - 0개
6개 일치 (2,000,000,000원) - 0개
```

- 수익률 출력 기능
- 소수점 둘째 자리에서 반올림
- `총 수익률은 62.5%입니다.`

- 에러 메시지 출력 기능
- 예외 발생 시 `[ERROR]`로 시작하는 에러 문구를 출력한다.
- `[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.`

## Domain 기능

### Lotto

- 로또 당첨 번호를 저장하는 클래스
- 6개의 숫자를 List에 저장
- 유효성 검증
- List의 길이가 6이 아니면 예외 처리
- 로또 번호의 중복된 번호가 있다면 예외 처리
- 로또 번호가 1 ~ 45의 범위에 해당하지 않는다면 예외 처리

### BonusNumber

- 보너스 번호를 저장하는 클래스
- 유효성 검증
- 보너스 번호가 로또 번호에 있다면 예외 처리
- 보너스 번호가 1 ~ 45의 범위에 해당하지 않는다면 예외 처리

### PurchaseAmount

- 구입 금액을 저장하는 클래스
- 유효성 검증
- 구입 금액이 0이면 예외 처리
- 구입 금액이 1000으로 나누어 떨어지지 않는다면 예외 처리

## Enum 기능

### LottoRank

- 등수와 상금을 저장하는 enum
- 등수와 상금을 저장

## Service 기능

- 구입 금액에 대해 로또를 생성하는 기능
- 구입한 로또가 당첨되었는지 판단하는 기능

## View 기능

- 입출력 메시지를 출력하는 기능
- 구입한 로또의 정보를 출력하는 기능
- 로또의 통계를 출력하는 기능

## Controller 기능

- 로또를 실행시키는 Controller
- 로또를 구매하는 기능
- 당첨, 보너스 번호를 저장하는 기능
- 로또의 결과를 출력하는 기능
5 changes: 4 additions & 1 deletion src/main/java/lotto/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package lotto;

import lotto.controller.LottoController;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
LottoController lottoController = new LottoController();
lottoController.playLottoGame();
}
}
20 changes: 0 additions & 20 deletions src/main/java/lotto/Lotto.java

This file was deleted.

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

import java.util.HashMap;
import java.util.List;
import lotto.domain.BonusNumber;
import lotto.domain.Lotto;
import lotto.domain.PurchaseAmount;
import lotto.enums.LottoRank;
import lotto.service.LottoService;
import lotto.util.InputUtil;
import lotto.view.LottoInputView;
import lotto.view.LottoOutputView;

public class LottoController {
private final LottoService lottoService;
private final LottoInputView lottoInputView;
private final LottoOutputView lottoOutputView;
private int ticketCount;
private PurchaseAmount purchaseAmount;
private List<Lotto> totalLottoNumbers;
private Lotto winningLottoNumbers;
private BonusNumber winningBonusNumber;

public LottoController() {
this.lottoService = new LottoService();
this.lottoInputView = new LottoInputView();
this.lottoOutputView = new LottoOutputView();
}

public void playLottoGame() {
purchaseLotto();
makeWinningLotto();
showLottoGameResult();
}

private void showLottoGameResult() {
HashMap<LottoRank, Integer> winningResults = lottoService.getWinningResults(totalLottoNumbers,
winningLottoNumbers, winningBonusNumber);
for (int rank = 5; rank > 0; rank--) {
LottoRank lottoRank = LottoRank.getEnumsValue(rank);
lottoOutputView.printLottoResultMessage(lottoRank, winningResults.get(lottoRank));
}
double rateOfReturn = lottoService.calculateRateOfReturn(winningResults, purchaseAmount);
lottoOutputView.printLottoRateOfReturnMessage(rateOfReturn);
}

private void makeWinningLotto() {
makeLotto();
makeBonusNumber();
}

private void makeBonusNumber() {
boolean checkInput = false;

while (!checkInput) {
try {
String inputBonusNumber = lottoInputView.readBonusNumberInput();
winningBonusNumber = new BonusNumber(InputUtil.convertStringToInt(inputBonusNumber));
checkInput = true;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}

private void makeLotto() {
boolean checkInput = false;

while (!checkInput) {
try {
String inputLotto = lottoInputView.readLottoNumberInput();
winningLottoNumbers = new Lotto(InputUtil.parseInputToLottoList(inputLotto));
checkInput = true;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}

private void purchaseLotto() {
getPurchaseAmount();
lottoOutputView.printPurchaseAmountMessage(ticketCount);
totalLottoNumbers = lottoService.generateTotalLottoNumbers(ticketCount);
lottoOutputView.printRandomLottoNumberMessage(totalLottoNumbers);
}

private void getPurchaseAmount() {
boolean checkInput = false;

while (!checkInput) {
try {
String inputCash = lottoInputView.readPurchaseAmountInput();
int purchaseCash = InputUtil.convertStringToInt(inputCash);
purchaseAmount = new PurchaseAmount(purchaseCash);
ticketCount = lottoService.calculateLottoTickets(purchaseAmount);
checkInput = true;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
}
28 changes: 28 additions & 0 deletions src/main/java/lotto/domain/BonusNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package lotto.domain;

public class BonusNumber {
private final int bonusNumber;

public BonusNumber(int bonusNumber) {
validateBonusNumber(bonusNumber);
this.bonusNumber = bonusNumber;
}

private void validateBonusNumber(int bonusNumber) {
if (bonusNumber <= 0 || bonusNumber > 45) {
throw new IllegalArgumentException("[ERROR] 보너스 번호는 1 ~ 45인 정수여야 합니다.");
}
}

public void validateExistLottoNumber(Lotto lotto) {
for (int number : lotto.getNumbers()) {
if (number == bonusNumber) {
throw new IllegalArgumentException("[ERROR] 보너스 번호는 로또 번호와 중복되지 않은 수여야 합니다.");
}
}
}

public int getBonusNumber() {
return bonusNumber;
}
}
39 changes: 39 additions & 0 deletions src/main/java/lotto/domain/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package lotto.domain;

import java.util.List;

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

public Lotto(List<Integer> numbers) {
validate(numbers);
validateLottoNumber(numbers);
validateUniqueLottoNumber(numbers);
this.numbers = numbers;
}

private void validate(List<Integer> numbers) {
if (numbers.size() != 6) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 6개여야 합니다.");
}
}

private void validateLottoNumber(List<Integer> numbers) {
for (int number : numbers) {
if (number <= 0 || number > 45) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 1 ~ 45인 정수여야 합니다.");
}
}
}

private void validateUniqueLottoNumber(List<Integer> numbers) {
long uniqueCount = numbers.stream().distinct().count();
if (uniqueCount != numbers.size()) {
throw new IllegalArgumentException("[ERROR] 로또 숫자는 중복되지 않은 수여야 합니다.");
}
}

public List<Integer> getNumbers() {
return numbers;
}
}
27 changes: 27 additions & 0 deletions src/main/java/lotto/domain/PurchaseAmount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package lotto.domain;

public class PurchaseAmount {
private final int money;

public PurchaseAmount(int money) {
validateMoney(money);
validateDivide1000(money);
this.money = money;
}

private void validateMoney(int money) {
if (money < 1000) {
throw new IllegalArgumentException("[ERROR] 구입 금액은 1000원이상의 값으로 입력되어야 합니다.");
}
}

private void validateDivide1000(int money) {
if (money % 1000 != 0) {
throw new IllegalArgumentException("[ERROR] 구입 금액은 1000원 단위로 입력되어야 합니다.");
}
}

public int getMoney() {
return money;
}
}
Loading