From 5c939e768a78e81559cb22cc7745f083d1e44d52 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Tue, 9 Apr 2019 11:17:22 +0900 Subject: [PATCH 01/13] Fix Rank.valueOf method --- src/main/java/domain/Rank.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/Rank.java b/src/main/java/domain/Rank.java index 00549b95..a9153f25 100644 --- a/src/main/java/domain/Rank.java +++ b/src/main/java/domain/Rank.java @@ -39,7 +39,7 @@ public static Rank valueOf(int countOfMatch, boolean matchBonus) { } for (Rank rank : values()) { - if (rank.matchCount(countOfMatch)) { + if (rank.matchCount(countOfMatch) && rank != SECOND) { return rank; } } From 5b6dd2e9794ac75e6c8c1b9584051a37893d33bd Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Wed, 10 Apr 2019 11:19:19 +0900 Subject: [PATCH 02/13] Add README.md and LEARNING.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LEARNING.md 는 무엇을 배웠는지를 스스로 정리할 필요가 있을 듯 해서 넣었음 --- LEARNING.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 10 ++++++ 2 files changed, 97 insertions(+) create mode 100644 LEARNING.md diff --git a/LEARNING.md b/LEARNING.md new file mode 100644 index 00000000..7dc9d471 --- /dev/null +++ b/LEARNING.md @@ -0,0 +1,87 @@ +## 어떤 것을 배우는 데 집중했는가? +[객체 간의 관계]메시지를 가지고 설계해보기 (각자가 책임을 가지고 있다고 가정하고 해당 객체가 필요한 요청을 메시지로 표현) +- 이번주 목표가 관계를 맺는 것인데... 어떻게 하면 좋은 관계를 맺을 수 있을까 고민했음 +- 그러다가 '객체지향의 사실과 오해'란 책이 생각났고 (ch5) 책에서 알아가게 된 것을 적용해보려고 함 + + + +## 배우는 방법을 배우는 것...ㅋㅋㅋㅋ + +나는 이번 과제를 진행하면서 무엇을 얻으려 했고 무엇을 얻는게 좋다고 생각했을까? + +원하는 것을 너무 잘 알려주셨다. + +먼저 +- 1주차 목표는 함수를 분리하는 연습 +- 2주차 목표는 += 클래스 분리하는 연습 +- 3주차 목표는 += 여러 개의 클래스를 분리한 후 서로 관계를 맺어 하나의 프로그램을 완성 + +이런 것들을 통해서 +- 자바 언어의 기본적인 문법을 익히고 +- 프로그래밍 구현에 대한 다른 접근 방식을 경험 +할 것을 기대하신 것 같다 + +극단적인 연습?(요구사항을 통한) 을 통해서 어떤 깨달음을 얻어갈까? + +나는 어떻게 학습 했을까? +얼마나 성장했을까? + + +### 내 생각 +알려주려는 개념의 이름이 아니라 요구사항등을 통해서 함수, 클래스 분리와 객체지향의 개념을 자연스럽게 경험할 수 있는 프로젝트여서 좋았음 + + +언어 + 개념 + + + +어떻게 성장하는 것이 도움이 될까?? + +주도적으로 학습할 수 있는지?? -> 그렇다면 주도적이라는게 무엇일까?? (열정 + 끈기 + 방향? 이것들을 혼자 잡아가는 건가?) + + + + + +### 내가 생각하기에 내가 채워가야하는 부분?? +설계하는 연습 (질 + 양) // 설계하고 그것을 구현하고 내가 했던 것을 반복하면서 더 나아지는 연습을 해야함, 지루하다 생각하냐???! + +좋은 개발자가 되기 위해서는 어떻게 진행하는게 좋을까?? + +내가 생각하는 좋은 개발자?? +코드를 읽기도 쉽고 (실력) +함께 개발하기 좋고 (의사소통, 성실성) + + +이 과정을 하면서 단련하기 좋은 것 +- 반복적인 연습 (버전관리 + 테스트) +- 새로운 언어를 어떻게 공부하는게 좋을지? +- 새로운 환경에 어떻게 적응하는게 좋을지? +- 특정 개념? 을 스스로 공부해나가는 방식 (내가 무엇을 배울 때 어떻게 접근하는지를 관찰하는 것도 좋은 습관인 것 같다) +- 공부한 개념을 스스로 정리? (남에게 말하려면 용어나.. 그것을 어떻게 설명하면 좋을지가 틀이 잡혀야함) + ++ +나는 이 과정을 하면서 정말로 테스트나 객체지향 같은 개념들이 유용한지 그리고 도움이 되는지를 확인 할 수 있을 것 같다 +그리고 어떻게 짜면 좋을지에 대한 고민을 조금은 해가는 것 같다 (이 고민이 거기서 끝나지 않고 그 고민을 해결하기 위한 연구로 갔으면) + + +이렇게 배워가는 과정이 있고 내가 계속할 수 있음을 느끼고 +조금씩 늘어가는 모습을 스스로 확인 할 수 있을 때 +개발을 계속 할 것이란 확신을 스스로, 그리고 남이 봐도 있게 되지 않을까? + + + + +### 히스토리 (배운 과정) +1. 일단 공부 전에 스스로 설계 +2. 공부 + - 객체지향 (객체지향의 사실과 오해) + - 입력 어떻게 확실히 하는지 (자바에서 받은 입력 처리) + - 좋은? exception 처리 + - 테스트? +3. 구현 + + +#### 참조 +- http://woowabros.github.io/tools/2017/07/10/java-enum-uses.html // java enum +- https://examples.javacodegeeks.com/core-java/mockito/mockito-verify-example/ // mockito verify \ No newline at end of file diff --git a/README.md b/README.md index e69de29b..685446da 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,10 @@ +## 기능목록 +-[ ] 게임을 실행 (전체적인 실행 흐름) +-[ ] 유저에게 돈 받아내기 +-[ ] 로또 만들기 +-[ ] 당첨로또 알아내기 +-[ ] 유저의 로또 결과 분석하기 + + + +만들면서 돌아가는 테스트를 만드는 것도 재미있을 듯 \ No newline at end of file From 7799c8d20fe108f3aec78be64320ce3041c774a4 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Wed, 10 Apr 2019 12:11:42 +0900 Subject: [PATCH 03/13] Add LottoGame and needed interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LottoGame 은 게임의 내용(흐름)을 나타냄 --- README.md | 2 +- src/main/java/FakeLottoAnalyzer.java | 12 ++++++++ src/main/java/FakeLottoFactory.java | 13 +++++++++ src/main/java/FakeLottoReader.java | 14 +++++++++ src/main/java/FakeMoneyReader.java | 11 +++++++ src/main/java/Main.java | 15 ++++++++++ src/main/java/domain/LottoAnalyzer.java | 7 +++++ src/main/java/domain/LottoFactory.java | 7 +++++ src/main/java/domain/LottoGame.java | 38 +++++++++++++++++++++++++ src/main/java/domain/LottoReader.java | 5 ++++ src/main/java/domain/MoneyReader.java | 5 ++++ 11 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/main/java/FakeLottoAnalyzer.java create mode 100644 src/main/java/FakeLottoFactory.java create mode 100644 src/main/java/FakeLottoReader.java create mode 100644 src/main/java/FakeMoneyReader.java create mode 100644 src/main/java/Main.java create mode 100644 src/main/java/domain/LottoAnalyzer.java create mode 100644 src/main/java/domain/LottoFactory.java create mode 100644 src/main/java/domain/LottoGame.java create mode 100644 src/main/java/domain/LottoReader.java create mode 100644 src/main/java/domain/MoneyReader.java diff --git a/README.md b/README.md index 685446da..6cdb870a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## 기능목록 --[ ] 게임을 실행 (전체적인 실행 흐름) +-[x] 게임을 실행 (전체적인 실행 흐름) -[ ] 유저에게 돈 받아내기 -[ ] 로또 만들기 -[ ] 당첨로또 알아내기 diff --git a/src/main/java/FakeLottoAnalyzer.java b/src/main/java/FakeLottoAnalyzer.java new file mode 100644 index 00000000..587591f4 --- /dev/null +++ b/src/main/java/FakeLottoAnalyzer.java @@ -0,0 +1,12 @@ +import domain.Lotto; +import domain.LottoAnalyzer; +import domain.WinningLotto; + +import java.util.List; + +public class FakeLottoAnalyzer implements LottoAnalyzer { + @Override + public void analyze(WinningLotto winningLotto, List lottos) { + System.out.println("analyze called"); + } +} diff --git a/src/main/java/FakeLottoFactory.java b/src/main/java/FakeLottoFactory.java new file mode 100644 index 00000000..4370e9b9 --- /dev/null +++ b/src/main/java/FakeLottoFactory.java @@ -0,0 +1,13 @@ +import domain.Lotto; +import domain.LottoFactory; + +import java.util.ArrayList; + +public class FakeLottoFactory implements LottoFactory { + @Override + public Lotto newLotto() { + System.out.println("newLotto called"); + + return new Lotto(new ArrayList<>()); + } +} diff --git a/src/main/java/FakeLottoReader.java b/src/main/java/FakeLottoReader.java new file mode 100644 index 00000000..76444b8d --- /dev/null +++ b/src/main/java/FakeLottoReader.java @@ -0,0 +1,14 @@ +import domain.Lotto; +import domain.LottoReader; +import domain.WinningLotto; + +import java.util.ArrayList; + +public class FakeLottoReader implements LottoReader { + @Override + public WinningLotto readWinningLotto() { + System.out.println("readWinningLotto called"); + + return new WinningLotto(new Lotto(new ArrayList()), 1); + } +} diff --git a/src/main/java/FakeMoneyReader.java b/src/main/java/FakeMoneyReader.java new file mode 100644 index 00000000..aef9bb9f --- /dev/null +++ b/src/main/java/FakeMoneyReader.java @@ -0,0 +1,11 @@ +import domain.MoneyReader; + +import java.util.Scanner; + +public class FakeMoneyReader implements MoneyReader { + @Override + public int readMoney() { + System.out.println("readMoney called"); + return 10000; + } +} diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 00000000..53d1e0cd --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,15 @@ +import domain.LottoGame; + +public class Main { + + + public static void main(String[] args) { + var game = new LottoGame( + new FakeMoneyReader(), + new FakeLottoFactory(), + new FakeLottoReader(), + new FakeLottoAnalyzer() + ); + game.run(); + } +} diff --git a/src/main/java/domain/LottoAnalyzer.java b/src/main/java/domain/LottoAnalyzer.java new file mode 100644 index 00000000..5e0a0e00 --- /dev/null +++ b/src/main/java/domain/LottoAnalyzer.java @@ -0,0 +1,7 @@ +package domain; + +import java.util.List; + +public interface LottoAnalyzer { + void analyze(WinningLotto winningLotto, List lottos); +} diff --git a/src/main/java/domain/LottoFactory.java b/src/main/java/domain/LottoFactory.java new file mode 100644 index 00000000..e6f775f5 --- /dev/null +++ b/src/main/java/domain/LottoFactory.java @@ -0,0 +1,7 @@ +package domain; + +import java.util.List; + +public interface LottoFactory { + Lotto newLotto(); +} diff --git a/src/main/java/domain/LottoGame.java b/src/main/java/domain/LottoGame.java new file mode 100644 index 00000000..567cf117 --- /dev/null +++ b/src/main/java/domain/LottoGame.java @@ -0,0 +1,38 @@ +package domain; + +import java.util.ArrayList; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class LottoGame { + public static final int LOTTO_PRICE = 1000; + + + private MoneyReader moneyReader; + private LottoFactory lottoFactory; + private LottoReader lottoReader; + private LottoAnalyzer lottoAnalyzer; + + public LottoGame(MoneyReader moneyReader, + LottoFactory lottoFactory, + LottoReader lottoReader, + LottoAnalyzer lottoAnalyzer) { + this.moneyReader = moneyReader; + this.lottoFactory = lottoFactory; + this.lottoReader = lottoReader; + this.lottoAnalyzer = lottoAnalyzer; + } + + public void run() { + var money = moneyReader.readMoney(); + var numLottos = money / LOTTO_PRICE; + + var lottos = Stream.generate(() -> lottoFactory.newLotto()) + .limit(numLottos) + .collect(Collectors.toCollection(ArrayList::new)); + + var winningLotto = lottoReader.readWinningLotto(); + + lottoAnalyzer.analyze(winningLotto, lottos); + } +} diff --git a/src/main/java/domain/LottoReader.java b/src/main/java/domain/LottoReader.java new file mode 100644 index 00000000..6644ea36 --- /dev/null +++ b/src/main/java/domain/LottoReader.java @@ -0,0 +1,5 @@ +package domain; + +public interface LottoReader { + WinningLotto readWinningLotto(); +} diff --git a/src/main/java/domain/MoneyReader.java b/src/main/java/domain/MoneyReader.java new file mode 100644 index 00000000..27ad477f --- /dev/null +++ b/src/main/java/domain/MoneyReader.java @@ -0,0 +1,5 @@ +package domain; + +public interface MoneyReader { + int readMoney(); +} From 6ef95fd495c43f680a0714e852ed6dd398dd4847 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Wed, 10 Apr 2019 17:00:14 +0900 Subject: [PATCH 04/13] Add LottoFactory and NumberPicker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LottoFactory - 로또를 생성(1~45까지 숫자 중에서 6개를 뽑아서 생성) NumberPicker - 입력받은 숫자들 중에서 입력받은 갯수만큼 뽑아서 리턴 - 정말로 뽑기하듯이 + 같은 위치의 수를 최대 1번만 뽑음 --- README.md | 5 +- src/main/java/FakeLottoFactory.java | 13 -- src/main/java/Main.java | 4 +- src/main/java/MyLottoFactory.java | 33 ++++++ src/main/java/NumberPickerByShuffling.java | 40 +++++++ src/main/java/domain/LottoFactory.java | 2 - src/main/java/domain/NumberPicker.java | 5 + src/test/java/MyLottoFactoryTest.java | 26 ++++ .../java/NumberPickerByShufflingTest.java | 111 ++++++++++++++++++ 9 files changed, 222 insertions(+), 17 deletions(-) delete mode 100644 src/main/java/FakeLottoFactory.java create mode 100644 src/main/java/MyLottoFactory.java create mode 100644 src/main/java/NumberPickerByShuffling.java create mode 100644 src/main/java/domain/NumberPicker.java create mode 100644 src/test/java/MyLottoFactoryTest.java create mode 100644 src/test/java/NumberPickerByShufflingTest.java diff --git a/README.md b/README.md index 6cdb870a..285b9ced 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ ## 기능목록 -[x] 게임을 실행 (전체적인 실행 흐름) -[ ] 유저에게 돈 받아내기 --[ ] 로또 만들기 +-[x] 로또 만들기 + -[x] 셔플로 만들기 + - 올바른 로또인지 확인하는 부분 (1~45까지의 수, 중복 없음, 총 6개) + - 만든 함수에서 예외처리 (ex.. 뽑을 집합보다 뽑을 갯수가 많은 경우) -[ ] 당첨로또 알아내기 -[ ] 유저의 로또 결과 분석하기 diff --git a/src/main/java/FakeLottoFactory.java b/src/main/java/FakeLottoFactory.java deleted file mode 100644 index 4370e9b9..00000000 --- a/src/main/java/FakeLottoFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -import domain.Lotto; -import domain.LottoFactory; - -import java.util.ArrayList; - -public class FakeLottoFactory implements LottoFactory { - @Override - public Lotto newLotto() { - System.out.println("newLotto called"); - - return new Lotto(new ArrayList<>()); - } -} diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 53d1e0cd..89a9531d 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,12 +1,14 @@ import domain.LottoGame; +import java.util.Random; + public class Main { public static void main(String[] args) { var game = new LottoGame( new FakeMoneyReader(), - new FakeLottoFactory(), + new MyLottoFactory(new NumberPickerByShuffling(new Random())), new FakeLottoReader(), new FakeLottoAnalyzer() ); diff --git a/src/main/java/MyLottoFactory.java b/src/main/java/MyLottoFactory.java new file mode 100644 index 00000000..46835ac3 --- /dev/null +++ b/src/main/java/MyLottoFactory.java @@ -0,0 +1,33 @@ +import domain.LottoFactory; + +import domain.Lotto; +import domain.NumberPicker; + +import java.util.Arrays; +import java.util.stream.IntStream; + +public class MyLottoFactory implements LottoFactory { + // [LOTTO_NUM_FROM, LOTTO_NUM_TO] + public static final int LOTTO_NUM_FROM = 1; + public static final int LOTTO_NUM_TO = 45; + public static final int LOTTO_LENGTH = 6; + + private NumberPicker picker; + + public MyLottoFactory(NumberPicker picker) { + this.picker = picker; + } + + @Override + public Lotto newLotto() { + var nums = IntStream.range(LOTTO_NUM_FROM, LOTTO_NUM_TO + 1) + .boxed() + .toArray(Integer[]::new); + + var pickedNums = picker.PickNums(nums, LOTTO_LENGTH); + + return new Lotto(Arrays.asList(pickedNums)); + } +} + + diff --git a/src/main/java/NumberPickerByShuffling.java b/src/main/java/NumberPickerByShuffling.java new file mode 100644 index 00000000..fae3dd23 --- /dev/null +++ b/src/main/java/NumberPickerByShuffling.java @@ -0,0 +1,40 @@ +import domain.NumberPicker; + +import java.util.Random; +import java.util.stream.IntStream; + +public class NumberPickerByShuffling implements NumberPicker { + + private Random rand; + + public NumberPickerByShuffling(Random rand) { + this.rand = rand; + } + + @Override + public Integer[] PickNums(Integer[] nums, int numPicked) { + var shuffledIdxs = initShuffledIdxs(nums.length); + + return IntStream.range(0, numPicked) + .map((i) -> nums[shuffledIdxs[i]]) + .boxed() + .toArray(Integer[]::new); + } + + private int[] initShuffledIdxs(int length) { + var idxs = IntStream.range(0, length).toArray(); + + IntStream.range(0, length).forEach((from) -> { + int to = rand.nextInt(length); + _swap(idxs, from, to); + }); + + return idxs; + } + + private void _swap(int[] nums, int from, int to) { + int tmp = nums[from]; + nums[from] = nums[to]; + nums[to] = tmp; + } +} diff --git a/src/main/java/domain/LottoFactory.java b/src/main/java/domain/LottoFactory.java index e6f775f5..8f1d8973 100644 --- a/src/main/java/domain/LottoFactory.java +++ b/src/main/java/domain/LottoFactory.java @@ -1,7 +1,5 @@ package domain; -import java.util.List; - public interface LottoFactory { Lotto newLotto(); } diff --git a/src/main/java/domain/NumberPicker.java b/src/main/java/domain/NumberPicker.java new file mode 100644 index 00000000..a6678f2e --- /dev/null +++ b/src/main/java/domain/NumberPicker.java @@ -0,0 +1,5 @@ +package domain; + +public interface NumberPicker { + Integer[] PickNums(Integer[] nums, int lottoLength); +} diff --git a/src/test/java/MyLottoFactoryTest.java b/src/test/java/MyLottoFactoryTest.java new file mode 100644 index 00000000..ab18335c --- /dev/null +++ b/src/test/java/MyLottoFactoryTest.java @@ -0,0 +1,26 @@ +import domain.NumberPicker; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public class MyLottoFactoryTest { + + private MyLottoFactory factory; + private NumberPicker mockedPicker; + + @org.junit.Test + public void newLottoPickValidLength() { + mockedPicker = mock(NumberPickerByShuffling.class); + when(mockedPicker.PickNums(any(Integer[].class), eq(factory.LOTTO_LENGTH))) + .thenReturn(new Integer[factory.LOTTO_LENGTH]); + + factory = new MyLottoFactory(mockedPicker); + + // Act + factory.newLotto(); + + // Assert + verify(mockedPicker).PickNums(any(Integer[].class), eq(factory.LOTTO_LENGTH)); + } +} \ No newline at end of file diff --git a/src/test/java/NumberPickerByShufflingTest.java b/src/test/java/NumberPickerByShufflingTest.java new file mode 100644 index 00000000..eb291a82 --- /dev/null +++ b/src/test/java/NumberPickerByShufflingTest.java @@ -0,0 +1,111 @@ +import domain.NumberPicker; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Random; +import java.util.stream.IntStream; + +import static org.junit.Assert.*; + +public class NumberPickerByShufflingTest { + + private static final int NUM_PICKED = 6; + + private NumberPickerByShuffling picker; + + @Before + public void setUp() throws Exception { + picker = new NumberPickerByShuffling(new Random()); + } + + // 원하는 갯수만큼 뽑았는지 + // 중복 없이 뽑았는지 (입력 받은 갯수를 초과해서 뽑지 않도록) + + @Test + public void pickNumsWithVariousNumPicked() { + var nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + var pickedNums = new int[]{0, 1, 3, 5, 7, 10}; + + for (var numPicked : pickedNums) { + // Act + var got = picker.PickNums(nums, numPicked); + + // Assert + Assert.assertEquals(numPicked, got.length); + } + } + + @Test + public void pickNumsNonDuplicatedNums() { + var nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + int n = 100; + + IntStream.range(0, n).forEach((i) -> { + // Act + var picked = picker.PickNums(nums, NUM_PICKED); + var counter = initCounter(picked); + + Assert.assertEquals(NUM_PICKED, counter.size()); + }); + } + + @Test + public void pickNumsNonDuplicatedNumsPickValidNum() { + var nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + var counter = initCounter(nums); + + int n = 100; + + IntStream.range(0, n).forEach((i) -> { + // Act + var picked = picker.PickNums(nums, NUM_PICKED); + var pickedCounter = initCounter(picked); + + // Assert + for(var pickedNum : pickedCounter.keySet()) { + Assert.assertTrue(counter.containsKey(pickedNum)); + } + }); + } + + + @Test + public void pickNumsDuplicatedNums() { + var nums = new Integer[]{1, 2, 2, 2, 2, 4, 4, 5, 9, 9, 9, 9, 9, 9, 10, 81, 100}; + var counter = initCounter(nums); + + int n = 100; + + IntStream.range(0, n).forEach((i) -> { + // Act + var picked = picker.PickNums(nums, NUM_PICKED); + System.out.println(Arrays.toString(picked)); + var pickedCounter = initCounter(picked); + + // Assert + for(var pickedNum : pickedCounter.keySet()) { + Assert.assertTrue(counter.containsKey(pickedNum)); + Assert.assertTrue(pickedCounter.get(pickedNum) <= counter.get(pickedNum)); + } + }); + } + + private HashMap initCounter(Integer[] nums) { + var counter = new HashMap(); + for (var num : nums) { + if (counter.containsKey(num)) { + counter.put(num, counter.get(num) + 1); + continue; + } + counter.put(num, 1); + } + + return counter; + } +} \ No newline at end of file From 499cba494fb04c7eed2bb12220a598614a7774b7 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Wed, 10 Apr 2019 17:17:22 +0900 Subject: [PATCH 05/13] Add MoneyReaderFromUser read from user input using scanner this need input check --- README.md | 3 ++- src/main/java/Main.java | 2 +- src/main/java/MoneyReaderFromUser.java | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 src/main/java/MoneyReaderFromUser.java diff --git a/README.md b/README.md index 285b9ced..b8a83bad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ## 기능목록 -[x] 게임을 실행 (전체적인 실행 흐름) --[ ] 유저에게 돈 받아내기 +-[x] 유저에게 돈 받아내기 + -[ ] 올바른 입력인지 확인 -[x] 로또 만들기 -[x] 셔플로 만들기 - 올바른 로또인지 확인하는 부분 (1~45까지의 수, 중복 없음, 총 6개) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 89a9531d..3ee40f68 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -7,7 +7,7 @@ public class Main { public static void main(String[] args) { var game = new LottoGame( - new FakeMoneyReader(), + new MoneyReaderFromUser(), new MyLottoFactory(new NumberPickerByShuffling(new Random())), new FakeLottoReader(), new FakeLottoAnalyzer() diff --git a/src/main/java/MoneyReaderFromUser.java b/src/main/java/MoneyReaderFromUser.java new file mode 100644 index 00000000..f8c89b0b --- /dev/null +++ b/src/main/java/MoneyReaderFromUser.java @@ -0,0 +1,19 @@ +import domain.MoneyReader; + +import java.util.Scanner; + +public class MoneyReaderFromUser implements MoneyReader { + + private Scanner sc; + + public MoneyReaderFromUser() { + this.sc = new Scanner(System.in); + } + @Override + public int readMoney() { + System.out.println("구입금액을 입력해 주세요."); + + // [TODO] check input is valid + return sc.nextInt(); + } +} From e0efcc7d762291bd737fab399e49f768b78ebf0d Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Wed, 10 Apr 2019 17:45:14 +0900 Subject: [PATCH 06/13] Implement Lotto.toString --- src/main/java/domain/Lotto.java | 18 ++++++++++++++++++ src/main/java/domain/LottoGame.java | 9 ++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 06694869..6d7d91ed 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -1,6 +1,11 @@ package domain; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * 로또 한장을 의미하는 객체 @@ -12,5 +17,18 @@ public Lotto(List numbers) { this.numbers = numbers; } + @Override + public String toString() { + ArrayList nums = new ArrayList(numbers); + Collections.sort(nums); + + var numStrs = IntStream.range(0, nums.size()) + .mapToObj(i -> Integer.toString(nums.get(i))) + .collect(Collectors.toList()); + + + return "[" + String.join(",", numStrs.toArray(new String[nums.size()])) + "]"; + } + // 추가 기능 구현 } diff --git a/src/main/java/domain/LottoGame.java b/src/main/java/domain/LottoGame.java index 567cf117..84e34b61 100644 --- a/src/main/java/domain/LottoGame.java +++ b/src/main/java/domain/LottoGame.java @@ -1,6 +1,7 @@ package domain; import java.util.ArrayList; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -30,9 +31,15 @@ public void run() { var lottos = Stream.generate(() -> lottoFactory.newLotto()) .limit(numLottos) .collect(Collectors.toCollection(ArrayList::new)); + _printLottos(lottos); var winningLotto = lottoReader.readWinningLotto(); - lottoAnalyzer.analyze(winningLotto, lottos); } + + private void _printLottos(List lottos) { + System.out.println(); + System.out.printf("%d개를 구매했습니다.\n", lottos.size()); + lottos.forEach((lotto) -> System.out.println(lotto.toString())); + } } From 4ddc4846beda41291b4ad47c7b015ad2152a665a Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Wed, 10 Apr 2019 18:00:26 +0900 Subject: [PATCH 07/13] Add LottoReaderFromUser [TODO] need to check input is valid --- README.md | 3 ++- src/main/java/LottoReaderFromUser.java | 33 ++++++++++++++++++++++++++ src/main/java/Main.java | 2 +- src/main/java/domain/LottoGame.java | 1 + src/main/java/domain/WinningLotto.java | 5 ++++ 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/main/java/LottoReaderFromUser.java diff --git a/README.md b/README.md index b8a83bad..ebc90270 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ -[x] 셔플로 만들기 - 올바른 로또인지 확인하는 부분 (1~45까지의 수, 중복 없음, 총 6개) - 만든 함수에서 예외처리 (ex.. 뽑을 집합보다 뽑을 갯수가 많은 경우) --[ ] 당첨로또 알아내기 +-[x] 당첨로또 알아내기 + -[ ] 올바른 입력인지 확인 -[ ] 유저의 로또 결과 분석하기 diff --git a/src/main/java/LottoReaderFromUser.java b/src/main/java/LottoReaderFromUser.java new file mode 100644 index 00000000..a5926042 --- /dev/null +++ b/src/main/java/LottoReaderFromUser.java @@ -0,0 +1,33 @@ +import domain.Lotto; +import domain.LottoReader; +import domain.WinningLotto; + +import java.util.ArrayList; +import java.util.Scanner; + +public class LottoReaderFromUser implements LottoReader { + + private Scanner sc; + + public LottoReaderFromUser() { + this.sc = new Scanner(System.in); + } + @Override + public WinningLotto readWinningLotto() { + System.out.println(); + System.out.println("지난 주 당첨 번호를 입력해 주세요."); + var numsStr = sc.next(); + + var nums = new ArrayList(); + for(var numStr : numsStr.split(",")) { + nums.add(Integer.parseInt(numStr)); + } + + System.out.println("보너스 볼을 입력해 주세요"); + var bonusNo = sc.nextInt(); + + // 아.. 어차피.. lotto 번호인지 확인하는 부분이 필요하구먼 + + return new WinningLotto(new Lotto(nums), bonusNo); + } +} diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 3ee40f68..5694e760 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -9,7 +9,7 @@ public static void main(String[] args) { var game = new LottoGame( new MoneyReaderFromUser(), new MyLottoFactory(new NumberPickerByShuffling(new Random())), - new FakeLottoReader(), + new LottoReaderFromUser(), new FakeLottoAnalyzer() ); game.run(); diff --git a/src/main/java/domain/LottoGame.java b/src/main/java/domain/LottoGame.java index 84e34b61..94595b30 100644 --- a/src/main/java/domain/LottoGame.java +++ b/src/main/java/domain/LottoGame.java @@ -34,6 +34,7 @@ public void run() { _printLottos(lottos); var winningLotto = lottoReader.readWinningLotto(); + System.out.println(winningLotto.toString()); lottoAnalyzer.analyze(winningLotto, lottos); } diff --git a/src/main/java/domain/WinningLotto.java b/src/main/java/domain/WinningLotto.java index d810418b..88c8d5e8 100644 --- a/src/main/java/domain/WinningLotto.java +++ b/src/main/java/domain/WinningLotto.java @@ -12,6 +12,11 @@ public WinningLotto(Lotto lotto, int bonusNo) { this.bonusNo = bonusNo; } + @Override + public String toString() { + return lotto.toString() + String.format(" + [%d]", bonusNo); + } + public Rank match(Lotto userLotto) { // TODO 로직 구현 return null; From 305c61c422efc089a4146eb23373529be5cee4b3 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Thu, 11 Apr 2019 09:29:52 +0900 Subject: [PATCH 08/13] Add MyLottoAnalyzer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 당첨 로또와 유저의 로또들을 가지고 분석하는 역할 - 각 등수가 얼마나 당청 되었는지 - 전체적인 수익 계산 분석할 때 필요한 메소드들을 Lotto와 WinningLotto에 추가함 --- src/main/java/FakeLottoAnalyzer.java | 2 +- src/main/java/Main.java | 3 +- src/main/java/MyLottoAnalyzer.java | 55 +++++++++++++++ src/main/java/domain/Lotto.java | 12 +++- src/main/java/domain/LottoAnalyzer.java | 2 +- src/main/java/domain/LottoGame.java | 2 +- src/main/java/domain/WinningLotto.java | 4 +- src/test/java/domain/LottoTest.java | 94 +++++++++++++++++++++++++ 8 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 src/main/java/MyLottoAnalyzer.java create mode 100644 src/test/java/domain/LottoTest.java diff --git a/src/main/java/FakeLottoAnalyzer.java b/src/main/java/FakeLottoAnalyzer.java index 587591f4..872dc746 100644 --- a/src/main/java/FakeLottoAnalyzer.java +++ b/src/main/java/FakeLottoAnalyzer.java @@ -6,7 +6,7 @@ public class FakeLottoAnalyzer implements LottoAnalyzer { @Override - public void analyze(WinningLotto winningLotto, List lottos) { + public void analyze(WinningLotto winningLotto, List lottos, int usedMoney) { System.out.println("analyze called"); } } diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 5694e760..1876fa5a 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -4,13 +4,12 @@ public class Main { - public static void main(String[] args) { var game = new LottoGame( new MoneyReaderFromUser(), new MyLottoFactory(new NumberPickerByShuffling(new Random())), new LottoReaderFromUser(), - new FakeLottoAnalyzer() + new MyLottoAnalyzer() ); game.run(); } diff --git a/src/main/java/MyLottoAnalyzer.java b/src/main/java/MyLottoAnalyzer.java new file mode 100644 index 00000000..8958c448 --- /dev/null +++ b/src/main/java/MyLottoAnalyzer.java @@ -0,0 +1,55 @@ +import domain.Lotto; +import domain.LottoAnalyzer; +import domain.Rank; +import domain.WinningLotto; + +import java.util.HashMap; +import java.util.List; + +public class MyLottoAnalyzer implements LottoAnalyzer { + private static final Rank[] ranksForPrint = {Rank.FIFTH, Rank.FOURTH, Rank.THIRD, Rank.SECOND, Rank.FIRST}; + + @Override + public void analyze(WinningLotto winningLotto, List lottos, int usedMoney) { + System.out.println("당첨 통계"); + System.out.println("--------"); + + var counter = _initCounter(winningLotto, lottos); + System.out.println(generateMatchStr(counter)); + + System.out.printf("총 수익률은 %f입니다.", (double) countTotalWinningMoney(counter) / usedMoney); + } + + private HashMap _initCounter(WinningLotto winningLotto, List lottos) { + var counter = new HashMap(); + + for (var lotto : lottos) { + var rank = winningLotto.match(lotto); + + var cnt = counter.getOrDefault(rank, 0); + counter.put(rank, cnt + 1); + } + return counter; + } + + private String generateMatchStr(HashMap counter) { + var sb = new StringBuilder(); + for (var r : ranksForPrint) { + sb.append(String.format("%d개 일치%s ", r.getCountOfMatch(), r == Rank.SECOND ? ", 보너스 볼 일치" : "")); + sb.append(String.format("(%d원)", r.getWinningMoney())); + sb.append(String.format("- %d개\n", counter.getOrDefault(r, 0))); + } + return sb.toString(); + } + + private long countTotalWinningMoney(HashMap counter) { + long total = 0; + + for (var r : counter.keySet()) { + long winningMoney = r.getWinningMoney(); + total += winningMoney * counter.get(r); + } + + return total; + } +} diff --git a/src/main/java/domain/Lotto.java b/src/main/java/domain/Lotto.java index 6d7d91ed..ca851436 100644 --- a/src/main/java/domain/Lotto.java +++ b/src/main/java/domain/Lotto.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -31,4 +30,15 @@ public String toString() { } // 추가 기능 구현 + public boolean contains(Integer num) { + return numbers.contains(num); + } + + public int countEqualNumbers(Lotto lotto) { + int countOfMatch = 0; + for (var num : numbers) { + countOfMatch += lotto.contains(num) ? 1 : 0; + } + return countOfMatch; + } } diff --git a/src/main/java/domain/LottoAnalyzer.java b/src/main/java/domain/LottoAnalyzer.java index 5e0a0e00..cc92b05b 100644 --- a/src/main/java/domain/LottoAnalyzer.java +++ b/src/main/java/domain/LottoAnalyzer.java @@ -3,5 +3,5 @@ import java.util.List; public interface LottoAnalyzer { - void analyze(WinningLotto winningLotto, List lottos); + void analyze(WinningLotto winningLotto, List lottos, int usedMoney); } diff --git a/src/main/java/domain/LottoGame.java b/src/main/java/domain/LottoGame.java index 94595b30..808b426a 100644 --- a/src/main/java/domain/LottoGame.java +++ b/src/main/java/domain/LottoGame.java @@ -35,7 +35,7 @@ public void run() { var winningLotto = lottoReader.readWinningLotto(); System.out.println(winningLotto.toString()); - lottoAnalyzer.analyze(winningLotto, lottos); + lottoAnalyzer.analyze(winningLotto, lottos, numLottos * LOTTO_PRICE); } private void _printLottos(List lottos) { diff --git a/src/main/java/domain/WinningLotto.java b/src/main/java/domain/WinningLotto.java index 88c8d5e8..c6b6101d 100644 --- a/src/main/java/domain/WinningLotto.java +++ b/src/main/java/domain/WinningLotto.java @@ -18,7 +18,7 @@ public String toString() { } public Rank match(Lotto userLotto) { - // TODO 로직 구현 - return null; + int countOfMatch = lotto.countEqualNumbers(userLotto); + return Rank.valueOf(countOfMatch, lotto.contains(bonusNo)); } } diff --git a/src/test/java/domain/LottoTest.java b/src/test/java/domain/LottoTest.java new file mode 100644 index 00000000..c78c9d7a --- /dev/null +++ b/src/test/java/domain/LottoTest.java @@ -0,0 +1,94 @@ +package domain; + +import com.sun.source.tree.AssertTree; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; + +import static org.junit.Assert.*; + +public class LottoTest { + private static final int LOTTO_NUM_START = 1; + private static final int LOTTO_NUM_END = 45; + + @Test + public void containsValids() { + List> numsList = Arrays.asList( + Arrays.asList(1, 2, 3, 4, 5, 6), + Arrays.asList(6, 5, 4, 3, 2, 1), + Arrays.asList(10, 20, 30, 40, 41, 45), + Arrays.asList(40, 30, 41, 45, 20, 10) + ); + + for (var nums : numsList) { + var lotto = new Lotto(nums); + + // Act & Assert + nums.forEach((num) -> { + Assert.assertTrue(lotto.contains(num)); + }); + } + } + + @Test + public void containsInvalids() { + List> numsList = Arrays.asList( + Arrays.asList(1, 2, 3, 4, 5, 6), + Arrays.asList(6, 5, 4, 3, 2, 1), + Arrays.asList(10, 20, 30, 40, 41, 45), + Arrays.asList(40, 30, 41, 45, 20, 10) + ); + + for (var nums : numsList) { + var lotto = new Lotto(nums); + + // Act & Assert + IntStream.range(LOTTO_NUM_START, LOTTO_NUM_END).forEach((num) -> { + if (nums.contains(num)) { + return; + } + Assert.assertFalse(lotto.contains(num)); + }); + } + } + + @Test + public void countEqualNumbers() { + List> numsList = Arrays.asList( + Arrays.asList(1, 2, 3, 4, 5, 6), + Arrays.asList(6, 5, 4, 3, 2, 1), + Arrays.asList(10, 20, 30, 40, 41, 45), + Arrays.asList(40, 30, 41, 45, 20, 10) + ); + List lottosForCompare = Arrays.asList( + new Lotto(Arrays.asList(1, 2, 3, 4, 5, 6)), + new Lotto(Arrays.asList(6, 5, 4, 3, 2, 1)), + new Lotto(Arrays.asList(10, 20, 30, 40, 41, 45)), + + new Lotto(Arrays.asList(2, 3, 10, 30, 41, 45)), + new Lotto(Arrays.asList(31, 32, 33, 34, 35, 36)) + ); + List> wantsList = Arrays.asList( + Arrays.asList(6, 6, 0, 2, 0), + Arrays.asList(6, 6, 0, 2, 0), + Arrays.asList(0, 0, 6, 4, 0), + Arrays.asList(0, 0, 6, 4, 0) + ); + + for (int i = 0; i < numsList.size(); i++) { + var lottoA = new Lotto(numsList.get(i)); + + // Act & Assert + for (int j = 0; j < lottosForCompare.size(); j++) { + var lottoB = lottosForCompare.get(j); + + Integer got = lottoA.countEqualNumbers(lottoB); + Assert.assertEquals(wantsList.get(i).get(j), got); + } + } + } +} \ No newline at end of file From 80f426fe94f73df34616fa84a6ee7007b41b93d6 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Thu, 11 Apr 2019 09:40:46 +0900 Subject: [PATCH 09/13] delete fake classes --- src/main/java/FakeLottoAnalyzer.java | 12 ------------ src/main/java/FakeLottoReader.java | 14 -------------- src/main/java/FakeMoneyReader.java | 11 ----------- src/main/java/MyLottoAnalyzer.java | 7 +++++-- 4 files changed, 5 insertions(+), 39 deletions(-) delete mode 100644 src/main/java/FakeLottoAnalyzer.java delete mode 100644 src/main/java/FakeLottoReader.java delete mode 100644 src/main/java/FakeMoneyReader.java diff --git a/src/main/java/FakeLottoAnalyzer.java b/src/main/java/FakeLottoAnalyzer.java deleted file mode 100644 index 872dc746..00000000 --- a/src/main/java/FakeLottoAnalyzer.java +++ /dev/null @@ -1,12 +0,0 @@ -import domain.Lotto; -import domain.LottoAnalyzer; -import domain.WinningLotto; - -import java.util.List; - -public class FakeLottoAnalyzer implements LottoAnalyzer { - @Override - public void analyze(WinningLotto winningLotto, List lottos, int usedMoney) { - System.out.println("analyze called"); - } -} diff --git a/src/main/java/FakeLottoReader.java b/src/main/java/FakeLottoReader.java deleted file mode 100644 index 76444b8d..00000000 --- a/src/main/java/FakeLottoReader.java +++ /dev/null @@ -1,14 +0,0 @@ -import domain.Lotto; -import domain.LottoReader; -import domain.WinningLotto; - -import java.util.ArrayList; - -public class FakeLottoReader implements LottoReader { - @Override - public WinningLotto readWinningLotto() { - System.out.println("readWinningLotto called"); - - return new WinningLotto(new Lotto(new ArrayList()), 1); - } -} diff --git a/src/main/java/FakeMoneyReader.java b/src/main/java/FakeMoneyReader.java deleted file mode 100644 index aef9bb9f..00000000 --- a/src/main/java/FakeMoneyReader.java +++ /dev/null @@ -1,11 +0,0 @@ -import domain.MoneyReader; - -import java.util.Scanner; - -public class FakeMoneyReader implements MoneyReader { - @Override - public int readMoney() { - System.out.println("readMoney called"); - return 10000; - } -} diff --git a/src/main/java/MyLottoAnalyzer.java b/src/main/java/MyLottoAnalyzer.java index 8958c448..af3cd43c 100644 --- a/src/main/java/MyLottoAnalyzer.java +++ b/src/main/java/MyLottoAnalyzer.java @@ -11,12 +11,15 @@ public class MyLottoAnalyzer implements LottoAnalyzer { @Override public void analyze(WinningLotto winningLotto, List lottos, int usedMoney) { - System.out.println("당첨 통계"); - System.out.println("--------"); + System.out.println("당첨 통계\n--------\n"); var counter = _initCounter(winningLotto, lottos); System.out.println(generateMatchStr(counter)); + if (usedMoney == 0) { + System.out.println("로또를 구매하지 않았습니다."); + return; + } System.out.printf("총 수익률은 %f입니다.", (double) countTotalWinningMoney(counter) / usedMoney); } From 52c04d158897c9c285113653c1857175e3ec7382 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Thu, 11 Apr 2019 09:58:12 +0900 Subject: [PATCH 10/13] MoneyReaderFromUser check input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 올바른 입력일 때까지 계속해서 받음 --- README.md | 4 ++-- src/main/java/MoneyReaderFromUser.java | 26 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ebc90270..7ce02498 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ ## 기능목록 -[x] 게임을 실행 (전체적인 실행 흐름) -[x] 유저에게 돈 받아내기 - -[ ] 올바른 입력인지 확인 + -[x] 올바른 입력인지 확인 -[x] 로또 만들기 -[x] 셔플로 만들기 - 올바른 로또인지 확인하는 부분 (1~45까지의 수, 중복 없음, 총 6개) - 만든 함수에서 예외처리 (ex.. 뽑을 집합보다 뽑을 갯수가 많은 경우) -[x] 당첨로또 알아내기 -[ ] 올바른 입력인지 확인 --[ ] 유저의 로또 결과 분석하기 +-[x] 유저의 로또 결과 분석하기 diff --git a/src/main/java/MoneyReaderFromUser.java b/src/main/java/MoneyReaderFromUser.java index f8c89b0b..9e485465 100644 --- a/src/main/java/MoneyReaderFromUser.java +++ b/src/main/java/MoneyReaderFromUser.java @@ -1,19 +1,41 @@ import domain.MoneyReader; +import java.util.InputMismatchException; import java.util.Scanner; public class MoneyReaderFromUser implements MoneyReader { + private static final int INVALID = -1; private Scanner sc; public MoneyReaderFromUser() { this.sc = new Scanner(System.in); } + @Override public int readMoney() { + var money = _readInt(); + + while (!isValidMoney(money)) { + System.out.println("잘못된 입력입니다. 음 아닌 정수를 입력해주세요"); + money = _readInt(); + } + return money; + } + + private boolean isValidMoney(int money) { + return INVALID < money; + } + + private int _readInt() { System.out.println("구입금액을 입력해 주세요."); + int num = INVALID; - // [TODO] check input is valid - return sc.nextInt(); + try { + num = sc.nextInt(); + } catch (InputMismatchException e) { + System.out.printf("got: \n" + sc.nextLine()); + } + return num; } } From 3809ea945318f321d1c8cefc81e42aa7ca092f9b Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Thu, 11 Apr 2019 11:52:14 +0900 Subject: [PATCH 11/13] Fix bug at WinningLotto.match --- src/main/java/domain/WinningLotto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/domain/WinningLotto.java b/src/main/java/domain/WinningLotto.java index c6b6101d..51a15a17 100644 --- a/src/main/java/domain/WinningLotto.java +++ b/src/main/java/domain/WinningLotto.java @@ -19,6 +19,6 @@ public String toString() { public Rank match(Lotto userLotto) { int countOfMatch = lotto.countEqualNumbers(userLotto); - return Rank.valueOf(countOfMatch, lotto.contains(bonusNo)); + return Rank.valueOf(countOfMatch, userLotto.contains(bonusNo)); } } From 9e22330d55ed3cac1ec3091379d1660fc47bc8d3 Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Thu, 11 Apr 2019 11:53:05 +0900 Subject: [PATCH 12/13] Handle invalid input for LottoReaderForUser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 입력으로 올바른 당첨 로또를 만들어 냄 올바르다는 것은 -6개의 숫자 (1~45사이의) -중복이 없는 숫자 -올바른 보너스 번호(올바른 범위 + 로또 번호와 중복없음) --- README.md | 4 +- src/main/java/LottoReaderFromUser.java | 104 +++++++++++++++++++++++-- src/main/java/MyLottoFactory.java | 9 +-- src/main/java/domain/LottoInfo.java | 11 +++ src/test/java/MyLottoFactoryTest.java | 7 +- 5 files changed, 116 insertions(+), 19 deletions(-) create mode 100644 src/main/java/domain/LottoInfo.java diff --git a/README.md b/README.md index 7ce02498..0d6f7c51 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ ## 기능목록 -[x] 게임을 실행 (전체적인 실행 흐름) -[x] 유저에게 돈 받아내기 - -[x] 올바른 입력인지 확인 + -[x] 올바른 입력인지 확인 (숫자로만 구성된 입력인지, 음 아닌 정수인지) -[x] 로또 만들기 -[x] 셔플로 만들기 - 올바른 로또인지 확인하는 부분 (1~45까지의 수, 중복 없음, 총 6개) - 만든 함수에서 예외처리 (ex.. 뽑을 집합보다 뽑을 갯수가 많은 경우) -[x] 당첨로또 알아내기 - -[ ] 올바른 입력인지 확인 + -[x] 올바른 입력인지 확인 -[x] 유저의 로또 결과 분석하기 diff --git a/src/main/java/LottoReaderFromUser.java b/src/main/java/LottoReaderFromUser.java index a5926042..756cab23 100644 --- a/src/main/java/LottoReaderFromUser.java +++ b/src/main/java/LottoReaderFromUser.java @@ -1,33 +1,121 @@ import domain.Lotto; +import domain.LottoInfo; import domain.LottoReader; import domain.WinningLotto; -import java.util.ArrayList; -import java.util.Scanner; +import java.util.*; +import java.util.regex.Pattern; public class LottoReaderFromUser implements LottoReader { + private static final int INVALID = -1; private Scanner sc; public LottoReaderFromUser() { this.sc = new Scanner(System.in); } + @Override public WinningLotto readWinningLotto() { System.out.println(); - System.out.println("지난 주 당첨 번호를 입력해 주세요."); - var numsStr = sc.next(); + + var nums = _readWinningNums(); + + var bonusNo = _readBonusNo(nums); + + return new WinningLotto(new Lotto(nums), bonusNo); + } + + private List _numsStrToNums(String numsStr) { + if (!Pattern.matches("^[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,*$", numsStr)) { + return new ArrayList(); + } var nums = new ArrayList(); - for(var numStr : numsStr.split(",")) { + for (var numStr : numsStr.split(",")) { nums.add(Integer.parseInt(numStr)); } + return nums; + } + + private boolean isAllUnique(List nums) { + var set = new HashSet(); + for (var num : nums) { + set.add(num); + } + return nums.size() == set.size(); + } + + private boolean isAllValidLottoNum(List nums) { + for (var num : nums) { + if (!LottoInfo.isLottoNum(num)) return false; + } + return true; + } + + private boolean isValidLottoNums(List nums) { + if (!isAllValidLottoNum(nums)) { + System.out.printf("입력되는 번호는 %d ~ %d 사이의 번호여야 합니다.\n", LottoInfo.LOTTO_NUM_START, LottoInfo.LOTTO_NUM_END); + return false; + } + if (!isAllUnique(nums)) { + System.out.println("중복되는 번호가 없어야 합니다."); + return false; + } + return nums.size() == LottoInfo.LOTTO_LENGTH; + } + + private List _tryReadWinningNums() { + var numsStr = sc.nextLine(); + System.out.println("line: " + numsStr); + var nums = _numsStrToNums(numsStr); + + if (!isValidLottoNums(nums)) return new ArrayList(); + + return nums; + } + + private List _readWinningNums() { + List winningNums = new ArrayList(); + while (winningNums.size() != LottoInfo.LOTTO_LENGTH) { + System.out.println("지난 주 당첨 번호를 입력해 주세요."); + System.out.println("정확한 입력을 위해 ','와 숫자만 사용해서 입력해주세요. 6개의 번호가 필요합니다 ex) 1,2,3,4,5,6"); + winningNums = _tryReadWinningNums(); + } + return winningNums; + } + private int _readInt() { System.out.println("보너스 볼을 입력해 주세요"); - var bonusNo = sc.nextInt(); + int num = INVALID; - // 아.. 어차피.. lotto 번호인지 확인하는 부분이 필요하구먼 + try { + num = sc.nextInt(); + } catch (InputMismatchException e) { + System.out.printf("got: \n" + sc.nextLine()); + sc.nextLine(); + } + return num; + } - return new WinningLotto(new Lotto(nums), bonusNo); + private int _tryReadBonusNo(List nums) { + var bonusNo = _readInt(); + if (bonusNo == INVALID || !LottoInfo.isLottoNum(bonusNo)) { + System.out.printf("로또번호는 %d ~ %d 인 숫자입니다\n", LottoInfo.LOTTO_NUM_START, LottoInfo.LOTTO_NUM_END); + return INVALID; + } + if (nums.contains(bonusNo)) { + System.out.println("보너스 볼은 당첨번호와 동일 할 수 없습니다.\n당첨번호 " + Arrays.toString(nums.toArray())); + return INVALID; + } + return bonusNo; + } + + private int _readBonusNo(List nums) { + var bonusNo = INVALID; + while (bonusNo == INVALID) { + bonusNo = _tryReadBonusNo(nums); + } + return bonusNo; } } diff --git a/src/main/java/MyLottoFactory.java b/src/main/java/MyLottoFactory.java index 46835ac3..c6f45709 100644 --- a/src/main/java/MyLottoFactory.java +++ b/src/main/java/MyLottoFactory.java @@ -1,16 +1,13 @@ import domain.LottoFactory; import domain.Lotto; +import domain.LottoInfo; import domain.NumberPicker; import java.util.Arrays; import java.util.stream.IntStream; public class MyLottoFactory implements LottoFactory { - // [LOTTO_NUM_FROM, LOTTO_NUM_TO] - public static final int LOTTO_NUM_FROM = 1; - public static final int LOTTO_NUM_TO = 45; - public static final int LOTTO_LENGTH = 6; private NumberPicker picker; @@ -20,11 +17,11 @@ public MyLottoFactory(NumberPicker picker) { @Override public Lotto newLotto() { - var nums = IntStream.range(LOTTO_NUM_FROM, LOTTO_NUM_TO + 1) + var nums = IntStream.range(LottoInfo.LOTTO_NUM_START, LottoInfo.LOTTO_NUM_END + 1) .boxed() .toArray(Integer[]::new); - var pickedNums = picker.PickNums(nums, LOTTO_LENGTH); + var pickedNums = picker.PickNums(nums, LottoInfo.LOTTO_LENGTH); return new Lotto(Arrays.asList(pickedNums)); } diff --git a/src/main/java/domain/LottoInfo.java b/src/main/java/domain/LottoInfo.java new file mode 100644 index 00000000..f9ded207 --- /dev/null +++ b/src/main/java/domain/LottoInfo.java @@ -0,0 +1,11 @@ +package domain; + +public class LottoInfo { + public static final int LOTTO_NUM_START = 1; + public static final int LOTTO_NUM_END = 45; + public static final int LOTTO_LENGTH = 6; + + public static boolean isLottoNum(int num) { + return LottoInfo.LOTTO_NUM_START <= num && num <= LottoInfo.LOTTO_NUM_END; + } +} diff --git a/src/test/java/MyLottoFactoryTest.java b/src/test/java/MyLottoFactoryTest.java index ab18335c..b8d36298 100644 --- a/src/test/java/MyLottoFactoryTest.java +++ b/src/test/java/MyLottoFactoryTest.java @@ -1,3 +1,4 @@ +import domain.LottoInfo; import domain.NumberPicker; import static org.junit.Assert.*; @@ -12,8 +13,8 @@ public class MyLottoFactoryTest { @org.junit.Test public void newLottoPickValidLength() { mockedPicker = mock(NumberPickerByShuffling.class); - when(mockedPicker.PickNums(any(Integer[].class), eq(factory.LOTTO_LENGTH))) - .thenReturn(new Integer[factory.LOTTO_LENGTH]); + when(mockedPicker.PickNums(any(Integer[].class), eq(LottoInfo.LOTTO_LENGTH))) + .thenReturn(new Integer[LottoInfo.LOTTO_LENGTH]); factory = new MyLottoFactory(mockedPicker); @@ -21,6 +22,6 @@ public void newLottoPickValidLength() { factory.newLotto(); // Assert - verify(mockedPicker).PickNums(any(Integer[].class), eq(factory.LOTTO_LENGTH)); + verify(mockedPicker).PickNums(any(Integer[].class), eq(LottoInfo.LOTTO_LENGTH)); } } \ No newline at end of file From 7014c7a91b39d105cab6bcf93bded2dee1cb89bc Mon Sep 17 00:00:00 2001 From: Ko eunsuk Date: Thu, 11 Apr 2019 12:47:14 +0900 Subject: [PATCH 13/13] Fix typeof --- README.md | 2 -- src/main/java/LottoReaderFromUser.java | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0d6f7c51..b7549f41 100644 --- a/README.md +++ b/README.md @@ -11,5 +11,3 @@ -[x] 유저의 로또 결과 분석하기 - -만들면서 돌아가는 테스트를 만드는 것도 재미있을 듯 \ No newline at end of file diff --git a/src/main/java/LottoReaderFromUser.java b/src/main/java/LottoReaderFromUser.java index 756cab23..cdd66281 100644 --- a/src/main/java/LottoReaderFromUser.java +++ b/src/main/java/LottoReaderFromUser.java @@ -19,9 +19,9 @@ public LottoReaderFromUser() { public WinningLotto readWinningLotto() { System.out.println(); - var nums = _readWinningNums(); + var nums = _readWinningNumsUntilSucceed(); - var bonusNo = _readBonusNo(nums); + var bonusNo = _readBonusNoUntilSucceed(nums); return new WinningLotto(new Lotto(nums), bonusNo); } @@ -75,7 +75,7 @@ private List _tryReadWinningNums() { return nums; } - private List _readWinningNums() { + private List _readWinningNumsUntilSucceed() { List winningNums = new ArrayList(); while (winningNums.size() != LottoInfo.LOTTO_LENGTH) { System.out.println("지난 주 당첨 번호를 입력해 주세요."); @@ -111,7 +111,7 @@ private int _tryReadBonusNo(List nums) { return bonusNo; } - private int _readBonusNo(List nums) { + private int _readBonusNoUntilSucceed(List nums) { var bonusNo = INVALID; while (bonusNo == INVALID) { bonusNo = _tryReadBonusNo(nums);