Skip to content
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
129 changes: 129 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,130 @@
# java-lotto-precourse

> 로또 맞게 해주세요...ㅠ

<details>
<summary>과제 세부 내용</summary>

## 과제 내용
로또 게임 기능을 구현해야 한다. 로또 게임은 아래와 같은 규칙으로 진행된다.
```
- 로또 번호의 숫자 범위는 1~45까지이다.
- 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다.
- 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다.
- 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다.
- 1등: 6개 번호 일치 / 2,000,000,000원
- 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원
- 3등: 5개 번호 일치 / 1,500,000원
- 4등: 4개 번호 일치 / 50,000원
- 5등: 3개 번호 일치 / 5,000원
```
- 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다.
- 로또 1장의 가격은 1,000원이다.
- 당첨 번호와 보너스 번호를 입력받는다.
- 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다.
- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
- `Exception`이 아닌 `IllegalArgumentException`, `IllegalStateException` 등과 같은 명확한 유형을 처리한다.

### 입출력
- 입력
- 로또 구입 금액
- 당첨 번호 6개
- 보너스 번호
- 출력
- 발행한 로또 수량 및 번호
- 당첨 내역
- 수익률
- (예외 문구)

ex)

```
구입금액을 입력해 주세요.
8000

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]

당첨 번호를 입력해 주세요.
1,2,3,4,5,6

보너스 번호를 입력해 주세요.
7

당첨 통계
---
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%입니다.
```

</details>

## 코드 흐름
- 로또 구매 금액을 입력받는다.
- 로또를 번호를 생성하고 출력한다.
- 당첨 번호를 입력받는다.
- 결과를 계산한 후 출력한다.

```mermaid
sequenceDiagram
participant View
participant Controller
participant Model

Controller->>View: 금액 입력 요청
View->>Controller: 구입 금액 반환
Controller->>Model: 구입 금액 전달
Model-->Model: 로또 생성
Model->>Controller: 로또 번호 반환
Controller->>View: 로또 번호 출력
View->>Controller: -
Controller->>View: 당첨 번호 입력 요청
View->>Controller: 당첨 번호 반환
Controller->>Model: 당첨 번호 전달
Model-->Model: 당첨 여부 확인
Model->>Controller: 결과 반환
Controller->>View: 결과 출력
View->>Controller: -
Controller-->Controller: 프로그램 종료

```

## 구현 기능 목록
- 입출력
- [ ] 구입 금액 입력
- [ ] 당첨 번호 입력
- [ ] 보너스 번호 입력
- [ ] 발행한 로또 수량 및 번호
- [ ] 당첨 내역
- [ ] 수익률
- [ ] 예외
- 로또
- [ ] 로또 생성
- [ ] 당첨 확인
- [ ] 수익률 계산

## 처리할 예외
- 나누어 떨어지지 않는 금액 (1000 단위로 떨어지지 않을 때)
- `[ERROR] 1,000원 단위로 입력해 주세요.`
- 너무 큰 구입 금액
- `[ERROR] $입력한 금액 보다 작은 금액을 입력해 주세요.`
- 부적절한 구입 금액 (음수 입력 등 포함, 입력 예외)
- `[ERROR] 유효한 구입 금액을 입력해 주세요`
- 부적절한 로또의 범위 (1-45 밖의 숫자)
- `[ERROR] 1부터 45 사이의 값을 입력해 주세요.`
- 중복되는 번호 / 보너스 번호
- `[ERROR] 중복되지 않은 번호를 입력해주세요.`
- 부적절한 양식 혹은 갯수
- `[ERROR] 당첨 번호 6개를 정확히 입력해주세요. ex)1,2,3,4,5,6`
- `[ERROR] 보너스 번호 하나를 정확히 입력해주세요. ex)7`
12 changes: 12 additions & 0 deletions src/main/java/lotto/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package lotto;

import lotto.adapter.in.InputTerminal;
import lotto.adapter.in.RandomLibrary;
import lotto.adapter.out.OutputTerminal;
import lotto.application.service.LottoService;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
LottoService lottoService = new LottoService(
new InputTerminal(),
new RandomLibrary(),
new OutputTerminal()
);

lottoService.run();
}
}
20 changes: 0 additions & 20 deletions src/main/java/lotto/Lotto.java

This file was deleted.

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

import camp.nextstep.edu.missionutils.Console;
import lotto.application.port.inport.GetLottoPropertyUseCase;

public class InputTerminal implements GetLottoPropertyUseCase {
@Override
public String getString() {
return Console.readLine();
}

@Override
public int getInteger() {
return Integer.parseInt(Console.readLine());
}
}
12 changes: 12 additions & 0 deletions src/main/java/lotto/adapter/in/RandomLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package lotto.adapter.in;

import camp.nextstep.edu.missionutils.Randoms;
import java.util.List;
import lotto.application.port.inport.GetRandomUseCase;

public class RandomLibrary implements GetRandomUseCase {
@Override
public List<Integer> getRandomNumbers(int min, int max, int amount) {
return Randoms.pickUniqueNumbersInRange(min, max, amount);
}
}
42 changes: 42 additions & 0 deletions src/main/java/lotto/application/domain/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package lotto.application.domain;

import java.util.List;
import lotto.utils.Validator;

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

private final static int LOTTO_SIZE = 6;
private final static int LOWER_BOUND = 1;
private final static int UPPER_BOUND = 45;

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

private void validate(List<Integer> numbers) {
try {
Validator.fitSize(numbers, LOTTO_SIZE);
Validator.hasNoDuplication(numbers);
Validator.isInRange(numbers, LOWER_BOUND, UPPER_BOUND);
} catch (RuntimeException e) {
throw new IllegalArgumentException("[ERROR] 부적절한 로또 번호 입니다.", e);
}
}

// TODO: 추가 기능 구현
Copy link

Copilot AI May 27, 2025

Choose a reason for hiding this comment

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

Leftover TODO comment. Remove or implement the pending functionality to avoid dead code markers.

Suggested change
// TODO: 추가 기능 구현
public List<Integer> getSortedNumbers() {
return numbers.stream()
.sorted()
.toList();
}

Copilot uses AI. Check for mistakes.
public boolean isDuplicate(int numbers) {
return this.numbers.contains(numbers);
}

public int countMatch(Lotto other) {
return (int) numbers.stream()
.filter(other.numbers::contains)
.count();
}

public boolean isMatch(int bonus) {
return numbers.contains(bonus);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package lotto.application.domain.dto;

import lotto.application.domain.enums.LottoPrize;

public record WinningDataDto(LottoPrize lottoPrize, int count) {
}
Comment on lines +1 to +6
Copy link

Copilot AI May 27, 2025

Choose a reason for hiding this comment

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

[nitpick] This DTO isn't referenced anywhere. Either integrate it in LottoService or remove it to avoid dead code.

Suggested change
package lotto.application.domain.dto;
import lotto.application.domain.enums.LottoPrize;
public record WinningDataDto(LottoPrize lottoPrize, int count) {
}
// File removed as WinningDataDto is not referenced anywhere in the codebase.

Copilot uses AI. Check for mistakes.
51 changes: 51 additions & 0 deletions src/main/java/lotto/application/domain/enums/LottoPrize.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package lotto.application.domain.enums;

import java.util.List;

public enum LottoPrize {
NOTHING("꽝", 0),
FIFTH_PRICE("3개 일치", 5_000),
FOURTH_PRICE("4개 일치", 50_000),
THIRD_PRICE("5개 일치", 1_500_000),
SECOND_PRICE("5개 일치, 보너스 볼 일치", 30_000_000),
FIRST_PRICE("6개 일치", 2_000_000_000);

private final String condition;
private final int price;

LottoPrize(String condition, int price) {
this.condition = condition;
this.price = price;
}

public String getCondition() {
return condition;
}

public int getPrice() {
return price;
}

public static List<LottoPrize> getPrizeTypes() {
Copy link

Copilot AI May 27, 2025

Choose a reason for hiding this comment

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

[nitpick] This method isn't used in LottoService, which hardcodes the prize sequence. Consider using this list to drive iterations and reduce duplication.

Copilot uses AI. Check for mistakes.
return List.of(FIFTH_PRICE, FOURTH_PRICE, THIRD_PRICE, SECOND_PRICE, FIRST_PRICE);
}

public static LottoPrize getLottoPrize(int matchCount, boolean matchBonus) {
if (matchCount == 6) {
return FIRST_PRICE;
}
if (matchCount == 5 && matchBonus) {
return SECOND_PRICE;
}
if (matchCount == 5) {
return THIRD_PRICE;
}
if (matchCount == 4) {
return FOURTH_PRICE;
}
if (matchCount == 3) {
return FIFTH_PRICE;
}
return NOTHING;
}
}
21 changes: 21 additions & 0 deletions src/main/java/lotto/application/domain/enums/MessageConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package lotto.application.domain.enums;

public enum MessageConstants {
PURCHASE_GUIDE("구입금액을 입력해 주세요."),
PURCHASE_RESULT("%d개를 구매했습니다."),
WINNING_NUMBER_GUIDE("당첨 번호를 입력해 주세요."),
BONUS_NUMBER_GUIDE("보너스 번호를 입력해 주세요."),
WINNING_STATUS("당첨 통계\n---"),
RESULT_LINE("%s (%,d원) - %d개"),
RETURN_RATE("총 수익률은 %.1f%%입니다.")


;
private String message;
MessageConstants(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lotto.application.domain.exceptions;

public class ProgramTerminationException extends IllegalArgumentException {
public ProgramTerminationException() {
super("[ERROR] 예기치 않은 문제로 프로그램을 종료합니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package lotto.application.port.inport;

public interface GetLottoPropertyUseCase {
String getString();
int getInteger();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lotto.application.port.inport;

import java.util.List;

public interface GetRandomUseCase {
List<Integer> getRandomNumbers(int min, int max, int amount);
}
12 changes: 12 additions & 0 deletions src/main/java/lotto/application/port/outport/LottoPort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package lotto.application.port.outport;

import java.util.List;
import lotto.application.domain.enums.MessageConstants;

public interface LottoPort {
void sendMessage(MessageConstants message);
void sendMessage(MessageConstants message, Object... params);
void sendMessage(String message);
void clear();
void printLottoNumbers(List<Integer> numbers);
}
Loading