From ad5c8972c0cf642bb7da333bc705a4eaa52a62eb Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:03:24 +0900 Subject: [PATCH 01/37] =?UTF-8?q?docs:=20=ED=8E=98=EC=96=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..0954416ba --- /dev/null +++ b/docs/README.md @@ -0,0 +1,15 @@ +[작성자]  +이름: 양홍주 +메일: willyouspeedup@naver.com  +  + +## 구현할 "기능 목록"을 정리 + +[페어 매칭] +- 크루들의 이름 목록을 List 형태로 준비한다. +- 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용한다. +- 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. +- 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. + - 이 경우 한 페어는 3인으로 구성한다. +- 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. + - 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. From 6d7874fce9b8ffcec1044b41ddb5e635435ce855 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:03:39 +0900 Subject: [PATCH 02/37] =?UTF-8?q?docs:=20=ED=8E=98=EC=96=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C,=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/README.md b/docs/README.md index 0954416ba..b80295aaf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,3 +13,14 @@ - 이 경우 한 페어는 3인으로 구성한다. - 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. - 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. + + +[페어 조회 기능] +- 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다. +- 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. + - 이 때, 에러 메세지는 다음과 같다. "[ERROR] 매칭 이력이 없습니다." + + +[페어 초기화 기능] +- 페어 매칭 정보를 모두 초기화시킨다. +  \ No newline at end of file From 9ffa133c79f3c03004b1c0a3720f5be0051fa116 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:03:57 +0900 Subject: [PATCH 03/37] =?UTF-8?q?docs:=20=EC=82=AC=EC=A0=84=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4,=20=EC=8B=9C=EC=9E=91=20=ED=99=94=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index b80295aaf..7e2ccb675 100644 --- a/docs/README.md +++ b/docs/README.md @@ -23,4 +23,46 @@ [페어 초기화 기능] - 페어 매칭 정보를 모두 초기화시킨다. -  \ No newline at end of file +   + [사전 제공 정보] +- 과정 + - 백엔드 + - 프론트엔드 +- 레벨 + - 레벨1 + - 레벨2 + - 레벨3 + - 레벨4 + - 레벨5 +- 미션 + - 레벨1 + - 자동차경주 + - 로또 + - 숫자야구게임 + - 레벨2 + - 장바구니 + - 결제 + - 지하철노선도 + - 레벨3 (페어메칭 없음) + - 레벨4 + - 성능개선 + - 배포 + - 레벨5 (페어메칭 없음) + +- 크루 정보는 src/resources 하위에 md 파일로 제공된다. + - 백엔드, 프론트엔드 각각 파일이 존재한다. + + +[시작 화면] +- 과정와 미션을 출력 +``` +############################################# +과정: 백엔드 | 프론트엔드 +미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: +############################################ +``` From d7855f3821ee8f6e9b96056227bad9a3bf846235 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:04:24 +0900 Subject: [PATCH 04/37] =?UTF-8?q?docs:=20=EC=9E=85=EB=A0=A5=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/README.md b/docs/README.md index 7e2ccb675..90a480f25 100644 --- a/docs/README.md +++ b/docs/README.md @@ -66,3 +66,27 @@ - 레벨5: ############################################ ``` + +  +[입력 화면] +- 사용자가 잘못된 값을 입력하면 IllegalArgumentException와 [ERROR]로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. +- 사용자는 "기능 메뉴 선택" 정수 1개를 입력 + - 1번은 페어 매칭, 2번은 페어 조회, 3번은 페어 초기화, Q는 종료 + - 검증: 만약 정수가 아닌 것을 입력하면 잘못 입력한 것. + - 검증: 만약 없는 메뉴를 입력하면 잘못 입력한 것. + - 오타 교정: 앞뒤로 공백을 제거해줌 +- 사용자는 "과정, 레벨, 미션"을 ,로 구분하여 한 줄에 입력 + - 검증: 없는 과정을 입력하면 잘못된 입력 + - 검증: 없는 레벨을 입력하면 잘못된 입력 + - 검증: 페어매칭이 없는 과정을 입력하면 잘못된 입력 + - 검증: 선택한 과정에 입력한 미션이 없으면 잘못된 입력 + - 오타 교정: 입력 항목 사이에 불필요한 ,는 자동으로 제거해줌 + - 오타 교정: 전체 입력 문장에서 모든 공백을 제거해줌. +- 이미 매칭 정보가 있는 경우 재매칭할지에 대한 정보를 입력받는다. + - 사용자는 문자 하나를 입력한다. + - 예를 선택할 경우 페어를 재매칭한다. + - 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. + - 검증: 예, 아니오가 아닌 값을 입력하면 잘못입력한 것. + +  + From 1a26d7ac5d4e686f4bc02813d90908a2b74a6dd0 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:04:35 +0900 Subject: [PATCH 05/37] =?UTF-8?q?docs:=20=EC=BB=A4=EB=B0=8B=20=EC=BB=A8?= =?UTF-8?q?=EB=B2=A4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/README.md b/docs/README.md index 90a480f25..4575482f6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -90,3 +90,23 @@   + +## 커밋 컨벤션 + +> 기본 형태 +~~~ +type: subject + +body +~~~ +  +> type + +feat: 새로운 기능  +fix: 버그 수정  +docs: 문서 수정  +style: 서식 지정, 세미콜론 누락 등 (코드 변경 없음)  +refactor: 코드 리팩토링  +test: 테스트 코드 추가, 테스트 코드 리팩토링 (생산 코드 변경 없음)  +chore: 빌드, 패키지 매니저 등 업데이트 (생산 코드 변경 없음)  +  From 00939ad26176bceef3163e809a7c0c21cdf36107 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:06:05 +0900 Subject: [PATCH 06/37] =?UTF-8?q?test:=20=ED=8E=98=EC=96=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20=ED=81=AC?= =?UTF-8?q?=EB=A3=A8=EB=93=A4=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=85=EC=B6=9C=EB=A0=A5=EC=9D=84=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EB=B6=88=EB=9F=AC=EC=98=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/pairmatching/util/FileUtilTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/java/pairmatching/util/FileUtilTest.java diff --git a/src/test/java/pairmatching/util/FileUtilTest.java b/src/test/java/pairmatching/util/FileUtilTest.java new file mode 100644 index 000000000..1b321dacc --- /dev/null +++ b/src/test/java/pairmatching/util/FileUtilTest.java @@ -0,0 +1,40 @@ +package pairmatching.util; + +import java.net.URISyntaxException; +import java.util.List; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.stream.Stream; +import java.nio.file.Paths; +import java.io.IOException; +import util.FileUtil; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FileUtilTest { + + private static Stream provideLinesForTest() { + return Stream.of( + Arguments.of(0, "백호"), Arguments.of(1, "태웅"), Arguments.of(2, "치수"), + Arguments.of(3, "태섭"), Arguments.of(4, "대만"), Arguments.of(5, "준호"), + Arguments.of(6, "대협"), Arguments.of(7, "덕규"), Arguments.of(8, "태산"), + Arguments.of(9, "경태"), Arguments.of(10, "수겸"), Arguments.of(11, "현준"), + Arguments.of(12, "준섭"), Arguments.of(13, "한나"), Arguments.of(14, "소연"), + Arguments.of(15, "호열"), Arguments.of(16, "대남"), Arguments.of(17, "용팔"), + Arguments.of(18, "구식"), Arguments.of(19, "달재") + ); + } + + @ParameterizedTest + @MethodSource("provideLinesForTest") + public void testFileContent(int lineIndex, String expectedLine) throws IOException, URISyntaxException { + final String filePath + = Paths.get(getClass().getClassLoader().getResource("backend-crew.md").toURI()).toString(); + final List members = FileUtil.readFileAsList(filePath); + final String result = members.get(lineIndex); + + assertEquals(expectedLine, result, "Mismatch at line " + (lineIndex + 1)); + } +} From a56846df4f1921b5432f43cd63ea6cc05354a270 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:06:18 +0900 Subject: [PATCH 07/37] =?UTF-8?q?feat:=20=ED=8E=98=EC=96=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20=ED=81=AC?= =?UTF-8?q?=EB=A3=A8=EB=93=A4=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=85=EC=B6=9C=EB=A0=A5=EC=9D=84=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EB=B6=88=EB=9F=AC=EC=98=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 ++ src/main/java/util/FileUtil.java | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/main/java/util/FileUtil.java diff --git a/docs/README.md b/docs/README.md index 4575482f6..f639f82f0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,8 @@ ## 구현할 "기능 목록"을 정리 [페어 매칭] +- 페어 매칭에 필요한 크루들의 이름을 파일 입출력을 통해 불러온다. O + - src/main/resources/backend-crew.md과 src/main/resources/frontend-crew.md 파일을 이용한다. O - 크루들의 이름 목록을 List 형태로 준비한다. - 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용한다. - 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. diff --git a/src/main/java/util/FileUtil.java b/src/main/java/util/FileUtil.java new file mode 100644 index 000000000..578d34e71 --- /dev/null +++ b/src/main/java/util/FileUtil.java @@ -0,0 +1,12 @@ +package util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +public class FileUtil { + public static List readFileAsList(String filePath) throws IOException { + return Files.readAllLines(Paths.get(filePath)); + } +} From 84af92ff5102cbd0476e135a88541f18279f2bfc Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:07:26 +0900 Subject: [PATCH 08/37] =?UTF-8?q?feat:=20=EB=B0=B1=EC=97=94=EB=93=9C,=20?= =?UTF-8?q?=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=94=EB=93=9C=20Course?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 +++--- src/main/java/domain/entity/Course.java | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/main/java/domain/entity/Course.java diff --git a/docs/README.md b/docs/README.md index f639f82f0..ec2ff8508 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,9 +27,9 @@ - 페어 매칭 정보를 모두 초기화시킨다.    [사전 제공 정보] -- 과정 - - 백엔드 - - 프론트엔드 +- 과정 O + - 백엔드 O + - 프론트엔드O - 레벨 - 레벨1 - 레벨2 diff --git a/src/main/java/domain/entity/Course.java b/src/main/java/domain/entity/Course.java new file mode 100644 index 000000000..7c00ff40d --- /dev/null +++ b/src/main/java/domain/entity/Course.java @@ -0,0 +1,23 @@ +package domain.entity; + +public enum Course { + BACKEND("백엔드", "backend-crew.md"), + FRONTEND("프론트엔드", "frontend-crew.md"); + + private final String name; + private final String filePath; + + Course(final String name, final String filePath) { + this.name = name; + this.filePath = filePath; + } + + + public String getName() { + return name; + } + + public String getFilePath() { + return filePath; + } +} \ No newline at end of file From 30137ebd326eecf0bf1cd0e2aabd5e725bb96644 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:10:02 +0900 Subject: [PATCH 09/37] =?UTF-8?q?docs:=20=EC=B6=9C=EB=A0=A5=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index ec2ff8508..a0e2d8fce 100644 --- a/docs/README.md +++ b/docs/README.md @@ -54,22 +54,7 @@ - 크루 정보는 src/resources 하위에 md 파일로 제공된다. - 백엔드, 프론트엔드 각각 파일이 존재한다. - -[시작 화면] -- 과정와 미션을 출력 -``` -############################################# -과정: 백엔드 | 프론트엔드 -미션: - - 레벨1: 자동차경주 | 로또 | 숫자야구게임 - - 레벨2: 장바구니 | 결제 | 지하철노선도 - - 레벨3: - - 레벨4: 성능개선 | 배포 - - 레벨5: -############################################ -``` - -  +  [입력 화면] - 사용자가 잘못된 값을 입력하면 IllegalArgumentException와 [ERROR]로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. - 사용자는 "기능 메뉴 선택" 정수 1개를 입력 @@ -90,7 +75,30 @@ - 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. - 검증: 예, 아니오가 아닌 값을 입력하면 잘못입력한 것. -  +[출력 화면] +- 과정와 미션을 출력 +``` +############################################# +과정: 백엔드 | 프론트엔드 +미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: +############################################ +``` +- 페어 매칭 결과 출력 +``` +페어 매칭 결과입니다. +이브 : 윌터 +보노 : 제키 +신디 : 로드 +제시 : 린다 +시저 : 라라 +니콜 : 다비 +리사 : 덴버 : 제키 +``` ## 커밋 컨벤션 From 51eb797e18da79a4914cd3f168b0dae3d2173369 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:26:20 +0900 Subject: [PATCH 10/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=A0=84=20=EC=A0=9C?= =?UTF-8?q?=EA=B3=B5=20=EC=A0=95=EB=B3=B4=20enum=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 48 +++++++++++++------------- src/main/java/domain/entity/Level.java | 20 +++++++++++ 2 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 src/main/java/domain/entity/Level.java diff --git a/docs/README.md b/docs/README.md index a0e2d8fce..98a70bda9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -26,33 +26,33 @@ [페어 초기화 기능] - 페어 매칭 정보를 모두 초기화시킨다.    - [사전 제공 정보] +[사전 제공 정보] - 과정 O - 백엔드 O - - 프론트엔드O -- 레벨 - - 레벨1 - - 레벨2 - - 레벨3 - - 레벨4 - - 레벨5 -- 미션 - - 레벨1 - - 자동차경주 - - 로또 - - 숫자야구게임 - - 레벨2 - - 장바구니 - - 결제 - - 지하철노선도 - - 레벨3 (페어메칭 없음) - - 레벨4 - - 성능개선 - - 배포 - - 레벨5 (페어메칭 없음) + - 프론트엔드 O +- 레벨 O + - 레벨1 O + - 레벨2 O + - 레벨3 O + - 레벨4 O + - 레벨5 O +- 미션 O + - 레벨1 O + - 자동차경주 O + - 로또 O + - 숫자야구게임 O + - 레벨2 O + - 장바구니 O + - 결제 O + - 지하철노선도 O + - 레벨3 (페어메칭 없음) O + - 레벨4 O + - 성능개선 O + - 배포 O + - 레벨5 (페어메칭 없음) O -- 크루 정보는 src/resources 하위에 md 파일로 제공된다. - - 백엔드, 프론트엔드 각각 파일이 존재한다. +- 크루 정보는 src/resources 하위에 md 파일로 제공된다. O + - 백엔드, 프론트엔드 각각 파일이 존재한다. O   [입력 화면] diff --git a/src/main/java/domain/entity/Level.java b/src/main/java/domain/entity/Level.java new file mode 100644 index 000000000..f67292a49 --- /dev/null +++ b/src/main/java/domain/entity/Level.java @@ -0,0 +1,20 @@ +package domain.entity; + +import java.util.Arrays; +import java.util.List; + +public enum Level { + LEVEL1("레벨1", Arrays.asList("자동차경주", "로또", "숫자야구게임")), // 실전에서는 List.of()사용 예정. 버전때문에 못씀. + LEVEL2("레벨2", Arrays.asList("장바구니", "결제", "지하철노선도")), + LEVEL3("레벨3", Arrays.asList()), + LEVEL4("레벨4", Arrays.asList("성능개선","배포")), + LEVEL5("레벨5", Arrays.asList()); + + private final String name; + private final List mission; + + Level(String name, List mission) { + this.name = name; + this.mission = mission; + } +} \ No newline at end of file From c8b9e13437cd242f49dd4f60892fa90fddea7a45 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:35:59 +0900 Subject: [PATCH 11/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EB=8A=94=20"=EA=B8=B0=EB=8A=A5=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D"=20=EC=A0=95=EC=88=98=201=EA=B0=9C=EB=A5=BC?= =?UTF-8?q?=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 9 ++++----- src/main/java/messages/IOMessages.java | 25 +++++++++++++++++++++++++ src/main/java/util/ExceptionUtil.java | 25 +++++++++++++++++++++++++ src/main/java/util/InputUtil.java | 21 +++++++++++++++++++++ src/main/java/util/StringUtil.java | 17 +++++++++++++++++ src/main/java/view/InputView.java | 17 +++++++++++++++++ 6 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 src/main/java/messages/IOMessages.java create mode 100644 src/main/java/util/ExceptionUtil.java create mode 100644 src/main/java/util/InputUtil.java create mode 100644 src/main/java/util/StringUtil.java create mode 100644 src/main/java/view/InputView.java diff --git a/docs/README.md b/docs/README.md index 98a70bda9..89127c716 100644 --- a/docs/README.md +++ b/docs/README.md @@ -57,11 +57,10 @@   [입력 화면] - 사용자가 잘못된 값을 입력하면 IllegalArgumentException와 [ERROR]로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. -- 사용자는 "기능 메뉴 선택" 정수 1개를 입력 - - 1번은 페어 매칭, 2번은 페어 조회, 3번은 페어 초기화, Q는 종료 - - 검증: 만약 정수가 아닌 것을 입력하면 잘못 입력한 것. - - 검증: 만약 없는 메뉴를 입력하면 잘못 입력한 것. - - 오타 교정: 앞뒤로 공백을 제거해줌 +- 사용자는 "기능 메뉴 선택" 정수 1개를 입력 O + - 1번은 페어 매칭, 2번은 페어 조회, 3번은 페어 초기화, Q는 종료 O + - 검증: 만약 없는 메뉴를 입력하면 잘못 입력한 것. O + - 오타 교정: 앞뒤로 공백을 제거해줌 O - 사용자는 "과정, 레벨, 미션"을 ,로 구분하여 한 줄에 입력 - 검증: 없는 과정을 입력하면 잘못된 입력 - 검증: 없는 레벨을 입력하면 잘못된 입력 diff --git a/src/main/java/messages/IOMessages.java b/src/main/java/messages/IOMessages.java new file mode 100644 index 000000000..f9bff3325 --- /dev/null +++ b/src/main/java/messages/IOMessages.java @@ -0,0 +1,25 @@ +package messages; + +public enum IOMessages { + + COURSE("과정"), + LEVEL("레벨"), + MISSION("미션"), + INPUT_SELECT_OPTIONS(String.format("%s, %s, %s을 선택하세요.",COURSE,LEVEL,MISSION)), + SELECT_EXAMPLE("ex) 백엔드, 레벨1, 자동차경주"), + INPUT_FUNCTION("기능을 선택하세요."), + OUTPUT_DIVIDING_LINE("#############################################"), + OUTPUT_PAIRMATCHING_RESULT("페어 매칭 결과입니다."), + OUTPUT_RESET("초기화 되었습니다."); + + + private final String message; + + IOMessages(final String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/util/ExceptionUtil.java b/src/main/java/util/ExceptionUtil.java new file mode 100644 index 000000000..b6ee4acd8 --- /dev/null +++ b/src/main/java/util/ExceptionUtil.java @@ -0,0 +1,25 @@ +package util; + +public final class ExceptionUtil { + + public static void throwInvalidValueException() { + + throw new IllegalArgumentException(); + } + + public static IllegalArgumentException returnInvalidValueException() { + + return new IllegalArgumentException(); + } + + public static void throwInvalidValueException(final String message) { + + throw new IllegalArgumentException(message); + } + + public static IllegalArgumentException returnInvalidValueException(final String message) { + + return new IllegalArgumentException(message); + } + +} diff --git a/src/main/java/util/InputUtil.java b/src/main/java/util/InputUtil.java new file mode 100644 index 000000000..6a45b2193 --- /dev/null +++ b/src/main/java/util/InputUtil.java @@ -0,0 +1,21 @@ +package util; + +import camp.nextstep.edu.missionutils.Console; +import java.util.function.Supplier; + +public final class InputUtil { + + public static String input() { + return Console.readLine(); + } + + public static T retryOnInvalidInput(Supplier inputSupplier, String errorMessage) { + while (true) { + try { + return inputSupplier.get(); + } catch (IllegalArgumentException e) { + System.out.println(errorMessage); + } + } + } +} diff --git a/src/main/java/util/StringUtil.java b/src/main/java/util/StringUtil.java new file mode 100644 index 000000000..3b6adc449 --- /dev/null +++ b/src/main/java/util/StringUtil.java @@ -0,0 +1,17 @@ +package util; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public final class StringUtil { + + public static String removeAllSpaces(final String input) { + return input.replace(" ", ""); + } + + public static String joinNonEmptyStrings(String delimiter, String... parts) { + return Arrays.stream(parts) + .filter(part -> !part.isEmpty()) + .collect(Collectors.joining(delimiter)); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 000000000..54e953ca1 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,17 @@ +package view; + +import static messages.IOMessages.INPUT_FUNCTION; + +import domain.dto.FunctionMapper; +import domain.entity.Function; +import util.InputUtil; + +public class InputView { + + public Function inputFunction() { + System.out.println(INPUT_FUNCTION.getMessage()); + String input = InputUtil.input(); + + return FunctionMapper.toFunction(input); + } +} From 8387cd19a0a904b0bf2de2f4fce8668259cbb7d3 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:36:37 +0900 Subject: [PATCH 12/37] =?UTF-8?q?feat:=20=EA=B8=B0=EB=8A=A5=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dto/FunctionMapper.java | 12 +++++++++ src/main/java/domain/entity/Function.java | 26 ++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/main/java/domain/dto/FunctionMapper.java create mode 100644 src/main/java/domain/entity/Function.java diff --git a/src/main/java/domain/dto/FunctionMapper.java b/src/main/java/domain/dto/FunctionMapper.java new file mode 100644 index 000000000..caf940258 --- /dev/null +++ b/src/main/java/domain/dto/FunctionMapper.java @@ -0,0 +1,12 @@ +package domain.dto; + +import domain.entity.Function; +import util.StringUtil; + +public class FunctionMapper { + public static Function toFunction(String input) { + final String deleteSpaces = StringUtil.removeAllSpaces(input); + + return Function.findFunction(deleteSpaces); + } +} diff --git a/src/main/java/domain/entity/Function.java b/src/main/java/domain/entity/Function.java new file mode 100644 index 000000000..f9d7303b5 --- /dev/null +++ b/src/main/java/domain/entity/Function.java @@ -0,0 +1,26 @@ +package domain.entity; + +import java.util.Arrays; +import util.ExceptionUtil; + +public enum Function { + PAIR_MATCHING("1","페어 매칭"), + PAIR_CHECK("2","페어 조회"), + PAIR_RESET("3","페어 초기화"), + QUIT("Q","종료"); + + private final String option; + private final String description; + + Function(String option, String description) { + this.option = option; + this.description = description; + } + + public static Function findFunction(String option) { + return Arrays.stream(Function.values()) + .filter(function -> function.option == option) + .findAny() + .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); + } +} From 4075c7ef716408183e9f22c9391918477ccfbfc4 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 19:57:44 +0900 Subject: [PATCH 13/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EB=8A=94=20"=EA=B3=BC=EC=A0=95,=20=EB=A0=88=EB=B2=A8,=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98"=EC=9D=84=20,=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=ED=95=9C=20=EC=A4=84=EC=97=90=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 ++--- .../java/domain/dto/CourseMissionMapper.java | 17 ++++++++++++++ .../java/domain/entity/CourseMission.java | 23 +++++++++++++++++++ src/main/java/view/InputView.java | 10 ++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/main/java/domain/dto/CourseMissionMapper.java create mode 100644 src/main/java/domain/entity/CourseMission.java diff --git a/docs/README.md b/docs/README.md index 89127c716..f4179dbda 100644 --- a/docs/README.md +++ b/docs/README.md @@ -61,13 +61,13 @@ - 1번은 페어 매칭, 2번은 페어 조회, 3번은 페어 초기화, Q는 종료 O - 검증: 만약 없는 메뉴를 입력하면 잘못 입력한 것. O - 오타 교정: 앞뒤로 공백을 제거해줌 O -- 사용자는 "과정, 레벨, 미션"을 ,로 구분하여 한 줄에 입력 +- 사용자는 "과정, 레벨, 미션"을 ,로 구분하여 한 줄에 입력 O - 검증: 없는 과정을 입력하면 잘못된 입력 - 검증: 없는 레벨을 입력하면 잘못된 입력 - 검증: 페어매칭이 없는 과정을 입력하면 잘못된 입력 - 검증: 선택한 과정에 입력한 미션이 없으면 잘못된 입력 - - 오타 교정: 입력 항목 사이에 불필요한 ,는 자동으로 제거해줌 - - 오타 교정: 전체 입력 문장에서 모든 공백을 제거해줌. + - 오타 교정: 입력 항목 사이에 불필요한 ,는 자동으로 제거해줌 O + - 오타 교정: 전체 입력 문장에서 모든 공백을 제거해줌. O - 이미 매칭 정보가 있는 경우 재매칭할지에 대한 정보를 입력받는다. - 사용자는 문자 하나를 입력한다. - 예를 선택할 경우 페어를 재매칭한다. diff --git a/src/main/java/domain/dto/CourseMissionMapper.java b/src/main/java/domain/dto/CourseMissionMapper.java new file mode 100644 index 000000000..0d4e26e7c --- /dev/null +++ b/src/main/java/domain/dto/CourseMissionMapper.java @@ -0,0 +1,17 @@ +package domain.dto; + +import domain.entity.CourseMission; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import util.StringUtil; + +public class CourseMissionMapper { + public static CourseMission toCourseMission(String input) { + String deleteSpaces = StringUtil.removeAllSpaces(input); + List separated = Arrays.stream(input.split(",")) + .collect(Collectors.toList()); //실전에선 toList() 사용 + + return CourseMission.create(separated); + } +} diff --git a/src/main/java/domain/entity/CourseMission.java b/src/main/java/domain/entity/CourseMission.java new file mode 100644 index 000000000..165603983 --- /dev/null +++ b/src/main/java/domain/entity/CourseMission.java @@ -0,0 +1,23 @@ +package domain.entity; + +import java.util.List; + +public class CourseMission { + private final String course; + private final String level; + private final String mission; + + public CourseMission(String course, String level, String mission) { + this.course = course; + this.level = level; + this.mission = mission; + } + + public static CourseMission create(List separated) { + String course = separated.get(0); + String level = separated.get(1); + String mission = separated.get(2); + + return new CourseMission(course, level, mission); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 54e953ca1..e1fa6c694 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,8 +1,11 @@ package view; import static messages.IOMessages.INPUT_FUNCTION; +import static messages.IOMessages.INPUT_SELECT_OPTIONS; +import domain.dto.CourseMissionMapper; import domain.dto.FunctionMapper; +import domain.entity.CourseMission; import domain.entity.Function; import util.InputUtil; @@ -14,4 +17,11 @@ public Function inputFunction() { return FunctionMapper.toFunction(input); } + + public CourseMission inputCourseMission() { + System.out.println(INPUT_SELECT_OPTIONS.getMessage()); + String input = InputUtil.input(); + + return CourseMissionMapper.toCourseMission(input); + } } From c3c20c9f9edee4b1324562a07698f37a433e2289 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 20:13:42 +0900 Subject: [PATCH 14/37] =?UTF-8?q?test:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EB=8A=94=20"=EA=B3=BC=EC=A0=95,=20=EB=A0=88=EB=B2=A8,=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98"=EC=9D=84=20,=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=ED=95=9C=20=EC=A4=84=EC=97=90=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dto/CourseMissionMapperTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java diff --git a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java new file mode 100644 index 000000000..1a58c1199 --- /dev/null +++ b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java @@ -0,0 +1,44 @@ +package pairmatching.domain.dto; + +import domain.dto.CourseMissionMapper; +import domain.entity.Course; +import domain.entity.CourseMission; +import domain.entity.Level; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.Arguments; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.stream.Stream; + +public class CourseMissionMapperTest { + + private static Stream provideInputForCourseMission() { + return Stream.of( + Arguments.of( + "백엔드, 레벨1, 자동차경주", + Course.BACKEND, + Level.LEVEL1, + "자동차경주"), + Arguments.of("프론트엔드, 레벨2, 장바구니", + Course.FRONTEND, + Level.LEVEL2, + "장바구니") + ); + } + + @ParameterizedTest + @MethodSource("provideInputForCourseMission") + public void testToCourseMission(String input, + Course expectedCourse, + Level expectedLevel, + String expectedMissionName) { + CourseMission courseMission = CourseMissionMapper.toCourseMission(input); + + assertNotNull(courseMission); + assertEquals(expectedCourse, courseMission.getCourse()); + assertEquals(expectedLevel, courseMission.getLevel()); + assertEquals(expectedMissionName, courseMission.getMission()); + } +} From 95981e3fa58b6acfe2fd2be2340043643c5d6ce0 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 20:14:14 +0900 Subject: [PATCH 15/37] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EB=8A=94=20"=EA=B3=BC=EC=A0=95,=20=EB=A0=88=EB=B2=A8,=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98"=EC=9D=84=20,=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=ED=95=9C=20=EC=A4=84=EC=97=90=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit String이 아닌 객체 사용 --- .../java/domain/entity/CourseMission.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/java/domain/entity/CourseMission.java b/src/main/java/domain/entity/CourseMission.java index 165603983..008d89ef5 100644 --- a/src/main/java/domain/entity/CourseMission.java +++ b/src/main/java/domain/entity/CourseMission.java @@ -3,21 +3,29 @@ import java.util.List; public class CourseMission { - private final String course; - private final String level; - private final String mission; + private final Course course; + private final Level level; + private final String mission; // TODO: 시간되면 VO 분리 - public CourseMission(String course, String level, String mission) { + private CourseMission(Course course, Level level, String mission) { this.course = course; this.level = level; this.mission = mission; } - public static CourseMission create(List separated) { - String course = separated.get(0); - String level = separated.get(1); - String mission = separated.get(2); + public static CourseMission create(Course course, Level level, String missionName) { + return new CourseMission(course, level, missionName); + } + + public Course getCourse() { + return course; + } + + public Level getLevel() { + return level; + } - return new CourseMission(course, level, mission); + public String getMission() { + return mission; } } From f7420a4cf837cc0ff23d4a265d893cfcff7ecab8 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 20:26:32 +0900 Subject: [PATCH 16/37] =?UTF-8?q?feat:=20=EC=97=86=EB=8A=94=20"=EA=B3=BC?= =?UTF-8?q?=EC=A0=95,=20=EB=A0=88=EB=B2=A8,=20=EB=AF=B8=EC=85=98"=EC=9D=84?= =?UTF-8?q?=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 8 ++-- .../java/domain/dto/CourseMissionMapper.java | 32 +++++++++++++++- src/main/java/domain/entity/Course.java | 9 +++++ .../java/domain/entity/CourseMission.java | 12 +++--- src/main/java/domain/entity/Function.java | 2 +- src/main/java/domain/entity/Level.java | 37 ++++++++++++++++--- src/main/java/domain/entity/Mission.java | 22 +++++++++++ 7 files changed, 102 insertions(+), 20 deletions(-) create mode 100644 src/main/java/domain/entity/Mission.java diff --git a/docs/README.md b/docs/README.md index f4179dbda..9cccfb380 100644 --- a/docs/README.md +++ b/docs/README.md @@ -62,10 +62,10 @@ - 검증: 만약 없는 메뉴를 입력하면 잘못 입력한 것. O - 오타 교정: 앞뒤로 공백을 제거해줌 O - 사용자는 "과정, 레벨, 미션"을 ,로 구분하여 한 줄에 입력 O - - 검증: 없는 과정을 입력하면 잘못된 입력 - - 검증: 없는 레벨을 입력하면 잘못된 입력 - - 검증: 페어매칭이 없는 과정을 입력하면 잘못된 입력 - - 검증: 선택한 과정에 입력한 미션이 없으면 잘못된 입력 + - 검증: 없는 과정을 입력하면 잘못된 입력 O + - 검증: 없는 레벨을 입력하면 잘못된 입력 O + - 검증: 페어매칭이 없는 과정을 입력하면 잘못된 입력 O + - 검증: 선택한 과정에 입력한 미션이 없으면 잘못된 입력 O - 오타 교정: 입력 항목 사이에 불필요한 ,는 자동으로 제거해줌 O - 오타 교정: 전체 입력 문장에서 모든 공백을 제거해줌. O - 이미 매칭 정보가 있는 경우 재매칭할지에 대한 정보를 입력받는다. diff --git a/src/main/java/domain/dto/CourseMissionMapper.java b/src/main/java/domain/dto/CourseMissionMapper.java index 0d4e26e7c..69bd40f43 100644 --- a/src/main/java/domain/dto/CourseMissionMapper.java +++ b/src/main/java/domain/dto/CourseMissionMapper.java @@ -1,6 +1,9 @@ package domain.dto; +import domain.entity.Course; import domain.entity.CourseMission; +import domain.entity.Level; +import domain.entity.Mission; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -8,10 +11,35 @@ public class CourseMissionMapper { public static CourseMission toCourseMission(String input) { + List separated = seperate(input); + + final String courseName = separated.get(0); + final String levelName = separated.get(1); + final String missionName = separated.get(2); + + Course course = toCourse(courseName); + Level level = toLevel(levelName); + Mission mission = toMission(level, missionName); + + return CourseMission.create(course, level, mission); + } + + private static List seperate(String input) { String deleteSpaces = StringUtil.removeAllSpaces(input); - List separated = Arrays.stream(input.split(",")) + List separated = Arrays.stream(deleteSpaces.split(",")) .collect(Collectors.toList()); //실전에선 toList() 사용 + return separated; + } + + private static Level toLevel(String levelName) { + return Level.findLevel(levelName); + } + + private static Course toCourse(String courseName) { + return Course.findCourse(courseName); + } - return CourseMission.create(separated); + private static Mission toMission(Level level, String missionName) { + return level.findMission(missionName); } } diff --git a/src/main/java/domain/entity/Course.java b/src/main/java/domain/entity/Course.java index 7c00ff40d..9a77d573e 100644 --- a/src/main/java/domain/entity/Course.java +++ b/src/main/java/domain/entity/Course.java @@ -1,5 +1,8 @@ package domain.entity; +import java.util.Arrays; +import util.ExceptionUtil; + public enum Course { BACKEND("백엔드", "backend-crew.md"), FRONTEND("프론트엔드", "frontend-crew.md"); @@ -12,6 +15,12 @@ public enum Course { this.filePath = filePath; } + public static Course findCourse(String courseName) { + return Arrays.stream(values()) + .filter(course -> course.name.equals(courseName)) + .findAny() + .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); + } public String getName() { return name; diff --git a/src/main/java/domain/entity/CourseMission.java b/src/main/java/domain/entity/CourseMission.java index 008d89ef5..a74763a3d 100644 --- a/src/main/java/domain/entity/CourseMission.java +++ b/src/main/java/domain/entity/CourseMission.java @@ -1,20 +1,18 @@ package domain.entity; -import java.util.List; - public class CourseMission { private final Course course; private final Level level; - private final String mission; // TODO: 시간되면 VO 분리 + private final Mission mission; - private CourseMission(Course course, Level level, String mission) { + private CourseMission(Course course, Level level, Mission mission) { this.course = course; this.level = level; this.mission = mission; } - public static CourseMission create(Course course, Level level, String missionName) { - return new CourseMission(course, level, missionName); + public static CourseMission create(Course course, Level level, Mission mission) { + return new CourseMission(course, level, mission); } public Course getCourse() { @@ -25,7 +23,7 @@ public Level getLevel() { return level; } - public String getMission() { + public Mission getMission() { return mission; } } diff --git a/src/main/java/domain/entity/Function.java b/src/main/java/domain/entity/Function.java index f9d7303b5..14a6d5167 100644 --- a/src/main/java/domain/entity/Function.java +++ b/src/main/java/domain/entity/Function.java @@ -19,7 +19,7 @@ public enum Function { public static Function findFunction(String option) { return Arrays.stream(Function.values()) - .filter(function -> function.option == option) + .filter(function -> function.option.equals(option)) .findAny() .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } diff --git a/src/main/java/domain/entity/Level.java b/src/main/java/domain/entity/Level.java index f67292a49..d39ed29dc 100644 --- a/src/main/java/domain/entity/Level.java +++ b/src/main/java/domain/entity/Level.java @@ -2,19 +2,44 @@ import java.util.Arrays; import java.util.List; +import util.ExceptionUtil; public enum Level { - LEVEL1("레벨1", Arrays.asList("자동차경주", "로또", "숫자야구게임")), // 실전에서는 List.of()사용 예정. 버전때문에 못씀. - LEVEL2("레벨2", Arrays.asList("장바구니", "결제", "지하철노선도")), + LEVEL1("레벨1", Arrays.asList(Mission.RACING_CAR, Mission.LOTTO, Mission.BASEBALL)), + LEVEL2("레벨2", Arrays.asList(Mission.SHOPPING_CART, Mission.PAYMENT, Mission.SUBWAY_MAP)), LEVEL3("레벨3", Arrays.asList()), - LEVEL4("레벨4", Arrays.asList("성능개선","배포")), + LEVEL4("레벨4", Arrays.asList(Mission.PERFORMANCE_IMPROVEMENT, Mission.DEPLOYMENT)), LEVEL5("레벨5", Arrays.asList()); private final String name; - private final List mission; + private final List missions; - Level(String name, List mission) { + Level(String name, List missions) { this.name = name; - this.mission = mission; + this.missions = missions; } + + public static Level findLevel(String levelName) { + return Arrays.stream(values()) + .filter(level -> level.name.equals(levelName)) + .findAny() + .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); + } + + public Mission findMission(String missionName) { + return this.missions + .stream() + .filter(mission -> mission.getDescription().equals(missionName)) + .findAny() + .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); + } + + public String getName() { + return name; + } + + public List getMissions() { + return missions; + } + } \ No newline at end of file diff --git a/src/main/java/domain/entity/Mission.java b/src/main/java/domain/entity/Mission.java new file mode 100644 index 000000000..6de1c339f --- /dev/null +++ b/src/main/java/domain/entity/Mission.java @@ -0,0 +1,22 @@ +package domain.entity; + +public enum Mission { + RACING_CAR("자동차경주"), + LOTTO("로또"), + BASEBALL("숫자야구게임"), + SHOPPING_CART("장바구니"), + PAYMENT("결제"), + SUBWAY_MAP("지하철노선도"), + PERFORMANCE_IMPROVEMENT("성능개선"), + DEPLOYMENT("배포"); + + private final String description; + + Mission(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +} From 16604fc20331aa22d586d30359fe7466f6db8aa4 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 20:34:54 +0900 Subject: [PATCH 17/37] =?UTF-8?q?refactor:=20Mission=EC=9D=84=20String=20?= =?UTF-8?q?=EB=8C=80=EC=8B=A0=20VO=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/domain/dto/CourseMissionMapperTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java index 1a58c1199..2cd9645a9 100644 --- a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java +++ b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java @@ -4,6 +4,7 @@ import domain.entity.Course; import domain.entity.CourseMission; import domain.entity.Level; +import domain.entity.Mission; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.Arguments; @@ -20,11 +21,11 @@ private static Stream provideInputForCourseMission() { "백엔드, 레벨1, 자동차경주", Course.BACKEND, Level.LEVEL1, - "자동차경주"), + Mission.RACING_CAR), Arguments.of("프론트엔드, 레벨2, 장바구니", Course.FRONTEND, Level.LEVEL2, - "장바구니") + Mission.SHOPPING_CART) ); } @@ -33,12 +34,12 @@ private static Stream provideInputForCourseMission() { public void testToCourseMission(String input, Course expectedCourse, Level expectedLevel, - String expectedMissionName) { + Mission expectedMission) { CourseMission courseMission = CourseMissionMapper.toCourseMission(input); assertNotNull(courseMission); assertEquals(expectedCourse, courseMission.getCourse()); assertEquals(expectedLevel, courseMission.getLevel()); - assertEquals(expectedMissionName, courseMission.getMission()); + assertEquals(expectedMission, courseMission.getMission()); } } From ea9fe485c73224fa26a0553e05b71e730b4cf4b3 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 20:44:02 +0900 Subject: [PATCH 18/37] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dto/CourseMissionMapper.java | 12 ++++++------ .../domain/dto/FunctionMapper.java | 6 +++--- .../{ => pairmatching}/domain/entity/Course.java | 16 ++++++++-------- .../domain/entity/CourseMission.java | 2 +- .../domain/entity/Function.java | 4 ++-- .../{ => pairmatching}/domain/entity/Level.java | 16 ++++++++-------- .../domain/entity/Mission.java | 2 +- .../{ => pairmatching}/messages/IOMessages.java | 2 +- .../{ => pairmatching}/util/ExceptionUtil.java | 2 +- .../java/{ => pairmatching}/util/FileUtil.java | 2 +- .../java/{ => pairmatching}/util/InputUtil.java | 2 +- .../java/{ => pairmatching}/util/StringUtil.java | 2 +- .../java/{ => pairmatching}/view/InputView.java | 16 ++++++++-------- .../domain/dto/CourseMissionMapperTest.java | 9 ++++----- .../java/pairmatching/util/FileUtilTest.java | 1 - 15 files changed, 46 insertions(+), 48 deletions(-) rename src/main/java/{ => pairmatching}/domain/dto/CourseMissionMapper.java (83%) rename src/main/java/{ => pairmatching}/domain/dto/FunctionMapper.java (65%) rename src/main/java/{ => pairmatching}/domain/entity/Course.java (58%) rename src/main/java/{ => pairmatching}/domain/entity/CourseMission.java (94%) rename src/main/java/{ => pairmatching}/domain/entity/Function.java (89%) rename src/main/java/{ => pairmatching}/domain/entity/Level.java (76%) rename src/main/java/{ => pairmatching}/domain/entity/Mission.java (92%) rename src/main/java/{ => pairmatching}/messages/IOMessages.java (95%) rename src/main/java/{ => pairmatching}/util/ExceptionUtil.java (95%) rename src/main/java/{ => pairmatching}/util/FileUtil.java (91%) rename src/main/java/{ => pairmatching}/util/InputUtil.java (94%) rename src/main/java/{ => pairmatching}/util/StringUtil.java (94%) rename src/main/java/{ => pairmatching}/view/InputView.java (53%) diff --git a/src/main/java/domain/dto/CourseMissionMapper.java b/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java similarity index 83% rename from src/main/java/domain/dto/CourseMissionMapper.java rename to src/main/java/pairmatching/domain/dto/CourseMissionMapper.java index 69bd40f43..e8552f16f 100644 --- a/src/main/java/domain/dto/CourseMissionMapper.java +++ b/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java @@ -1,13 +1,13 @@ -package domain.dto; +package pairmatching.domain.dto; -import domain.entity.Course; -import domain.entity.CourseMission; -import domain.entity.Level; -import domain.entity.Mission; +import pairmatching.domain.entity.Course; +import pairmatching.domain.entity.CourseMission; +import pairmatching.domain.entity.Level; +import pairmatching.domain.entity.Mission; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import util.StringUtil; +import pairmatching.util.StringUtil; public class CourseMissionMapper { public static CourseMission toCourseMission(String input) { diff --git a/src/main/java/domain/dto/FunctionMapper.java b/src/main/java/pairmatching/domain/dto/FunctionMapper.java similarity index 65% rename from src/main/java/domain/dto/FunctionMapper.java rename to src/main/java/pairmatching/domain/dto/FunctionMapper.java index caf940258..6ab91a11b 100644 --- a/src/main/java/domain/dto/FunctionMapper.java +++ b/src/main/java/pairmatching/domain/dto/FunctionMapper.java @@ -1,7 +1,7 @@ -package domain.dto; +package pairmatching.domain.dto; -import domain.entity.Function; -import util.StringUtil; +import pairmatching.domain.entity.Function; +import pairmatching.util.StringUtil; public class FunctionMapper { public static Function toFunction(String input) { diff --git a/src/main/java/domain/entity/Course.java b/src/main/java/pairmatching/domain/entity/Course.java similarity index 58% rename from src/main/java/domain/entity/Course.java rename to src/main/java/pairmatching/domain/entity/Course.java index 9a77d573e..d55fe7571 100644 --- a/src/main/java/domain/entity/Course.java +++ b/src/main/java/pairmatching/domain/entity/Course.java @@ -1,29 +1,29 @@ -package domain.entity; +package pairmatching.domain.entity; import java.util.Arrays; -import util.ExceptionUtil; +import pairmatching.util.ExceptionUtil; public enum Course { BACKEND("백엔드", "backend-crew.md"), FRONTEND("프론트엔드", "frontend-crew.md"); - private final String name; + private final String description; private final String filePath; - Course(final String name, final String filePath) { - this.name = name; + Course(final String description, final String filePath) { + this.description = description; this.filePath = filePath; } public static Course findCourse(String courseName) { return Arrays.stream(values()) - .filter(course -> course.name.equals(courseName)) + .filter(course -> course.description.equals(courseName)) .findAny() .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } - public String getName() { - return name; + public String getDescription() { + return description; } public String getFilePath() { diff --git a/src/main/java/domain/entity/CourseMission.java b/src/main/java/pairmatching/domain/entity/CourseMission.java similarity index 94% rename from src/main/java/domain/entity/CourseMission.java rename to src/main/java/pairmatching/domain/entity/CourseMission.java index a74763a3d..b6130df7c 100644 --- a/src/main/java/domain/entity/CourseMission.java +++ b/src/main/java/pairmatching/domain/entity/CourseMission.java @@ -1,4 +1,4 @@ -package domain.entity; +package pairmatching.domain.entity; public class CourseMission { private final Course course; diff --git a/src/main/java/domain/entity/Function.java b/src/main/java/pairmatching/domain/entity/Function.java similarity index 89% rename from src/main/java/domain/entity/Function.java rename to src/main/java/pairmatching/domain/entity/Function.java index 14a6d5167..a4891bb0a 100644 --- a/src/main/java/domain/entity/Function.java +++ b/src/main/java/pairmatching/domain/entity/Function.java @@ -1,7 +1,7 @@ -package domain.entity; +package pairmatching.domain.entity; import java.util.Arrays; -import util.ExceptionUtil; +import pairmatching.util.ExceptionUtil; public enum Function { PAIR_MATCHING("1","페어 매칭"), diff --git a/src/main/java/domain/entity/Level.java b/src/main/java/pairmatching/domain/entity/Level.java similarity index 76% rename from src/main/java/domain/entity/Level.java rename to src/main/java/pairmatching/domain/entity/Level.java index d39ed29dc..93744a9d6 100644 --- a/src/main/java/domain/entity/Level.java +++ b/src/main/java/pairmatching/domain/entity/Level.java @@ -1,8 +1,8 @@ -package domain.entity; +package pairmatching.domain.entity; import java.util.Arrays; import java.util.List; -import util.ExceptionUtil; +import pairmatching.util.ExceptionUtil; public enum Level { LEVEL1("레벨1", Arrays.asList(Mission.RACING_CAR, Mission.LOTTO, Mission.BASEBALL)), @@ -11,17 +11,17 @@ public enum Level { LEVEL4("레벨4", Arrays.asList(Mission.PERFORMANCE_IMPROVEMENT, Mission.DEPLOYMENT)), LEVEL5("레벨5", Arrays.asList()); - private final String name; + private final String description; private final List missions; - Level(String name, List missions) { - this.name = name; + Level(String description, List missions) { + this.description = description; this.missions = missions; } public static Level findLevel(String levelName) { return Arrays.stream(values()) - .filter(level -> level.name.equals(levelName)) + .filter(level -> level.description.equals(levelName)) .findAny() .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } @@ -34,8 +34,8 @@ public Mission findMission(String missionName) { .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } - public String getName() { - return name; + public String getDescription() { + return description; } public List getMissions() { diff --git a/src/main/java/domain/entity/Mission.java b/src/main/java/pairmatching/domain/entity/Mission.java similarity index 92% rename from src/main/java/domain/entity/Mission.java rename to src/main/java/pairmatching/domain/entity/Mission.java index 6de1c339f..e26f21ae3 100644 --- a/src/main/java/domain/entity/Mission.java +++ b/src/main/java/pairmatching/domain/entity/Mission.java @@ -1,4 +1,4 @@ -package domain.entity; +package pairmatching.domain.entity; public enum Mission { RACING_CAR("자동차경주"), diff --git a/src/main/java/messages/IOMessages.java b/src/main/java/pairmatching/messages/IOMessages.java similarity index 95% rename from src/main/java/messages/IOMessages.java rename to src/main/java/pairmatching/messages/IOMessages.java index f9bff3325..7141c92f8 100644 --- a/src/main/java/messages/IOMessages.java +++ b/src/main/java/pairmatching/messages/IOMessages.java @@ -1,4 +1,4 @@ -package messages; +package pairmatching.messages; public enum IOMessages { diff --git a/src/main/java/util/ExceptionUtil.java b/src/main/java/pairmatching/util/ExceptionUtil.java similarity index 95% rename from src/main/java/util/ExceptionUtil.java rename to src/main/java/pairmatching/util/ExceptionUtil.java index b6ee4acd8..8c1b26c6e 100644 --- a/src/main/java/util/ExceptionUtil.java +++ b/src/main/java/pairmatching/util/ExceptionUtil.java @@ -1,4 +1,4 @@ -package util; +package pairmatching.util; public final class ExceptionUtil { diff --git a/src/main/java/util/FileUtil.java b/src/main/java/pairmatching/util/FileUtil.java similarity index 91% rename from src/main/java/util/FileUtil.java rename to src/main/java/pairmatching/util/FileUtil.java index 578d34e71..88a8e89ad 100644 --- a/src/main/java/util/FileUtil.java +++ b/src/main/java/pairmatching/util/FileUtil.java @@ -1,4 +1,4 @@ -package util; +package pairmatching.util; import java.io.IOException; import java.nio.file.Files; diff --git a/src/main/java/util/InputUtil.java b/src/main/java/pairmatching/util/InputUtil.java similarity index 94% rename from src/main/java/util/InputUtil.java rename to src/main/java/pairmatching/util/InputUtil.java index 6a45b2193..bd37657ff 100644 --- a/src/main/java/util/InputUtil.java +++ b/src/main/java/pairmatching/util/InputUtil.java @@ -1,4 +1,4 @@ -package util; +package pairmatching.util; import camp.nextstep.edu.missionutils.Console; import java.util.function.Supplier; diff --git a/src/main/java/util/StringUtil.java b/src/main/java/pairmatching/util/StringUtil.java similarity index 94% rename from src/main/java/util/StringUtil.java rename to src/main/java/pairmatching/util/StringUtil.java index 3b6adc449..3100090bd 100644 --- a/src/main/java/util/StringUtil.java +++ b/src/main/java/pairmatching/util/StringUtil.java @@ -1,4 +1,4 @@ -package util; +package pairmatching.util; import java.util.Arrays; import java.util.stream.Collectors; diff --git a/src/main/java/view/InputView.java b/src/main/java/pairmatching/view/InputView.java similarity index 53% rename from src/main/java/view/InputView.java rename to src/main/java/pairmatching/view/InputView.java index e1fa6c694..41b8ade54 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -1,13 +1,13 @@ -package view; +package pairmatching.view; -import static messages.IOMessages.INPUT_FUNCTION; -import static messages.IOMessages.INPUT_SELECT_OPTIONS; +import static pairmatching.messages.IOMessages.INPUT_FUNCTION; +import static pairmatching.messages.IOMessages.INPUT_SELECT_OPTIONS; -import domain.dto.CourseMissionMapper; -import domain.dto.FunctionMapper; -import domain.entity.CourseMission; -import domain.entity.Function; -import util.InputUtil; +import pairmatching.domain.dto.CourseMissionMapper; +import pairmatching.domain.dto.FunctionMapper; +import pairmatching.domain.entity.CourseMission; +import pairmatching.domain.entity.Function; +import pairmatching.util.InputUtil; public class InputView { diff --git a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java index 2cd9645a9..533583f1f 100644 --- a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java +++ b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java @@ -1,10 +1,9 @@ package pairmatching.domain.dto; -import domain.dto.CourseMissionMapper; -import domain.entity.Course; -import domain.entity.CourseMission; -import domain.entity.Level; -import domain.entity.Mission; +import pairmatching.domain.entity.Course; +import pairmatching.domain.entity.CourseMission; +import pairmatching.domain.entity.Level; +import pairmatching.domain.entity.Mission; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.Arguments; diff --git a/src/test/java/pairmatching/util/FileUtilTest.java b/src/test/java/pairmatching/util/FileUtilTest.java index 1b321dacc..4093c7c37 100644 --- a/src/test/java/pairmatching/util/FileUtilTest.java +++ b/src/test/java/pairmatching/util/FileUtilTest.java @@ -9,7 +9,6 @@ import java.util.stream.Stream; import java.nio.file.Paths; import java.io.IOException; -import util.FileUtil; import static org.junit.jupiter.api.Assertions.assertEquals; From a01b46cdc50026ce38de525eef4e2a01825e7a9d Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 20:45:03 +0900 Subject: [PATCH 19/37] =?UTF-8?q?feat:=20=EA=B3=BC=EC=A0=95=EC=99=80=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=EC=9D=84=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../java/pairmatching/view/OutputView.java | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pairmatching/view/OutputView.java diff --git a/docs/README.md b/docs/README.md index 9cccfb380..fe1d11ff0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -75,7 +75,7 @@ - 검증: 예, 아니오가 아닌 값을 입력하면 잘못입력한 것. [출력 화면] -- 과정와 미션을 출력 +- 과정와 미션을 출력 O ``` ############################################# 과정: 백엔드 | 프론트엔드 diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java new file mode 100644 index 000000000..a0c75cadf --- /dev/null +++ b/src/main/java/pairmatching/view/OutputView.java @@ -0,0 +1,51 @@ +package pairmatching.view; + +import static pairmatching.messages.IOMessages.COURSE; +import static pairmatching.messages.IOMessages.MISSION; +import static pairmatching.messages.IOMessages.OUTPUT_DIVIDING_LINE; +import static pairmatching.messages.IOMessages.OUTPUT_PAIRMATCHING_RESULT; + +import pairmatching.domain.entity.Course; +import pairmatching.domain.entity.Level; +import pairmatching.domain.entity.Mission; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class OutputView { + + public void outputCourseMission() { + System.out.println(OUTPUT_DIVIDING_LINE.getMessage()); + + outputCourses(); + outputMissions(); + + System.out.println(OUTPUT_DIVIDING_LINE.getMessage()); + } + + public void outputPairMatchingResult() { + System.out.println(OUTPUT_PAIRMATCHING_RESULT.getMessage()); + } + + private void outputCourses() { + String courses = Arrays.stream(Course.values()) + .map(Course::getDescription) + .collect(Collectors.joining(" | ")); + System.out.println(COURSE.getMessage() + ": " + courses); + } + + private void outputMissions() { + System.out.println(MISSION.getMessage() + ": "); + Arrays.stream(Level.values()) + .map(this::formatMissionsForLevel) + .forEach(System.out::println); + } + + private String formatMissionsForLevel(Level level) { + String missions = level.getMissions() + .stream() + .map(Mission::getDescription) + .collect(Collectors.joining(" | ")); + + return " - " + level.getDescription() + ": " + missions; + } +} From d3be8259bfbb51bb5644058e458814e31cf1ac98 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:08:47 +0900 Subject: [PATCH 20/37] =?UTF-8?q?test:=20Course=EC=9D=98=20path=EB=A1=9C?= =?UTF-8?q?=20crew=20List=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/domain/dto/CourseTest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/test/java/pairmatching/domain/dto/CourseTest.java diff --git a/src/test/java/pairmatching/domain/dto/CourseTest.java b/src/test/java/pairmatching/domain/dto/CourseTest.java new file mode 100644 index 000000000..c85a23c4a --- /dev/null +++ b/src/test/java/pairmatching/domain/dto/CourseTest.java @@ -0,0 +1,43 @@ +package pairmatching.domain.dto; + +import java.util.List; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.Arguments; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.stream.Stream; +import pairmatching.domain.entity.Course; + +public class CourseTest { + + private static Stream 코스이름_및_예상코스() { + return Stream.of( + Arguments.of("백엔드", Course.BACKEND, 20), + Arguments.of("프론트엔드", Course.FRONTEND, 15) + ); + } + + @ParameterizedTest + @MethodSource("코스이름_및_예상코스") + public void 주어진_코스이름으로_코스찾기_테스트(String courseName, Course expectedCourse) { + // when + Course result = Course.findCourse(courseName); + + // then + assertEquals(expectedCourse, result); + } + + @ParameterizedTest + @MethodSource("코스이름_및_예상코스") + public void 주어진_코스의_크루목록_가져오기_테스트(String courseName, Course course, int size) { + // when + List crews = course.getCrews(); + + // then + assertNotNull(crews); + assertThat(crews.size()).isEqualTo(size); + } +} From 4051f418bafe6989b84a03418d9459e653094dc9 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:08:54 +0900 Subject: [PATCH 21/37] =?UTF-8?q?feat:=20Course=EC=9D=98=20path=EB=A1=9C?= =?UTF-8?q?=20crew=20List=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../pairmatching/domain/entity/Course.java | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index fe1d11ff0..ea43174ad 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,7 +8,7 @@ [페어 매칭] - 페어 매칭에 필요한 크루들의 이름을 파일 입출력을 통해 불러온다. O - src/main/resources/backend-crew.md과 src/main/resources/frontend-crew.md 파일을 이용한다. O -- 크루들의 이름 목록을 List 형태로 준비한다. +- 크루들의 이름 목록을 List 형태로 준비한다. O - 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용한다. - 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. - 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. diff --git a/src/main/java/pairmatching/domain/entity/Course.java b/src/main/java/pairmatching/domain/entity/Course.java index d55fe7571..f01d20685 100644 --- a/src/main/java/pairmatching/domain/entity/Course.java +++ b/src/main/java/pairmatching/domain/entity/Course.java @@ -1,7 +1,12 @@ package pairmatching.domain.entity; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; import java.util.Arrays; +import java.util.List; import pairmatching.util.ExceptionUtil; +import pairmatching.util.FileUtil; public enum Course { BACKEND("백엔드", "backend-crew.md"), @@ -22,11 +27,24 @@ public static Course findCourse(String courseName) { .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } + public List getCrews() { + try { + return FileUtil.readFileAsList(getFilePath()); + } catch (IOException e) { + throw ExceptionUtil.returnInvalidValueException(); + } catch (URISyntaxException e) { + throw ExceptionUtil.returnInvalidValueException(); + } + } + public String getDescription() { return description; } - public String getFilePath() { - return filePath; + public String getFilePath() throws URISyntaxException { + return Paths.get(getClass() + .getClassLoader() + .getResource(filePath) + .toURI()).toString(); } } \ No newline at end of file From 464abd8a070808baccf18b830b3c92e6185d8598 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:10:55 +0900 Subject: [PATCH 22/37] =?UTF-8?q?test:=20CourseName=EC=9C=BC=EB=A1=9C=20Co?= =?UTF-8?q?urse=20=EA=B0=9D=EC=B2=B4=20=EC=B0=BE=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/domain/dto/CourseTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/java/pairmatching/domain/dto/CourseTest.java b/src/test/java/pairmatching/domain/dto/CourseTest.java index c85a23c4a..089e61782 100644 --- a/src/test/java/pairmatching/domain/dto/CourseTest.java +++ b/src/test/java/pairmatching/domain/dto/CourseTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.params.provider.Arguments; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; import java.util.stream.Stream; @@ -20,6 +21,10 @@ public class CourseTest { ); } + private static Stream provideInvalidCourseNames() { + return Stream.of("잘못된코스", "존재하지않음", "비어있음"); + } + @ParameterizedTest @MethodSource("코스이름_및_예상코스") public void 주어진_코스이름으로_코스찾기_테스트(String courseName, Course expectedCourse) { @@ -40,4 +45,18 @@ public class CourseTest { assertNotNull(crews); assertThat(crews.size()).isEqualTo(size); } + + @ParameterizedTest + @MethodSource("코스이름_및_예상코스") + void 유효한_코스_찾기_테스트(String courseName, Course expectedCourse) { + Course actualCourse = Course.findCourse(courseName); + assertEquals(expectedCourse, actualCourse); + } + + @ParameterizedTest + @MethodSource("provideInvalidCourseNames") + void 잘못된_코스_찾기_예외_테스트(String courseName) { + assertThatThrownBy(() -> Course.findCourse(courseName)) + .isInstanceOf(IllegalArgumentException.class); + } } From 386b73c17572e1099a65b943673dfeb762eb9dd8 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:17:56 +0900 Subject: [PATCH 23/37] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/domain/entity/Function.java | 8 ++++++++ src/main/java/pairmatching/view/InputView.java | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/pairmatching/domain/entity/Function.java b/src/main/java/pairmatching/domain/entity/Function.java index a4891bb0a..b2522f064 100644 --- a/src/main/java/pairmatching/domain/entity/Function.java +++ b/src/main/java/pairmatching/domain/entity/Function.java @@ -23,4 +23,12 @@ public static Function findFunction(String option) { .findAny() .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } + + public String getOption() { + return option; + } + + public String getDescription() { + return description; + } } diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 41b8ade54..18012dea0 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -3,6 +3,7 @@ import static pairmatching.messages.IOMessages.INPUT_FUNCTION; import static pairmatching.messages.IOMessages.INPUT_SELECT_OPTIONS; +import java.util.Arrays; import pairmatching.domain.dto.CourseMissionMapper; import pairmatching.domain.dto.FunctionMapper; import pairmatching.domain.entity.CourseMission; @@ -13,6 +14,8 @@ public class InputView { public Function inputFunction() { System.out.println(INPUT_FUNCTION.getMessage()); + outputFunctions(); + String input = InputUtil.input(); return FunctionMapper.toFunction(input); @@ -24,4 +27,10 @@ public CourseMission inputCourseMission() { return CourseMissionMapper.toCourseMission(input); } + + private static void outputFunctions() { + Arrays.stream(Function.values()) + .forEach(function + -> System.out.println(function.getOption() + ". " + function.getDescription())); + } } From 2fa1c6b071b861fbbe800dec82f5d2ce4fd0f5d5 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:29:55 +0900 Subject: [PATCH 24/37] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/util/InputUtil.java | 6 ++++-- src/main/java/pairmatching/view/OutputView.java | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/pairmatching/util/InputUtil.java b/src/main/java/pairmatching/util/InputUtil.java index bd37657ff..1d5b67fc2 100644 --- a/src/main/java/pairmatching/util/InputUtil.java +++ b/src/main/java/pairmatching/util/InputUtil.java @@ -1,6 +1,7 @@ package pairmatching.util; import camp.nextstep.edu.missionutils.Console; +import java.util.function.Consumer; import java.util.function.Supplier; public final class InputUtil { @@ -9,12 +10,13 @@ public static String input() { return Console.readLine(); } - public static T retryOnInvalidInput(Supplier inputSupplier, String errorMessage) { + public static T retryOnInvalidInput(Supplier inputSupplier, + Consumer errorHandler) { while (true) { try { return inputSupplier.get(); } catch (IllegalArgumentException e) { - System.out.println(errorMessage); + errorHandler.accept(e.getMessage()); } } } diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index a0c75cadf..9f3aa79ca 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -5,6 +5,7 @@ import static pairmatching.messages.IOMessages.OUTPUT_DIVIDING_LINE; import static pairmatching.messages.IOMessages.OUTPUT_PAIRMATCHING_RESULT; +import pairmatching.domain.dto.MatchingResultDto; import pairmatching.domain.entity.Course; import pairmatching.domain.entity.Level; import pairmatching.domain.entity.Mission; @@ -22,8 +23,13 @@ public void outputCourseMission() { System.out.println(OUTPUT_DIVIDING_LINE.getMessage()); } - public void outputPairMatchingResult() { + public void outputPairMatchingResult(MatchingResultDto matchingResultDto) { System.out.println(OUTPUT_PAIRMATCHING_RESULT.getMessage()); + + } + + public void outputErrorMessage(String message) { + System.out.println(message); } private void outputCourses() { @@ -48,4 +54,5 @@ private String formatMissionsForLevel(Level level) { return " - " + level.getDescription() + ": " + missions; } + } From f4130e368e29af2bf2ecb9957aa8a2589b1914d0 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:30:24 +0900 Subject: [PATCH 25/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=9E=98=EB=AA=BB=EB=90=9C=20=EA=B0=92=EC=9D=84=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=ED=95=98=EB=A9=B4=20IllegalArgumentException?= =?UTF-8?q?=EC=99=80=20[ERROR]=EB=A1=9C=20=EC=8B=9C=EC=9E=91=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=20=ED=9B=84=20=ED=95=B4=EB=8B=B9?= =?UTF-8?q?=20=EB=B6=80=EB=B6=84=EB=B6=80=ED=84=B0=20=EB=8B=A4=EC=8B=9C=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EC=9D=84=20=EB=B0=9B=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../controller/MatchingController.java | 34 +++++++++++++++++++ .../pairmatching/messages/ErrorMessages.java | 19 +++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pairmatching/controller/MatchingController.java create mode 100644 src/main/java/pairmatching/messages/ErrorMessages.java diff --git a/docs/README.md b/docs/README.md index ea43174ad..0906bec90 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,7 +56,7 @@   [입력 화면] -- 사용자가 잘못된 값을 입력하면 IllegalArgumentException와 [ERROR]로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. +- 사용자가 잘못된 값을 입력하면 IllegalArgumentException와 [ERROR]로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. O - 사용자는 "기능 메뉴 선택" 정수 1개를 입력 O - 1번은 페어 매칭, 2번은 페어 조회, 3번은 페어 초기화, Q는 종료 O - 검증: 만약 없는 메뉴를 입력하면 잘못 입력한 것. O diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java new file mode 100644 index 000000000..5b4c9861a --- /dev/null +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -0,0 +1,34 @@ +package pairmatching.controller; + +import static pairmatching.messages.ErrorMessages.INVALID_FUNCTION; + +import pairmatching.domain.entity.Function; +import pairmatching.util.InputUtil; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; + +public class MatchingController { + + private final InputView inputView; + private final OutputView outputView; + + public MatchingController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void play() { + final Function function = inputValidFunction(); + } + + private Function inputValidFunction() { + return InputUtil.retryOnInvalidInput(this::inputFunction, + errorMessage -> outputView.outputErrorMessage(errorMessage)); + } + + private Function inputFunction() { + return inputView.inputFunction(); + } + + +} diff --git a/src/main/java/pairmatching/messages/ErrorMessages.java b/src/main/java/pairmatching/messages/ErrorMessages.java new file mode 100644 index 000000000..2fd7247a0 --- /dev/null +++ b/src/main/java/pairmatching/messages/ErrorMessages.java @@ -0,0 +1,19 @@ +package pairmatching.messages; + +public enum ErrorMessages { + + INVALID_FUNCTION("타당하지 않은 기능입니다."), + INVALID_COURSE_MISSION("타당하지 않은 과정, 레벨, 미션입니다."), + INVALID_REMATCHING_SELECT("타당하지 않은 선택입니다."); + + private final String message; + private static final String prefix = "[ERROR] "; + + ErrorMessages(final String message) { + this.message = prefix + message; + } + + public String getMessage() { + return message; + } +} From a2eac25d7817305410fead0c1ef86babb40502be Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:30:53 +0900 Subject: [PATCH 26/37] =?UTF-8?q?test:=20=ED=8E=98=EC=96=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EA=B2=B0=EA=B3=BC=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dto/MatchingResultDtoTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java diff --git a/src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java b/src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java new file mode 100644 index 000000000..fdef93fe3 --- /dev/null +++ b/src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java @@ -0,0 +1,34 @@ +package pairmatching.domain.dto; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.Pair; + +public class MatchingResultDtoTest { + private static Stream 제공_매칭결과와_예상결과() { + return Stream.of( + Arguments.of( + new MatchingResult(Arrays.asList(new Pair(Arrays.asList("크루1", "크루2")))), + Arrays.asList(Arrays.asList("크루1", "크루2")) + ) + ); + } + + + @ParameterizedTest + @MethodSource("제공_매칭결과와_예상결과") + void 매칭결과_DTO_변환_테스트(MatchingResult matchingResult, List> expected) { + // When: 실행 + List> actual = MatchingResultDto.from(matchingResult); + + // Then: 검증 + assertEquals(expected, actual); + } +} From 22e2c6abefefadd366a406354887e150f1fad8e5 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:31:10 +0900 Subject: [PATCH 27/37] =?UTF-8?q?feat:=20=ED=8E=98=EC=96=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EA=B2=B0=EA=B3=BC=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dto/MatchingResultDto.java | 19 +++++++++++++++++++ .../domain/entity/MatchingResult.java | 15 +++++++++++++++ .../java/pairmatching/domain/entity/Pair.java | 15 +++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 src/main/java/pairmatching/domain/dto/MatchingResultDto.java create mode 100644 src/main/java/pairmatching/domain/entity/MatchingResult.java create mode 100644 src/main/java/pairmatching/domain/entity/Pair.java diff --git a/src/main/java/pairmatching/domain/dto/MatchingResultDto.java b/src/main/java/pairmatching/domain/dto/MatchingResultDto.java new file mode 100644 index 000000000..8875e928a --- /dev/null +++ b/src/main/java/pairmatching/domain/dto/MatchingResultDto.java @@ -0,0 +1,19 @@ +package pairmatching.domain.dto; + +import java.util.List; +import java.util.stream.Collectors; +import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.Pair; + +public class MatchingResultDto { + + public static List> from(MatchingResult matchingResult) { + List pairs = matchingResult.getPairs(); + + return pairs + .stream() + .map(pair -> pair.getCrews()) + .collect(Collectors.toList()); + } +} + diff --git a/src/main/java/pairmatching/domain/entity/MatchingResult.java b/src/main/java/pairmatching/domain/entity/MatchingResult.java new file mode 100644 index 000000000..2f6fdb662 --- /dev/null +++ b/src/main/java/pairmatching/domain/entity/MatchingResult.java @@ -0,0 +1,15 @@ +package pairmatching.domain.entity; + +import java.util.List; + +public class MatchingResult { + private final List pairs; + + public MatchingResult(List pairs) { + this.pairs = pairs; + } + + public List getPairs() { + return pairs; + } +} diff --git a/src/main/java/pairmatching/domain/entity/Pair.java b/src/main/java/pairmatching/domain/entity/Pair.java new file mode 100644 index 000000000..31498b2d2 --- /dev/null +++ b/src/main/java/pairmatching/domain/entity/Pair.java @@ -0,0 +1,15 @@ +package pairmatching.domain.entity; + +import java.util.List; + +public class Pair { + private final List crews; + + public Pair(List crews) { + this.crews = crews; + } + + public List getCrews() { + return crews; + } +} From 08d1d95e0c59afaa98ae322b959d9596444252b1 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:33:21 +0900 Subject: [PATCH 28/37] =?UTF-8?q?refactor:=20util=EC=84=B1=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EC=97=90=20private=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/pairmatching/domain/dto/CourseMissionMapper.java | 5 +++++ src/main/java/pairmatching/domain/dto/FunctionMapper.java | 3 +++ src/main/java/pairmatching/domain/dto/MatchingResultDto.java | 3 +++ src/main/java/pairmatching/util/ExceptionUtil.java | 4 ++++ src/main/java/pairmatching/util/FileUtil.java | 5 +++++ src/main/java/pairmatching/util/InputUtil.java | 4 ++++ src/main/java/pairmatching/util/StringUtil.java | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java b/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java index e8552f16f..daaac298a 100644 --- a/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java +++ b/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java @@ -10,6 +10,11 @@ import pairmatching.util.StringUtil; public class CourseMissionMapper { + + private CourseMissionMapper() { + + } + public static CourseMission toCourseMission(String input) { List separated = seperate(input); diff --git a/src/main/java/pairmatching/domain/dto/FunctionMapper.java b/src/main/java/pairmatching/domain/dto/FunctionMapper.java index 6ab91a11b..9d2cc3ef7 100644 --- a/src/main/java/pairmatching/domain/dto/FunctionMapper.java +++ b/src/main/java/pairmatching/domain/dto/FunctionMapper.java @@ -4,6 +4,9 @@ import pairmatching.util.StringUtil; public class FunctionMapper { + private FunctionMapper() { + + } public static Function toFunction(String input) { final String deleteSpaces = StringUtil.removeAllSpaces(input); diff --git a/src/main/java/pairmatching/domain/dto/MatchingResultDto.java b/src/main/java/pairmatching/domain/dto/MatchingResultDto.java index 8875e928a..ff7762428 100644 --- a/src/main/java/pairmatching/domain/dto/MatchingResultDto.java +++ b/src/main/java/pairmatching/domain/dto/MatchingResultDto.java @@ -6,6 +6,8 @@ import pairmatching.domain.entity.Pair; public class MatchingResultDto { + private MatchingResultDto() { + } public static List> from(MatchingResult matchingResult) { List pairs = matchingResult.getPairs(); @@ -15,5 +17,6 @@ public static List> from(MatchingResult matchingResult) { .map(pair -> pair.getCrews()) .collect(Collectors.toList()); } + } diff --git a/src/main/java/pairmatching/util/ExceptionUtil.java b/src/main/java/pairmatching/util/ExceptionUtil.java index 8c1b26c6e..b47f4a94e 100644 --- a/src/main/java/pairmatching/util/ExceptionUtil.java +++ b/src/main/java/pairmatching/util/ExceptionUtil.java @@ -2,6 +2,10 @@ public final class ExceptionUtil { + private ExceptionUtil() { + + } + public static void throwInvalidValueException() { throw new IllegalArgumentException(); diff --git a/src/main/java/pairmatching/util/FileUtil.java b/src/main/java/pairmatching/util/FileUtil.java index 88a8e89ad..905673b9d 100644 --- a/src/main/java/pairmatching/util/FileUtil.java +++ b/src/main/java/pairmatching/util/FileUtil.java @@ -6,6 +6,11 @@ import java.util.List; public class FileUtil { + + private FileUtil() { + + } + public static List readFileAsList(String filePath) throws IOException { return Files.readAllLines(Paths.get(filePath)); } diff --git a/src/main/java/pairmatching/util/InputUtil.java b/src/main/java/pairmatching/util/InputUtil.java index 1d5b67fc2..287847ec6 100644 --- a/src/main/java/pairmatching/util/InputUtil.java +++ b/src/main/java/pairmatching/util/InputUtil.java @@ -6,6 +6,10 @@ public final class InputUtil { + private InputUtil() { + + } + public static String input() { return Console.readLine(); } diff --git a/src/main/java/pairmatching/util/StringUtil.java b/src/main/java/pairmatching/util/StringUtil.java index 3100090bd..2e26760de 100644 --- a/src/main/java/pairmatching/util/StringUtil.java +++ b/src/main/java/pairmatching/util/StringUtil.java @@ -5,6 +5,10 @@ public final class StringUtil { + private StringUtil() { + + } + public static String removeAllSpaces(final String input) { return input.replace(" ", ""); } From 5d223d27860b6502339cbd50c3090d83200b6c83 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:44:51 +0900 Subject: [PATCH 29/37] =?UTF-8?q?feat:=20=ED=81=AC=EB=A3=A8=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=EC=9D=98=20=EC=88=9C=EC=84=9C=EB=A5=BC=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=EC=9C=BC=EB=A1=9C=20=EC=84=9E=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- src/main/java/pairmatching/util/RandonUtil.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pairmatching/util/RandonUtil.java diff --git a/docs/README.md b/docs/README.md index 0906bec90..8306d6935 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,7 +9,7 @@ - 페어 매칭에 필요한 크루들의 이름을 파일 입출력을 통해 불러온다. O - src/main/resources/backend-crew.md과 src/main/resources/frontend-crew.md 파일을 이용한다. O - 크루들의 이름 목록을 List 형태로 준비한다. O -- 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용한다. +- 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용한다. O - 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. - 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. - 이 경우 한 페어는 3인으로 구성한다. diff --git a/src/main/java/pairmatching/util/RandonUtil.java b/src/main/java/pairmatching/util/RandonUtil.java new file mode 100644 index 000000000..ef1fe603c --- /dev/null +++ b/src/main/java/pairmatching/util/RandonUtil.java @@ -0,0 +1,15 @@ +package pairmatching.util; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; + +public class RandonUtil { + + private RandonUtil() { + + } + + public List suffle(List elements) { + return Randoms.shuffle(elements); + } +} From c554794e767e1437fa6becd7eb115db07d8237c8 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:47:35 +0900 Subject: [PATCH 30/37] =?UTF-8?q?feat:=20=ED=8E=98=EC=96=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EA=B2=B0=EA=B3=BC=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- .../domain/dto/MatchingResultDto.java | 17 +++++--------- .../domain/dto/MatchingResultMapper.java | 22 +++++++++++++++++++ .../java/pairmatching/view/OutputView.java | 9 ++++++++ ...est.java => MatchingResultMapperTest.java} | 4 ++-- 5 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 src/main/java/pairmatching/domain/dto/MatchingResultMapper.java rename src/test/java/pairmatching/domain/dto/{MatchingResultDtoTest.java => MatchingResultMapperTest.java} (89%) diff --git a/docs/README.md b/docs/README.md index 8306d6935..e52a2c460 100644 --- a/docs/README.md +++ b/docs/README.md @@ -87,7 +87,7 @@ - 레벨5: ############################################ ``` -- 페어 매칭 결과 출력 +- 페어 매칭 결과 출력 O ``` 페어 매칭 결과입니다. 이브 : 윌터 diff --git a/src/main/java/pairmatching/domain/dto/MatchingResultDto.java b/src/main/java/pairmatching/domain/dto/MatchingResultDto.java index ff7762428..96e38ce4c 100644 --- a/src/main/java/pairmatching/domain/dto/MatchingResultDto.java +++ b/src/main/java/pairmatching/domain/dto/MatchingResultDto.java @@ -1,22 +1,17 @@ package pairmatching.domain.dto; import java.util.List; -import java.util.stream.Collectors; -import pairmatching.domain.entity.MatchingResult; -import pairmatching.domain.entity.Pair; public class MatchingResultDto { - private MatchingResultDto() { - } - public static List> from(MatchingResult matchingResult) { - List pairs = matchingResult.getPairs(); + private final List> matchingResult; - return pairs - .stream() - .map(pair -> pair.getCrews()) - .collect(Collectors.toList()); + public MatchingResultDto(List> matchingResult) { + this.matchingResult = matchingResult; } + public List> getMatchingResult() { + return matchingResult; + } } diff --git a/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java b/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java new file mode 100644 index 000000000..2d79bfa6e --- /dev/null +++ b/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java @@ -0,0 +1,22 @@ +package pairmatching.domain.dto; + +import java.util.List; +import java.util.stream.Collectors; +import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.Pair; + +public class MatchingResultMapper { + + private MatchingResultMapper() { + } + + public static List> from(MatchingResult matchingResult) { + List pairs = matchingResult.getPairs(); + + return pairs + .stream() + .map(pair -> pair.getCrews()) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 9f3aa79ca..52111e65a 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -5,6 +5,7 @@ import static pairmatching.messages.IOMessages.OUTPUT_DIVIDING_LINE; import static pairmatching.messages.IOMessages.OUTPUT_PAIRMATCHING_RESULT; +import java.util.List; import pairmatching.domain.dto.MatchingResultDto; import pairmatching.domain.entity.Course; import pairmatching.domain.entity.Level; @@ -26,6 +27,14 @@ public void outputCourseMission() { public void outputPairMatchingResult(MatchingResultDto matchingResultDto) { System.out.println(OUTPUT_PAIRMATCHING_RESULT.getMessage()); + List> matchings = matchingResultDto.getMatchingResult(); + matchings.stream() + .map(this::formatPair) + .forEach(System.out::println); + } + + private String formatPair(List list) { + return String.join(" : ", list); } public void outputErrorMessage(String message) { diff --git a/src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java b/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java similarity index 89% rename from src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java rename to src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java index fdef93fe3..556e6b29d 100644 --- a/src/test/java/pairmatching/domain/dto/MatchingResultDtoTest.java +++ b/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java @@ -11,7 +11,7 @@ import pairmatching.domain.entity.MatchingResult; import pairmatching.domain.entity.Pair; -public class MatchingResultDtoTest { +public class MatchingResultMapperTest { private static Stream 제공_매칭결과와_예상결과() { return Stream.of( Arguments.of( @@ -26,7 +26,7 @@ public class MatchingResultDtoTest { @MethodSource("제공_매칭결과와_예상결과") void 매칭결과_DTO_변환_테스트(MatchingResult matchingResult, List> expected) { // When: 실행 - List> actual = MatchingResultDto.from(matchingResult); + List> actual = MatchingResultMapper.from(matchingResult); // Then: 검증 assertEquals(expected, actual); From 4a83a2bd0fd2ad3c434706d02d4334231c1ffd7b Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:53:15 +0900 Subject: [PATCH 31/37] =?UTF-8?q?refactor:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=ED=8C=A9=ED=84=B0=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/pairmatching/domain/entity/MatchingResult.java | 6 +++++- src/main/java/pairmatching/domain/entity/Pair.java | 6 +++++- .../pairmatching/domain/dto/MatchingResultMapperTest.java | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/pairmatching/domain/entity/MatchingResult.java b/src/main/java/pairmatching/domain/entity/MatchingResult.java index 2f6fdb662..a03cb861e 100644 --- a/src/main/java/pairmatching/domain/entity/MatchingResult.java +++ b/src/main/java/pairmatching/domain/entity/MatchingResult.java @@ -5,10 +5,14 @@ public class MatchingResult { private final List pairs; - public MatchingResult(List pairs) { + private MatchingResult(List pairs) { this.pairs = pairs; } + public static MatchingResult create(List pairs) { + return new MatchingResult(pairs); + } + public List getPairs() { return pairs; } diff --git a/src/main/java/pairmatching/domain/entity/Pair.java b/src/main/java/pairmatching/domain/entity/Pair.java index 31498b2d2..6cbc91e09 100644 --- a/src/main/java/pairmatching/domain/entity/Pair.java +++ b/src/main/java/pairmatching/domain/entity/Pair.java @@ -5,10 +5,14 @@ public class Pair { private final List crews; - public Pair(List crews) { + private Pair(List crews) { this.crews = crews; } + public static Pair create(List crews) { + return new Pair(crews); + } + public List getCrews() { return crews; } diff --git a/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java b/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java index 556e6b29d..5ee6f6a6e 100644 --- a/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java +++ b/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java @@ -15,7 +15,7 @@ public class MatchingResultMapperTest { private static Stream 제공_매칭결과와_예상결과() { return Stream.of( Arguments.of( - new MatchingResult(Arrays.asList(new Pair(Arrays.asList("크루1", "크루2")))), + MatchingResult.create(Arrays.asList(Pair.create(Arrays.asList("크루1", "크루2")))), Arrays.asList(Arrays.asList("크루1", "크루2")) ) ); From 26b2dcbd407f8c854e4880d488dc7a4f7775c919 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 21:53:21 +0900 Subject: [PATCH 32/37] =?UTF-8?q?fix:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/util/RandonUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pairmatching/util/RandonUtil.java b/src/main/java/pairmatching/util/RandonUtil.java index ef1fe603c..17f6d4828 100644 --- a/src/main/java/pairmatching/util/RandonUtil.java +++ b/src/main/java/pairmatching/util/RandonUtil.java @@ -9,7 +9,7 @@ private RandonUtil() { } - public List suffle(List elements) { + public static List shuffle(List elements) { return Randoms.shuffle(elements); } } From 60b14ef4e271ca23ebf459cb820c842b96f3c411 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 22:29:09 +0900 Subject: [PATCH 33/37] =?UTF-8?q?feat:=20=EC=A0=80=EC=9E=A5=EC=86=8C?= =?UTF-8?q?=EC=97=90=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/domain/entity/Course.java | 2 + .../domain/entity/CourseMission.java | 23 ++++++++++ .../repository/MatchingResultRepository.java | 24 ++++++++++ .../domain/entity/CourseMissionTest.java | 46 +++++++++++++++++++ .../domain/{dto => entity}/CourseTest.java | 3 +- 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/main/java/pairmatching/repository/MatchingResultRepository.java create mode 100644 src/test/java/pairmatching/domain/entity/CourseMissionTest.java rename src/test/java/pairmatching/domain/{dto => entity}/CourseTest.java (96%) diff --git a/src/main/java/pairmatching/domain/entity/Course.java b/src/main/java/pairmatching/domain/entity/Course.java index f01d20685..619b76444 100644 --- a/src/main/java/pairmatching/domain/entity/Course.java +++ b/src/main/java/pairmatching/domain/entity/Course.java @@ -47,4 +47,6 @@ public String getFilePath() throws URISyntaxException { .getResource(filePath) .toURI()).toString(); } + + } \ No newline at end of file diff --git a/src/main/java/pairmatching/domain/entity/CourseMission.java b/src/main/java/pairmatching/domain/entity/CourseMission.java index b6130df7c..2d5d2436a 100644 --- a/src/main/java/pairmatching/domain/entity/CourseMission.java +++ b/src/main/java/pairmatching/domain/entity/CourseMission.java @@ -1,5 +1,7 @@ package pairmatching.domain.entity; +import java.util.Objects; + public class CourseMission { private final Course course; private final Level level; @@ -26,4 +28,25 @@ public Level getLevel() { public Mission getMission() { return mission; } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || getClass() != other.getClass()) { + return false; + } + + CourseMission compared = (CourseMission) other; + return course.equals(compared.getCourse()) && + level.equals(compared.getLevel()) && + mission.equals(compared.getMission()); + } + + @Override + public int hashCode() { + return Objects.hash(course, level, mission); + } } diff --git a/src/main/java/pairmatching/repository/MatchingResultRepository.java b/src/main/java/pairmatching/repository/MatchingResultRepository.java new file mode 100644 index 000000000..edf660b68 --- /dev/null +++ b/src/main/java/pairmatching/repository/MatchingResultRepository.java @@ -0,0 +1,24 @@ +package pairmatching.repository; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; +import pairmatching.domain.entity.CourseMission; +import pairmatching.domain.entity.MatchingResult; + +public class MatchingResultRepository { + + protected final Map store = new LinkedHashMap<>(); + + public void save(CourseMission courseMission, MatchingResult matchingResult) { + store.put(courseMission, matchingResult); + } + + public Optional findBySameObject(CourseMission courseMission) { + return Optional.ofNullable(store.get(courseMission)); + } + + public void deleteAll() { + store.clear(); + } +} diff --git a/src/test/java/pairmatching/domain/entity/CourseMissionTest.java b/src/test/java/pairmatching/domain/entity/CourseMissionTest.java new file mode 100644 index 000000000..3bb14d4e6 --- /dev/null +++ b/src/test/java/pairmatching/domain/entity/CourseMissionTest.java @@ -0,0 +1,46 @@ +package pairmatching.domain.entity; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.Arguments; + +import static org.junit.jupiter.api.Assertions.*; +import java.util.stream.Stream; + +public class CourseMissionTest { + + private static Stream 제공_코스미션_비교_데이터() { + return Stream.of( + Arguments.of( + CourseMission.create(Course.BACKEND, Level.LEVEL1, Mission.RACING_CAR), + CourseMission.create(Course.BACKEND, Level.LEVEL1, Mission.RACING_CAR), + true + ), + Arguments.of( + CourseMission.create(Course.BACKEND, Level.LEVEL1, Mission.RACING_CAR), + CourseMission.create(Course.BACKEND, Level.LEVEL2, Mission.SHOPPING_CART), + false + ), + Arguments.of( + CourseMission.create(Course.BACKEND, Level.LEVEL1, Mission.RACING_CAR), + new Object(), + false + ), + Arguments.of( + CourseMission.create(Course.BACKEND, Level.LEVEL1, Mission.RACING_CAR), + null, + false + ) + ); + } + + @ParameterizedTest + @MethodSource("제공_코스미션_비교_데이터") + void 코스미션_동등성_테스트(CourseMission mission1, Object mission2, boolean expected) { + // When: 실행 + boolean result = mission1.equals(mission2); + + // Then: 검증 + assertEquals(expected, result); + } +} diff --git a/src/test/java/pairmatching/domain/dto/CourseTest.java b/src/test/java/pairmatching/domain/entity/CourseTest.java similarity index 96% rename from src/test/java/pairmatching/domain/dto/CourseTest.java rename to src/test/java/pairmatching/domain/entity/CourseTest.java index 089e61782..fa22dbe82 100644 --- a/src/test/java/pairmatching/domain/dto/CourseTest.java +++ b/src/test/java/pairmatching/domain/entity/CourseTest.java @@ -1,4 +1,4 @@ -package pairmatching.domain.dto; +package pairmatching.domain.entity; import java.util.List; import org.junit.jupiter.params.ParameterizedTest; @@ -10,7 +10,6 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.stream.Stream; -import pairmatching.domain.entity.Course; public class CourseTest { From be1195655ea6123b3fdda2e3726d8843a0a6bed5 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 22:48:31 +0900 Subject: [PATCH 34/37] =?UTF-8?q?feat:=20=EB=A7=A4=EC=B9=AD=20=EC=9D=B4?= =?UTF-8?q?=EB=A0=A5=EC=9D=B4=20=EC=97=86=EC=9C=BC=EB=A9=B4=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EC=9D=B4=EB=A0=A5=EC=9D=B4=20=EC=97=86=EB=8B=A4?= =?UTF-8?q?=EA=B3=A0=20=EC=95=88=EB=82=B4=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 14 ++-- src/main/java/pairmatching/Application.java | 3 +- .../controller/MatchingController.java | 80 ++++++++++++++++++- .../domain/dto/MatchingResultMapper.java | 7 +- .../pairmatching/domain/entity/Course.java | 1 + .../java/pairmatching/domain/entity/Pair.java | 4 + .../pairmatching/messages/ErrorMessages.java | 1 + .../java/pairmatching/view/OutputView.java | 8 +- .../domain/dto/MatchingResultMapperTest.java | 2 +- 9 files changed, 101 insertions(+), 19 deletions(-) diff --git a/docs/README.md b/docs/README.md index e52a2c460..9ec2852b7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,21 +10,21 @@ - src/main/resources/backend-crew.md과 src/main/resources/frontend-crew.md 파일을 이용한다. O - 크루들의 이름 목록을 List 형태로 준비한다. O - 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용한다. O -- 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. -- 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. - - 이 경우 한 페어는 3인으로 구성한다. +- 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. O +- 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. O + - 이 경우 한 페어는 3인으로 구성한다. O - 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. - 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. [페어 조회 기능] -- 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다. -- 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. - - 이 때, 에러 메세지는 다음과 같다. "[ERROR] 매칭 이력이 없습니다." +- 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다. O +- 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. O + - 이 때, 에러 메세지는 다음과 같다. "[ERROR] 매칭 이력이 없습니다." O [페어 초기화 기능] -- 페어 매칭 정보를 모두 초기화시킨다. +- 페어 매칭 정보를 모두 초기화시킨다. O    [사전 제공 정보] - 과정 O diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index 6f56e741c..584899466 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -1,7 +1,8 @@ package pairmatching; +import pairmatching.domain.entity.Course; + public class Application { public static void main(String[] args) { - // TODO 구현 진행 } } diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java index 5b4c9861a..beb47a404 100644 --- a/src/main/java/pairmatching/controller/MatchingController.java +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -1,8 +1,20 @@ package pairmatching.controller; +import static pairmatching.domain.entity.Function.PAIR_CHECK; +import static pairmatching.domain.entity.Function.PAIR_MATCHING; +import static pairmatching.domain.entity.Function.PAIR_RESET; +import static pairmatching.domain.entity.Function.QUIT; +import static pairmatching.messages.ErrorMessages.INVALID_COURSE_MISSION; import static pairmatching.messages.ErrorMessages.INVALID_FUNCTION; +import static pairmatching.messages.ErrorMessages.NOT_EXIST_MATCHING_RESULT; +import java.util.Optional; +import pairmatching.domain.dto.MatchingResultMapper; +import pairmatching.domain.entity.Course; +import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.Function; +import pairmatching.domain.entity.MatchingResult; +import pairmatching.service.MatchingService; import pairmatching.util.InputUtil; import pairmatching.view.InputView; import pairmatching.view.OutputView; @@ -11,19 +23,81 @@ public class MatchingController { private final InputView inputView; private final OutputView outputView; + private final MatchingService matchingService; - public MatchingController(InputView inputView, OutputView outputView) { + public MatchingController(InputView inputView, OutputView outputView, MatchingService matchingService) { this.inputView = inputView; this.outputView = outputView; + this.matchingService = matchingService; } public void play() { - final Function function = inputValidFunction(); + + while (true) { + final Function function = inputValidFunction(); + + if (function.equals(QUIT)) { + return; + } + + processFunctionInput(function); + } + } + + private void processFunctionInput(Function function) { + processPairMatching(function); + + processPairCheck(function); + + processPairReset(function); + } + + private void processPairReset(Function function) { + if (function.equals(PAIR_RESET)) { + matchingService.resetMatching(); + } + } + + private void processPairCheck(Function function) { + if (function.equals(PAIR_CHECK)) { + outputView.outputCourseMission(); + final CourseMission courseMission = inputValidCourseMission(); + + Optional matchingResult = matchingService.findMatchingResult(courseMission); + + if (!matchingResult.isPresent()) { + outputView.outputErrorMessage(NOT_EXIST_MATCHING_RESULT.getMessage()); + } + else { + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult.get())); + } + } + } + + private void processPairMatching(Function function) { + if (function.equals(PAIR_MATCHING)) { + outputView.outputCourseMission(); + final CourseMission courseMission = inputValidCourseMission(); + + Course course = courseMission.getCourse(); + MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); + + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); + } + } + + private CourseMission inputValidCourseMission() { + return InputUtil.retryOnInvalidInput(this::inputCourseMission, + errorMessage -> outputView.outputErrorMessage(INVALID_COURSE_MISSION.getMessage())); + } + + private CourseMission inputCourseMission() { + return inputView.inputCourseMission(); } private Function inputValidFunction() { return InputUtil.retryOnInvalidInput(this::inputFunction, - errorMessage -> outputView.outputErrorMessage(errorMessage)); + errorMessage -> outputView.outputErrorMessage(INVALID_FUNCTION.getMessage())); } private Function inputFunction() { diff --git a/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java b/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java index 2d79bfa6e..c435d51bb 100644 --- a/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java +++ b/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java @@ -10,13 +10,14 @@ public class MatchingResultMapper { private MatchingResultMapper() { } - public static List> from(MatchingResult matchingResult) { + public static MatchingResultDto from(MatchingResult matchingResult) { List pairs = matchingResult.getPairs(); - - return pairs + List> transformed = pairs .stream() .map(pair -> pair.getCrews()) .collect(Collectors.toList()); + + return new MatchingResultDto(transformed); } } diff --git a/src/main/java/pairmatching/domain/entity/Course.java b/src/main/java/pairmatching/domain/entity/Course.java index 619b76444..ce437b05f 100644 --- a/src/main/java/pairmatching/domain/entity/Course.java +++ b/src/main/java/pairmatching/domain/entity/Course.java @@ -27,6 +27,7 @@ public static Course findCourse(String courseName) { .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); } + public List getCrews() { try { return FileUtil.readFileAsList(getFilePath()); diff --git a/src/main/java/pairmatching/domain/entity/Pair.java b/src/main/java/pairmatching/domain/entity/Pair.java index 6cbc91e09..a736eae24 100644 --- a/src/main/java/pairmatching/domain/entity/Pair.java +++ b/src/main/java/pairmatching/domain/entity/Pair.java @@ -16,4 +16,8 @@ public static Pair create(List crews) { public List getCrews() { return crews; } + + public void addCrew(String crew) { + crews.add(crew); + } } diff --git a/src/main/java/pairmatching/messages/ErrorMessages.java b/src/main/java/pairmatching/messages/ErrorMessages.java index 2fd7247a0..bc65ec255 100644 --- a/src/main/java/pairmatching/messages/ErrorMessages.java +++ b/src/main/java/pairmatching/messages/ErrorMessages.java @@ -4,6 +4,7 @@ public enum ErrorMessages { INVALID_FUNCTION("타당하지 않은 기능입니다."), INVALID_COURSE_MISSION("타당하지 않은 과정, 레벨, 미션입니다."), + NOT_EXIST_MATCHING_RESULT("매칭 이력이 없습니다."), INVALID_REMATCHING_SELECT("타당하지 않은 선택입니다."); private final String message; diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 52111e65a..5b321ebb7 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -33,14 +33,14 @@ public void outputPairMatchingResult(MatchingResultDto matchingResultDto) { .forEach(System.out::println); } - private String formatPair(List list) { - return String.join(" : ", list); - } - public void outputErrorMessage(String message) { System.out.println(message); } + private String formatPair(List list) { + return String.join(" : ", list); + } + private void outputCourses() { String courses = Arrays.stream(Course.values()) .map(Course::getDescription) diff --git a/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java b/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java index 5ee6f6a6e..18c363824 100644 --- a/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java +++ b/src/test/java/pairmatching/domain/dto/MatchingResultMapperTest.java @@ -26,7 +26,7 @@ public class MatchingResultMapperTest { @MethodSource("제공_매칭결과와_예상결과") void 매칭결과_DTO_변환_테스트(MatchingResult matchingResult, List> expected) { // When: 실행 - List> actual = MatchingResultMapper.from(matchingResult); + List> actual = MatchingResultMapper.from(matchingResult).getMatchingResult(); // Then: 검증 assertEquals(expected, actual); From 2a0ac29a1bb70bca41f953a6d246d2c4b4d22eb4 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 23:01:24 +0900 Subject: [PATCH 35/37] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EC=A0=95=EB=B3=B4=EA=B0=80=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=9E=AC=EB=A7=A4=EC=B9=AD=ED=95=A0?= =?UTF-8?q?=EC=A7=80=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 10 +++---- .../controller/MatchingController.java | 30 +++++++++++++++++-- .../domain/dto/RematchingOptionMapper.java | 9 ++++++ .../domain/entity/RematchingOption.java | 26 ++++++++++++++++ .../pairmatching/messages/IOMessages.java | 3 +- .../java/pairmatching/view/InputView.java | 13 ++++++++ 6 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 src/main/java/pairmatching/domain/dto/RematchingOptionMapper.java create mode 100644 src/main/java/pairmatching/domain/entity/RematchingOption.java diff --git a/docs/README.md b/docs/README.md index 9ec2852b7..d35eb18d4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -68,11 +68,11 @@ - 검증: 선택한 과정에 입력한 미션이 없으면 잘못된 입력 O - 오타 교정: 입력 항목 사이에 불필요한 ,는 자동으로 제거해줌 O - 오타 교정: 전체 입력 문장에서 모든 공백을 제거해줌. O -- 이미 매칭 정보가 있는 경우 재매칭할지에 대한 정보를 입력받는다. - - 사용자는 문자 하나를 입력한다. - - 예를 선택할 경우 페어를 재매칭한다. - - 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. - - 검증: 예, 아니오가 아닌 값을 입력하면 잘못입력한 것. +- 이미 매칭 정보가 있는 경우 재매칭할지에 대한 정보를 입력받는다. O + - 사용자는 문자 하나를 입력한다. O + - 예를 선택할 경우 페어를 재매칭한다. O + - 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. O + - 검증: 예, 아니오가 아닌 값을 입력하면 잘못입력한 것. O [출력 화면] - 과정와 미션을 출력 O diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java index beb47a404..28648112a 100644 --- a/src/main/java/pairmatching/controller/MatchingController.java +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -4,8 +4,10 @@ import static pairmatching.domain.entity.Function.PAIR_MATCHING; import static pairmatching.domain.entity.Function.PAIR_RESET; import static pairmatching.domain.entity.Function.QUIT; +import static pairmatching.domain.entity.RematchingOption.YES; import static pairmatching.messages.ErrorMessages.INVALID_COURSE_MISSION; import static pairmatching.messages.ErrorMessages.INVALID_FUNCTION; +import static pairmatching.messages.ErrorMessages.INVALID_REMATCHING_SELECT; import static pairmatching.messages.ErrorMessages.NOT_EXIST_MATCHING_RESULT; import java.util.Optional; @@ -14,6 +16,7 @@ import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.Function; import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.RematchingOption; import pairmatching.service.MatchingService; import pairmatching.util.InputUtil; import pairmatching.view.InputView; @@ -78,14 +81,35 @@ private void processPairMatching(Function function) { if (function.equals(PAIR_MATCHING)) { outputView.outputCourseMission(); final CourseMission courseMission = inputValidCourseMission(); - Course course = courseMission.getCourse(); - MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); - outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); + Optional foundMatchingResult = matchingService.findMatchingResult(courseMission); + if (!foundMatchingResult.isPresent()) { + RematchingOption rematchingOption = inputValidRematchingOption(); + if (rematchingOption.equals(YES)) { + MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); + matchingService.save(courseMission, matchingResult); + } + } + + else { + MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); + matchingService.save(courseMission, matchingResult); + } } } + private RematchingOption inputValidRematchingOption() { + return InputUtil.retryOnInvalidInput(this::inputRematchingOption, + errorMessage -> outputView.outputErrorMessage(INVALID_REMATCHING_SELECT.getMessage())); + } + + private RematchingOption inputRematchingOption() { + return inputView.inputRematchingOption(); + } + private CourseMission inputValidCourseMission() { return InputUtil.retryOnInvalidInput(this::inputCourseMission, errorMessage -> outputView.outputErrorMessage(INVALID_COURSE_MISSION.getMessage())); diff --git a/src/main/java/pairmatching/domain/dto/RematchingOptionMapper.java b/src/main/java/pairmatching/domain/dto/RematchingOptionMapper.java new file mode 100644 index 000000000..9d894e438 --- /dev/null +++ b/src/main/java/pairmatching/domain/dto/RematchingOptionMapper.java @@ -0,0 +1,9 @@ +package pairmatching.domain.dto; + +import pairmatching.domain.entity.RematchingOption; + +public class RematchingOptionMapper { + public static RematchingOption toRematchingOption(String input) { + return RematchingOption.findRematchingOption(input); + } +} diff --git a/src/main/java/pairmatching/domain/entity/RematchingOption.java b/src/main/java/pairmatching/domain/entity/RematchingOption.java new file mode 100644 index 000000000..231367e71 --- /dev/null +++ b/src/main/java/pairmatching/domain/entity/RematchingOption.java @@ -0,0 +1,26 @@ +package pairmatching.domain.entity; + +import java.util.Arrays; +import pairmatching.util.ExceptionUtil; + +public enum RematchingOption { + YES("네"), + NO("아니오"); + + private final String description; + + RematchingOption(String description) { + this.description = description; + } + + public static RematchingOption findRematchingOption(String input) { + return Arrays.stream(values()) + .filter(rematchingOption -> rematchingOption.description.equals(input)) + .findAny() + .orElseThrow(() -> ExceptionUtil.returnInvalidValueException()); + } + + public String getDescription() { + return description; + } +} diff --git a/src/main/java/pairmatching/messages/IOMessages.java b/src/main/java/pairmatching/messages/IOMessages.java index 7141c92f8..5ab367a3d 100644 --- a/src/main/java/pairmatching/messages/IOMessages.java +++ b/src/main/java/pairmatching/messages/IOMessages.java @@ -8,9 +8,10 @@ public enum IOMessages { INPUT_SELECT_OPTIONS(String.format("%s, %s, %s을 선택하세요.",COURSE,LEVEL,MISSION)), SELECT_EXAMPLE("ex) 백엔드, 레벨1, 자동차경주"), INPUT_FUNCTION("기능을 선택하세요."), + INPUT_REMATCHING("매칭 정보가 있습니다. 다시 매칭하시겠습니까?"), OUTPUT_DIVIDING_LINE("#############################################"), OUTPUT_PAIRMATCHING_RESULT("페어 매칭 결과입니다."), - OUTPUT_RESET("초기화 되었습니다."); + OUTPUT_RESET("초기화 되었습니다."),; private final String message; diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 18012dea0..1dd5d4445 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -1,13 +1,17 @@ package pairmatching.view; import static pairmatching.messages.IOMessages.INPUT_FUNCTION; +import static pairmatching.messages.IOMessages.INPUT_REMATCHING; import static pairmatching.messages.IOMessages.INPUT_SELECT_OPTIONS; +import static pairmatching.messages.IOMessages.SELECT_EXAMPLE; import java.util.Arrays; import pairmatching.domain.dto.CourseMissionMapper; import pairmatching.domain.dto.FunctionMapper; +import pairmatching.domain.dto.RematchingOptionMapper; import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.Function; +import pairmatching.domain.entity.RematchingOption; import pairmatching.util.InputUtil; public class InputView { @@ -23,11 +27,20 @@ public Function inputFunction() { public CourseMission inputCourseMission() { System.out.println(INPUT_SELECT_OPTIONS.getMessage()); + System.out.println(SELECT_EXAMPLE.getMessage()); String input = InputUtil.input(); return CourseMissionMapper.toCourseMission(input); } + public RematchingOption inputRematchingOption() { + System.out.println(INPUT_REMATCHING); + System.out.println(RematchingOption.YES+" | "+RematchingOption.NO); + String input = InputUtil.input(); + + return RematchingOptionMapper.toRematchingOption(input); + } + private static void outputFunctions() { Arrays.stream(Function.values()) .forEach(function From 10c7a42ae505858dfa33e3930717917c1be60335 Mon Sep 17 00:00:00 2001 From: inpink Date: Mon, 27 Nov 2023 23:22:57 +0900 Subject: [PATCH 36/37] =?UTF-8?q?feat:=20=ED=99=80=EC=88=98=EC=9D=B8=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EB=A7=88=EC=A7=80=EB=A7=89=20=EB=82=A8?= =?UTF-8?q?=EC=9D=80=20=ED=81=AC=EB=A3=A8=EB=8A=94=20=EB=A7=88=EC=A7=80?= =?UTF-8?q?=EB=A7=89=20=ED=8E=98=EC=96=B4=EC=97=90=20=ED=8F=AC=ED=95=A8?= =?UTF-8?q?=EC=8B=9C=ED=82=A8=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MatchingController.java | 27 ++++---- .../pairmatching/service/MatchingService.java | 61 +++++++++++++++++++ src/main/java/pairmatching/util/MathUtil.java | 10 +++ .../service/MatchingServiceTest.java | 39 ++++++++++++ 4 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 src/main/java/pairmatching/service/MatchingService.java create mode 100644 src/main/java/pairmatching/util/MathUtil.java create mode 100644 src/test/java/pairmatching/service/MatchingServiceTest.java diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java index 28648112a..7bceaeef0 100644 --- a/src/main/java/pairmatching/controller/MatchingController.java +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -42,7 +42,7 @@ public void play() { if (function.equals(QUIT)) { return; } - + processFunctionInput(function); } } @@ -70,10 +70,9 @@ private void processPairCheck(Function function) { if (!matchingResult.isPresent()) { outputView.outputErrorMessage(NOT_EXIST_MATCHING_RESULT.getMessage()); + return; } - else { - outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult.get())); - } + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult.get())); } } @@ -87,20 +86,20 @@ private void processPairMatching(Function function) { if (!foundMatchingResult.isPresent()) { RematchingOption rematchingOption = inputValidRematchingOption(); if (rematchingOption.equals(YES)) { - MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); - outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); - matchingService.save(courseMission, matchingResult); + processMatchingResult(course, courseMission); } + return; } - - else { - MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); - outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); - matchingService.save(courseMission, matchingResult); - } + processMatchingResult(course, courseMission); } } + private void processMatchingResult(Course course, CourseMission courseMission) { + MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); + matchingService.save(courseMission, matchingResult); + } + private RematchingOption inputValidRematchingOption() { return InputUtil.retryOnInvalidInput(this::inputRematchingOption, errorMessage -> outputView.outputErrorMessage(INVALID_REMATCHING_SELECT.getMessage())); @@ -127,6 +126,4 @@ private Function inputValidFunction() { private Function inputFunction() { return inputView.inputFunction(); } - - } diff --git a/src/main/java/pairmatching/service/MatchingService.java b/src/main/java/pairmatching/service/MatchingService.java new file mode 100644 index 000000000..249e2e423 --- /dev/null +++ b/src/main/java/pairmatching/service/MatchingService.java @@ -0,0 +1,61 @@ +package pairmatching.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import pairmatching.domain.entity.CourseMission; +import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.Pair; +import pairmatching.repository.MatchingResultRepository; +import pairmatching.util.MathUtil; +import pairmatching.util.RandonUtil; + +public class MatchingService { + + private final MatchingResultRepository matchingResultRepository; + + public MatchingService(MatchingResultRepository matchingResultRepository) { + this.matchingResultRepository = matchingResultRepository; + } + + public MatchingResult createMatchingResult(List crews) { + List shuffledCrews = RandonUtil.shuffle(crews); + List pairs = new ArrayList<>(); + final int crewSize = crews.size(); + final int pairSize = crewSize / 2; + + for (int pairStartIndex = 0; pairStartIndex < pairSize; pairStartIndex++) { + pairs.add(createPair(shuffledCrews, pairStartIndex)); + } + + if (MathUtil.isOddNumber(crewSize)) { + String lastCrew = crews.get(crewSize-1); + pairs.get(pairSize-1).addCrew(lastCrew); + } + + return MatchingResult.create(pairs); + } + + + public Optional findMatchingResult(CourseMission courseMission) { + return matchingResultRepository.findBySameObject(courseMission); + } + + public void resetMatching() { + matchingResultRepository.deleteAll(); + } + + public void save(CourseMission courseMission, MatchingResult matchingResult) { + matchingResultRepository.save(courseMission, matchingResult); + } + + private Pair createPair(final List shuffledCrews,final int index) { + List pairMembers = new ArrayList<>(); + pairMembers.add(shuffledCrews.get(index)); + pairMembers.add(shuffledCrews.get(index + 1)); + + return Pair.create(pairMembers); + } + +} + diff --git a/src/main/java/pairmatching/util/MathUtil.java b/src/main/java/pairmatching/util/MathUtil.java new file mode 100644 index 000000000..4987f7509 --- /dev/null +++ b/src/main/java/pairmatching/util/MathUtil.java @@ -0,0 +1,10 @@ +package pairmatching.util; + +public class MathUtil { + private MathUtil() { + } + + public static boolean isOddNumber(final int size) { + return size % 2 == 1; + } +} diff --git a/src/test/java/pairmatching/service/MatchingServiceTest.java b/src/test/java/pairmatching/service/MatchingServiceTest.java new file mode 100644 index 000000000..d0a9318d1 --- /dev/null +++ b/src/test/java/pairmatching/service/MatchingServiceTest.java @@ -0,0 +1,39 @@ +package pairmatching.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import pairmatching.domain.entity.MatchingResult; +import pairmatching.repository.MatchingResultRepository; + +public class MatchingServiceTest { + + private static Stream 제공_크루목록과_예상_매칭결과() { + return Stream.of( + Arguments.of(Arrays.asList("크루1", "크루2"), 1), // 2명의 크루, 1개의 페어 예상 + Arguments.of(Arrays.asList("크루1", "크루2", "크루3"), 1), // 3명의 크루, 1개의 페어 예상 (3인 페어) + Arguments.of(Arrays.asList("크루1", "크루2", "크루3", "크루4"), 2), // 4명의 크루, 2개의 페어 예상 + Arguments.of(Arrays.asList("크루1", "크루2", "크루3", "크루4", "크루5"), 2), // 5명의 크루, 3개의 페어 예상 + Arguments.of(Arrays.asList( + "크루1", "크루2", "크루3", "크루4", "크루5", "크루6"), 3) // 6명의 크루, 3개의 페어 예상 + ); + } + + @ParameterizedTest + @MethodSource("제공_크루목록과_예상_매칭결과") + void 매칭결과_생성_테스트(List crews, int expectedNumberOfPairs) { + MatchingService matchingService = new MatchingService(new MatchingResultRepository()); + // When: 실행 + MatchingResult matchingResult = matchingService.createMatchingResult(crews); + + // Then: 검증 + assertNotNull(matchingResult); + assertEquals(expectedNumberOfPairs, matchingResult.getPairs().size()); + } +} From 284d263c7921d0e855102298e51d393495c79ca8 Mon Sep 17 00:00:00 2001 From: inpink Date: Tue, 28 Nov 2023 00:40:02 +0900 Subject: [PATCH 37/37] =?UTF-8?q?feat:=203=ED=9A=8C=20=EC=8B=9C=EB=8F=84?= =?UTF-8?q?=EA=B9=8C=EC=A7=80=20=EB=A7=A4=EC=B9=AD=EC=9D=B4=20=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EA=B1=B0=EB=82=98=20=EB=A7=A4=EC=B9=AD?= =?UTF-8?q?=EC=9D=84=20=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=EC=9D=98=20=EC=88=98=EA=B0=80=20=EC=97=86?= =?UTF-8?q?=EC=9C=BC=EB=A9=B4=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 4 +- src/main/java/pairmatching/Application.java | 13 +++- .../controller/MatchingController.java | 75 ++++++++++++++----- .../domain/dto/CourseMissionMapper.java | 6 +- .../domain/dto/FunctionMapper.java | 1 + .../domain/dto/MatchingResultMapper.java | 2 +- .../pairmatching/domain/entity/Function.java | 8 +- .../java/pairmatching/domain/entity/Pair.java | 22 ++++++ .../pairmatching/messages/ErrorMessages.java | 5 +- .../pairmatching/messages/IOMessages.java | 5 +- .../repository/MatchingResultRepository.java | 10 +++ .../pairmatching/service/MatchingService.java | 42 ++++++++--- .../java/pairmatching/util/ExceptionUtil.java | 2 +- .../java/pairmatching/view/InputView.java | 16 ++-- .../java/pairmatching/view/OutputView.java | 8 +- .../java/pairmatching/ApplicationTest.java | 19 +++-- .../domain/dto/CourseMissionMapperTest.java | 14 ++-- .../domain/entity/CourseMissionTest.java | 8 +- .../domain/entity/CourseTest.java | 12 +-- .../java/pairmatching/util/FileUtilTest.java | 15 ++-- 20 files changed, 197 insertions(+), 90 deletions(-) diff --git a/docs/README.md b/docs/README.md index d35eb18d4..70fe9960b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,8 +13,8 @@ - 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. O - 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. O - 이 경우 한 페어는 3인으로 구성한다. O -- 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. - - 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. +- 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. O + - 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. O [페어 조회 기능] diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index 584899466..b71275d50 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -1,8 +1,19 @@ package pairmatching; -import pairmatching.domain.entity.Course; +import pairmatching.controller.MatchingController; +import pairmatching.repository.MatchingResultRepository; +import pairmatching.service.MatchingService; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; public class Application { public static void main(String[] args) { + MatchingController matchingController = new MatchingController( + new InputView(), + new OutputView(), + new MatchingService(new MatchingResultRepository()) + ); + + matchingController.play(); } } diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java index 7bceaeef0..cf6fc4ed8 100644 --- a/src/main/java/pairmatching/controller/MatchingController.java +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -5,6 +5,7 @@ import static pairmatching.domain.entity.Function.PAIR_RESET; import static pairmatching.domain.entity.Function.QUIT; import static pairmatching.domain.entity.RematchingOption.YES; +import static pairmatching.messages.ErrorMessages.FAIL_TO_MATCH; import static pairmatching.messages.ErrorMessages.INVALID_COURSE_MISSION; import static pairmatching.messages.ErrorMessages.INVALID_FUNCTION; import static pairmatching.messages.ErrorMessages.INVALID_REMATCHING_SELECT; @@ -24,6 +25,8 @@ public class MatchingController { + private final int REMATCHING_COUNT = 3; + private final InputView inputView; private final OutputView outputView; private final MatchingService matchingService; @@ -42,22 +45,20 @@ public void play() { if (function.equals(QUIT)) { return; } - processFunctionInput(function); } } private void processFunctionInput(Function function) { processPairMatching(function); - processPairCheck(function); - processPairReset(function); } private void processPairReset(Function function) { if (function.equals(PAIR_RESET)) { matchingService.resetMatching(); + outputView.ouputReset(); } } @@ -66,14 +67,18 @@ private void processPairCheck(Function function) { outputView.outputCourseMission(); final CourseMission courseMission = inputValidCourseMission(); - Optional matchingResult = matchingService.findMatchingResult(courseMission); + checkMatchingResult(courseMission); + } + } - if (!matchingResult.isPresent()) { - outputView.outputErrorMessage(NOT_EXIST_MATCHING_RESULT.getMessage()); - return; - } - outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult.get())); + private void checkMatchingResult(CourseMission courseMission) { + Optional matchingResult = matchingService.findMatchingResult(courseMission); + + if (!matchingResult.isPresent()) { + outputView.outputErrorMessage(NOT_EXIST_MATCHING_RESULT.getMessage()); + return; } + outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult.get())); } private void processPairMatching(Function function) { @@ -82,24 +87,56 @@ private void processPairMatching(Function function) { final CourseMission courseMission = inputValidCourseMission(); Course course = courseMission.getCourse(); - Optional foundMatchingResult = matchingService.findMatchingResult(courseMission); - if (!foundMatchingResult.isPresent()) { - RematchingOption rematchingOption = inputValidRematchingOption(); - if (rematchingOption.equals(YES)) { - processMatchingResult(course, courseMission); - } - return; - } + processExistResult(courseMission, course); + } + } + + private void processExistResult(CourseMission courseMission, Course course) { + Optional foundMatchingResult = matchingService.findMatchingResult(courseMission); + + if (foundMatchingResult.isPresent()) { + RematchingOption rematchingOption = inputValidRematchingOption(); + processRematching(rematchingOption, course, courseMission); + return; + } + processMatchingResult(course, courseMission); + } + + private void processRematching(RematchingOption rematchingOption, Course course, CourseMission courseMission) { + if (rematchingOption.equals(YES)) { processMatchingResult(course, courseMission); } } private void processMatchingResult(Course course, CourseMission courseMission) { - MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); + Optional nonDuplicatedResult = createNonDuplicatedResult(courseMission, course); + + if (!nonDuplicatedResult.isPresent()) { + outputView.outputErrorMessage(FAIL_TO_MATCH.getMessage()); + } + + processNonDuplicatedResult(courseMission, nonDuplicatedResult); + } + + private void processNonDuplicatedResult(CourseMission courseMission, Optional nonDuplicatedResult) { + MatchingResult matchingResult = nonDuplicatedResult.get(); outputView.outputPairMatchingResult(MatchingResultMapper.from(matchingResult)); matchingService.save(courseMission, matchingResult); } + private Optional createNonDuplicatedResult(CourseMission courseMission, Course course) { + int count = 0; + + while (count < REMATCHING_COUNT) { + MatchingResult matchingResult = matchingService.createMatchingResult(course.getCrews()); + if (!matchingService.isDuplicatedPair(courseMission,matchingResult)) { + return Optional.ofNullable(matchingResult); + } + } + + return Optional.empty(); + } + private RematchingOption inputValidRematchingOption() { return InputUtil.retryOnInvalidInput(this::inputRematchingOption, errorMessage -> outputView.outputErrorMessage(INVALID_REMATCHING_SELECT.getMessage())); @@ -126,4 +163,4 @@ private Function inputValidFunction() { private Function inputFunction() { return inputView.inputFunction(); } -} +} \ No newline at end of file diff --git a/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java b/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java index daaac298a..7712c35d7 100644 --- a/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java +++ b/src/main/java/pairmatching/domain/dto/CourseMissionMapper.java @@ -1,12 +1,12 @@ package pairmatching.domain.dto; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import pairmatching.domain.entity.Course; import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.Level; import pairmatching.domain.entity.Mission; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; import pairmatching.util.StringUtil; public class CourseMissionMapper { diff --git a/src/main/java/pairmatching/domain/dto/FunctionMapper.java b/src/main/java/pairmatching/domain/dto/FunctionMapper.java index 9d2cc3ef7..23d754882 100644 --- a/src/main/java/pairmatching/domain/dto/FunctionMapper.java +++ b/src/main/java/pairmatching/domain/dto/FunctionMapper.java @@ -7,6 +7,7 @@ public class FunctionMapper { private FunctionMapper() { } + public static Function toFunction(String input) { final String deleteSpaces = StringUtil.removeAllSpaces(input); diff --git a/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java b/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java index c435d51bb..9c8be5d0e 100644 --- a/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java +++ b/src/main/java/pairmatching/domain/dto/MatchingResultMapper.java @@ -12,7 +12,7 @@ private MatchingResultMapper() { public static MatchingResultDto from(MatchingResult matchingResult) { List pairs = matchingResult.getPairs(); - List> transformed = pairs + List> transformed = pairs .stream() .map(pair -> pair.getCrews()) .collect(Collectors.toList()); diff --git a/src/main/java/pairmatching/domain/entity/Function.java b/src/main/java/pairmatching/domain/entity/Function.java index b2522f064..30f252b61 100644 --- a/src/main/java/pairmatching/domain/entity/Function.java +++ b/src/main/java/pairmatching/domain/entity/Function.java @@ -4,10 +4,10 @@ import pairmatching.util.ExceptionUtil; public enum Function { - PAIR_MATCHING("1","페어 매칭"), - PAIR_CHECK("2","페어 조회"), - PAIR_RESET("3","페어 초기화"), - QUIT("Q","종료"); + PAIR_MATCHING("1", "페어 매칭"), + PAIR_CHECK("2", "페어 조회"), + PAIR_RESET("3", "페어 초기화"), + QUIT("Q", "종료"); private final String option; private final String description; diff --git a/src/main/java/pairmatching/domain/entity/Pair.java b/src/main/java/pairmatching/domain/entity/Pair.java index a736eae24..cb2b5068b 100644 --- a/src/main/java/pairmatching/domain/entity/Pair.java +++ b/src/main/java/pairmatching/domain/entity/Pair.java @@ -1,11 +1,14 @@ package pairmatching.domain.entity; +import java.util.Collections; import java.util.List; +import java.util.Objects; public class Pair { private final List crews; private Pair(List crews) { + Collections.sort(crews); this.crews = crews; } @@ -20,4 +23,23 @@ public List getCrews() { public void addCrew(String crew) { crews.add(crew); } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + + Pair otherPair = (Pair) other; + + return otherPair.getCrews().equals(crews); + } + + @Override + public int hashCode() { + return Objects.hash(crews); + } } diff --git a/src/main/java/pairmatching/messages/ErrorMessages.java b/src/main/java/pairmatching/messages/ErrorMessages.java index bc65ec255..6e8c78734 100644 --- a/src/main/java/pairmatching/messages/ErrorMessages.java +++ b/src/main/java/pairmatching/messages/ErrorMessages.java @@ -5,10 +5,11 @@ public enum ErrorMessages { INVALID_FUNCTION("타당하지 않은 기능입니다."), INVALID_COURSE_MISSION("타당하지 않은 과정, 레벨, 미션입니다."), NOT_EXIST_MATCHING_RESULT("매칭 이력이 없습니다."), - INVALID_REMATCHING_SELECT("타당하지 않은 선택입니다."); + INVALID_REMATCHING_SELECT("타당하지 않은 선택입니다."), + FAIL_TO_MATCH("매칭 실패"); - private final String message; private static final String prefix = "[ERROR] "; + private final String message; ErrorMessages(final String message) { this.message = prefix + message; diff --git a/src/main/java/pairmatching/messages/IOMessages.java b/src/main/java/pairmatching/messages/IOMessages.java index 5ab367a3d..aacbd4316 100644 --- a/src/main/java/pairmatching/messages/IOMessages.java +++ b/src/main/java/pairmatching/messages/IOMessages.java @@ -5,13 +5,14 @@ public enum IOMessages { COURSE("과정"), LEVEL("레벨"), MISSION("미션"), - INPUT_SELECT_OPTIONS(String.format("%s, %s, %s을 선택하세요.",COURSE,LEVEL,MISSION)), + INPUT_SELECT_OPTIONS( + String.format("%s, %s, %s을 선택하세요.", COURSE.getMessage(), LEVEL.getMessage(), MISSION.getMessage())), SELECT_EXAMPLE("ex) 백엔드, 레벨1, 자동차경주"), INPUT_FUNCTION("기능을 선택하세요."), INPUT_REMATCHING("매칭 정보가 있습니다. 다시 매칭하시겠습니까?"), OUTPUT_DIVIDING_LINE("#############################################"), OUTPUT_PAIRMATCHING_RESULT("페어 매칭 결과입니다."), - OUTPUT_RESET("초기화 되었습니다."),; + OUTPUT_RESET("초기화 되었습니다."); private final String message; diff --git a/src/main/java/pairmatching/repository/MatchingResultRepository.java b/src/main/java/pairmatching/repository/MatchingResultRepository.java index edf660b68..946a80750 100644 --- a/src/main/java/pairmatching/repository/MatchingResultRepository.java +++ b/src/main/java/pairmatching/repository/MatchingResultRepository.java @@ -5,6 +5,7 @@ import java.util.Optional; import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.Mission; public class MatchingResultRepository { @@ -18,7 +19,16 @@ public Optional findBySameObject(CourseMission courseMission) { return Optional.ofNullable(store.get(courseMission)); } + public Optional findByMission(Mission mission) { + return store.keySet() + .stream() + .filter(courseMission -> courseMission.getMission().equals(mission)) + .map(courseMission -> store.get(courseMission)) + .findAny(); + } + public void deleteAll() { store.clear(); } + } diff --git a/src/main/java/pairmatching/service/MatchingService.java b/src/main/java/pairmatching/service/MatchingService.java index 249e2e423..7c1a5068f 100644 --- a/src/main/java/pairmatching/service/MatchingService.java +++ b/src/main/java/pairmatching/service/MatchingService.java @@ -5,6 +5,7 @@ import java.util.Optional; import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.MatchingResult; +import pairmatching.domain.entity.Mission; import pairmatching.domain.entity.Pair; import pairmatching.repository.MatchingResultRepository; import pairmatching.util.MathUtil; @@ -19,23 +20,25 @@ public MatchingService(MatchingResultRepository matchingResultRepository) { } public MatchingResult createMatchingResult(List crews) { - List shuffledCrews = RandonUtil.shuffle(crews); - List pairs = new ArrayList<>(); - final int crewSize = crews.size(); + final List shuffledCrews = RandonUtil.shuffle(crews); + final List pairs = new ArrayList<>(); + final int crewSize = shuffledCrews.size(); final int pairSize = crewSize / 2; - for (int pairStartIndex = 0; pairStartIndex < pairSize; pairStartIndex++) { + for (int pairStartIndex = 0; pairStartIndex < crewSize; pairStartIndex += 2) { pairs.add(createPair(shuffledCrews, pairStartIndex)); } - if (MathUtil.isOddNumber(crewSize)) { - String lastCrew = crews.get(crewSize-1); - pairs.get(pairSize-1).addCrew(lastCrew); - } - + processLastCrew(crewSize, shuffledCrews, pairs, pairSize); return MatchingResult.create(pairs); } + private static void processLastCrew(int crewSize, List shuffledCrews, List pairs, int pairSize) { + if (MathUtil.isOddNumber(crewSize)) { + String lastCrew = shuffledCrews.get(crewSize - 1); + pairs.get(pairSize - 1).addCrew(lastCrew); + } + } public Optional findMatchingResult(CourseMission courseMission) { return matchingResultRepository.findBySameObject(courseMission); @@ -49,7 +52,26 @@ public void save(CourseMission courseMission, MatchingResult matchingResult) { matchingResultRepository.save(courseMission, matchingResult); } - private Pair createPair(final List shuffledCrews,final int index) { + public boolean isDuplicatedPair(CourseMission courseMission, MatchingResult matchingResult) { + List missions = courseMission.getLevel().getMissions(); + List pairs = matchingResult.getPairs(); + + return missions.stream() + .allMatch(mission -> { + Optional foundMatchingResult + = matchingResultRepository.findByMission(mission); + + if (!foundMatchingResult.isPresent()) { + return false; + } + + List foundPairs = foundMatchingResult.get().getPairs(); + return foundPairs.stream() + .allMatch(pair -> pairs.contains(pair)); + }); + } + + private Pair createPair(final List shuffledCrews, final int index) { List pairMembers = new ArrayList<>(); pairMembers.add(shuffledCrews.get(index)); pairMembers.add(shuffledCrews.get(index + 1)); diff --git a/src/main/java/pairmatching/util/ExceptionUtil.java b/src/main/java/pairmatching/util/ExceptionUtil.java index b47f4a94e..4c09c027a 100644 --- a/src/main/java/pairmatching/util/ExceptionUtil.java +++ b/src/main/java/pairmatching/util/ExceptionUtil.java @@ -23,7 +23,7 @@ public static void throwInvalidValueException(final String message) { public static IllegalArgumentException returnInvalidValueException(final String message) { - return new IllegalArgumentException(message); + return new IllegalArgumentException(message); } } diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 1dd5d4445..d22afae75 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -16,6 +16,12 @@ public class InputView { + private static void outputFunctions() { + Arrays.stream(Function.values()) + .forEach(function + -> System.out.println(function.getOption() + ". " + function.getDescription())); + } + public Function inputFunction() { System.out.println(INPUT_FUNCTION.getMessage()); outputFunctions(); @@ -34,16 +40,10 @@ public CourseMission inputCourseMission() { } public RematchingOption inputRematchingOption() { - System.out.println(INPUT_REMATCHING); - System.out.println(RematchingOption.YES+" | "+RematchingOption.NO); + System.out.println(INPUT_REMATCHING.getMessage()); + System.out.println(RematchingOption.YES.getDescription() + " | " + RematchingOption.NO.getDescription()); String input = InputUtil.input(); return RematchingOptionMapper.toRematchingOption(input); } - - private static void outputFunctions() { - Arrays.stream(Function.values()) - .forEach(function - -> System.out.println(function.getOption() + ". " + function.getDescription())); - } } diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 5b321ebb7..3e1219e49 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -4,14 +4,15 @@ import static pairmatching.messages.IOMessages.MISSION; import static pairmatching.messages.IOMessages.OUTPUT_DIVIDING_LINE; import static pairmatching.messages.IOMessages.OUTPUT_PAIRMATCHING_RESULT; +import static pairmatching.messages.IOMessages.OUTPUT_RESET; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import pairmatching.domain.dto.MatchingResultDto; import pairmatching.domain.entity.Course; import pairmatching.domain.entity.Level; import pairmatching.domain.entity.Mission; -import java.util.Arrays; -import java.util.stream.Collectors; public class OutputView { @@ -37,6 +38,9 @@ public void outputErrorMessage(String message) { System.out.println(message); } + public void ouputReset() { + System.out.println(OUTPUT_RESET.getMessage()); + } private String formatPair(List list) { return String.join(" : ", list); } diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index 2dff1e6d3..e24e6eb1f 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -7,7 +7,6 @@ import camp.nextstep.edu.missionutils.test.NsTest; import java.util.Arrays; import org.junit.jupiter.api.Test; -import pairmatching.Application; class ApplicationTest extends NsTest { @@ -16,21 +15,21 @@ class ApplicationTest extends NsTest { @Test void 짝수_인원_페어_매칭() { assertShuffleTest( - () -> { - run("1", "백엔드, 레벨1, 자동차경주", "Q"); - assertThat(output()).contains("태웅 : 백호", "치수 : 태섭"); - }, - Arrays.asList("태웅", "백호", "치수", "태섭") + () -> { + run("1", "백엔드, 레벨1, 자동차경주", "Q"); + assertThat(output()).contains("태웅 : 백호", "치수 : 태섭"); + }, + Arrays.asList("태웅", "백호", "치수", "태섭") ); } @Test void 없는_미션에_대한_예외_처리() { assertSimpleTest( - () -> { - runException("1", "백엔드, 레벨1, 오징어게임"); - assertThat(output()).contains(ERROR_MESSAGE); - } + () -> { + runException("1", "백엔드, 레벨1, 오징어게임"); + assertThat(output()).contains(ERROR_MESSAGE); + } ); } diff --git a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java index 533583f1f..98caaeece 100644 --- a/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java +++ b/src/test/java/pairmatching/domain/dto/CourseMissionMapperTest.java @@ -1,16 +1,16 @@ package pairmatching.domain.dto; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import pairmatching.domain.entity.Course; import pairmatching.domain.entity.CourseMission; import pairmatching.domain.entity.Level; import pairmatching.domain.entity.Mission; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.Arguments; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.stream.Stream; public class CourseMissionMapperTest { diff --git a/src/test/java/pairmatching/domain/entity/CourseMissionTest.java b/src/test/java/pairmatching/domain/entity/CourseMissionTest.java index 3bb14d4e6..2758d5f4d 100644 --- a/src/test/java/pairmatching/domain/entity/CourseMissionTest.java +++ b/src/test/java/pairmatching/domain/entity/CourseMissionTest.java @@ -1,11 +1,11 @@ package pairmatching.domain.entity; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.Arguments; +import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.*; import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; public class CourseMissionTest { diff --git a/src/test/java/pairmatching/domain/entity/CourseTest.java b/src/test/java/pairmatching/domain/entity/CourseTest.java index fa22dbe82..f9919b7c1 100644 --- a/src/test/java/pairmatching/domain/entity/CourseTest.java +++ b/src/test/java/pairmatching/domain/entity/CourseTest.java @@ -1,15 +1,15 @@ package pairmatching.domain.entity; -import java.util.List; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.Arguments; - import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.util.List; import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; public class CourseTest { diff --git a/src/test/java/pairmatching/util/FileUtilTest.java b/src/test/java/pairmatching/util/FileUtilTest.java index 4093c7c37..822bb2752 100644 --- a/src/test/java/pairmatching/util/FileUtilTest.java +++ b/src/test/java/pairmatching/util/FileUtilTest.java @@ -1,16 +1,15 @@ package pairmatching.util; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; import java.net.URISyntaxException; +import java.nio.file.Paths; import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.Arguments; - -import java.util.stream.Stream; -import java.nio.file.Paths; -import java.io.IOException; - -import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.params.provider.MethodSource; public class FileUtilTest { @@ -31,7 +30,7 @@ private static Stream provideLinesForTest() { public void testFileContent(int lineIndex, String expectedLine) throws IOException, URISyntaxException { final String filePath = Paths.get(getClass().getClassLoader().getResource("backend-crew.md").toURI()).toString(); - final List members = FileUtil.readFileAsList(filePath); + final List members = FileUtil.readFileAsList(filePath); final String result = members.get(lineIndex); assertEquals(expectedLine, result, "Mismatch at line " + (lineIndex + 1));