Skip to content
Merged
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
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,21 @@ src/main/java/lotto/

### 1. 도메인 객체 구현

#### 1.1 Lotto 객체 구현
#### 1.2 Rank 열거형 구현

**정상 케이스:**
- [ ] 일치 개수와 보너스 일치 여부로 등수를 판별한다
- [ ] 각 등수별 상금을 반환한다
- [ ] 5등: 3개 일치 / 5,000원
- [ ] 4등: 4개 일치 / 50,000원
- [ ] 3등: 5개 일치 / 1,500,000원
- [ ] 2등: 5개 + 보너스 일치 / 30,000,000원
- [ ] 1등: 6개 일치 / 2,000,000,000원
- [ ] 당첨되지 않으면 NONE 반환

**커밋:** `feat(domain): Rank 열거형 구현`

#### 1.2 Lotto 객체 구현

**정상 케이스:**
- [ ] 6개의 로또 번호를 저장한다
Expand All @@ -123,20 +137,6 @@ src/main/java/lotto/

**커밋:** `feat(domain): Lotto 객체 기본 기능 구현`

#### 1.2 Rank 열거형 구현

**정상 케이스:**
- [ ] 일치 개수와 보너스 일치 여부로 등수를 판별한다
- [ ] 각 등수별 상금을 반환한다
- [ ] 5등: 3개 일치 / 5,000원
- [ ] 4등: 4개 일치 / 50,000원
- [ ] 3등: 5개 일치 / 1,500,000원
- [ ] 2등: 5개 + 보너스 일치 / 30,000,000원
- [ ] 1등: 6개 일치 / 2,000,000,000원
- [ ] 당첨되지 않으면 NONE 반환

**커밋:** `feat(domain): Rank 열거형 구현`

#### 1.3 WinningLotto 객체 구현

**정상 케이스:**
Expand Down
68 changes: 68 additions & 0 deletions src/main/java/lotto/domain/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package lotto.domain;

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

public class Lotto {
private static final int LOTTO_NUMBER_COUNT = 6;
private static final int MIN_LOTTO_NUMBER = 1;
private static final int MAX_LOTTO_NUMBER = 45;

private final List<Integer> numbers;

public Lotto(List<Integer> numbers) {
validate(numbers);
this.numbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
}

private void validate(List<Integer> numbers) {
validateNotNull(numbers);
validateSize(numbers);
validateDuplicate(numbers);
validateRange(numbers);
}

private void validateNotNull(List<Integer> numbers) {
if (numbers == null) {
throw new IllegalArgumentException("[ERROR] 로또 번호를 입력해주세요.");
}
}

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

private void validateDuplicate(List<Integer> numbers) {
if (numbers.size() != new HashSet<>(numbers).size()) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 중복될 수 없습니다.");
}
}

private void validateRange(List<Integer> numbers) {
boolean isOutOfRange = numbers.stream()
.anyMatch(number -> number < MIN_LOTTO_NUMBER || number > MAX_LOTTO_NUMBER);

if (isOutOfRange) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}
}

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

public int countMatches(List<Integer> winningNumbers) {
return (int) numbers.stream()
.filter(winningNumbers::contains)
.count();
}

public boolean contains(int number) {
return numbers.contains(number);
}
}
56 changes: 56 additions & 0 deletions src/main/java/lotto/domain/WinningLotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package lotto.domain;

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

public class WinningLotto {
private static final int MIN_LOTTO_NUMBER = 1;
private static final int MAX_LOTTO_NUMBER = 45;
private final Lotto winningNumbers;
private final int bonusNumber;

public WinningLotto(Lotto winningNumbers, int bonusNumber) {
validate(winningNumbers, bonusNumber);
this.winningNumbers = winningNumbers;
this.bonusNumber = bonusNumber;
}

private void validate(Lotto winningNumbers, int bonusNumber) {
validateNotNull(winningNumbers);
validateBonusNumberRange(bonusNumber);
validateDuplicateWithWinningNumbers(winningNumbers, bonusNumber);
}

private void validateNotNull(Lotto winningNumbers) {
if (Objects.isNull(winningNumbers)) {
throw new IllegalArgumentException("[ERROR] 당첨 번호를 입력해주세요.");
}
}

private void validateBonusNumberRange(int bonusNumber) {
if (bonusNumber < MIN_LOTTO_NUMBER || bonusNumber > MAX_LOTTO_NUMBER) {
throw new IllegalArgumentException("[ERROR] 보너스 번호는 1부터 45 사이의 숫자여야 합니다.");
}
}

private void validateDuplicateWithWinningNumbers(Lotto winningNumbers, int bonusNumber) {
if (winningNumbers.contains(bonusNumber)) {
throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다.");
}
}

/**
* 구매한 로또와 당첨 번호를 비교하여 등수를 반환합니다.
*/
public Rank match(Lotto userLotto) {
// 1. 일치하는 번호 개수 계산
List<Integer> numbers = winningNumbers.getNumbers();
int matchCount = userLotto.countMatches(numbers);

// 2. 보너스 번호 일치 여부 확인
boolean matchBonus = userLotto.contains(bonusNumber);

// 3. Rank Enum을 통해 등수 판별
return Rank.valueOf(matchCount, matchBonus);
}
}
25 changes: 0 additions & 25 deletions src/test/java/lotto/LottoTest.java

This file was deleted.

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import java.util.List;

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

class LottoTest {

@DisplayName("정상1: 로또 번호 6개를 저장한다")
@Test
void test1() {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);

Lotto lotto = new Lotto(numbers); // 전체 경로 제거
assertThat(lotto.getNumbers()).hasSize(6);
assertThat(lotto.getNumbers()).containsExactly(1, 2, 3, 4, 5, 6);
}

@DisplayName("정상2: 로또 번호는 1~45 범위의 중복되지 않는 숫자이다")
@Test
void test2() {
List<Integer> numbers = List.of(1, 15, 23, 32, 41, 45);

Lotto lotto = new Lotto(numbers);
assertThat(lotto.getNumbers()).allMatch(num -> num >= 1 && num <= 45);
}

@DisplayName("정상3: 로또 번호를 오름차순으로 정렬하여 반환한다")
@Test
void test3() {
List<Integer> numbers = List.of(45, 1, 32, 15, 23, 8);

Lotto lotto = new Lotto(numbers);
assertThat(lotto.getNumbers()).containsExactly(1, 8, 15, 23, 32, 45);
}

@DisplayName("정상4: 주어진 번호 리스트와 일치하는 개수를 반환한다")
@Test
void test4() {
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 6));
List<Integer> winningNumbers = List.of(1, 2, 3, 7, 8, 9);

int matchCount = lotto.countMatches(winningNumbers);
assertThat(matchCount).isEqualTo(3);
}

@DisplayName("정상5: 일치하는 번호가 없을 때 0을 반환한다")
@Test
void test5() {
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 6));
List<Integer> winningNumbers = List.of(7, 8, 9, 10, 11, 12);

int matchCount = lotto.countMatches(winningNumbers);
assertThat(matchCount).isEqualTo(0);
}

@DisplayName("정상6: 모든 번호가 일치할 때 6을 반환한다")
@Test
void test6() {
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 6));
List<Integer> winningNumbers = List.of(1, 2, 3, 4, 5, 6);

int matchCount = lotto.countMatches(winningNumbers);
assertThat(matchCount).isEqualTo(6);
}

@DisplayName("정상7: 특정 번호 포함 여부를 확인한다 - 포함하는 경우")
@Test
void test7() {
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 6));

assertThat(lotto.contains(1)).isTrue();
assertThat(lotto.contains(3)).isTrue();
assertThat(lotto.contains(6)).isTrue();
}

@DisplayName("정상8: 특정 번호 포함 여부를 확인한다 - 포함하지 않는 경우")
@Test
void test8() {
Lotto lotto = new Lotto(List.of(1, 2, 3, 4, 5, 6));

assertThat(lotto.contains(7)).isFalse();
assertThat(lotto.contains(45)).isFalse();
}

@DisplayName("예외1: 로또 번호가 null이면 예외가 발생한다")
@Test
void test9() {
assertThatThrownBy(() -> new Lotto(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("[ERROR]");
}

@DisplayName("예외2: 로또 번호의 개수가 6개가 넘어가면 예외가 발생한다")
@Test
void test10() {
assertThatThrownBy(() -> new Lotto(List.of(1,2,3,4,5,6,7)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("[ERROR] 로또 번호는 6개여야 합니다.");
}

@DisplayName("예외3: 로또 번호의 개수가 6개 미만이면 예외가 발생한다")
@Test
void test11() {
assertThatThrownBy(() -> new Lotto(List.of(1,2,3,4,5)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("[ERROR] 로또 번호는 6개여야 합니다.");
}

@Tag("error")
@DisplayName("예외4: 로또 번호에 중복된 숫자가 있으면 예외가 발생한다")
@Test
void test12() {
assertThatThrownBy(() -> new Lotto(List.of(1,2,3,4,5,5)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("[ERROR] 로또 번호는 중복될 수 없습니다.");
}

@DisplayName("예외5: 로또 번호가 1보다 작으면 예외가 발생한다")
@Test
void test13() {
assertThatThrownBy(() -> new Lotto(List.of(0,1,2,3,4,5)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}

@DisplayName("예외6: 로또 번호가 45보다 크면 예외가 발생한다")
@Test
void test14() {
assertThatThrownBy(() -> new Lotto(List.of(1,2,3,4,5,46)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}

@DisplayName("예외7: 로또 번호가 음수이면 예외가 발생한다")
@Test
void test15() {
assertThatThrownBy(() -> new Lotto(List.of(-1,1,2,3,4,5)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}
}
Loading