From b3bdbe7f380d26d6212ee68788b0721b41b24ab2 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 13:53:07 +0900 Subject: [PATCH 01/16] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..5a212e20e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,44 @@ +# 기능 구현 체크리스트 + +## 구현 기능 + +### 입력 부분 + +- [ ] 기능 선택 + - [ ] 1, 2, 3, Q 아닌 입력 값은 예외 처리 + +### 예외 처리 + +- [ ] 예외 처리 시 IllegalArgumentException를 발생 +- [ ] [ERROR]로 시작하는 에러 메시지 출력 +- [ ] 에러 메시지 출력 후 해당 부분부터 재입력 받기 + +### 출력 부분 + +- [ ] 기능 선택 출력 +- [ ] 페어 매칭 출력 +- [ ] 페어 매칭 결과 출력 + +### 페어 정보 + +- [ ] 크루 목록이 담긴 파일 리스트에 저장 +- [ ] 미션 목록 리스트 저장 +- [ ] 페어 정보 관리 + +### 페어 매칭 + +- [ ] 크루 목록 셔플 +- [ ] 순서대로 두명씩 페어 매칭 + - [ ] 총 인원이 홀수인 경우 마지막 페어에 포함 +- [ ] 같은 레벨에서 페어 만난 경험이 있는 경우 셔플 후 재매칭 +- [ ] 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력 + +### 페어 조회 + +- [ ] 매칭 이력 없은 경우 에러 메시지 출력 +- [ ] 매칭 이력이 있는 경우 목록 출력 + +### 페어 초기화 + +- [ ] 페어 목록 초기화 + - [ ] 초기화 메시지 출력 From 95e141b91f26c64c9469bd4453e327a5ebc5e1f9 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:06:58 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat(OptionCommand):=20=EA=B8=B0=EB=8A=A5?= =?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 --- .../pairmatching/domain/OptionCommand.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/pairmatching/domain/OptionCommand.java diff --git a/src/main/java/pairmatching/domain/OptionCommand.java b/src/main/java/pairmatching/domain/OptionCommand.java new file mode 100644 index 000000000..424d083c9 --- /dev/null +++ b/src/main/java/pairmatching/domain/OptionCommand.java @@ -0,0 +1,25 @@ +package pairmatching.domain; + +import java.util.Arrays; +import pairmatching.exception.ExceptionMessage; + +public enum OptionCommand { + MATCHING("1"), + CHECK("2"), + RESET("3"), + QUIT("Q"); + + private final String command; + + OptionCommand(String command) { + this.command = command; + } + + public static OptionCommand from(String input) { + return Arrays.stream(OptionCommand.values()) + .filter(optionCommand -> optionCommand.command.equals(input)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException( + ExceptionMessage.INVALID_COMMAND.getMessage())); + } +} From 04a49524c4ab0fab2a0077054d0efa5f38ec9d92 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:09:47 +0900 Subject: [PATCH 03/16] =?UTF-8?q?feat(OptionCommand):=20getter=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/domain/OptionCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/pairmatching/domain/OptionCommand.java b/src/main/java/pairmatching/domain/OptionCommand.java index 424d083c9..e195e7d1e 100644 --- a/src/main/java/pairmatching/domain/OptionCommand.java +++ b/src/main/java/pairmatching/domain/OptionCommand.java @@ -22,4 +22,8 @@ public static OptionCommand from(String input) { .orElseThrow(() -> new IllegalArgumentException( ExceptionMessage.INVALID_COMMAND.getMessage())); } + + public String getCommand() { + return command; + } } From 8ef7c6f50b2630d366f6055a5866a716b0a31f3c Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:10:18 +0900 Subject: [PATCH 04/16] =?UTF-8?q?feat(InputView):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/view/InputView.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/pairmatching/view/InputView.java diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java new file mode 100644 index 000000000..38f23bfd5 --- /dev/null +++ b/src/main/java/pairmatching/view/InputView.java @@ -0,0 +1,16 @@ +package pairmatching.view; + +import camp.nextstep.edu.missionutils.Console; +import pairmatching.domain.OptionCommand; + +public class InputView { + + public String readCommand() { + String input = input(); + return OptionCommand.from(input).getCommand(); + } + + private String input() { + return Console.readLine(); + } +} From d0751def405b26280cdc10183cec3d6e966facc7 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:10:50 +0900 Subject: [PATCH 05/16] =?UTF-8?q?feat(ExceptionMessage):=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/ExceptionMessage.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/pairmatching/exception/ExceptionMessage.java diff --git a/src/main/java/pairmatching/exception/ExceptionMessage.java b/src/main/java/pairmatching/exception/ExceptionMessage.java new file mode 100644 index 000000000..fc4715226 --- /dev/null +++ b/src/main/java/pairmatching/exception/ExceptionMessage.java @@ -0,0 +1,18 @@ +package pairmatching.exception; + +public enum ExceptionMessage { + INVALID_COMMAND("잘못된 입력값 입니다. 다시 입력해 주세요. " + + "(매칭 - 1, 조회 - 2, 초기화 - 3, 종료 - Q)"), + NON_EXISTENT_HISTORY("매칭 이력이 없습니다."); + + private static final String ERROR_MESSAGE = "[ERROR] "; + private final String message; + + ExceptionMessage(String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_MESSAGE + message; + } +} From 1d72bac2bcf326c1c6691de62c5d2ea825fde7e4 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:12:43 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat(MatchinController):=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/Application.java | 4 ++++ .../java/pairmatching/controller/MatchingController.java | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 src/main/java/pairmatching/controller/MatchingController.java diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index 6f56e741c..4cf2ca8bc 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -1,7 +1,11 @@ package pairmatching; +import pairmatching.controller.MatchingController; + public class Application { public static void main(String[] args) { // TODO 구현 진행 + MatchingController matchingController = new MatchingController(); + matchingController.run(); } } diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java new file mode 100644 index 000000000..067f807b5 --- /dev/null +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -0,0 +1,8 @@ +package pairmatching.controller; + +public class MatchingController { + + public void run() { + + } +} From 28ac6e35b36a4b0fad0b488159c409ec05bbfd17 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:49:24 +0900 Subject: [PATCH 07/16] =?UTF-8?q?feat(Mission):=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/pairmatching/domain/Mission.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/pairmatching/domain/Mission.java diff --git a/src/main/java/pairmatching/domain/Mission.java b/src/main/java/pairmatching/domain/Mission.java new file mode 100644 index 000000000..6eade89fb --- /dev/null +++ b/src/main/java/pairmatching/domain/Mission.java @@ -0,0 +1,33 @@ +package pairmatching.domain; + +import java.util.Arrays; +import pairmatching.exception.ExceptionMessage; + +public enum Mission { + RACING_CAR("자동차경주", Level.LEVEL1), + LOTTO("로또", Level.LEVEL1), + BASEBALL_GAME("숫자야구게임", Level.LEVEL1), + + SHOPPING_BASKET("장바구니", Level.LEVEL2), + PAYMENT("결제", Level.LEVEL2), + SUBWAY_MAP("지하철노선도", Level.LEVEL2), + + PERFORMANCE_IMPROVEMENT("성능개선", Level.LEVEL4), + DEPLOYMENT("배포", Level.LEVEL4); + + private final String name; + private final Level level; + + Mission(String name, Level level) { + this.name = name; + this.level = level; + } + + public static Mission from(String input) { + return Arrays.stream(Mission.values()) + .filter(mission -> mission.name.equals(input)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException( + ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); + } +} From 84dfa0c4599dddcf157373ad3d6c10f39f70cc3e Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Tue, 12 Dec 2023 14:58:53 +0900 Subject: [PATCH 08/16] =?UTF-8?q?feat(InputView):=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/view/InputView.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 38f23bfd5..8b457ebcd 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -6,10 +6,14 @@ public class InputView { public String readCommand() { - String input = input(); + String input = input().trim(); return OptionCommand.from(input).getCommand(); } + public String readInfo() { + return input(); + } + private String input() { return Console.readLine(); } From 04d310afb8f009f205f60d7ee137b38f3aa98872 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 14:48:05 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=EB=A6=AC=EC=85=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/domain/Course.java | 28 ++++++++++++++++++ src/main/java/pairmatching/domain/Level.java | 26 +++++++++++++++++ .../java/pairmatching/domain/Mission.java | 4 +++ .../domain/RematchingCommand.java | 27 +++++++++++++++++ .../exception/ExceptionMessage.java | 7 +++-- .../java/pairmatching/view/InputView.java | 14 +++++++-- .../java/pairmatching/view/OutputView.java | 22 ++++++++++++++ .../java/pairmatching/view/ViewMessage.java | 29 +++++++++++++++++++ 8 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 src/main/java/pairmatching/domain/Course.java create mode 100644 src/main/java/pairmatching/domain/Level.java create mode 100644 src/main/java/pairmatching/domain/RematchingCommand.java create mode 100644 src/main/java/pairmatching/view/OutputView.java create mode 100644 src/main/java/pairmatching/view/ViewMessage.java diff --git a/src/main/java/pairmatching/domain/Course.java b/src/main/java/pairmatching/domain/Course.java new file mode 100644 index 000000000..0ea240908 --- /dev/null +++ b/src/main/java/pairmatching/domain/Course.java @@ -0,0 +1,28 @@ +package pairmatching.domain; + +import java.util.Arrays; +import pairmatching.exception.ExceptionMessage; + +public enum Course { + BACKEND("백엔드"), + FRONTEND("프론트엔드"); + + private String name; + + Course(String name) { + this.name = name; + } + + public static Course from(String input) { + return Arrays.stream(Course.values()) + .filter(course -> course.name.equals(input)) + .findAny() + .orElseThrow( + () -> new IllegalArgumentException( + ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/pairmatching/domain/Level.java b/src/main/java/pairmatching/domain/Level.java new file mode 100644 index 000000000..c596a31cf --- /dev/null +++ b/src/main/java/pairmatching/domain/Level.java @@ -0,0 +1,26 @@ +package pairmatching.domain; + +import java.util.Arrays; +import pairmatching.exception.ExceptionMessage; + +public enum Level { + LEVEL1("레벨1"), + LEVEL2("레벨2"), + LEVEL3("레벨3"), + LEVEL4("레벨4"), + LEVEL5("레벨5"); + + private String name; + + Level(String name) { + this.name = name; + } + + public static Level from(String input) { + return Arrays.stream(Level.values()) + .filter(level -> level.name.equals(input)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException( + ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); + } +} diff --git a/src/main/java/pairmatching/domain/Mission.java b/src/main/java/pairmatching/domain/Mission.java index 6eade89fb..207f2085a 100644 --- a/src/main/java/pairmatching/domain/Mission.java +++ b/src/main/java/pairmatching/domain/Mission.java @@ -30,4 +30,8 @@ public static Mission from(String input) { .orElseThrow(() -> new IllegalArgumentException( ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); } + + public Level getLevel() { + return level; + } } diff --git a/src/main/java/pairmatching/domain/RematchingCommand.java b/src/main/java/pairmatching/domain/RematchingCommand.java new file mode 100644 index 000000000..7927685fc --- /dev/null +++ b/src/main/java/pairmatching/domain/RematchingCommand.java @@ -0,0 +1,27 @@ +package pairmatching.domain; + +import java.util.Arrays; +import pairmatching.exception.ExceptionMessage; + +public enum RematchingCommand { + REMATCHING("네"), + QUIT("아니오"); + + private final String command; + + RematchingCommand(String command) { + this.command = command; + } + + public static RematchingCommand from(String input) { + return Arrays.stream(RematchingCommand.values()) + .filter(rematchingCommand -> rematchingCommand.command.equals(input)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException( + ExceptionMessage.INVALID_REMATCHING_COMMAND.getMessage())); + } + + public String getCommand() { + return command; + } +} diff --git a/src/main/java/pairmatching/exception/ExceptionMessage.java b/src/main/java/pairmatching/exception/ExceptionMessage.java index fc4715226..e90f87132 100644 --- a/src/main/java/pairmatching/exception/ExceptionMessage.java +++ b/src/main/java/pairmatching/exception/ExceptionMessage.java @@ -1,9 +1,12 @@ package pairmatching.exception; public enum ExceptionMessage { - INVALID_COMMAND("잘못된 입력값 입니다. 다시 입력해 주세요. " + INVALID_COMMAND("잘못된 입력값 입니다. 다시 입력해주세요. " + "(매칭 - 1, 조회 - 2, 초기화 - 3, 종료 - Q)"), - NON_EXISTENT_HISTORY("매칭 이력이 없습니다."); + INVALID_MATCHING_REQUEST("잘못된 입력 양식입니다. 다시 입력해주세요. (과정, 레벨, 미션)"), + NON_EXISTENT_HISTORY("매칭 이력이 없습니다."), + FAIL_MATCHING("매칭에 실패했습니다."), + INVALID_REMATCHING_COMMAND("잘못된 입력 양식입니다. 다시 입력해주세요. (네, 아니오)"); private static final String ERROR_MESSAGE = "[ERROR] "; private final String message; diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 8b457ebcd..2ef2676b9 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -1,17 +1,27 @@ package pairmatching.view; import camp.nextstep.edu.missionutils.Console; +import java.util.Arrays; +import java.util.List; import pairmatching.domain.OptionCommand; +import pairmatching.domain.RematchingCommand; public class InputView { + private static final String DELIMITER = ", "; + public String readCommand() { String input = input().trim(); return OptionCommand.from(input).getCommand(); } - public String readInfo() { - return input(); + public List readInfo() { + return Arrays.asList(input().split(DELIMITER)); + } + + public String readRematching() { + String input = input().trim(); + return RematchingCommand.from(input).getCommand(); } private String input() { diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java new file mode 100644 index 000000000..111cb0820 --- /dev/null +++ b/src/main/java/pairmatching/view/OutputView.java @@ -0,0 +1,22 @@ +package pairmatching.view; + +import static pairmatching.view.ViewMessage.*; + +public class OutputView { + + public void printException(IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + + public void printSelectOption() { + System.out.printf(SELECT_OPTION.getMessage()); + } + + public void printSelectInfo() { + System.out.printf(INFO.getMessage()); + } + + public void printRematching() { + System.out.printf(REMATCHING.getMessage()); + } +} diff --git a/src/main/java/pairmatching/view/ViewMessage.java b/src/main/java/pairmatching/view/ViewMessage.java new file mode 100644 index 000000000..861ed3870 --- /dev/null +++ b/src/main/java/pairmatching/view/ViewMessage.java @@ -0,0 +1,29 @@ +package pairmatching.view; + +public enum ViewMessage { + SELECT_OPTION("기능을 선택하세요.%n1. 페어 매칭%n2. 페어 조회%n3. 페어 초기화%nQ. 종료%n"), + INFO("#############################################%n" + + "과정: 백엔드 | 프론트엔드%n" + + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임%n" + + " - 레벨2: 장바구니 | 결제 | 지하철노선도%n" + + " - 레벨3: %n" + + " - 레벨4: 성능개선 | 배포%n" + + " - 레벨5: %n" + + "#############################################%n" + + "과정, 레벨, 미션을 선택하세요.%n" + + "ex) 백엔드, 레벨1, 자동차경주%n"), + REMATCHING("매칭 정보가 있습니다. 다시 매칭하시겠습니까?%n" + + "네 | 아니오%n"), + RESULT("%페어 매칭 결과입니다.%n"), + RESULT_DELIMITER(" | "); + + private final String message; + + ViewMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} From 97242d1c43b6812a6a5a1f51a3e9c4d209ce43dd Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 18:03:12 +0900 Subject: [PATCH 10/16] =?UTF-8?q?=EA=B0=99=EC=9D=80=20=EB=A0=88=EB=B2=A8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=8E=98=EC=96=B4=20=EB=A7=8C=EB=82=9C=20?= =?UTF-8?q?=EA=B2=BD=ED=97=98,=203=ED=9A=8C=20=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MatchingController.java | 98 +++++++++++++++++++ src/main/java/pairmatching/domain/Course.java | 2 +- src/main/java/pairmatching/domain/Crew.java | 14 +++ src/main/java/pairmatching/domain/Level.java | 2 +- .../domain/MatchingConditions.java | 38 +++++++ .../domain/MatchingRepository.java | 39 ++++++++ .../java/pairmatching/domain/Mission.java | 2 +- src/main/java/pairmatching/domain/Pair.java | 22 +++++ src/main/java/pairmatching/domain/Pairs.java | 28 ++++++ .../exception/ExceptionMessage.java | 5 +- .../pairmatching/service/MatchingService.java | 70 +++++++++++++ src/main/java/pairmatching/util/MDParser.java | 45 +++++++++ .../java/pairmatching/view/InputView.java | 4 +- .../java/pairmatching/view/OutputView.java | 22 ++++- .../java/pairmatching/view/ViewMessage.java | 11 ++- 15 files changed, 389 insertions(+), 13 deletions(-) create mode 100644 src/main/java/pairmatching/domain/Crew.java create mode 100644 src/main/java/pairmatching/domain/MatchingConditions.java create mode 100644 src/main/java/pairmatching/domain/MatchingRepository.java create mode 100644 src/main/java/pairmatching/domain/Pair.java create mode 100644 src/main/java/pairmatching/domain/Pairs.java create mode 100644 src/main/java/pairmatching/service/MatchingService.java create mode 100644 src/main/java/pairmatching/util/MDParser.java diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java index 067f807b5..b482dbf89 100644 --- a/src/main/java/pairmatching/controller/MatchingController.java +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -1,8 +1,106 @@ package pairmatching.controller; +import java.util.List; +import pairmatching.domain.MatchingConditions; +import pairmatching.domain.OptionCommand; +import pairmatching.domain.Pairs; +import pairmatching.domain.RematchingCommand; +import pairmatching.service.MatchingService; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; + public class MatchingController { + private final InputView inputView; + private final OutputView outputView; + private final MatchingService matchingService; + + public MatchingController() { + this.inputView = new InputView(); + this.outputView = new OutputView(); + this.matchingService = new MatchingService(); + } + public void run() { + start(); + } + + private void start() { + while (true) { + String option = readOption(); + if (option.equals(OptionCommand.MATCHING.getCommand())) { + match(); + } + if (option.equals(OptionCommand.CHECK.getCommand())) { + check(); + } + if (option.equals(OptionCommand.RESET.getCommand())) { + reset(); + } + if (option.equals(OptionCommand.QUIT.getCommand())) { + break; + } + } + } + + private String readOption() { + outputView.printSelectOption(); + while (true) { + try { + return inputView.readOption(); + } catch (IllegalArgumentException e) { + outputView.printException(e); + } + } + } + + private void match() { + MatchingConditions matchingConditions; + while (true) { + matchingConditions = readConditions(); + if (matchingService.hasConditions(matchingConditions)) { + break; + } + outputView.printRematching(); + RematchingCommand rematching = RematchingCommand.from(inputView.readRematching()); + if (rematching == RematchingCommand.REMATCHING) { + break; + } + } + Pairs pairs = matchingService.matchPair(matchingConditions); + outputView.printPairs(pairs); + } + + private MatchingConditions readConditions() { + outputView.printSelectCondition(); + while (true) { + try { + List conditions = inputView.readConditions(); + return new MatchingConditions(conditions); + } catch (IllegalArgumentException e) { + outputView.printException(e); + } + } + } + + private void check() { + Pairs pairs = checkPairs(); + outputView.printPairs(pairs); + } + + private Pairs checkPairs() { + while (true) { + try { + MatchingConditions matchingConditions = readConditions(); + return matchingService.findPairs(matchingConditions); + } catch (IllegalArgumentException e) { + outputView.printException(e); + } + } + } + private void reset() { + matchingService.resetData(); + outputView.printReset(); } } diff --git a/src/main/java/pairmatching/domain/Course.java b/src/main/java/pairmatching/domain/Course.java index 0ea240908..5a2194445 100644 --- a/src/main/java/pairmatching/domain/Course.java +++ b/src/main/java/pairmatching/domain/Course.java @@ -19,7 +19,7 @@ public static Course from(String input) { .findAny() .orElseThrow( () -> new IllegalArgumentException( - ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); + ExceptionMessage.INVALID_MATCHING_CONDITIONS.getMessage())); } public String getName() { diff --git a/src/main/java/pairmatching/domain/Crew.java b/src/main/java/pairmatching/domain/Crew.java new file mode 100644 index 000000000..f713e2f06 --- /dev/null +++ b/src/main/java/pairmatching/domain/Crew.java @@ -0,0 +1,14 @@ +package pairmatching.domain; + +public class Crew { + + private final String name; + + public Crew(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/pairmatching/domain/Level.java b/src/main/java/pairmatching/domain/Level.java index c596a31cf..fc3468a8e 100644 --- a/src/main/java/pairmatching/domain/Level.java +++ b/src/main/java/pairmatching/domain/Level.java @@ -21,6 +21,6 @@ public static Level from(String input) { .filter(level -> level.name.equals(input)) .findAny() .orElseThrow(() -> new IllegalArgumentException( - ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); + ExceptionMessage.INVALID_MATCHING_CONDITIONS.getMessage())); } } diff --git a/src/main/java/pairmatching/domain/MatchingConditions.java b/src/main/java/pairmatching/domain/MatchingConditions.java new file mode 100644 index 000000000..bfe9066d7 --- /dev/null +++ b/src/main/java/pairmatching/domain/MatchingConditions.java @@ -0,0 +1,38 @@ +package pairmatching.domain; + +import java.util.List; +import pairmatching.exception.ExceptionMessage; + +public class MatchingConditions { + + private static final int INPUT_SIZE = 3; + private final Course course; + private final Level level; + private final Mission mission; + + public MatchingConditions(List conditions) { + validateSize(conditions); + this.course = Course.from(conditions.get(0)); + this.level = Level.from(conditions.get(1)); + this.mission = Mission.from(conditions.get(2)); + } + + private void validateSize(List conditions) { + if (conditions.size() != INPUT_SIZE) { + throw new IllegalArgumentException( + ExceptionMessage.INVALID_MATCHING_CONDITIONS.getMessage()); + } + } + + public Course getCourse() { + return course; + } + + public Level getLevel() { + return level; + } + + public Mission getMission() { + return mission; + } +} diff --git a/src/main/java/pairmatching/domain/MatchingRepository.java b/src/main/java/pairmatching/domain/MatchingRepository.java new file mode 100644 index 000000000..a8c3f4108 --- /dev/null +++ b/src/main/java/pairmatching/domain/MatchingRepository.java @@ -0,0 +1,39 @@ +package pairmatching.domain; + +import java.util.ArrayList; +import java.util.List; +import pairmatching.exception.ExceptionMessage; + +public class MatchingRepository { + + private List matchingRepository; + + public MatchingRepository() { + this.matchingRepository = new ArrayList<>(); + } + + public void add(Pairs pairs) { + matchingRepository.add(pairs); + } + + public Pairs search(MatchingConditions conditions) { + return matchingRepository.stream() + .filter(pairs -> pairs.getMatchingConditions().getCourse() == conditions.getCourse()) + .filter(pairs -> pairs.getMatchingConditions().getLevel() == conditions.getLevel()) + .filter(pairs -> pairs.getMatchingConditions().getMission() == conditions.getMission()) + .findAny() + .orElseThrow(() -> new IllegalArgumentException( + ExceptionMessage.NON_EXISTENT_HISTORY.getMessage())); + } + + public boolean hasConditionsPair(MatchingConditions conditions) { + return matchingRepository.stream() + .filter(pairs -> pairs.getMatchingConditions().getCourse() == conditions.getCourse()) + .filter(pairs -> pairs.getMatchingConditions().getLevel() == conditions.getLevel()) + .noneMatch(pairs -> pairs.getMatchingConditions().getMission() == conditions.getMission()); + } + + public void reset() { + matchingRepository = new ArrayList<>(); + } +} diff --git a/src/main/java/pairmatching/domain/Mission.java b/src/main/java/pairmatching/domain/Mission.java index 207f2085a..206ea9bbd 100644 --- a/src/main/java/pairmatching/domain/Mission.java +++ b/src/main/java/pairmatching/domain/Mission.java @@ -28,7 +28,7 @@ public static Mission from(String input) { .filter(mission -> mission.name.equals(input)) .findAny() .orElseThrow(() -> new IllegalArgumentException( - ExceptionMessage.INVALID_MATCHING_REQUEST.getMessage())); + ExceptionMessage.INVALID_MATCHING_CONDITIONS.getMessage())); } public Level getLevel() { diff --git a/src/main/java/pairmatching/domain/Pair.java b/src/main/java/pairmatching/domain/Pair.java new file mode 100644 index 000000000..bf7da1807 --- /dev/null +++ b/src/main/java/pairmatching/domain/Pair.java @@ -0,0 +1,22 @@ +package pairmatching.domain; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Pair { + + private final List crews; + + public Pair() { + this.crews = new ArrayList<>(); + } + + public void add(Crew crew) { + crews.add(crew); + } + + public List getCrews() { + return Collections.unmodifiableList(crews); + } +} diff --git a/src/main/java/pairmatching/domain/Pairs.java b/src/main/java/pairmatching/domain/Pairs.java new file mode 100644 index 000000000..a4c537a0d --- /dev/null +++ b/src/main/java/pairmatching/domain/Pairs.java @@ -0,0 +1,28 @@ +package pairmatching.domain; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Pairs { + + private final MatchingConditions matchingConditions; + private final List pairs; + + public Pairs(MatchingConditions matchingConditions) { + this.matchingConditions = matchingConditions; + this.pairs = new ArrayList<>(); + } + + public void add(Pair pair) { + pairs.add(pair); + } + + public MatchingConditions getMatchingConditions() { + return matchingConditions; + } + + public List getPairs() { + return Collections.unmodifiableList(pairs); + } +} diff --git a/src/main/java/pairmatching/exception/ExceptionMessage.java b/src/main/java/pairmatching/exception/ExceptionMessage.java index e90f87132..663bf81f2 100644 --- a/src/main/java/pairmatching/exception/ExceptionMessage.java +++ b/src/main/java/pairmatching/exception/ExceptionMessage.java @@ -3,10 +3,11 @@ public enum ExceptionMessage { INVALID_COMMAND("잘못된 입력값 입니다. 다시 입력해주세요. " + "(매칭 - 1, 조회 - 2, 초기화 - 3, 종료 - Q)"), - INVALID_MATCHING_REQUEST("잘못된 입력 양식입니다. 다시 입력해주세요. (과정, 레벨, 미션)"), + INVALID_MATCHING_CONDITIONS("잘못된 입력 양식입니다. 다시 입력해주세요. (과정, 레벨, 미션)"), NON_EXISTENT_HISTORY("매칭 이력이 없습니다."), FAIL_MATCHING("매칭에 실패했습니다."), - INVALID_REMATCHING_COMMAND("잘못된 입력 양식입니다. 다시 입력해주세요. (네, 아니오)"); + INVALID_REMATCHING_COMMAND("잘못된 입력 양식입니다. 다시 입력해주세요. (네, 아니오)"), + PARSER_ERROR("파일을 읽을 수 없습니다."); private static final String ERROR_MESSAGE = "[ERROR] "; private final String message; diff --git a/src/main/java/pairmatching/service/MatchingService.java b/src/main/java/pairmatching/service/MatchingService.java new file mode 100644 index 000000000..965751b1c --- /dev/null +++ b/src/main/java/pairmatching/service/MatchingService.java @@ -0,0 +1,70 @@ +package pairmatching.service; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.ArrayList; +import java.util.List; +import pairmatching.domain.Crew; +import pairmatching.domain.MatchingConditions; +import pairmatching.domain.MatchingRepository; +import pairmatching.domain.Pair; +import pairmatching.domain.Pairs; +import pairmatching.util.MDParser; + +public class MatchingService { + + private final MatchingRepository matchingRepository; + + public MatchingService() { + this.matchingRepository = new MatchingRepository(); + } + + public Pairs matchPair(MatchingConditions matchingConditions) { + List crewNames = getCrews(matchingConditions); + List crews = mixRandomly(crewNames); + Pairs pairs = makePairs(crews, matchingConditions); + matchingRepository.add(pairs); + return pairs; + } + + private List getCrews(MatchingConditions matchingConditions) { + MDParser mdParser = new MDParser(); + return mdParser.parserCrewData(matchingConditions.getCourse()); + } + + private List mixRandomly(List crewNames) { + List shuffle = Randoms.shuffle(crewNames); + List crews = new ArrayList<>(); + for (String name : shuffle) { + crews.add(new Crew(name)); + } + return crews; + } + + private Pairs makePairs(List crews, MatchingConditions matchingConditions) { + Pairs pairs = new Pairs(matchingConditions); + for (int i = 0; i < crews.size(); i += 2) { + Pair pair = new Pair(); + pair.add(crews.get(i)); + pair.add(crews.get(i + 1)); + if (crews.size() % 2 == 1 && i == crews.size() - 3) { + pair.add(crews.get(i + 2)); + pairs.add(pair); + break; + } + pairs.add(pair); + } + return pairs; + } + + public Pairs findPairs(MatchingConditions matchingConditions) { + return matchingRepository.search(matchingConditions); + } + + public void resetData() { + matchingRepository.reset(); + } + + public boolean hasConditions(MatchingConditions matchingConditions) { + return matchingRepository.hasConditionsPair(matchingConditions); + } +} diff --git a/src/main/java/pairmatching/util/MDParser.java b/src/main/java/pairmatching/util/MDParser.java new file mode 100644 index 000000000..20608151f --- /dev/null +++ b/src/main/java/pairmatching/util/MDParser.java @@ -0,0 +1,45 @@ +package pairmatching.util; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import pairmatching.domain.Course; +import pairmatching.domain.Crew; +import pairmatching.exception.ExceptionMessage; + +public class MDParser { + + private static final String BACKEND_FILE_PATH = "src/main/resources/backend-crew.md"; + private static final String FRONTEND_FILE_PATH = "src/main/resources/frontend-crew.md"; + + public List parserCrewData(Course course) { + List crewNames = new ArrayList<>(); + try { + if (course == Course.BACKEND) { + crewNames = parseData(BACKEND_FILE_PATH); + } + if (course == Course.FRONTEND) { + crewNames = parseData(FRONTEND_FILE_PATH); + } + } catch (IOException e) { + System.out.println(ExceptionMessage.PARSER_ERROR.getMessage()); + } + return crewNames; + } + + private List parseData(String filePath) throws IOException { + List crewNames = new ArrayList<>(); + BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)); + while (true) { + String name = bufferedReader.readLine(); + if (name == null) { + break; + } + crewNames.add(name); + } + bufferedReader.close(); + return crewNames; + } +} diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 2ef2676b9..588cd326c 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -10,12 +10,12 @@ public class InputView { private static final String DELIMITER = ", "; - public String readCommand() { + public String readOption() { String input = input().trim(); return OptionCommand.from(input).getCommand(); } - public List readInfo() { + public List readConditions() { return Arrays.asList(input().split(DELIMITER)); } diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 111cb0820..eac603955 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -2,6 +2,11 @@ import static pairmatching.view.ViewMessage.*; +import java.util.StringJoiner; +import pairmatching.domain.Crew; +import pairmatching.domain.Pair; +import pairmatching.domain.Pairs; + public class OutputView { public void printException(IllegalArgumentException e) { @@ -12,10 +17,25 @@ public void printSelectOption() { System.out.printf(SELECT_OPTION.getMessage()); } - public void printSelectInfo() { + public void printSelectCondition() { System.out.printf(INFO.getMessage()); } + public void printPairs(Pairs pairs) { + System.out.printf(RESULT.getMessage()); + for (Pair pair : pairs.getPairs()) { + StringJoiner result = new StringJoiner(RESULT_DELIMITER.getMessage()); + for (Crew crew : pair.getCrews()) { + result.add(crew.getName()); + } + System.out.println(result); + } + } + + public void printReset() { + System.out.printf(RESET.getMessage()); + } + public void printRematching() { System.out.printf(REMATCHING.getMessage()); } diff --git a/src/main/java/pairmatching/view/ViewMessage.java b/src/main/java/pairmatching/view/ViewMessage.java index 861ed3870..f16753a5a 100644 --- a/src/main/java/pairmatching/view/ViewMessage.java +++ b/src/main/java/pairmatching/view/ViewMessage.java @@ -1,8 +1,8 @@ package pairmatching.view; public enum ViewMessage { - SELECT_OPTION("기능을 선택하세요.%n1. 페어 매칭%n2. 페어 조회%n3. 페어 초기화%nQ. 종료%n"), - INFO("#############################################%n" + SELECT_OPTION("%n기능을 선택하세요.%n1. 페어 매칭%n2. 페어 조회%n3. 페어 초기화%nQ. 종료%n"), + INFO("%n#############################################%n" + "과정: 백엔드 | 프론트엔드%n" + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임%n" + " - 레벨2: 장바구니 | 결제 | 지하철노선도%n" @@ -12,10 +12,11 @@ public enum ViewMessage { + "#############################################%n" + "과정, 레벨, 미션을 선택하세요.%n" + "ex) 백엔드, 레벨1, 자동차경주%n"), - REMATCHING("매칭 정보가 있습니다. 다시 매칭하시겠습니까?%n" + REMATCHING("%n매칭 정보가 있습니다. 다시 매칭하시겠습니까?%n" + "네 | 아니오%n"), - RESULT("%페어 매칭 결과입니다.%n"), - RESULT_DELIMITER(" | "); + RESULT("%n페어 매칭 결과입니다.%n"), + RESULT_DELIMITER(" : "), + RESET("%n초기화 되었습니다.%n"); private final String message; From fadf15c9b05e62435c98cf16b1b824005b002717 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 19:03:38 +0900 Subject: [PATCH 11/16] =?UTF-8?q?feat(MatchingConditions):=20equals=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=EB=9D=BC=EC=9D=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/MatchingConditions.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/pairmatching/domain/MatchingConditions.java b/src/main/java/pairmatching/domain/MatchingConditions.java index bfe9066d7..d7e1ac589 100644 --- a/src/main/java/pairmatching/domain/MatchingConditions.java +++ b/src/main/java/pairmatching/domain/MatchingConditions.java @@ -1,6 +1,7 @@ package pairmatching.domain; import java.util.List; +import java.util.Objects; import pairmatching.exception.ExceptionMessage; public class MatchingConditions { @@ -35,4 +36,21 @@ public Level getLevel() { public Mission getMission() { return mission; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof MatchingConditions)) { + return false; + } + MatchingConditions conditions = (MatchingConditions) o; + return course == conditions.course && level == conditions.level && mission == conditions.mission; + } + + @Override + public int hashCode() { + return Objects.hash(course, level, mission); + } } From 77e9215e12368f0259c04d493ad1e0d0fe0db228 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 19:04:08 +0900 Subject: [PATCH 12/16] =?UTF-8?q?feat(MatchingRepository):=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/domain/MatchingRepository.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/pairmatching/domain/MatchingRepository.java b/src/main/java/pairmatching/domain/MatchingRepository.java index a8c3f4108..fb2311b9e 100644 --- a/src/main/java/pairmatching/domain/MatchingRepository.java +++ b/src/main/java/pairmatching/domain/MatchingRepository.java @@ -18,9 +18,7 @@ public void add(Pairs pairs) { public Pairs search(MatchingConditions conditions) { return matchingRepository.stream() - .filter(pairs -> pairs.getMatchingConditions().getCourse() == conditions.getCourse()) - .filter(pairs -> pairs.getMatchingConditions().getLevel() == conditions.getLevel()) - .filter(pairs -> pairs.getMatchingConditions().getMission() == conditions.getMission()) + .filter(pairs -> pairs.getMatchingConditions().equals(conditions)) .findAny() .orElseThrow(() -> new IllegalArgumentException( ExceptionMessage.NON_EXISTENT_HISTORY.getMessage())); @@ -28,9 +26,7 @@ public Pairs search(MatchingConditions conditions) { public boolean hasConditionsPair(MatchingConditions conditions) { return matchingRepository.stream() - .filter(pairs -> pairs.getMatchingConditions().getCourse() == conditions.getCourse()) - .filter(pairs -> pairs.getMatchingConditions().getLevel() == conditions.getLevel()) - .noneMatch(pairs -> pairs.getMatchingConditions().getMission() == conditions.getMission()); + .noneMatch(pairs -> pairs.getMatchingConditions().equals(conditions)); } public void reset() { From 55a11a9eb56e42148f9c941d7ecf0303d94bf9dc Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 19:30:50 +0900 Subject: [PATCH 13/16] =?UTF-8?q?feat(MatchingRepository):=20=ED=8E=98?= =?UTF-8?q?=EC=96=B4=20=EC=A1=B4=EC=9E=AC=EC=97=AC=EB=B6=80=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/MatchingRepository.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/main/java/pairmatching/domain/MatchingRepository.java b/src/main/java/pairmatching/domain/MatchingRepository.java index fb2311b9e..69cd359fa 100644 --- a/src/main/java/pairmatching/domain/MatchingRepository.java +++ b/src/main/java/pairmatching/domain/MatchingRepository.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import pairmatching.exception.ExceptionMessage; public class MatchingRepository { @@ -16,6 +17,38 @@ public void add(Pairs pairs) { matchingRepository.add(pairs); } + public boolean hasPairs(MatchingConditions conditions, Pairs makePairs) { + List sameLevelPairs = matchingRepository.stream() + .filter(pairs -> pairs.getMatchingConditions().getLevel() == conditions.getLevel()) + .collect(Collectors.toList()); + + for (Pairs sameLevel : sameLevelPairs) { + if (checkPair(makePairs, sameLevel)) { + return true; + } + } + return false; + } + + private boolean checkPair(Pairs makePairs, Pairs sameLevel) { + for (Pair pair : sameLevel.getPairs()) { + if (hasPair(makePairs, pair)) { + return true; + } + } + return false; + } + + private boolean hasPair(Pairs makePairs, Pair pair) { + for (Pair makePair : makePairs.getPairs()) { + boolean result = pair.isCrews(makePair); + if (result) { + return true; + } + } + return false; + } + public Pairs search(MatchingConditions conditions) { return matchingRepository.stream() .filter(pairs -> pairs.getMatchingConditions().equals(conditions)) From b02fa55f0fc5f678705be8a63eac1d7fcaa5a7de Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 19:31:10 +0900 Subject: [PATCH 14/16] =?UTF-8?q?feat(Pair):=20=ED=8E=98=EC=96=B4=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/domain/Pair.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/pairmatching/domain/Pair.java b/src/main/java/pairmatching/domain/Pair.java index bf7da1807..0e769b29a 100644 --- a/src/main/java/pairmatching/domain/Pair.java +++ b/src/main/java/pairmatching/domain/Pair.java @@ -6,6 +6,7 @@ public class Pair { + private static final int DUPLICATION_NUMBER = 1; private final List crews; public Pair() { @@ -16,6 +17,12 @@ public void add(Crew crew) { crews.add(crew); } + public boolean isCrews(Pair pair) { + return pair.getCrews().stream() + .filter(this.crews::contains) + .count() > DUPLICATION_NUMBER; + } + public List getCrews() { return Collections.unmodifiableList(crews); } From 64e44d6bfc1cb9e97befc83a97f3240d89f541ea Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 19:31:30 +0900 Subject: [PATCH 15/16] =?UTF-8?q?feat(MatchingService):=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/service/MatchingService.java | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/main/java/pairmatching/service/MatchingService.java b/src/main/java/pairmatching/service/MatchingService.java index 965751b1c..a4e1d0563 100644 --- a/src/main/java/pairmatching/service/MatchingService.java +++ b/src/main/java/pairmatching/service/MatchingService.java @@ -8,10 +8,12 @@ import pairmatching.domain.MatchingRepository; import pairmatching.domain.Pair; import pairmatching.domain.Pairs; +import pairmatching.exception.ExceptionMessage; import pairmatching.util.MDParser; public class MatchingService { + private static final int NUMBER_OF_LOOPS = 3; private final MatchingRepository matchingRepository; public MatchingService() { @@ -19,13 +21,35 @@ public MatchingService() { } public Pairs matchPair(MatchingConditions matchingConditions) { + Pairs pairs; List crewNames = getCrews(matchingConditions); - List crews = mixRandomly(crewNames); - Pairs pairs = makePairs(crews, matchingConditions); - matchingRepository.add(pairs); + pairs = getPairs(matchingConditions, crewNames); return pairs; } + private Pairs getPairs(MatchingConditions matchingConditions, List crewNames) { + Pairs pairs; + int count = 0; + while (true) { + checkNumberOfLoops(count); + List crews = mixRandomly(crewNames); + pairs = makePairs(crews, matchingConditions); + if (matchingRepository.hasPairs(matchingConditions, pairs)) { + count++; + continue; + } + matchingRepository.add(pairs); + break; + } + return pairs; + } + + private void checkNumberOfLoops(int count) { + if (count == NUMBER_OF_LOOPS) { + throw new IllegalArgumentException(ExceptionMessage.FAIL_MATCHING.getMessage()); + } + } + private List getCrews(MatchingConditions matchingConditions) { MDParser mdParser = new MDParser(); return mdParser.parserCrewData(matchingConditions.getCourse()); From 60b01152eff7e0177557591132c6cacf7ab17898 Mon Sep 17 00:00:00 2001 From: kcw0360 Date: Wed, 13 Dec 2023 19:32:40 +0900 Subject: [PATCH 16/16] =?UTF-8?q?rename:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EB=B0=8F=20=EA=B2=BD=EB=A1=9C=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/controller/MatchingController.java | 4 ++-- src/main/java/pairmatching/domain/MatchingConditions.java | 3 +++ src/main/java/pairmatching/domain/{ => constant}/Course.java | 2 +- src/main/java/pairmatching/domain/{ => constant}/Level.java | 2 +- src/main/java/pairmatching/domain/{ => constant}/Mission.java | 2 +- .../pairmatching/domain/{ => constant}/OptionCommand.java | 2 +- .../pairmatching/domain/{ => constant}/RematchingCommand.java | 2 +- src/main/java/pairmatching/util/MDParser.java | 3 +-- src/main/java/pairmatching/view/InputView.java | 4 ++-- 9 files changed, 13 insertions(+), 11 deletions(-) rename src/main/java/pairmatching/domain/{ => constant}/Course.java (94%) rename src/main/java/pairmatching/domain/{ => constant}/Level.java (94%) rename src/main/java/pairmatching/domain/{ => constant}/Mission.java (96%) rename src/main/java/pairmatching/domain/{ => constant}/OptionCommand.java (94%) rename src/main/java/pairmatching/domain/{ => constant}/RematchingCommand.java (94%) diff --git a/src/main/java/pairmatching/controller/MatchingController.java b/src/main/java/pairmatching/controller/MatchingController.java index b482dbf89..9c72c7cc4 100644 --- a/src/main/java/pairmatching/controller/MatchingController.java +++ b/src/main/java/pairmatching/controller/MatchingController.java @@ -2,9 +2,9 @@ import java.util.List; import pairmatching.domain.MatchingConditions; -import pairmatching.domain.OptionCommand; +import pairmatching.domain.constant.OptionCommand; import pairmatching.domain.Pairs; -import pairmatching.domain.RematchingCommand; +import pairmatching.domain.constant.RematchingCommand; import pairmatching.service.MatchingService; import pairmatching.view.InputView; import pairmatching.view.OutputView; diff --git a/src/main/java/pairmatching/domain/MatchingConditions.java b/src/main/java/pairmatching/domain/MatchingConditions.java index d7e1ac589..617bceb31 100644 --- a/src/main/java/pairmatching/domain/MatchingConditions.java +++ b/src/main/java/pairmatching/domain/MatchingConditions.java @@ -2,6 +2,9 @@ import java.util.List; import java.util.Objects; +import pairmatching.domain.constant.Course; +import pairmatching.domain.constant.Level; +import pairmatching.domain.constant.Mission; import pairmatching.exception.ExceptionMessage; public class MatchingConditions { diff --git a/src/main/java/pairmatching/domain/Course.java b/src/main/java/pairmatching/domain/constant/Course.java similarity index 94% rename from src/main/java/pairmatching/domain/Course.java rename to src/main/java/pairmatching/domain/constant/Course.java index 5a2194445..6e75a8b54 100644 --- a/src/main/java/pairmatching/domain/Course.java +++ b/src/main/java/pairmatching/domain/constant/Course.java @@ -1,4 +1,4 @@ -package pairmatching.domain; +package pairmatching.domain.constant; import java.util.Arrays; import pairmatching.exception.ExceptionMessage; diff --git a/src/main/java/pairmatching/domain/Level.java b/src/main/java/pairmatching/domain/constant/Level.java similarity index 94% rename from src/main/java/pairmatching/domain/Level.java rename to src/main/java/pairmatching/domain/constant/Level.java index fc3468a8e..fe9fa4906 100644 --- a/src/main/java/pairmatching/domain/Level.java +++ b/src/main/java/pairmatching/domain/constant/Level.java @@ -1,4 +1,4 @@ -package pairmatching.domain; +package pairmatching.domain.constant; import java.util.Arrays; import pairmatching.exception.ExceptionMessage; diff --git a/src/main/java/pairmatching/domain/Mission.java b/src/main/java/pairmatching/domain/constant/Mission.java similarity index 96% rename from src/main/java/pairmatching/domain/Mission.java rename to src/main/java/pairmatching/domain/constant/Mission.java index 206ea9bbd..30593efc5 100644 --- a/src/main/java/pairmatching/domain/Mission.java +++ b/src/main/java/pairmatching/domain/constant/Mission.java @@ -1,4 +1,4 @@ -package pairmatching.domain; +package pairmatching.domain.constant; import java.util.Arrays; import pairmatching.exception.ExceptionMessage; diff --git a/src/main/java/pairmatching/domain/OptionCommand.java b/src/main/java/pairmatching/domain/constant/OptionCommand.java similarity index 94% rename from src/main/java/pairmatching/domain/OptionCommand.java rename to src/main/java/pairmatching/domain/constant/OptionCommand.java index e195e7d1e..2d01aa358 100644 --- a/src/main/java/pairmatching/domain/OptionCommand.java +++ b/src/main/java/pairmatching/domain/constant/OptionCommand.java @@ -1,4 +1,4 @@ -package pairmatching.domain; +package pairmatching.domain.constant; import java.util.Arrays; import pairmatching.exception.ExceptionMessage; diff --git a/src/main/java/pairmatching/domain/RematchingCommand.java b/src/main/java/pairmatching/domain/constant/RematchingCommand.java similarity index 94% rename from src/main/java/pairmatching/domain/RematchingCommand.java rename to src/main/java/pairmatching/domain/constant/RematchingCommand.java index 7927685fc..0929c9935 100644 --- a/src/main/java/pairmatching/domain/RematchingCommand.java +++ b/src/main/java/pairmatching/domain/constant/RematchingCommand.java @@ -1,4 +1,4 @@ -package pairmatching.domain; +package pairmatching.domain.constant; import java.util.Arrays; import pairmatching.exception.ExceptionMessage; diff --git a/src/main/java/pairmatching/util/MDParser.java b/src/main/java/pairmatching/util/MDParser.java index 20608151f..2fe726922 100644 --- a/src/main/java/pairmatching/util/MDParser.java +++ b/src/main/java/pairmatching/util/MDParser.java @@ -5,8 +5,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import pairmatching.domain.Course; -import pairmatching.domain.Crew; +import pairmatching.domain.constant.Course; import pairmatching.exception.ExceptionMessage; public class MDParser { diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 588cd326c..eb89728ae 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -3,8 +3,8 @@ import camp.nextstep.edu.missionutils.Console; import java.util.Arrays; import java.util.List; -import pairmatching.domain.OptionCommand; -import pairmatching.domain.RematchingCommand; +import pairmatching.domain.constant.OptionCommand; +import pairmatching.domain.constant.RematchingCommand; public class InputView {