diff --git a/README.md b/README.md new file mode 100644 index 00000000..ce9bcbeb --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +## Lotto + +### step1 + +- 크기가 6인 int List : numbers + - [x] 1 ~ 45 사이의 숫자 + - [x] 중복되지 않아야 함 + - [x] 크기가 6이어야 함 + +- [x] 로또 금액을 입력 받아야 함 +- [x] 1000원 단위로 입력 +- [x] 최소 1000원 이상 +- [x] 로또 번호는 랜덤으로 설정 +- [x] 숫자들끼리 중복되지 않도록 +- [x] 1 ~ 45 사이 +- [x] 출력 시 숫자들이 오름차순으로 정렬 + +### step2 + +<프로그래밍 요구사항> + +- [ ] 원시값 포장 +- [ ] 문자열 포장 +- [ ] 일급 컬렉션 사용 + +<구현 해야하는 기능> + +- [x] 당첨 번호 입력 + - [x] 문자열의 형태로 입력 +- [ ] 당첨 통계 출력 + - [ ] 당첨 금액 & 개수 별 출력 + - [ ] 총 수익률 계산 \ No newline at end of file diff --git a/src/main/java/InputView.java b/src/main/java/InputView.java new file mode 100644 index 00000000..20ff2fcb --- /dev/null +++ b/src/main/java/InputView.java @@ -0,0 +1,26 @@ +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +public class InputView { + + public static final Scanner SCANNER = new Scanner(System.in); + + public int inputLottoPrice() { + System.out.println("구입금액을 입력해 주세요."); + return SCANNER.nextInt(); + } + + public Lotto inputLottoNumbers() { + System.out.println("지난 주 당첨 번호를 입력해 주세요."); + return stringToLotto(SCANNER.nextLine()); + } + + public Lotto stringToLotto(String string) { + List numbers = Arrays.stream(string.split(",")).map(Integer::parseInt).toList(); + List lottoNumbers = numbers.stream() + .map(LottoNumber::new) + .toList(); + return new Lotto(lottoNumbers); + } +} diff --git a/src/main/java/Lotto.java b/src/main/java/Lotto.java new file mode 100644 index 00000000..fac83aa2 --- /dev/null +++ b/src/main/java/Lotto.java @@ -0,0 +1,41 @@ +import java.util.Collections; +import java.util.List; + +public class Lotto { + + public static final int LOTTO_SIZE = 6; + + private final List numbers; + + public Lotto(List numbers) { + validate(numbers); + this.numbers = sortNumbers(numbers); + } + + private void validate(List numbers) { + validateSize(numbers); + validateDuplication(numbers); + } + + private void validateSize(List numbers) { + if (numbers.size() != LOTTO_SIZE) { + throw new IllegalArgumentException("로또는 6개의 수로 이루어져야 한다. "); + } + } + + private void validateDuplication(List numbers) { + long duplicatedSize = numbers.stream().distinct().count(); + if (numbers.size() != duplicatedSize) { + throw new IllegalArgumentException("로또 숫자는 중복이 없어야 한다. "); + } + } + + private List sortNumbers(List numbers) { + Collections.sort(numbers); + return numbers; + } + + public List numbers() { + return List.copyOf(numbers); + } +} diff --git a/src/main/java/LottoGame.java b/src/main/java/LottoGame.java new file mode 100644 index 00000000..4141d83a --- /dev/null +++ b/src/main/java/LottoGame.java @@ -0,0 +1,32 @@ +import java.util.ArrayList; +import java.util.List; + +public class LottoGame { + + private final InputView inputView; + private final OutputView outputView; + + public LottoGame(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + int inputPrice = inputView.inputLottoPrice(); + LottoPrice price = new LottoPrice(inputPrice); + List lottos = getLottos(price); + outputView.printLotto(lottos); + } + + private List getLottos(LottoPrice price) { + List lottos = new ArrayList<>(); + + RandomLottoGenerator randomLottoGenerator = new RandomLottoGenerator(); + + for (int i = 0; i < price.getPrice() / 1000; i++) { + lottos.add(new Lotto(randomLottoGenerator.generateLotto().numbers())); + } + + return lottos; + } +} diff --git a/src/main/java/LottoNumber.java b/src/main/java/LottoNumber.java new file mode 100644 index 00000000..77a9366a --- /dev/null +++ b/src/main/java/LottoNumber.java @@ -0,0 +1,23 @@ +public class LottoNumber implements Comparable { + + public static final int MIN_VALUE = 0; + public static final int MAX_VALUE = 45; + + private final int number; + + public LottoNumber(int number) { + validateRange(number); + this.number = number; + } + + private void validateRange(int number) { + if (number < MIN_VALUE || number > MAX_VALUE) { + throw new IllegalArgumentException(); + } + } + + @Override + public int compareTo(LottoNumber o) { + return Integer.compare(this.number, o.number); + } +} diff --git a/src/main/java/LottoPrice.java b/src/main/java/LottoPrice.java new file mode 100644 index 00000000..5cb4dc42 --- /dev/null +++ b/src/main/java/LottoPrice.java @@ -0,0 +1,34 @@ +public class LottoPrice { + + public static final int MIN_PRICE = 0; + public static final int PRICE_UNIT = 1_000; + + private final int price; + + public LottoPrice(int price) { + validate(price); + this.price = price; + } + + private void validate(int price) { + validateRange(price); + validateUnit(price); + } + + + private void validateRange(int price) { + if (price < MIN_PRICE) { + throw new IllegalArgumentException("로또 금액은 0이상 이어야 한다."); + } + } + + private void validateUnit(int price) { + if (price % PRICE_UNIT != 0) { + throw new IllegalArgumentException("로또 금액은 1000원 단위여야 한다."); + } + } + + public int getPrice() { + return price; + } +} diff --git a/src/main/java/OutputView.java b/src/main/java/OutputView.java new file mode 100644 index 00000000..5bd6a6f5 --- /dev/null +++ b/src/main/java/OutputView.java @@ -0,0 +1,11 @@ +import java.util.List; + +public class OutputView { + + public void printLotto(List lottos) { + System.out.println(); + System.out.println(lottos.size() + "개를 구매했습니다."); + lottos.stream().map(Lotto::numbers).forEach(System.out::println); + } + +} diff --git a/src/main/java/RandomLottoGenerator.java b/src/main/java/RandomLottoGenerator.java new file mode 100644 index 00000000..cd18fcbf --- /dev/null +++ b/src/main/java/RandomLottoGenerator.java @@ -0,0 +1,23 @@ +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; + +public class RandomLottoGenerator { + + + public static final Random RANDOM = new Random(); + + public Lotto generateLotto() { + Set numbers = new HashSet<>(); + while (numbers.size() < 6) { + int randomNumber = RANDOM.nextInt(1, 45); + numbers.add(randomNumber); + } + + List lottoNumbers = numbers.stream() + .map(LottoNumber::new) + .toList(); + return new Lotto(lottoNumbers); + } +} diff --git a/src/test/java/LottoPriceTest.java b/src/test/java/LottoPriceTest.java new file mode 100644 index 00000000..660b3c64 --- /dev/null +++ b/src/test/java/LottoPriceTest.java @@ -0,0 +1,19 @@ +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class LottoPriceTest { + @Test + void 로또_금액은_0이상_이어야_한다() { + int price = -1000; + + assertThatThrownBy(() -> new LottoPrice(price)).isInstanceOf(IllegalArgumentException.class).hasMessage("로또 금액은 0이상 이어야 한다."); + } + + @Test + void 로또_금액은_1000원_단위여야_한다() { + int price = 9999; + + assertThatThrownBy(() -> new LottoPrice(price)).isInstanceOf(IllegalArgumentException.class).hasMessage("로또 금액은 1000원 단위여야 한다."); + } +} diff --git a/src/test/java/LottoTest.java b/src/test/java/LottoTest.java new file mode 100644 index 00000000..470d63b6 --- /dev/null +++ b/src/test/java/LottoTest.java @@ -0,0 +1,36 @@ +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class LottoTest { + @Test + void 로또는_6개의_수로_이루어져야_한다() { + var numbers = List.of(new LottoNumber(1), new LottoNumber(2), new LottoNumber(3)); + + assertThatThrownBy(() -> new Lotto(numbers)).isInstanceOf(IllegalArgumentException.class).hasMessage("로또는 6개의 수로 이루어져야 한다. "); + } + + // fail + @Test + void 로또_숫자는_중복이_없어야_한다() { + var numbers = List.of(new LottoNumber(1), new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), new LottoNumber(4), new LottoNumber(5)); + + assertThatThrownBy(() -> new Lotto(numbers)).isInstanceOf(IllegalArgumentException.class).hasMessage("로또 숫자는 중복이 없어야 한다. "); + } + + // fail + @Test + void 로또_숫자는_오름차순_정렬되어있다() { + var unsortedNumbers = List.of(new LottoNumber(6), new LottoNumber(5), new LottoNumber(4), new LottoNumber(3), new LottoNumber(2), new LottoNumber(1)); + // var sortedNumbers = List.of(new LottoNumber(1), new LottoNumber(2), new LottoNumber(3), new LottoNumber(4), new LottoNumber(5), new LottoNumber(6)); + + var unsortedLotto = new Lotto(unsortedNumbers); + // var sortedLotto = new Lotto(sortedNumbers); + + //assertThat(unsortedLotto.numbers().equals(sortedLotto.numbers())); + assertThat(unsortedLotto.numbers()).isSorted(); + } +} diff --git a/src/test/java/RandomLottoGeneratorTest.java b/src/test/java/RandomLottoGeneratorTest.java new file mode 100644 index 00000000..e58e1288 --- /dev/null +++ b/src/test/java/RandomLottoGeneratorTest.java @@ -0,0 +1,15 @@ +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.RepeatedTest; + +import java.util.Random; + +class RandomLottoGeneratorTest { + + @RepeatedTest(1000) + void test() { + int result = new Random().nextInt(1, 45); + + Assertions.assertThat(result).isBetween(1, 45); + } + +} \ No newline at end of file