From 37917bc4adb4e3220e929733667e9b1abe271bbb Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 17:20:35 +0900 Subject: [PATCH 01/18] =?UTF-8?q?docs=20:=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=AA=A9=EB=A1=9D=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..af8d8d2e1 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,69 @@ +# 기능 구현 목록 +- [ ] : 페어 이름을 초기화 받는다. +- [ ] : 기능 선택 목록을 출력한다. +- [ ] : 기능을 선택 받는다. + - [ ] `예외 처리` : 빈 값을 입력한 경우 + - [ ] `예외 처리` : 1~3, Q 이외의 값을 입력한 경우. + +## 페어 매칭 기능 +- [ ] : 페어 매칭 안내 문자열을 출력한다. + ``` + ############################################# + 과정: 백엔드 | 프론트엔드 + 미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: + ############################################ + 과정, 레벨, 미션을 선택하세요. + ex) 백엔드, 레벨1, 자동차경주 + ``` +- [ ] : 과정, 레벨, 미션을 `, `기준으로 구분되어 입력 받는다. (ex `백엔드, 레벨1, 자동차경주`) + - [ ] `예외 처리` : 빈 값을 입력한 경우 + - [ ] `예외 처리` : 구분자를 잘못 입력한 경우 + - [ ] `예외 처리` : 일치하는 값이 없는 경우 +- [ ] 페어를 매칭한다. + - [ ] : 두명씩 매칭한다. + - [ ] : 매칭 대상이 홀수인 경우 한 페어는 3인으로 구성된다. + - [ ] : 같은 레벨에서 이미 페어를 맺은 크루와는 다시 매칭되지 않는다. + +- [ ] : 크루들 이름 목록을 List 형태로 준비한다. +- [ ] : 크루 목록의 순서를 랜덤으로 섞는다. (shuffle 메서드를 활용해야 한다.) +- [ ] : 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. + +- [ ] : 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. + - [ ] : 안내 문구를 출력 후 사용자에게 네, 아니오를 입력받는다. + - [ ] `예외 처리` : 빈 값을 입력한 경우 + - [ ] `예외 처리` : 네, 아니오가 아닌 값을 입력 받은 경우 + ```text + 매칭 정보가 있습니다. 다시 매칭하시겠습니까? + 네 | 아니오 + ``` + - [ ] : 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. + - [ ] : 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. + +- [ ] : 매칭 결과를 출력한다. + ```text + 페어 매칭 결과입니다. + 용팔 : 대만 + 대협 : 덕규 + 치수 : 준호 + 태웅 : 백호 + 달재 : 태산 + 한나 : 수겸 + 태섭 : 대남 + 준섭 : 소연 + 현준 : 호열 + 구식 : 경태 + ``` + +## 페어 조회 기능 +- [ ] : 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다. +- [ ] : 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. ( `[ERROR] 매칭 이력이 없습니다.` ) + + +## 페어 초기화 기능 +- [ ] : 페어를 초기화한다. + From b0bb8550a4ba7d8d145601194da128d737b14936 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 17:30:59 +0900 Subject: [PATCH 02/18] =?UTF-8?q?feat=20:=20=ED=8E=98=EC=96=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=B4=88=EA=B8=B0=ED=99=94=20=EA=B8=B0=EB=8A=A5=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 | 2 +- src/main/java/pairmatching/Application.java | 2 +- .../java/pairmatching/CrewRepository.java | 39 +++++++++++++++++++ .../pairmatching/PairMatchingController.java | 18 +++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/main/java/pairmatching/CrewRepository.java create mode 100644 src/main/java/pairmatching/PairMatchingController.java diff --git a/docs/README.md b/docs/README.md index af8d8d2e1..ca128911a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,5 @@ # 기능 구현 목록 -- [ ] : 페어 이름을 초기화 받는다. +- [X] : 페어 이름을 초기화 받는다. - [ ] : 기능 선택 목록을 출력한다. - [ ] : 기능을 선택 받는다. - [ ] `예외 처리` : 빈 값을 입력한 경우 diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index 6f56e741c..c9f254ad8 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -2,6 +2,6 @@ public class Application { public static void main(String[] args) { - // TODO 구현 진행 + PairMatchingController.run(); } } diff --git a/src/main/java/pairmatching/CrewRepository.java b/src/main/java/pairmatching/CrewRepository.java new file mode 100644 index 000000000..1f684c8f7 --- /dev/null +++ b/src/main/java/pairmatching/CrewRepository.java @@ -0,0 +1,39 @@ +package pairmatching; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class CrewRepository { + private List backend = new ArrayList<>(); + private List frontend = new ArrayList<>(); + + public void initBackend(String path) { + addCrewsByFile(path, backend); + } + + public void initFrontend(String path) { + addCrewsByFile(path, frontend); + } + + public void addCrewsByFile(String path, List repository) { + try (BufferedReader br = new BufferedReader(new FileReader(path))) { + String line; + while ((line = br.readLine()) != null) { + repository.add(line); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public List getBackend() { + return new ArrayList<>(backend); + } + + public List getFrontend() { + return new ArrayList<>(frontend); + } +} diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java new file mode 100644 index 000000000..a463fbce4 --- /dev/null +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -0,0 +1,18 @@ +package pairmatching; + +import java.util.List; + +public class PairMatchingController { + static CrewRepository crewRepository = new CrewRepository(); + + public static void run() { + crewRepository.initBackend("src/main/resources/backend-crew.md"); + crewRepository.initFrontend("src/main/resources/frontend-crew.md"); + + List backend = crewRepository.getBackend(); + List frontend = crewRepository.getFrontend(); + + System.out.println("frontend = " + frontend); + System.out.println("backend = " + backend); + } +} From e89ff167314da04b89b5cc64aab2b0273568bc22 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 17:46:49 +0900 Subject: [PATCH 03/18] =?UTF-8?q?feat=20:=20=EB=A9=94=EB=89=B4=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 ++-- .../pairmatching/PairMatchingController.java | 28 ++++++++++++++---- .../pairmatching/PairMatchingService.java | 17 +++++++++++ .../java/pairmatching/view/InputView.java | 29 +++++++++++++++++++ .../java/pairmatching/view/OutputView.java | 7 +++++ .../pairmatching/PairMatchingServiceTest.java | 25 ++++++++++++++++ 6 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 src/main/java/pairmatching/PairMatchingService.java create mode 100644 src/main/java/pairmatching/view/InputView.java create mode 100644 src/main/java/pairmatching/view/OutputView.java create mode 100644 src/test/java/pairmatching/PairMatchingServiceTest.java diff --git a/docs/README.md b/docs/README.md index ca128911a..5acc0ae13 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,9 @@ # 기능 구현 목록 - [X] : 페어 이름을 초기화 받는다. - [ ] : 기능 선택 목록을 출력한다. -- [ ] : 기능을 선택 받는다. - - [ ] `예외 처리` : 빈 값을 입력한 경우 - - [ ] `예외 처리` : 1~3, Q 이외의 값을 입력한 경우. +- [X] : 기능을 선택 받는다. + - [X] `예외 처리` : 빈 값을 입력한 경우 + - [X] `예외 처리` : 1~3, Q 이외의 값을 입력한 경우. ## 페어 매칭 기능 - [ ] : 페어 매칭 안내 문자열을 출력한다. diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index a463fbce4..fb2f7a198 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -1,18 +1,36 @@ package pairmatching; -import java.util.List; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; public class PairMatchingController { static CrewRepository crewRepository = new CrewRepository(); public static void run() { + initCrewRepsoitory(); + proceed(); + } + + private static void initCrewRepsoitory() { crewRepository.initBackend("src/main/resources/backend-crew.md"); crewRepository.initFrontend("src/main/resources/frontend-crew.md"); + } - List backend = crewRepository.getBackend(); - List frontend = crewRepository.getFrontend(); + private static void proceed() { + while (true) { + String validateMenu = getValidateMenu(); + if (validateMenu.equals("Q")) { + break; + } + } + } - System.out.println("frontend = " + frontend); - System.out.println("backend = " + backend); + private static String getValidateMenu() { + try { + return PairMatchingService.getValidateMenu(InputView.readMenu()); + } catch (IllegalArgumentException error) { + OutputView.printException(error); + return getValidateMenu(); + } } } diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java new file mode 100644 index 000000000..599765591 --- /dev/null +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -0,0 +1,17 @@ +package pairmatching; + +public class PairMatchingService { + public static String getValidateMenu(String input) { + validateMenu(input); + return input; + } + + private static void validateMenu(String input) { + if (input.length() != 1) { + throw new IllegalArgumentException("메뉴에 없는 기능입니다."); + } + if (!"123Q".contains(input)) { + throw new IllegalArgumentException("메뉴에 없는 기능입니다."); + } + } +} diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java new file mode 100644 index 000000000..80e95e764 --- /dev/null +++ b/src/main/java/pairmatching/view/InputView.java @@ -0,0 +1,29 @@ +package pairmatching.view; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + public static final String MENU_MESSAGE = "기능을 선택하세요.\n" + + "1. 페어 매칭\n" + + "2. 페어 조회\n" + + "3. 페어 초기화\n" + + "Q. 종료"; + + public static String readMenu() { + System.out.println(MENU_MESSAGE); + String input = readString(); + return input; + } + + private static String readString() { + String input = Console.readLine().trim(); + validateBlank(input); + return input; + } + + private static void validateBlank(String input) { + if (input == null || input.isEmpty()) { + throw new IllegalArgumentException("공백은 입력할 수 없습니다."); + } + } +} diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java new file mode 100644 index 000000000..4ba8806f8 --- /dev/null +++ b/src/main/java/pairmatching/view/OutputView.java @@ -0,0 +1,7 @@ +package pairmatching.view; + +public class OutputView { + public static void printException(Exception error) { + System.out.println(error.getMessage()); + } +} diff --git a/src/test/java/pairmatching/PairMatchingServiceTest.java b/src/test/java/pairmatching/PairMatchingServiceTest.java new file mode 100644 index 000000000..33894e1e6 --- /dev/null +++ b/src/test/java/pairmatching/PairMatchingServiceTest.java @@ -0,0 +1,25 @@ +package pairmatching; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class PairMatchingServiceTest { + + @ParameterizedTest + @ValueSource(strings = {"1", "2", "3", "Q"}) + void getValidateMenuSuccess(String value) { + Assertions.assertThatNoException().isThrownBy(() -> { + PairMatchingService.getValidateMenu(value); + }); + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", "", "B", "q", "12", "2b", "4", "a"}) + void getValidateMenuFail(String value) { + Assertions.assertThatThrownBy(() -> { + PairMatchingService.getValidateMenu(value); + }); + } +} \ No newline at end of file From 448767a3a291cc68332f9186a5c3f52fe61cb16c Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 18:29:58 +0900 Subject: [PATCH 04/18] =?UTF-8?q?feat=20:=20=EB=8B=A8=EC=88=9C=20=ED=8E=98?= =?UTF-8?q?=EC=96=B4=20=EB=A7=A4=EC=B9=AD=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 15 +++--- src/main/java/pairmatching/Course.java | 12 +++++ src/main/java/pairmatching/Crew.java | 6 +++ .../java/pairmatching/CrewRepository.java | 14 +++--- src/main/java/pairmatching/Level.java | 15 ++++++ src/main/java/pairmatching/Pair.java | 22 +++++++++ .../pairmatching/PairMatchingController.java | 30 +++++++++--- .../pairmatching/PairMatchingService.java | 48 +++++++++++++++++++ .../java/pairmatching/view/InputView.java | 6 +++ .../java/pairmatching/view/OutputView.java | 12 +++++ .../java/pairmatching/ApplicationTest.java | 11 +++++ 11 files changed, 171 insertions(+), 20 deletions(-) create mode 100644 src/main/java/pairmatching/Course.java create mode 100644 src/main/java/pairmatching/Crew.java create mode 100644 src/main/java/pairmatching/Level.java create mode 100644 src/main/java/pairmatching/Pair.java diff --git a/docs/README.md b/docs/README.md index 5acc0ae13..670351da9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # 기능 구현 목록 - [X] : 페어 이름을 초기화 받는다. -- [ ] : 기능 선택 목록을 출력한다. +- [X] : 기능 선택 목록을 출력한다. - [X] : 기능을 선택 받는다. - [X] `예외 처리` : 빈 값을 입력한 경우 - [X] `예외 처리` : 1~3, Q 이외의 값을 입력한 경우. @@ -24,14 +24,15 @@ - [ ] `예외 처리` : 빈 값을 입력한 경우 - [ ] `예외 처리` : 구분자를 잘못 입력한 경우 - [ ] `예외 처리` : 일치하는 값이 없는 경우 -- [ ] 페어를 매칭한다. - - [ ] : 두명씩 매칭한다. - - [ ] : 매칭 대상이 홀수인 경우 한 페어는 3인으로 구성된다. + +- [X] 페어를 매칭한다. + - [X] : 두명씩 매칭한다. + - [X] : 매칭 대상이 홀수인 경우 한 페어는 3인으로 구성된다. - [ ] : 같은 레벨에서 이미 페어를 맺은 크루와는 다시 매칭되지 않는다. -- [ ] : 크루들 이름 목록을 List 형태로 준비한다. -- [ ] : 크루 목록의 순서를 랜덤으로 섞는다. (shuffle 메서드를 활용해야 한다.) -- [ ] : 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. +- [X] : 크루들 이름 목록을 List 형태로 준비한다. +- [X] : 크루 목록의 순서를 랜덤으로 섞는다. (shuffle 메서드를 활용해야 한다.) +- [X] : 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. - [ ] : 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. - [ ] : 안내 문구를 출력 후 사용자에게 네, 아니오를 입력받는다. diff --git a/src/main/java/pairmatching/Course.java b/src/main/java/pairmatching/Course.java new file mode 100644 index 000000000..9f6aa249f --- /dev/null +++ b/src/main/java/pairmatching/Course.java @@ -0,0 +1,12 @@ +package pairmatching; + +public enum Course { + BACKEND("백엔드"), + FRONTEND("프론트엔드"); + + private String name; + + Course(String name) { + this.name = name; + } +} diff --git a/src/main/java/pairmatching/Crew.java b/src/main/java/pairmatching/Crew.java new file mode 100644 index 000000000..87d9f7ba5 --- /dev/null +++ b/src/main/java/pairmatching/Crew.java @@ -0,0 +1,6 @@ +package pairmatching; + +public class Crew { + private Course course; + private String name; +} diff --git a/src/main/java/pairmatching/CrewRepository.java b/src/main/java/pairmatching/CrewRepository.java index 1f684c8f7..93edfd965 100644 --- a/src/main/java/pairmatching/CrewRepository.java +++ b/src/main/java/pairmatching/CrewRepository.java @@ -29,11 +29,13 @@ public void addCrewsByFile(String path, List repository) { } } - public List getBackend() { - return new ArrayList<>(backend); - } - - public List getFrontend() { - return new ArrayList<>(frontend); + public List findByCourse(Course course) { + if (course == Course.FRONTEND) { + return new ArrayList<>(frontend); + } + if (course == Course.BACKEND) { + return new ArrayList<>(backend); + } + return null; } } diff --git a/src/main/java/pairmatching/Level.java b/src/main/java/pairmatching/Level.java new file mode 100644 index 000000000..882e94cab --- /dev/null +++ b/src/main/java/pairmatching/Level.java @@ -0,0 +1,15 @@ +package pairmatching; + +public enum Level { + LEVEL1("레벨1"), + LEVEL2("레벨2"), + LEVEL3("레벨3"), + LEVEL4("레벨4"), + LEVEL5("레벨5"); + + private String name; + + Level(String name) { + this.name = name; + } +} diff --git a/src/main/java/pairmatching/Pair.java b/src/main/java/pairmatching/Pair.java new file mode 100644 index 000000000..bfa418af0 --- /dev/null +++ b/src/main/java/pairmatching/Pair.java @@ -0,0 +1,22 @@ +package pairmatching; + +import java.util.ArrayList; +import java.util.List; + +public class Pair { + private List crews; + + public Pair(String firstCrew, String secondCrew) { + crews = new ArrayList<>(); + crews.add(firstCrew); + crews.add(secondCrew); + } + + public void addCrew(String crew) { + crews.add(crew); + } + + public List getCrews() { + return new ArrayList<>(crews); + } +} diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index fb2f7a198..9f7f341a9 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -1,27 +1,24 @@ package pairmatching; +import java.util.List; import pairmatching.view.InputView; import pairmatching.view.OutputView; public class PairMatchingController { - static CrewRepository crewRepository = new CrewRepository(); public static void run() { - initCrewRepsoitory(); + PairMatchingService.initCrews(); proceed(); } - private static void initCrewRepsoitory() { - crewRepository.initBackend("src/main/resources/backend-crew.md"); - crewRepository.initFrontend("src/main/resources/frontend-crew.md"); - } - private static void proceed() { while (true) { String validateMenu = getValidateMenu(); if (validateMenu.equals("Q")) { break; } + + // TODO 메뉴에 따라 기능 수행 } } @@ -33,4 +30,23 @@ private static String getValidateMenu() { return getValidateMenu(); } } + + private static void pairMatching(Course course, Level level) { + List matchingResult = PairMatchingService.pairMatching(course); + if (PairMatchingService.hasSamePair(course, level) && getValidateRematch().equals("네")) { + // 3번 리매칭 + + return; + } + OutputView.printMatchingResult(matchingResult); + } + + private static String getValidateRematch() { + try { + return PairMatchingService.getValidateRematch(InputView.readRematch()); + } catch (IllegalArgumentException error) { + OutputView.printException(error); + return getValidateRematch(); + } + } } diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index 599765591..46d615962 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -1,6 +1,20 @@ package pairmatching; +import camp.nextstep.edu.missionutils.Randoms; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class PairMatchingService { + private static final CrewRepository crewRepository = new CrewRepository(); + private static final Map history = new HashMap<>(); + + public static void initCrews() { + crewRepository.initBackend("src/main/resources/backend-crew.md"); + crewRepository.initFrontend("src/main/resources/frontend-crew.md"); + } + public static String getValidateMenu(String input) { validateMenu(input); return input; @@ -14,4 +28,38 @@ private static void validateMenu(String input) { throw new IllegalArgumentException("메뉴에 없는 기능입니다."); } } + + public static List pairMatching(Course course) { + List crewNames = crewRepository.findByCourse(course); + if (crewNames == null) { + throw new IllegalArgumentException("존재하지 않는 코스입니다."); + } + List shuffleCrew = Randoms.shuffle(crewNames); + List result = new ArrayList<>(); + for (int i = 0; i < shuffleCrew.size(); i += 2) { + if (i + 1 == shuffleCrew.size()) { + Pair lastPair = result.get(result.size() - 1); + lastPair.addCrew(shuffleCrew.get(i)); + break; + } + Pair pair = new Pair(shuffleCrew.get(i), shuffleCrew.get(i + 1)); + result.add(pair); + } + return result; + } + + public static boolean hasSamePair(Course course, Level level) { + return history.containsKey(course.name() + level.name()); + } + + public static String getValidateRematch(String input) { + validateRematch(input); + return input; + } + + private static void validateRematch(String input) { + if (!input.equals("네") && !input.equals("아니오")) { + throw new IllegalArgumentException("잘못된 입력입니다."); + } + } } diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 80e95e764..4a186b40e 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -26,4 +26,10 @@ private static void validateBlank(String input) { throw new IllegalArgumentException("공백은 입력할 수 없습니다."); } } + + public static String readRematch() { + System.out.println("매칭 정보가 있습니다. 다시 매칭하시겠습니까?"); + System.out.println("네 | 아니오"); + return readString(); + } } diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 4ba8806f8..4d4900866 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -1,7 +1,19 @@ package pairmatching.view; +import java.util.List; +import java.util.stream.Collectors; +import pairmatching.Pair; + public class OutputView { public static void printException(Exception error) { System.out.println(error.getMessage()); } + + public static void printMatchingResult(List matchingResult) { + System.out.println("페어 매칭 결과입니다."); + for (Pair pair : matchingResult) { + String pairString = String.join(" : ", pair.getCrews()); + System.out.println(pairString); + } + } } diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index 2dff1e6d3..5bc496016 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -24,6 +24,17 @@ class ApplicationTest extends NsTest { ); } + @Test + void 홀수_인원_페어_매칭() { + assertShuffleTest( + () -> { + run("1", "프론트, 레벨1, 자동차경주", "Q"); + assertThat(output()).contains("보노 : 시저", "쉐리 : 신디 : 다비"); + }, + Arrays.asList("보노", "시저", "쉐리", "신디", "다비") + ); + } + @Test void 없는_미션에_대한_예외_처리() { assertSimpleTest( From 9a233bbde730049b1bd1182f45b0af78663c30a9 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 19:01:49 +0900 Subject: [PATCH 05/18] =?UTF-8?q?feat=20:=20=ED=8E=98=EC=96=B4=20=EC=9E=AC?= =?UTF-8?q?=EB=A7=A4=EC=B9=AD=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 12 +++--- src/main/java/pairmatching/Pair.java | 40 +++++++++++++++++++ .../pairmatching/PairMatchingController.java | 19 +++++++-- .../pairmatching/PairMatchingService.java | 19 ++++++++- .../java/pairmatching/ApplicationTest.java | 13 ++++++ 5 files changed, 92 insertions(+), 11 deletions(-) diff --git a/docs/README.md b/docs/README.md index 670351da9..1a3aedd0e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -28,22 +28,22 @@ - [X] 페어를 매칭한다. - [X] : 두명씩 매칭한다. - [X] : 매칭 대상이 홀수인 경우 한 페어는 3인으로 구성된다. - - [ ] : 같은 레벨에서 이미 페어를 맺은 크루와는 다시 매칭되지 않는다. + - [X] : 같은 레벨에서 이미 페어를 맺은 크루와는 다시 매칭되지 않는다. - [X] : 크루들 이름 목록을 List 형태로 준비한다. - [X] : 크루 목록의 순서를 랜덤으로 섞는다. (shuffle 메서드를 활용해야 한다.) - [X] : 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. -- [ ] : 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. - - [ ] : 안내 문구를 출력 후 사용자에게 네, 아니오를 입력받는다. - - [ ] `예외 처리` : 빈 값을 입력한 경우 - - [ ] `예외 처리` : 네, 아니오가 아닌 값을 입력 받은 경우 +- [X] : 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. + - [X] : 안내 문구를 출력 후 사용자에게 네, 아니오를 입력받는다. + - [X] `예외 처리` : 빈 값을 입력한 경우 + - [X] `예외 처리` : 네, 아니오가 아닌 값을 입력 받은 경우 ```text 매칭 정보가 있습니다. 다시 매칭하시겠습니까? 네 | 아니오 ``` - [ ] : 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. - - [ ] : 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. + - [X] : 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. - [ ] : 매칭 결과를 출력한다. ```text diff --git a/src/main/java/pairmatching/Pair.java b/src/main/java/pairmatching/Pair.java index bfa418af0..ddfa36b47 100644 --- a/src/main/java/pairmatching/Pair.java +++ b/src/main/java/pairmatching/Pair.java @@ -1,7 +1,12 @@ package pairmatching; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; public class Pair { private List crews; @@ -19,4 +24,39 @@ public void addCrew(String crew) { public List getCrews() { return new ArrayList<>(crews); } + + + public boolean hasSamePair(Pair pair) { + if (crews.size() == 2 && pair.crews.size() == 2) { + Set set = new HashSet<>(); + set.addAll(crews); + set.addAll(pair.crews); + return set.size() == 2; + } + if (crews.size() == 3 && pair.crews.size() == 3) { + Set set = new HashSet<>(); + set.addAll(crews); + set.addAll(pair.crews); + return set.size() == 3; + } + return countDuplicateElements(crews, pair.crews) > 2; + } + + private int countDuplicateElements(List list1, List list2) { + Map countMap = new HashMap<>(); + + for (String str : list1) { + countMap.put(str, countMap.getOrDefault(str, 0) + 1); + } + + int duplicateCount = 0; + + for (String str : list2) { + if (countMap.containsKey(str) && countMap.get(str) > 0) { + duplicateCount++; + } + } + + return duplicateCount; + } } diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index 9f7f341a9..3788c1467 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -19,6 +19,7 @@ private static void proceed() { } // TODO 메뉴에 따라 기능 수행 + pairMatching(Course.BACKEND, Level.LEVEL1); } } @@ -33,14 +34,25 @@ private static String getValidateMenu() { private static void pairMatching(Course course, Level level) { List matchingResult = PairMatchingService.pairMatching(course); - if (PairMatchingService.hasSamePair(course, level) && getValidateRematch().equals("네")) { + if (PairMatchingService.hasHistory(course, level) && getValidateRematch().equals("네")) { // 3번 리매칭 - - return; + matchingResult = handleRematch(course, level); } OutputView.printMatchingResult(matchingResult); } + private static List handleRematch(Course course, Level level) { + List history = PairMatchingService.getHistory(course, level); + for (int i = 0; i < 3; i++) { + List rematch = PairMatchingService.pairMatching(course); + if (PairMatchingService.hasSamePair(history, rematch)) { + continue; + } + return rematch; + } + throw new IllegalArgumentException("3번의 리매칭을 모두 실패했습니다."); + } + private static String getValidateRematch() { try { return PairMatchingService.getValidateRematch(InputView.readRematch()); @@ -49,4 +61,5 @@ private static String getValidateRematch() { return getValidateRematch(); } } + } diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index 46d615962..b3e4b950a 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -8,7 +8,7 @@ public class PairMatchingService { private static final CrewRepository crewRepository = new CrewRepository(); - private static final Map history = new HashMap<>(); + private static final Map> history = new HashMap<>(); public static void initCrews() { crewRepository.initBackend("src/main/resources/backend-crew.md"); @@ -48,10 +48,14 @@ public static List pairMatching(Course course) { return result; } - public static boolean hasSamePair(Course course, Level level) { + public static boolean hasHistory(Course course, Level level) { return history.containsKey(course.name() + level.name()); } + public static List getHistory(Course course, Level level) { + return history.get(course.name() + level.name()); + } + public static String getValidateRematch(String input) { validateRematch(input); return input; @@ -62,4 +66,15 @@ private static void validateRematch(String input) { throw new IllegalArgumentException("잘못된 입력입니다."); } } + + public static boolean hasSamePair(List history, List rematch) { + for (Pair pair : history) { + for (Pair rematchPair : rematch) { + if (pair.hasSamePair(rematchPair)) { + return true; + } + } + } + return false; + } } diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index 5bc496016..abbe3dd8f 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -35,6 +35,19 @@ class ApplicationTest extends NsTest { ); } + @Test + void 재매칭_실패() { + assertShuffleTest( + () -> { + run("1", "백엔드, 레벨1, 자동차경주", "1", "프론트, 레벨1, 자동차경주", "네"); + assertThat(output()).contains("태웅 : 백호", "치수 : 태섭"); + }, + Arrays.asList("태웅", "백호", "치수", "태섭"), + Arrays.asList("태웅", "백호", "치수", "태섭"), + Arrays.asList("태웅", "백호", "치수", "태섭") + ); + } + @Test void 없는_미션에_대한_예외_처리() { assertSimpleTest( From d77e2f9fc5704ad18c64b9e12c4c617558cab874 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 19:24:05 +0900 Subject: [PATCH 06/18] =?UTF-8?q?feat=20:=20=ED=8E=98=EC=96=B4=20=EC=9E=AC?= =?UTF-8?q?=EB=A7=A4=EC=B9=AD=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 6 +-- src/main/java/pairmatching/Course.java | 11 +++++ src/main/java/pairmatching/Level.java | 9 ++++ src/main/java/pairmatching/Mission.java | 29 ++++++++++++ .../pairmatching/PairMatchingController.java | 45 ++++++++++++++++--- .../pairmatching/PairMatchingService.java | 9 ++-- .../java/pairmatching/view/InputView.java | 15 +++++++ .../java/pairmatching/ApplicationTest.java | 4 +- 8 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 src/main/java/pairmatching/Mission.java diff --git a/docs/README.md b/docs/README.md index 1a3aedd0e..6abccb21f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,7 +6,7 @@ - [X] `예외 처리` : 1~3, Q 이외의 값을 입력한 경우. ## 페어 매칭 기능 -- [ ] : 페어 매칭 안내 문자열을 출력한다. +- [X] : 페어 매칭 안내 문자열을 출력한다. ``` ############################################# 과정: 백엔드 | 프론트엔드 @@ -42,10 +42,10 @@ 매칭 정보가 있습니다. 다시 매칭하시겠습니까? 네 | 아니오 ``` - - [ ] : 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. + - [X] : 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다. - [X] : 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. -- [ ] : 매칭 결과를 출력한다. +- [X] : 매칭 결과를 출력한다. ```text 페어 매칭 결과입니다. 용팔 : 대만 diff --git a/src/main/java/pairmatching/Course.java b/src/main/java/pairmatching/Course.java index 9f6aa249f..3c10f31ce 100644 --- a/src/main/java/pairmatching/Course.java +++ b/src/main/java/pairmatching/Course.java @@ -9,4 +9,15 @@ public enum Course { Course(String name) { this.name = name; } + + + + public static Course findByName(String name) { + for (Course course : Course.values()) { + if (course.name.equals(name)) { + return course; + } + } + throw new IllegalArgumentException("잘못된 입력입니다."); + } } diff --git a/src/main/java/pairmatching/Level.java b/src/main/java/pairmatching/Level.java index 882e94cab..1f2dae305 100644 --- a/src/main/java/pairmatching/Level.java +++ b/src/main/java/pairmatching/Level.java @@ -12,4 +12,13 @@ public enum Level { Level(String name) { this.name = name; } + + public static Level findByName(String name) { + for (Level level : Level.values()) { + if (level.name.equals(name)) { + return level; + } + } + throw new IllegalArgumentException("잘못된 입력입니다."); + } } diff --git a/src/main/java/pairmatching/Mission.java b/src/main/java/pairmatching/Mission.java new file mode 100644 index 000000000..ae6e40b60 --- /dev/null +++ b/src/main/java/pairmatching/Mission.java @@ -0,0 +1,29 @@ +package pairmatching; + +public enum Mission { + RACING_CAR("자동차경주", Level.LEVEL1), + LOTTO("로또", Level.LEVEL1), + BASEBALL("숫자야구게임", Level.LEVEL1), + SHOPPING_CART("장바구니", Level.LEVEL2), + PAYMENT("결제", Level.LEVEL2), + SUBWAY("지하철노선도", Level.LEVEL2), + PERFORMANCE_IMPROVEMENT("성능개선", Level.LEVEL4), + DEPLOYMENT("배포", Level.LEVEL4); + + private String name; + private Level level; + + Mission(String name, Level level) { + this.name = name; + this.level = level; + } + + public static Mission findByName(String name) { + for (Mission mission : Mission.values()) { + if (mission.name.equals(name)) { + return mission; + } + } + throw new IllegalArgumentException("잘못된 입력입니다."); + } +} diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index 3788c1467..572ae4f75 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -17,9 +17,33 @@ private static void proceed() { if (validateMenu.equals("Q")) { break; } + handleByMenu(validateMenu); + } + } + + private static void handleByMenu(String validateMenu) { + if (validateMenu.equals("1")) { + handlePairMatching(); + return; + } + + } - // TODO 메뉴에 따라 기능 수행 - pairMatching(Course.BACKEND, Level.LEVEL1); + private static void handlePairMatching() { + try { + String option = InputView.readOption(); + String[] split = option.split(", "); + if (split.length != 3) { + throw new IllegalArgumentException("잘못된 입력입니다."); + } + Course course = Course.findByName(split[0]); + Level level = Level.findByName(split[1]); + Mission mission = Mission.findByName(split[2]); + + pairMatching(course, level); + } catch (IllegalArgumentException error) { + OutputView.printException(error); + handlePairMatching(); } } @@ -33,18 +57,25 @@ private static String getValidateMenu() { } private static void pairMatching(Course course, Level level) { - List matchingResult = PairMatchingService.pairMatching(course); - if (PairMatchingService.hasHistory(course, level) && getValidateRematch().equals("네")) { - // 3번 리매칭 - matchingResult = handleRematch(course, level); + List matchingResult; + if (PairMatchingService.hasHistory(course, level)) { + if (getValidateRematch().equals("네")) { + // 3번 리매칭 + matchingResult = handleRematch(course, level); + OutputView.printMatchingResult(matchingResult); + return; + } + handlePairMatching(); // 코스, 레벨, 미션을 다시 선택한다. + return; } + matchingResult = PairMatchingService.pairMatching(course, level); OutputView.printMatchingResult(matchingResult); } private static List handleRematch(Course course, Level level) { List history = PairMatchingService.getHistory(course, level); for (int i = 0; i < 3; i++) { - List rematch = PairMatchingService.pairMatching(course); + List rematch = PairMatchingService.pairMatching(course, level); if (PairMatchingService.hasSamePair(history, rematch)) { continue; } diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index b3e4b950a..ae16dbbfd 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -7,10 +7,12 @@ import java.util.Map; public class PairMatchingService { - private static final CrewRepository crewRepository = new CrewRepository(); - private static final Map> history = new HashMap<>(); + private static CrewRepository crewRepository = new CrewRepository(); + private static Map> history = new HashMap<>(); public static void initCrews() { + crewRepository = new CrewRepository(); + history = new HashMap<>(); crewRepository.initBackend("src/main/resources/backend-crew.md"); crewRepository.initFrontend("src/main/resources/frontend-crew.md"); } @@ -29,7 +31,7 @@ private static void validateMenu(String input) { } } - public static List pairMatching(Course course) { + public static List pairMatching(Course course, Level level) { List crewNames = crewRepository.findByCourse(course); if (crewNames == null) { throw new IllegalArgumentException("존재하지 않는 코스입니다."); @@ -45,6 +47,7 @@ public static List pairMatching(Course course) { Pair pair = new Pair(shuffleCrew.get(i), shuffleCrew.get(i + 1)); result.add(pair); } + history.put(course.name() + level.name(), result); return result; } diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 4a186b40e..2899fe2cc 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -32,4 +32,19 @@ public static String readRematch() { System.out.println("네 | 아니오"); return readString(); } + + public static String readOption() { + System.out.println("#############################################\n" + + " 과정: 백엔드 | 프론트엔드\n" + + " 미션:\n" + + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임\n" + + " - 레벨2: 장바구니 | 결제 | 지하철노선도\n" + + " - 레벨3: \n" + + " - 레벨4: 성능개선 | 배포\n" + + " - 레벨5: \n" + + " ############################################"); + System.out.println("과정, 레벨, 미션을 선택하세요.\n" + + " ex) 백엔드, 레벨1, 자동차경주"); + return readString(); + } } diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index abbe3dd8f..143ea6871 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -28,7 +28,7 @@ class ApplicationTest extends NsTest { void 홀수_인원_페어_매칭() { assertShuffleTest( () -> { - run("1", "프론트, 레벨1, 자동차경주", "Q"); + run("1", "프론트엔드, 레벨1, 자동차경주", "Q"); assertThat(output()).contains("보노 : 시저", "쉐리 : 신디 : 다비"); }, Arrays.asList("보노", "시저", "쉐리", "신디", "다비") @@ -39,7 +39,7 @@ class ApplicationTest extends NsTest { void 재매칭_실패() { assertShuffleTest( () -> { - run("1", "백엔드, 레벨1, 자동차경주", "1", "프론트, 레벨1, 자동차경주", "네"); + runException("1", "백엔드, 레벨1, 자동차경주", "1", "백엔드, 레벨1, 자동차경주", "네"); assertThat(output()).contains("태웅 : 백호", "치수 : 태섭"); }, Arrays.asList("태웅", "백호", "치수", "태섭"), From 69feb68e32b84b5a97765544ce9d373f2adab709 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 19:39:59 +0900 Subject: [PATCH 07/18] =?UTF-8?q?fix=20:=20=ED=8E=98=EC=96=B4=20=EC=9E=AC?= =?UTF-8?q?=EB=A7=A4=EC=B9=AD=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=9E=98=EB=AA=BB=EB=90=9C=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=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/Mission.java | 9 ++++++ .../pairmatching/PairMatchingController.java | 16 +++++----- .../pairmatching/PairMatchingService.java | 30 ++++++++++++------- .../java/pairmatching/view/InputView.java | 12 +++++++- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/main/java/pairmatching/Mission.java b/src/main/java/pairmatching/Mission.java index ae6e40b60..eeea12ded 100644 --- a/src/main/java/pairmatching/Mission.java +++ b/src/main/java/pairmatching/Mission.java @@ -1,5 +1,10 @@ package pairmatching; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + public enum Mission { RACING_CAR("자동차경주", Level.LEVEL1), LOTTO("로또", Level.LEVEL1), @@ -26,4 +31,8 @@ public static Mission findByName(String name) { } throw new IllegalArgumentException("잘못된 입력입니다."); } + + public static List findAll() { + return new ArrayList<>(Arrays.asList(Mission.values())); + } } diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index 572ae4f75..e79ed6f32 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -40,7 +40,7 @@ private static void handlePairMatching() { Level level = Level.findByName(split[1]); Mission mission = Mission.findByName(split[2]); - pairMatching(course, level); + pairMatching(course, level, mission); } catch (IllegalArgumentException error) { OutputView.printException(error); handlePairMatching(); @@ -56,26 +56,26 @@ private static String getValidateMenu() { } } - private static void pairMatching(Course course, Level level) { + private static void pairMatching(Course course, Level level, Mission mission) { List matchingResult; - if (PairMatchingService.hasHistory(course, level)) { + if (PairMatchingService.hasHistory(course, level, mission)) { if (getValidateRematch().equals("네")) { // 3번 리매칭 - matchingResult = handleRematch(course, level); + matchingResult = handleRematch(course, level, mission); OutputView.printMatchingResult(matchingResult); return; } handlePairMatching(); // 코스, 레벨, 미션을 다시 선택한다. return; } - matchingResult = PairMatchingService.pairMatching(course, level); + matchingResult = PairMatchingService.pairMatching(course, level, mission); OutputView.printMatchingResult(matchingResult); } - private static List handleRematch(Course course, Level level) { - List history = PairMatchingService.getHistory(course, level); + private static List handleRematch(Course course, Level level, Mission mission) { + List> history = PairMatchingService.getHistory(course, level); for (int i = 0; i < 3; i++) { - List rematch = PairMatchingService.pairMatching(course, level); + List rematch = PairMatchingService.pairMatching(course, level, mission); if (PairMatchingService.hasSamePair(history, rematch)) { continue; } diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index ae16dbbfd..868cead0c 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -31,7 +31,7 @@ private static void validateMenu(String input) { } } - public static List pairMatching(Course course, Level level) { + public static List pairMatching(Course course, Level level, Mission mission) { List crewNames = crewRepository.findByCourse(course); if (crewNames == null) { throw new IllegalArgumentException("존재하지 않는 코스입니다."); @@ -47,16 +47,22 @@ public static List pairMatching(Course course, Level level) { Pair pair = new Pair(shuffleCrew.get(i), shuffleCrew.get(i + 1)); result.add(pair); } - history.put(course.name() + level.name(), result); + history.put(course.name() + level.name() + mission.name(), result); return result; } - public static boolean hasHistory(Course course, Level level) { - return history.containsKey(course.name() + level.name()); + public static boolean hasHistory(Course course, Level level, Mission mission) { + return history.containsKey(course.name() + level.name() + mission.name()); } - public static List getHistory(Course course, Level level) { - return history.get(course.name() + level.name()); + public static List> getHistory(Course course, Level level) { + List> result = new ArrayList<>(); + Mission.findAll().forEach(mission -> { + if (hasHistory(course, level, mission)) { + result.add(history.get(course.name() + level.name() + mission.name())); + } + }); + return result; } public static String getValidateRematch(String input) { @@ -70,11 +76,13 @@ private static void validateRematch(String input) { } } - public static boolean hasSamePair(List history, List rematch) { - for (Pair pair : history) { - for (Pair rematchPair : rematch) { - if (pair.hasSamePair(rematchPair)) { - return true; + public static boolean hasSamePair(List> history, List rematch) { + for (List pairs : history) { + for (Pair pair : pairs) { + for (Pair rematchPair : rematch) { + if (pair.hasSamePair(rematchPair)) { + return true; + } } } } diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 2899fe2cc..ca952e39e 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -1,6 +1,7 @@ package pairmatching.view; import camp.nextstep.edu.missionutils.Console; +import java.util.regex.Pattern; public class InputView { public static final String MENU_MESSAGE = "기능을 선택하세요.\n" @@ -45,6 +46,15 @@ public static String readOption() { + " ############################################"); System.out.println("과정, 레벨, 미션을 선택하세요.\n" + " ex) 백엔드, 레벨1, 자동차경주"); - return readString(); + String input = readString(); + String regexPattern = "^[가-힣]+,\\s[가-힣]+\\d,\\s[가-힣]+$"; + + // 정규표현식 검사 + boolean isMatch = Pattern.matches(regexPattern, input); + + if (!isMatch) { + throw new IllegalArgumentException("입력 형식이 잘못되었습니다."); + } + return input; } } From 51e7d947a29379f00c5de95841630937bd703006 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 19:46:38 +0900 Subject: [PATCH 08/18] =?UTF-8?q?feat=20:=20=ED=8E=98=EC=96=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=B0=8F=20=EC=B4=88=EA=B8=B0=ED=99=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 14 ++++---- .../pairmatching/PairMatchingController.java | 36 ++++++++++++++++++- .../pairmatching/PairMatchingService.java | 8 +++++ .../java/pairmatching/view/OutputView.java | 3 +- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/docs/README.md b/docs/README.md index 6abccb21f..b7009a40e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,10 +20,10 @@ 과정, 레벨, 미션을 선택하세요. ex) 백엔드, 레벨1, 자동차경주 ``` -- [ ] : 과정, 레벨, 미션을 `, `기준으로 구분되어 입력 받는다. (ex `백엔드, 레벨1, 자동차경주`) - - [ ] `예외 처리` : 빈 값을 입력한 경우 - - [ ] `예외 처리` : 구분자를 잘못 입력한 경우 - - [ ] `예외 처리` : 일치하는 값이 없는 경우 +- [X] : 과정, 레벨, 미션을 `, `기준으로 구분되어 입력 받는다. (ex `백엔드, 레벨1, 자동차경주`) + - [X] `예외 처리` : 빈 값을 입력한 경우 + - [X] `예외 처리` : 구분자를 잘못 입력한 경우 + - [X] `예외 처리` : 일치하는 값이 없는 경우 - [X] 페어를 매칭한다. - [X] : 두명씩 매칭한다. @@ -61,10 +61,10 @@ ``` ## 페어 조회 기능 -- [ ] : 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다. -- [ ] : 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. ( `[ERROR] 매칭 이력이 없습니다.` ) +- [X] : 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다. +- [X] : 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. ( `[ERROR] 매칭 이력이 없습니다.` ) ## 페어 초기화 기능 -- [ ] : 페어를 초기화한다. +- [X] : 페어를 초기화한다. diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index e79ed6f32..f8c13571f 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -26,9 +26,19 @@ private static void handleByMenu(String validateMenu) { handlePairMatching(); return; } - + if (validateMenu.equals("2")) { + handlePairHistory(); + return; + } + if (validateMenu.equals("3")) { + handlePairReset(); + return; + } + throw new IllegalArgumentException("잘못된 입력입니다."); } + + private static void handlePairMatching() { try { String option = InputView.readOption(); @@ -93,4 +103,28 @@ private static String getValidateRematch() { } } + private static void handlePairHistory() { + try { + String option = InputView.readOption(); + String[] split = option.split(", "); + if (split.length != 3) { + throw new IllegalArgumentException("잘못된 입력입니다."); + } + Course course = Course.findByName(split[0]); + Level level = Level.findByName(split[1]); + Mission mission = Mission.findByName(split[2]); + if (!PairMatchingService.hasHistory(course, level, mission)) { + throw new IllegalArgumentException("매칭 이력이 없습니다."); + } + List result = PairMatchingService.findHistory(course, level, mission); + OutputView.printMatchingResult(result); + } catch (IllegalArgumentException error) { + OutputView.printException(error); + handlePairHistory(); + } + } + + private static void handlePairReset() { + PairMatchingService.reset(); + } } diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index 868cead0c..3765a7bd7 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -88,4 +88,12 @@ public static boolean hasSamePair(List> history, List rematch) } return false; } + + public static List findHistory(Course course, Level level, Mission mission) { + return history.get(course.name() + level.name() + mission.name()); + } + + public static void reset() { + history = new HashMap<>(); + } } diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 4d4900866..cc8d62b20 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -1,12 +1,11 @@ package pairmatching.view; import java.util.List; -import java.util.stream.Collectors; import pairmatching.Pair; public class OutputView { public static void printException(Exception error) { - System.out.println(error.getMessage()); + System.out.println("[ERROR] : " + error.getMessage()); } public static void printMatchingResult(List matchingResult) { From 885ceb413e330a80021f1f21866fda8fdd8c93fc Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 19:57:46 +0900 Subject: [PATCH 09/18] =?UTF-8?q?refactor=20:=20Utils=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/Pair.java | 20 +------------------- src/main/java/pairmatching/Utils.java | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 src/main/java/pairmatching/Utils.java diff --git a/src/main/java/pairmatching/Pair.java b/src/main/java/pairmatching/Pair.java index ddfa36b47..e593ada1f 100644 --- a/src/main/java/pairmatching/Pair.java +++ b/src/main/java/pairmatching/Pair.java @@ -39,24 +39,6 @@ public boolean hasSamePair(Pair pair) { set.addAll(pair.crews); return set.size() == 3; } - return countDuplicateElements(crews, pair.crews) > 2; - } - - private int countDuplicateElements(List list1, List list2) { - Map countMap = new HashMap<>(); - - for (String str : list1) { - countMap.put(str, countMap.getOrDefault(str, 0) + 1); - } - - int duplicateCount = 0; - - for (String str : list2) { - if (countMap.containsKey(str) && countMap.get(str) > 0) { - duplicateCount++; - } - } - - return duplicateCount; + return Utils.countDuplicateElements(crews, pair.crews) > 2; } } diff --git a/src/main/java/pairmatching/Utils.java b/src/main/java/pairmatching/Utils.java new file mode 100644 index 000000000..8b21f8ee1 --- /dev/null +++ b/src/main/java/pairmatching/Utils.java @@ -0,0 +1,25 @@ +package pairmatching; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Utils { + public static int countDuplicateElements(List list1, List list2) { + Map countMap = new HashMap<>(); + + for (String str : list1) { + countMap.put(str, countMap.getOrDefault(str, 0) + 1); + } + + int duplicateCount = 0; + + for (String str : list2) { + if (countMap.containsKey(str) && countMap.get(str) > 0) { + duplicateCount++; + } + } + + return duplicateCount; + } +} From 033616a678b3a2cddfe9d411a041e5ea7ee5c17a Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 20:10:22 +0900 Subject: [PATCH 10/18] =?UTF-8?q?refactor=20:=20=EC=B6=9C=EB=A0=A5=20?= =?UTF-8?q?=EB=9D=84=EC=96=B4=EC=93=B0=EA=B8=B0=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/view/OutputView.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index cc8d62b20..1413611a1 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -2,15 +2,16 @@ import java.util.List; import pairmatching.Pair; +import pairmatching.Pairs; public class OutputView { public static void printException(Exception error) { System.out.println("[ERROR] : " + error.getMessage()); } - public static void printMatchingResult(List matchingResult) { + public static void printMatchingResult(Pairs matchingResult) { System.out.println("페어 매칭 결과입니다."); - for (Pair pair : matchingResult) { + for (Pair pair : matchingResult.getPairs()) { String pairString = String.join(" : ", pair.getCrews()); System.out.println(pairString); } From d8e110449099bc737b4fa5aaca024ad986f406e5 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 20:14:14 +0900 Subject: [PATCH 11/18] =?UTF-8?q?refactor=20:=20Pairs=20=EC=9D=BC=EA=B8=89?= =?UTF-8?q?=20=EC=BB=AC=EB=A0=89=EC=85=98=20=EB=A6=AC=ED=8C=A9=ED=84=B0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/Pair.java | 3 -- .../pairmatching/PairMatchingController.java | 12 +++---- .../pairmatching/PairMatchingService.java | 35 ++++++++----------- src/main/java/pairmatching/Pairs.java | 30 ++++++++++++++++ .../java/pairmatching/view/InputView.java | 21 +++++------ .../java/pairmatching/ApplicationTest.java | 8 +++-- 6 files changed, 66 insertions(+), 43 deletions(-) create mode 100644 src/main/java/pairmatching/Pairs.java diff --git a/src/main/java/pairmatching/Pair.java b/src/main/java/pairmatching/Pair.java index e593ada1f..1b5dec3e8 100644 --- a/src/main/java/pairmatching/Pair.java +++ b/src/main/java/pairmatching/Pair.java @@ -1,11 +1,8 @@ package pairmatching; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Objects; import java.util.Set; public class Pair { diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index f8c13571f..1d79288ee 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -67,7 +67,7 @@ private static String getValidateMenu() { } private static void pairMatching(Course course, Level level, Mission mission) { - List matchingResult; + Pairs matchingResult; if (PairMatchingService.hasHistory(course, level, mission)) { if (getValidateRematch().equals("네")) { // 3번 리매칭 @@ -82,10 +82,10 @@ private static void pairMatching(Course course, Level level, Mission mission) { OutputView.printMatchingResult(matchingResult); } - private static List handleRematch(Course course, Level level, Mission mission) { - List> history = PairMatchingService.getHistory(course, level); + private static Pairs handleRematch(Course course, Level level, Mission mission) { + List history = PairMatchingService.getHistory(course, level); for (int i = 0; i < 3; i++) { - List rematch = PairMatchingService.pairMatching(course, level, mission); + Pairs rematch = PairMatchingService.pairMatching(course, level, mission); if (PairMatchingService.hasSamePair(history, rematch)) { continue; } @@ -116,8 +116,8 @@ private static void handlePairHistory() { if (!PairMatchingService.hasHistory(course, level, mission)) { throw new IllegalArgumentException("매칭 이력이 없습니다."); } - List result = PairMatchingService.findHistory(course, level, mission); - OutputView.printMatchingResult(result); + Pairs matchedPairs = PairMatchingService.findHistory(course, level, mission); + OutputView.printMatchingResult(matchedPairs); } catch (IllegalArgumentException error) { OutputView.printException(error); handlePairHistory(); diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index 3765a7bd7..794a73d05 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -8,7 +8,7 @@ public class PairMatchingService { private static CrewRepository crewRepository = new CrewRepository(); - private static Map> history = new HashMap<>(); + private static Map history = new HashMap<>(); public static void initCrews() { crewRepository = new CrewRepository(); @@ -31,32 +31,25 @@ private static void validateMenu(String input) { } } - public static List pairMatching(Course course, Level level, Mission mission) { + public static Pairs pairMatching(Course course, Level level, Mission mission) { List crewNames = crewRepository.findByCourse(course); if (crewNames == null) { throw new IllegalArgumentException("존재하지 않는 코스입니다."); } + List shuffleCrew = Randoms.shuffle(crewNames); - List result = new ArrayList<>(); - for (int i = 0; i < shuffleCrew.size(); i += 2) { - if (i + 1 == shuffleCrew.size()) { - Pair lastPair = result.get(result.size() - 1); - lastPair.addCrew(shuffleCrew.get(i)); - break; - } - Pair pair = new Pair(shuffleCrew.get(i), shuffleCrew.get(i + 1)); - result.add(pair); - } - history.put(course.name() + level.name() + mission.name(), result); - return result; + Pairs pairs = Pairs.createByNameList(shuffleCrew); + + history.put(course.name() + level.name() + mission.name(), pairs); + return pairs; } public static boolean hasHistory(Course course, Level level, Mission mission) { return history.containsKey(course.name() + level.name() + mission.name()); } - public static List> getHistory(Course course, Level level) { - List> result = new ArrayList<>(); + public static List getHistory(Course course, Level level) { + List result = new ArrayList<>(); Mission.findAll().forEach(mission -> { if (hasHistory(course, level, mission)) { result.add(history.get(course.name() + level.name() + mission.name())); @@ -76,10 +69,10 @@ private static void validateRematch(String input) { } } - public static boolean hasSamePair(List> history, List rematch) { - for (List pairs : history) { - for (Pair pair : pairs) { - for (Pair rematchPair : rematch) { + public static boolean hasSamePair(List history, Pairs rematch) { + for (Pairs pairs : history) { + for (Pair pair : pairs.getPairs()) { + for (Pair rematchPair : rematch.getPairs()) { if (pair.hasSamePair(rematchPair)) { return true; } @@ -89,7 +82,7 @@ public static boolean hasSamePair(List> history, List rematch) return false; } - public static List findHistory(Course course, Level level, Mission mission) { + public static Pairs findHistory(Course course, Level level, Mission mission) { return history.get(course.name() + level.name() + mission.name()); } diff --git a/src/main/java/pairmatching/Pairs.java b/src/main/java/pairmatching/Pairs.java new file mode 100644 index 000000000..ac2e10be8 --- /dev/null +++ b/src/main/java/pairmatching/Pairs.java @@ -0,0 +1,30 @@ +package pairmatching; + +import java.util.ArrayList; +import java.util.List; + +public class Pairs { + private List pairs; + + public Pairs(List pairs) { + this.pairs = pairs; + } + + public static Pairs createByNameList(List names) { + List pairs = new ArrayList<>(); + for (int i = 0; i < names.size(); i += 2) { + if (i + 1 == names.size()) { + Pair lastPair = pairs.get(pairs.size() - 1); + lastPair.addCrew(names.get(i)); + break; + } + Pair pair = new Pair(names.get(i), names.get(i + 1)); + pairs.add(pair); + } + return new Pairs(pairs); + } + + public List getPairs() { + return new ArrayList<>(pairs); + } +} diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index ca952e39e..346aa713d 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -35,17 +35,18 @@ public static String readRematch() { } public static String readOption() { - System.out.println("#############################################\n" - + " 과정: 백엔드 | 프론트엔드\n" - + " 미션:\n" - + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임\n" - + " - 레벨2: 장바구니 | 결제 | 지하철노선도\n" - + " - 레벨3: \n" - + " - 레벨4: 성능개선 | 배포\n" - + " - 레벨5: \n" - + " ############################################"); + System.out.println( + "#############################################\n" + + "과정: 백엔드 | 프론트엔드\n" + + "미션:\n" + + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임\n" + + " - 레벨2: 장바구니 | 결제 | 지하철노선도\n" + + " - 레벨3: \n" + + " - 레벨4: 성능개선 | 배포\n" + + " - 레벨5: \n" + + "############################################"); System.out.println("과정, 레벨, 미션을 선택하세요.\n" - + " ex) 백엔드, 레벨1, 자동차경주"); + + "ex) 백엔드, 레벨1, 자동차경주"); String input = readString(); String regexPattern = "^[가-힣]+,\\s[가-힣]+\\d,\\s[가-힣]+$"; diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index 143ea6871..bd952207e 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -39,12 +39,14 @@ class ApplicationTest extends NsTest { void 재매칭_실패() { assertShuffleTest( () -> { - runException("1", "백엔드, 레벨1, 자동차경주", "1", "백엔드, 레벨1, 자동차경주", "네"); - assertThat(output()).contains("태웅 : 백호", "치수 : 태섭"); + runException("1", "백엔드, 레벨1, 자동차경주", "1", "백엔드, 레벨1, 자동차경주", "네", "프론트앤드, 레벨1, 자동차경주"); + assertThat(output()).contains("3번의 리매칭을 모두 실패했습니다."); }, Arrays.asList("태웅", "백호", "치수", "태섭"), Arrays.asList("태웅", "백호", "치수", "태섭"), - Arrays.asList("태웅", "백호", "치수", "태섭") + Arrays.asList("태웅", "백호", "치수", "태섭"), + Arrays.asList("태웅", "백호", "치수", "태섭"), + Arrays.asList("보노", "시저", "쉐리", "신디", "다비") ); } From 407f7c0f4758a3efeb94366cc5142846f400844c Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 20:24:36 +0900 Subject: [PATCH 12/18] =?UTF-8?q?refactor=20:=20PairOption=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/PairMatchingController.java | 39 ++++-------- .../pairmatching/PairMatchingService.java | 31 +++++----- src/main/java/pairmatching/PairOption.java | 61 +++++++++++++++++++ .../java/pairmatching/view/InputView.java | 13 +--- 4 files changed, 93 insertions(+), 51 deletions(-) create mode 100644 src/main/java/pairmatching/PairOption.java diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/PairMatchingController.java index 1d79288ee..005a361ea 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/PairMatchingController.java @@ -41,16 +41,8 @@ private static void handleByMenu(String validateMenu) { private static void handlePairMatching() { try { - String option = InputView.readOption(); - String[] split = option.split(", "); - if (split.length != 3) { - throw new IllegalArgumentException("잘못된 입력입니다."); - } - Course course = Course.findByName(split[0]); - Level level = Level.findByName(split[1]); - Mission mission = Mission.findByName(split[2]); - - pairMatching(course, level, mission); + PairOption pairOption = InputView.readOption(); + pairMatching(pairOption); } catch (IllegalArgumentException error) { OutputView.printException(error); handlePairMatching(); @@ -66,26 +58,26 @@ private static String getValidateMenu() { } } - private static void pairMatching(Course course, Level level, Mission mission) { + private static void pairMatching(PairOption pairOption) { Pairs matchingResult; - if (PairMatchingService.hasHistory(course, level, mission)) { + if (PairMatchingService.hasHistory(pairOption)) { if (getValidateRematch().equals("네")) { // 3번 리매칭 - matchingResult = handleRematch(course, level, mission); + matchingResult = handleRematch(pairOption); OutputView.printMatchingResult(matchingResult); return; } handlePairMatching(); // 코스, 레벨, 미션을 다시 선택한다. return; } - matchingResult = PairMatchingService.pairMatching(course, level, mission); + matchingResult = PairMatchingService.pairMatching(pairOption); OutputView.printMatchingResult(matchingResult); } - private static Pairs handleRematch(Course course, Level level, Mission mission) { - List history = PairMatchingService.getHistory(course, level); + private static Pairs handleRematch(PairOption pairOption) { + List history = PairMatchingService.getHistory(pairOption.getCourse(), pairOption.getLevel()); for (int i = 0; i < 3; i++) { - Pairs rematch = PairMatchingService.pairMatching(course, level, mission); + Pairs rematch = PairMatchingService.pairMatching(pairOption); if (PairMatchingService.hasSamePair(history, rematch)) { continue; } @@ -105,18 +97,11 @@ private static String getValidateRematch() { private static void handlePairHistory() { try { - String option = InputView.readOption(); - String[] split = option.split(", "); - if (split.length != 3) { - throw new IllegalArgumentException("잘못된 입력입니다."); - } - Course course = Course.findByName(split[0]); - Level level = Level.findByName(split[1]); - Mission mission = Mission.findByName(split[2]); - if (!PairMatchingService.hasHistory(course, level, mission)) { + PairOption pairOption = InputView.readOption(); + if (!PairMatchingService.hasHistory(pairOption)) { throw new IllegalArgumentException("매칭 이력이 없습니다."); } - Pairs matchedPairs = PairMatchingService.findHistory(course, level, mission); + Pairs matchedPairs = PairMatchingService.findHistory(pairOption); OutputView.printMatchingResult(matchedPairs); } catch (IllegalArgumentException error) { OutputView.printException(error); diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/PairMatchingService.java index 794a73d05..1a3e3f98f 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/PairMatchingService.java @@ -8,7 +8,7 @@ public class PairMatchingService { private static CrewRepository crewRepository = new CrewRepository(); - private static Map history = new HashMap<>(); + private static Map history = new HashMap<>(); public static void initCrews() { crewRepository = new CrewRepository(); @@ -31,28 +31,31 @@ private static void validateMenu(String input) { } } - public static Pairs pairMatching(Course course, Level level, Mission mission) { + public static Pairs pairMatching(PairOption option) { + List shuffleCrew = getShuffleCrew(option.getCourse()); + Pairs pairs = Pairs.createByNameList(shuffleCrew); + history.put(option, pairs); + return pairs; + } + + private static List getShuffleCrew(Course course) { List crewNames = crewRepository.findByCourse(course); if (crewNames == null) { throw new IllegalArgumentException("존재하지 않는 코스입니다."); } - - List shuffleCrew = Randoms.shuffle(crewNames); - Pairs pairs = Pairs.createByNameList(shuffleCrew); - - history.put(course.name() + level.name() + mission.name(), pairs); - return pairs; + return Randoms.shuffle(crewNames); } - public static boolean hasHistory(Course course, Level level, Mission mission) { - return history.containsKey(course.name() + level.name() + mission.name()); + public static boolean hasHistory(PairOption option) { + return history.containsKey(option); } public static List getHistory(Course course, Level level) { List result = new ArrayList<>(); Mission.findAll().forEach(mission -> { - if (hasHistory(course, level, mission)) { - result.add(history.get(course.name() + level.name() + mission.name())); + PairOption option = new PairOption(course, level, mission); + if (hasHistory(option)) { + result.add(history.get(option)); } }); return result; @@ -82,8 +85,8 @@ public static boolean hasSamePair(List history, Pairs rematch) { return false; } - public static Pairs findHistory(Course course, Level level, Mission mission) { - return history.get(course.name() + level.name() + mission.name()); + public static Pairs findHistory(PairOption option) { + return history.get(option); } public static void reset() { diff --git a/src/main/java/pairmatching/PairOption.java b/src/main/java/pairmatching/PairOption.java new file mode 100644 index 000000000..c695378cb --- /dev/null +++ b/src/main/java/pairmatching/PairOption.java @@ -0,0 +1,61 @@ +package pairmatching; + +import java.util.Objects; +import java.util.regex.Pattern; + +public class PairOption { + private final Course course; + private final Level level; + private final Mission mission; + + public PairOption(Course course, Level level, Mission mission) { + this.course = course; + this.level = level; + this.mission = mission; + } + + public static PairOption createByString(String value) { + validateRegex(value); + String[] split = value.split(", "); + Course course = Course.findByName(split[0]); + Level level = Level.findByName(split[1]); + Mission mission = Mission.findByName(split[2]); + return new PairOption(course, level, mission); + } + + private static void validateRegex(String value) { + String regexPattern = "^[가-힣]+,\\s[가-힣]+\\d,\\s[가-힣]+$"; + + // 정규표현식 검사 + boolean isMatch = Pattern.matches(regexPattern, value); + + if (!isMatch) { + throw new IllegalArgumentException("입력 형식이 잘못되었습니다."); + } + } + + public Course getCourse() { + return course; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PairOption that = (PairOption) o; + return course == that.course && level == that.level && mission == that.mission; + } + + @Override + public int hashCode() { + return Objects.hash(course, level, mission); + } + + public Level getLevel() { + return level; + } +} diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 346aa713d..e913ff81c 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -2,6 +2,7 @@ import camp.nextstep.edu.missionutils.Console; import java.util.regex.Pattern; +import pairmatching.PairOption; public class InputView { public static final String MENU_MESSAGE = "기능을 선택하세요.\n" @@ -34,7 +35,7 @@ public static String readRematch() { return readString(); } - public static String readOption() { + public static PairOption readOption() { System.out.println( "#############################################\n" + "과정: 백엔드 | 프론트엔드\n" @@ -48,14 +49,6 @@ public static String readOption() { System.out.println("과정, 레벨, 미션을 선택하세요.\n" + "ex) 백엔드, 레벨1, 자동차경주"); String input = readString(); - String regexPattern = "^[가-힣]+,\\s[가-힣]+\\d,\\s[가-힣]+$"; - - // 정규표현식 검사 - boolean isMatch = Pattern.matches(regexPattern, input); - - if (!isMatch) { - throw new IllegalArgumentException("입력 형식이 잘못되었습니다."); - } - return input; + return PairOption.createByString(input); } } From 61f79ab2c4d4cd704b7c7d6300908e86d7ca018b Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 20:26:23 +0900 Subject: [PATCH 13/18] =?UTF-8?q?refactor=20:=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/pairmatching/Application.java | 2 ++ src/main/java/pairmatching/Crew.java | 6 ------ .../java/pairmatching/{ => domain}/CrewRepository.java | 3 ++- .../pairmatching/{ => domain}/PairMatchingController.java | 4 +++- .../pairmatching/{ => domain}/PairMatchingService.java | 8 +++++++- .../java/pairmatching/{ => domain/option}/Course.java | 2 +- src/main/java/pairmatching/{ => domain/option}/Level.java | 2 +- .../java/pairmatching/{ => domain/option}/Mission.java | 3 +-- src/main/java/pairmatching/{ => domain/pair}/Pair.java | 3 ++- .../java/pairmatching/{ => domain/pair}/PairOption.java | 5 ++++- src/main/java/pairmatching/{ => domain/pair}/Pairs.java | 2 +- src/main/java/pairmatching/view/InputView.java | 3 +-- src/main/java/pairmatching/view/OutputView.java | 5 ++--- src/test/java/pairmatching/PairMatchingServiceTest.java | 2 +- 14 files changed, 28 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/pairmatching/Crew.java rename src/main/java/pairmatching/{ => domain}/CrewRepository.java (93%) rename src/main/java/pairmatching/{ => domain}/PairMatchingController.java (97%) rename src/main/java/pairmatching/{ => domain}/PairMatchingService.java (91%) rename src/main/java/pairmatching/{ => domain/option}/Course.java (92%) rename src/main/java/pairmatching/{ => domain/option}/Level.java (93%) rename src/main/java/pairmatching/{ => domain/option}/Mission.java (95%) rename src/main/java/pairmatching/{ => domain/pair}/Pair.java (94%) rename src/main/java/pairmatching/{ => domain/pair}/PairOption.java (91%) rename src/main/java/pairmatching/{ => domain/pair}/Pairs.java (95%) diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index c9f254ad8..807030c2d 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -1,5 +1,7 @@ package pairmatching; +import pairmatching.domain.PairMatchingController; + public class Application { public static void main(String[] args) { PairMatchingController.run(); diff --git a/src/main/java/pairmatching/Crew.java b/src/main/java/pairmatching/Crew.java deleted file mode 100644 index 87d9f7ba5..000000000 --- a/src/main/java/pairmatching/Crew.java +++ /dev/null @@ -1,6 +0,0 @@ -package pairmatching; - -public class Crew { - private Course course; - private String name; -} diff --git a/src/main/java/pairmatching/CrewRepository.java b/src/main/java/pairmatching/domain/CrewRepository.java similarity index 93% rename from src/main/java/pairmatching/CrewRepository.java rename to src/main/java/pairmatching/domain/CrewRepository.java index 93edfd965..ae5fedaa6 100644 --- a/src/main/java/pairmatching/CrewRepository.java +++ b/src/main/java/pairmatching/domain/CrewRepository.java @@ -1,10 +1,11 @@ -package pairmatching; +package pairmatching.domain; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import pairmatching.domain.option.Course; public class CrewRepository { private List backend = new ArrayList<>(); diff --git a/src/main/java/pairmatching/PairMatchingController.java b/src/main/java/pairmatching/domain/PairMatchingController.java similarity index 97% rename from src/main/java/pairmatching/PairMatchingController.java rename to src/main/java/pairmatching/domain/PairMatchingController.java index 005a361ea..dcfec06e5 100644 --- a/src/main/java/pairmatching/PairMatchingController.java +++ b/src/main/java/pairmatching/domain/PairMatchingController.java @@ -1,6 +1,8 @@ -package pairmatching; +package pairmatching.domain; import java.util.List; +import pairmatching.domain.pair.PairOption; +import pairmatching.domain.pair.Pairs; import pairmatching.view.InputView; import pairmatching.view.OutputView; diff --git a/src/main/java/pairmatching/PairMatchingService.java b/src/main/java/pairmatching/domain/PairMatchingService.java similarity index 91% rename from src/main/java/pairmatching/PairMatchingService.java rename to src/main/java/pairmatching/domain/PairMatchingService.java index 1a3e3f98f..93c377c3f 100644 --- a/src/main/java/pairmatching/PairMatchingService.java +++ b/src/main/java/pairmatching/domain/PairMatchingService.java @@ -1,10 +1,16 @@ -package pairmatching; +package pairmatching.domain; import camp.nextstep.edu.missionutils.Randoms; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import pairmatching.domain.option.Course; +import pairmatching.domain.option.Level; +import pairmatching.domain.option.Mission; +import pairmatching.domain.pair.Pair; +import pairmatching.domain.pair.PairOption; +import pairmatching.domain.pair.Pairs; public class PairMatchingService { private static CrewRepository crewRepository = new CrewRepository(); diff --git a/src/main/java/pairmatching/Course.java b/src/main/java/pairmatching/domain/option/Course.java similarity index 92% rename from src/main/java/pairmatching/Course.java rename to src/main/java/pairmatching/domain/option/Course.java index 3c10f31ce..f44ed42ac 100644 --- a/src/main/java/pairmatching/Course.java +++ b/src/main/java/pairmatching/domain/option/Course.java @@ -1,4 +1,4 @@ -package pairmatching; +package pairmatching.domain.option; public enum Course { BACKEND("백엔드"), diff --git a/src/main/java/pairmatching/Level.java b/src/main/java/pairmatching/domain/option/Level.java similarity index 93% rename from src/main/java/pairmatching/Level.java rename to src/main/java/pairmatching/domain/option/Level.java index 1f2dae305..04d98f5b1 100644 --- a/src/main/java/pairmatching/Level.java +++ b/src/main/java/pairmatching/domain/option/Level.java @@ -1,4 +1,4 @@ -package pairmatching; +package pairmatching.domain.option; public enum Level { LEVEL1("레벨1"), diff --git a/src/main/java/pairmatching/Mission.java b/src/main/java/pairmatching/domain/option/Mission.java similarity index 95% rename from src/main/java/pairmatching/Mission.java rename to src/main/java/pairmatching/domain/option/Mission.java index eeea12ded..7dea52402 100644 --- a/src/main/java/pairmatching/Mission.java +++ b/src/main/java/pairmatching/domain/option/Mission.java @@ -1,9 +1,8 @@ -package pairmatching; +package pairmatching.domain.option; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; public enum Mission { RACING_CAR("자동차경주", Level.LEVEL1), diff --git a/src/main/java/pairmatching/Pair.java b/src/main/java/pairmatching/domain/pair/Pair.java similarity index 94% rename from src/main/java/pairmatching/Pair.java rename to src/main/java/pairmatching/domain/pair/Pair.java index 1b5dec3e8..88fe9e73c 100644 --- a/src/main/java/pairmatching/Pair.java +++ b/src/main/java/pairmatching/domain/pair/Pair.java @@ -1,9 +1,10 @@ -package pairmatching; +package pairmatching.domain.pair; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import pairmatching.Utils; public class Pair { private List crews; diff --git a/src/main/java/pairmatching/PairOption.java b/src/main/java/pairmatching/domain/pair/PairOption.java similarity index 91% rename from src/main/java/pairmatching/PairOption.java rename to src/main/java/pairmatching/domain/pair/PairOption.java index c695378cb..8f96e71c2 100644 --- a/src/main/java/pairmatching/PairOption.java +++ b/src/main/java/pairmatching/domain/pair/PairOption.java @@ -1,7 +1,10 @@ -package pairmatching; +package pairmatching.domain.pair; import java.util.Objects; import java.util.regex.Pattern; +import pairmatching.domain.option.Course; +import pairmatching.domain.option.Level; +import pairmatching.domain.option.Mission; public class PairOption { private final Course course; diff --git a/src/main/java/pairmatching/Pairs.java b/src/main/java/pairmatching/domain/pair/Pairs.java similarity index 95% rename from src/main/java/pairmatching/Pairs.java rename to src/main/java/pairmatching/domain/pair/Pairs.java index ac2e10be8..8eb211758 100644 --- a/src/main/java/pairmatching/Pairs.java +++ b/src/main/java/pairmatching/domain/pair/Pairs.java @@ -1,4 +1,4 @@ -package pairmatching; +package pairmatching.domain.pair; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index e913ff81c..3f6084592 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -1,8 +1,7 @@ package pairmatching.view; import camp.nextstep.edu.missionutils.Console; -import java.util.regex.Pattern; -import pairmatching.PairOption; +import pairmatching.domain.pair.PairOption; public class InputView { public static final String MENU_MESSAGE = "기능을 선택하세요.\n" diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index 1413611a1..dbbff4ca2 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -1,8 +1,7 @@ package pairmatching.view; -import java.util.List; -import pairmatching.Pair; -import pairmatching.Pairs; +import pairmatching.domain.pair.Pair; +import pairmatching.domain.pair.Pairs; public class OutputView { public static void printException(Exception error) { diff --git a/src/test/java/pairmatching/PairMatchingServiceTest.java b/src/test/java/pairmatching/PairMatchingServiceTest.java index 33894e1e6..4c82643db 100644 --- a/src/test/java/pairmatching/PairMatchingServiceTest.java +++ b/src/test/java/pairmatching/PairMatchingServiceTest.java @@ -1,9 +1,9 @@ package pairmatching; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import pairmatching.domain.PairMatchingService; class PairMatchingServiceTest { From 6d8306864e7d01c483c9b239ef185817dbcc9e49 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 20:42:22 +0900 Subject: [PATCH 14/18] =?UTF-8?q?refactor=20:=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/PairMatchingController.java | 18 +++++++----- .../domain/PairMatchingService.java | 18 +++++++----- .../pairmatching/domain/option/Course.java | 4 ++- .../pairmatching/domain/option/Level.java | 4 ++- .../pairmatching/domain/option/Mission.java | 3 +- .../pairmatching/domain/pair/PairOption.java | 15 ++++++---- .../message/ExceptionMessage.java | 10 +++++++ .../pairmatching/message/ProgramOption.java | 15 ++++++++++ .../pairmatching/message/ViewMessage.java | 20 +++++++++++++ .../java/pairmatching/view/InputView.java | 29 +++++-------------- .../java/pairmatching/view/OutputView.java | 8 +++-- 11 files changed, 95 insertions(+), 49 deletions(-) create mode 100644 src/main/java/pairmatching/message/ExceptionMessage.java create mode 100644 src/main/java/pairmatching/message/ProgramOption.java create mode 100644 src/main/java/pairmatching/message/ViewMessage.java diff --git a/src/main/java/pairmatching/domain/PairMatchingController.java b/src/main/java/pairmatching/domain/PairMatchingController.java index dcfec06e5..e41034c8c 100644 --- a/src/main/java/pairmatching/domain/PairMatchingController.java +++ b/src/main/java/pairmatching/domain/PairMatchingController.java @@ -3,6 +3,8 @@ import java.util.List; import pairmatching.domain.pair.PairOption; import pairmatching.domain.pair.Pairs; +import pairmatching.message.ExceptionMessage; +import pairmatching.message.ProgramOption; import pairmatching.view.InputView; import pairmatching.view.OutputView; @@ -16,7 +18,7 @@ public static void run() { private static void proceed() { while (true) { String validateMenu = getValidateMenu(); - if (validateMenu.equals("Q")) { + if (validateMenu.equals(ProgramOption.QUIT)) { break; } handleByMenu(validateMenu); @@ -24,19 +26,19 @@ private static void proceed() { } private static void handleByMenu(String validateMenu) { - if (validateMenu.equals("1")) { + if (validateMenu.equals(ProgramOption.PAIR_MATCHING)) { handlePairMatching(); return; } - if (validateMenu.equals("2")) { + if (validateMenu.equals(ProgramOption.PAIR_SEARCH)) { handlePairHistory(); return; } - if (validateMenu.equals("3")) { + if (validateMenu.equals(ProgramOption.PAIR_RESET)) { handlePairReset(); return; } - throw new IllegalArgumentException("잘못된 입력입니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT); } @@ -63,7 +65,7 @@ private static String getValidateMenu() { private static void pairMatching(PairOption pairOption) { Pairs matchingResult; if (PairMatchingService.hasHistory(pairOption)) { - if (getValidateRematch().equals("네")) { + if (getValidateRematch().equals(ProgramOption.YES)) { // 3번 리매칭 matchingResult = handleRematch(pairOption); OutputView.printMatchingResult(matchingResult); @@ -85,7 +87,7 @@ private static Pairs handleRematch(PairOption pairOption) { } return rematch; } - throw new IllegalArgumentException("3번의 리매칭을 모두 실패했습니다."); + throw new IllegalArgumentException(ExceptionMessage.REMATCHING_FAIL); } private static String getValidateRematch() { @@ -101,7 +103,7 @@ private static void handlePairHistory() { try { PairOption pairOption = InputView.readOption(); if (!PairMatchingService.hasHistory(pairOption)) { - throw new IllegalArgumentException("매칭 이력이 없습니다."); + throw new IllegalArgumentException(ExceptionMessage.NO_MATCHING_HISTORY); } Pairs matchedPairs = PairMatchingService.findHistory(pairOption); OutputView.printMatchingResult(matchedPairs); diff --git a/src/main/java/pairmatching/domain/PairMatchingService.java b/src/main/java/pairmatching/domain/PairMatchingService.java index 93c377c3f..a1efbdd97 100644 --- a/src/main/java/pairmatching/domain/PairMatchingService.java +++ b/src/main/java/pairmatching/domain/PairMatchingService.java @@ -11,6 +11,8 @@ import pairmatching.domain.pair.Pair; import pairmatching.domain.pair.PairOption; import pairmatching.domain.pair.Pairs; +import pairmatching.message.ExceptionMessage; +import pairmatching.message.ProgramOption; public class PairMatchingService { private static CrewRepository crewRepository = new CrewRepository(); @@ -19,8 +21,8 @@ public class PairMatchingService { public static void initCrews() { crewRepository = new CrewRepository(); history = new HashMap<>(); - crewRepository.initBackend("src/main/resources/backend-crew.md"); - crewRepository.initFrontend("src/main/resources/frontend-crew.md"); + crewRepository.initBackend(ProgramOption.BACKEND_FILE_PATH); + crewRepository.initFrontend(ProgramOption.FRONTEND_FILE_PATH); } public static String getValidateMenu(String input) { @@ -30,10 +32,10 @@ public static String getValidateMenu(String input) { private static void validateMenu(String input) { if (input.length() != 1) { - throw new IllegalArgumentException("메뉴에 없는 기능입니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT); } - if (!"123Q".contains(input)) { - throw new IllegalArgumentException("메뉴에 없는 기능입니다."); + if (!ProgramOption.MENU_INPUT_OPTIONS.contains(input)) { + throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT); } } @@ -47,7 +49,7 @@ public static Pairs pairMatching(PairOption option) { private static List getShuffleCrew(Course course) { List crewNames = crewRepository.findByCourse(course); if (crewNames == null) { - throw new IllegalArgumentException("존재하지 않는 코스입니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT); } return Randoms.shuffle(crewNames); } @@ -73,8 +75,8 @@ public static String getValidateRematch(String input) { } private static void validateRematch(String input) { - if (!input.equals("네") && !input.equals("아니오")) { - throw new IllegalArgumentException("잘못된 입력입니다."); + if (!input.equals(ProgramOption.YES) && !input.equals(ProgramOption.NO)) { + throw new IllegalArgumentException(ExceptionMessage.INVALID_REMATCH_INPUT); } } diff --git a/src/main/java/pairmatching/domain/option/Course.java b/src/main/java/pairmatching/domain/option/Course.java index f44ed42ac..39555853a 100644 --- a/src/main/java/pairmatching/domain/option/Course.java +++ b/src/main/java/pairmatching/domain/option/Course.java @@ -1,5 +1,7 @@ package pairmatching.domain.option; +import pairmatching.message.ExceptionMessage; + public enum Course { BACKEND("백엔드"), FRONTEND("프론트엔드"); @@ -18,6 +20,6 @@ public static Course findByName(String name) { return course; } } - throw new IllegalArgumentException("잘못된 입력입니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); } } diff --git a/src/main/java/pairmatching/domain/option/Level.java b/src/main/java/pairmatching/domain/option/Level.java index 04d98f5b1..65d82d9a1 100644 --- a/src/main/java/pairmatching/domain/option/Level.java +++ b/src/main/java/pairmatching/domain/option/Level.java @@ -1,5 +1,7 @@ package pairmatching.domain.option; +import pairmatching.message.ExceptionMessage; + public enum Level { LEVEL1("레벨1"), LEVEL2("레벨2"), @@ -19,6 +21,6 @@ public static Level findByName(String name) { return level; } } - throw new IllegalArgumentException("잘못된 입력입니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); } } diff --git a/src/main/java/pairmatching/domain/option/Mission.java b/src/main/java/pairmatching/domain/option/Mission.java index 7dea52402..856ad949c 100644 --- a/src/main/java/pairmatching/domain/option/Mission.java +++ b/src/main/java/pairmatching/domain/option/Mission.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import pairmatching.message.ExceptionMessage; public enum Mission { RACING_CAR("자동차경주", Level.LEVEL1), @@ -28,7 +29,7 @@ public static Mission findByName(String name) { return mission; } } - throw new IllegalArgumentException("잘못된 입력입니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); } public static List findAll() { diff --git a/src/main/java/pairmatching/domain/pair/PairOption.java b/src/main/java/pairmatching/domain/pair/PairOption.java index 8f96e71c2..08bbaa458 100644 --- a/src/main/java/pairmatching/domain/pair/PairOption.java +++ b/src/main/java/pairmatching/domain/pair/PairOption.java @@ -5,8 +5,13 @@ import pairmatching.domain.option.Course; import pairmatching.domain.option.Level; import pairmatching.domain.option.Mission; +import pairmatching.message.ExceptionMessage; public class PairOption { + public static final int COURSE_INDEX = 0; + public static final int LEVEL_INDEX = 1; + public static final int MISSION_INDEX = 2; + public static final String OPTION_DELIMITER = ", "; private final Course course; private final Level level; private final Mission mission; @@ -19,10 +24,10 @@ public PairOption(Course course, Level level, Mission mission) { public static PairOption createByString(String value) { validateRegex(value); - String[] split = value.split(", "); - Course course = Course.findByName(split[0]); - Level level = Level.findByName(split[1]); - Mission mission = Mission.findByName(split[2]); + String[] split = value.split(OPTION_DELIMITER); + Course course = Course.findByName(split[COURSE_INDEX]); + Level level = Level.findByName(split[LEVEL_INDEX]); + Mission mission = Mission.findByName(split[MISSION_INDEX]); return new PairOption(course, level, mission); } @@ -33,7 +38,7 @@ private static void validateRegex(String value) { boolean isMatch = Pattern.matches(regexPattern, value); if (!isMatch) { - throw new IllegalArgumentException("입력 형식이 잘못되었습니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); } } diff --git a/src/main/java/pairmatching/message/ExceptionMessage.java b/src/main/java/pairmatching/message/ExceptionMessage.java new file mode 100644 index 000000000..e567c948e --- /dev/null +++ b/src/main/java/pairmatching/message/ExceptionMessage.java @@ -0,0 +1,10 @@ +package pairmatching.message; + +public class ExceptionMessage { + public static final String EXCEPTION_PREFIX = "[ERROR] : "; + public static final String INVALID_INPUT = "잘못된 입력입니다."; + public static final String INVALID_MENU_INPUT = "잘못된 메뉴 입력입니다."; + public static final String INVALID_REMATCH_INPUT = "잘못된 리매칭 입력입니다."; + public static final String REMATCHING_FAIL = "3번의 리매칭을 모두 실패했습니다."; + public static final String NO_MATCHING_HISTORY = "매칭 기록이 없습니다."; +} diff --git a/src/main/java/pairmatching/message/ProgramOption.java b/src/main/java/pairmatching/message/ProgramOption.java new file mode 100644 index 000000000..d9f5d42ef --- /dev/null +++ b/src/main/java/pairmatching/message/ProgramOption.java @@ -0,0 +1,15 @@ +package pairmatching.message; + +public class ProgramOption { + public static final String BACKEND_FILE_PATH = "src/main/resources/backend.txt"; + public static final String FRONTEND_FILE_PATH = "src/main/resources/frontend.txt"; + + public static final String PAIR_MATCHING = "1"; + public static final String PAIR_SEARCH = "2"; + public static final String PAIR_RESET = "3"; + public static final String QUIT = "Q"; + public static final String MENU_INPUT_OPTIONS = "123Q"; + + public static final String YES = "네"; + public static final String NO = "아니오"; +} diff --git a/src/main/java/pairmatching/message/ViewMessage.java b/src/main/java/pairmatching/message/ViewMessage.java new file mode 100644 index 000000000..5d2db24e6 --- /dev/null +++ b/src/main/java/pairmatching/message/ViewMessage.java @@ -0,0 +1,20 @@ +package pairmatching.message; + +public class ViewMessage { + public static final String INPUT_MENU_MESSAGE = "기능을 선택하세요.\n1. 페어 매칭\n2. 페어 조회\n3. 페어 초기화\nQ. 종료"; + public static final String INPUT_REMATCH_MESSAGE = "매칭 정보가 있습니다. 다시 매칭하시겠습니까?\n네 | 아니오"; + public static final String INPUT_OPTION_PRE_MESSAGE = + "#############################################\n" + + "과정: 백엔드 | 프론트엔드\n" + + "미션:\n" + + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임\n" + + " - 레벨2: 장바구니 | 결제 | 지하철노선도\n" + + " - 레벨3: \n" + + " - 레벨4: 성능개선 | 배포\n" + + " - 레벨5: \n" + + "############################################"; + public static final String INPUT_OPTION_MESSAGE = "과정, 레벨, 미션을 선택하세요.\nex) 백엔드, 레벨1, 자동차경주"; + + public static final String OUTPUT_PAIR_RESULT_PRE_MESSAGE = "페어 매칭 결과입니다."; + public static final String OUTPUT_PAIR_DELIMITER = " : "; +} diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java index 3f6084592..c7ea6e398 100644 --- a/src/main/java/pairmatching/view/InputView.java +++ b/src/main/java/pairmatching/view/InputView.java @@ -2,16 +2,12 @@ import camp.nextstep.edu.missionutils.Console; import pairmatching.domain.pair.PairOption; +import pairmatching.message.ExceptionMessage; +import pairmatching.message.ViewMessage; public class InputView { - public static final String MENU_MESSAGE = "기능을 선택하세요.\n" - + "1. 페어 매칭\n" - + "2. 페어 조회\n" - + "3. 페어 초기화\n" - + "Q. 종료"; - public static String readMenu() { - System.out.println(MENU_MESSAGE); + System.out.println(ViewMessage.INPUT_MENU_MESSAGE); String input = readString(); return input; } @@ -24,29 +20,18 @@ private static String readString() { private static void validateBlank(String input) { if (input == null || input.isEmpty()) { - throw new IllegalArgumentException("공백은 입력할 수 없습니다."); + throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); } } public static String readRematch() { - System.out.println("매칭 정보가 있습니다. 다시 매칭하시겠습니까?"); - System.out.println("네 | 아니오"); + System.out.println(ViewMessage.INPUT_REMATCH_MESSAGE); return readString(); } public static PairOption readOption() { - System.out.println( - "#############################################\n" - + "과정: 백엔드 | 프론트엔드\n" - + "미션:\n" - + " - 레벨1: 자동차경주 | 로또 | 숫자야구게임\n" - + " - 레벨2: 장바구니 | 결제 | 지하철노선도\n" - + " - 레벨3: \n" - + " - 레벨4: 성능개선 | 배포\n" - + " - 레벨5: \n" - + "############################################"); - System.out.println("과정, 레벨, 미션을 선택하세요.\n" - + "ex) 백엔드, 레벨1, 자동차경주"); + System.out.println(ViewMessage.INPUT_OPTION_PRE_MESSAGE); + System.out.println(ViewMessage.INPUT_OPTION_MESSAGE); String input = readString(); return PairOption.createByString(input); } diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java index dbbff4ca2..7215a78dd 100644 --- a/src/main/java/pairmatching/view/OutputView.java +++ b/src/main/java/pairmatching/view/OutputView.java @@ -2,16 +2,18 @@ import pairmatching.domain.pair.Pair; import pairmatching.domain.pair.Pairs; +import pairmatching.message.ExceptionMessage; +import pairmatching.message.ViewMessage; public class OutputView { public static void printException(Exception error) { - System.out.println("[ERROR] : " + error.getMessage()); + System.out.println(ExceptionMessage.EXCEPTION_PREFIX + error.getMessage()); } public static void printMatchingResult(Pairs matchingResult) { - System.out.println("페어 매칭 결과입니다."); + System.out.println(ViewMessage.OUTPUT_PAIR_RESULT_PRE_MESSAGE); for (Pair pair : matchingResult.getPairs()) { - String pairString = String.join(" : ", pair.getCrews()); + String pairString = String.join(ViewMessage.OUTPUT_PAIR_DELIMITER, pair.getCrews()); System.out.println(pairString); } } From 533af6d0fe5e3884fe3ec7a24f1f569a6d02f170 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 20:55:44 +0900 Subject: [PATCH 15/18] =?UTF-8?q?refactor=20:=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EA=B0=80=EB=8F=85=EC=84=B1=20=EC=9E=88?= =?UTF-8?q?=EA=B2=8C=20=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pairmatching/domain/CrewRepository.java | 4 +- .../domain/PairMatchingController.java | 52 ++++++++++--------- .../domain/PairMatchingService.java | 7 ++- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/main/java/pairmatching/domain/CrewRepository.java b/src/main/java/pairmatching/domain/CrewRepository.java index ae5fedaa6..4e9dade8d 100644 --- a/src/main/java/pairmatching/domain/CrewRepository.java +++ b/src/main/java/pairmatching/domain/CrewRepository.java @@ -8,8 +8,8 @@ import pairmatching.domain.option.Course; public class CrewRepository { - private List backend = new ArrayList<>(); - private List frontend = new ArrayList<>(); + private final List backend = new ArrayList<>(); + private final List frontend = new ArrayList<>(); public void initBackend(String path) { addCrewsByFile(path, backend); diff --git a/src/main/java/pairmatching/domain/PairMatchingController.java b/src/main/java/pairmatching/domain/PairMatchingController.java index e41034c8c..6aa05e8bc 100644 --- a/src/main/java/pairmatching/domain/PairMatchingController.java +++ b/src/main/java/pairmatching/domain/PairMatchingController.java @@ -25,13 +25,22 @@ private static void proceed() { } } + private static String getValidateMenu() { + try { + return PairMatchingService.getValidateMenu(InputView.readMenu()); + } catch (IllegalArgumentException error) { + OutputView.printException(error); + return getValidateMenu(); + } + } + private static void handleByMenu(String validateMenu) { if (validateMenu.equals(ProgramOption.PAIR_MATCHING)) { handlePairMatching(); return; } if (validateMenu.equals(ProgramOption.PAIR_SEARCH)) { - handlePairHistory(); + handlePairSearch(); return; } if (validateMenu.equals(ProgramOption.PAIR_RESET)) { @@ -41,8 +50,6 @@ private static void handleByMenu(String validateMenu) { throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT); } - - private static void handlePairMatching() { try { PairOption pairOption = InputView.readOption(); @@ -53,38 +60,35 @@ private static void handlePairMatching() { } } - private static String getValidateMenu() { - try { - return PairMatchingService.getValidateMenu(InputView.readMenu()); - } catch (IllegalArgumentException error) { - OutputView.printException(error); - return getValidateMenu(); - } - } - private static void pairMatching(PairOption pairOption) { Pairs matchingResult; if (PairMatchingService.hasHistory(pairOption)) { - if (getValidateRematch().equals(ProgramOption.YES)) { - // 3번 리매칭 - matchingResult = handleRematch(pairOption); - OutputView.printMatchingResult(matchingResult); - return; - } - handlePairMatching(); // 코스, 레벨, 미션을 다시 선택한다. + handleRematch(pairOption); return; } - matchingResult = PairMatchingService.pairMatching(pairOption); + matchingResult = PairMatchingService.createPairMatching(pairOption); OutputView.printMatchingResult(matchingResult); } - private static Pairs handleRematch(PairOption pairOption) { + private static void handleRematch(PairOption pairOption) { + if (getValidateRematch().equals(ProgramOption.YES)) { + // 3번 리매칭 + Pairs matchingResult = tryRematch(pairOption); + OutputView.printMatchingResult(matchingResult); + return; + } + // 아니오를 선택한 경우 다시 코스, 레벨, 미션을 선택한다. + handlePairMatching(); + } + + private static Pairs tryRematch(PairOption pairOption) { List history = PairMatchingService.getHistory(pairOption.getCourse(), pairOption.getLevel()); for (int i = 0; i < 3; i++) { - Pairs rematch = PairMatchingService.pairMatching(pairOption); + Pairs rematch = PairMatchingService.createPairMatching(pairOption); if (PairMatchingService.hasSamePair(history, rematch)) { continue; } + PairMatchingService.addPairsToHistory(pairOption, rematch); return rematch; } throw new IllegalArgumentException(ExceptionMessage.REMATCHING_FAIL); @@ -99,7 +103,7 @@ private static String getValidateRematch() { } } - private static void handlePairHistory() { + private static void handlePairSearch() { try { PairOption pairOption = InputView.readOption(); if (!PairMatchingService.hasHistory(pairOption)) { @@ -109,7 +113,7 @@ private static void handlePairHistory() { OutputView.printMatchingResult(matchedPairs); } catch (IllegalArgumentException error) { OutputView.printException(error); - handlePairHistory(); + handlePairSearch(); } } diff --git a/src/main/java/pairmatching/domain/PairMatchingService.java b/src/main/java/pairmatching/domain/PairMatchingService.java index a1efbdd97..1a23a08f6 100644 --- a/src/main/java/pairmatching/domain/PairMatchingService.java +++ b/src/main/java/pairmatching/domain/PairMatchingService.java @@ -39,13 +39,16 @@ private static void validateMenu(String input) { } } - public static Pairs pairMatching(PairOption option) { + public static Pairs createPairMatching(PairOption option) { List shuffleCrew = getShuffleCrew(option.getCourse()); Pairs pairs = Pairs.createByNameList(shuffleCrew); - history.put(option, pairs); return pairs; } + public static void addPairsToHistory(PairOption option, Pairs pairs) { + history.put(option, pairs); + } + private static List getShuffleCrew(Course course) { List crewNames = crewRepository.findByCourse(course); if (crewNames == null) { From e3c6cfc95f2067950a5e5abba8ccffc17fd51636 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 21:15:44 +0900 Subject: [PATCH 16/18] =?UTF-8?q?refactor=20:=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EA=B3=84=EC=B8=B5=20=EA=B0=80=EB=8F=85=EC=84=B1=20?= =?UTF-8?q?=EC=9E=88=EA=B2=8C=20=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/PairMatchingController.java | 20 +++---------- .../domain/PairMatchingService.java | 30 +++++++++++++------ .../java/pairmatching/domain/pair/Pairs.java | 11 +++++++ .../pairmatching/message/ProgramOption.java | 4 +-- .../java/pairmatching/ApplicationTest.java | 2 +- 5 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/main/java/pairmatching/domain/PairMatchingController.java b/src/main/java/pairmatching/domain/PairMatchingController.java index 6aa05e8bc..580e4db7e 100644 --- a/src/main/java/pairmatching/domain/PairMatchingController.java +++ b/src/main/java/pairmatching/domain/PairMatchingController.java @@ -61,19 +61,20 @@ private static void handlePairMatching() { } private static void pairMatching(PairOption pairOption) { - Pairs matchingResult; if (PairMatchingService.hasHistory(pairOption)) { handleRematch(pairOption); return; } - matchingResult = PairMatchingService.createPairMatching(pairOption); + Pairs matchingResult = PairMatchingService.createNewPairMatching(pairOption); + PairMatchingService.addPairsToHistory(pairOption, matchingResult); OutputView.printMatchingResult(matchingResult); } private static void handleRematch(PairOption pairOption) { if (getValidateRematch().equals(ProgramOption.YES)) { // 3번 리매칭 - Pairs matchingResult = tryRematch(pairOption); + List history = PairMatchingService.getHistory(pairOption.getCourse(), pairOption.getLevel()); + Pairs matchingResult = PairMatchingService.createNoDuplicatePairMatching(pairOption, history); OutputView.printMatchingResult(matchingResult); return; } @@ -81,19 +82,6 @@ private static void handleRematch(PairOption pairOption) { handlePairMatching(); } - private static Pairs tryRematch(PairOption pairOption) { - List history = PairMatchingService.getHistory(pairOption.getCourse(), pairOption.getLevel()); - for (int i = 0; i < 3; i++) { - Pairs rematch = PairMatchingService.createPairMatching(pairOption); - if (PairMatchingService.hasSamePair(history, rematch)) { - continue; - } - PairMatchingService.addPairsToHistory(pairOption, rematch); - return rematch; - } - throw new IllegalArgumentException(ExceptionMessage.REMATCHING_FAIL); - } - private static String getValidateRematch() { try { return PairMatchingService.getValidateRematch(InputView.readRematch()); diff --git a/src/main/java/pairmatching/domain/PairMatchingService.java b/src/main/java/pairmatching/domain/PairMatchingService.java index 1a23a08f6..335af2a33 100644 --- a/src/main/java/pairmatching/domain/PairMatchingService.java +++ b/src/main/java/pairmatching/domain/PairMatchingService.java @@ -38,11 +38,27 @@ private static void validateMenu(String input) { throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT); } } + public static Pairs createNewPairMatching(PairOption option) { + Pairs pairs = createPairMatching(option); + addPairsToHistory(option, pairs); + return pairs; + } - public static Pairs createPairMatching(PairOption option) { + public static Pairs createNoDuplicatePairMatching(PairOption option, List history) { + for (int i = 0; i < 3; i++) { + Pairs rematch = createPairMatching(option); + if (hasSamePair(history, rematch)) { + continue; + } + addPairsToHistory(option, rematch); + return rematch; + } + throw new IllegalArgumentException(ExceptionMessage.REMATCHING_FAIL); + } + + private static Pairs createPairMatching(PairOption option) { List shuffleCrew = getShuffleCrew(option.getCourse()); - Pairs pairs = Pairs.createByNameList(shuffleCrew); - return pairs; + return Pairs.createByNameList(shuffleCrew); } public static void addPairsToHistory(PairOption option, Pairs pairs) { @@ -85,12 +101,8 @@ private static void validateRematch(String input) { public static boolean hasSamePair(List history, Pairs rematch) { for (Pairs pairs : history) { - for (Pair pair : pairs.getPairs()) { - for (Pair rematchPair : rematch.getPairs()) { - if (pair.hasSamePair(rematchPair)) { - return true; - } - } + if (pairs.hasSamePair(rematch)) { + return true; } } return false; diff --git a/src/main/java/pairmatching/domain/pair/Pairs.java b/src/main/java/pairmatching/domain/pair/Pairs.java index 8eb211758..22a1bdb5b 100644 --- a/src/main/java/pairmatching/domain/pair/Pairs.java +++ b/src/main/java/pairmatching/domain/pair/Pairs.java @@ -24,6 +24,17 @@ public static Pairs createByNameList(List names) { return new Pairs(pairs); } + public boolean hasSamePair(Pairs source) { + for (Pair pair : source.pairs) { + for (Pair thisPair : this.pairs) { + if (thisPair.hasSamePair(pair)) { + return true; + } + } + } + return false; + } + public List getPairs() { return new ArrayList<>(pairs); } diff --git a/src/main/java/pairmatching/message/ProgramOption.java b/src/main/java/pairmatching/message/ProgramOption.java index d9f5d42ef..966fadb69 100644 --- a/src/main/java/pairmatching/message/ProgramOption.java +++ b/src/main/java/pairmatching/message/ProgramOption.java @@ -1,8 +1,8 @@ package pairmatching.message; public class ProgramOption { - public static final String BACKEND_FILE_PATH = "src/main/resources/backend.txt"; - public static final String FRONTEND_FILE_PATH = "src/main/resources/frontend.txt"; + public static final String BACKEND_FILE_PATH = "src/main/resources/backend-crew.md"; + public static final String FRONTEND_FILE_PATH = "src/main/resources/frontend-crew.md"; public static final String PAIR_MATCHING = "1"; public static final String PAIR_SEARCH = "2"; diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index bd952207e..1b63f4333 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -39,7 +39,7 @@ class ApplicationTest extends NsTest { void 재매칭_실패() { assertShuffleTest( () -> { - runException("1", "백엔드, 레벨1, 자동차경주", "1", "백엔드, 레벨1, 자동차경주", "네", "프론트앤드, 레벨1, 자동차경주"); + runException("1", "백엔드, 레벨1, 자동차경주", "1", "백엔드, 레벨1, 자동차경주", "네", "프론트엔드, 레벨1, 자동차경주"); assertThat(output()).contains("3번의 리매칭을 모두 실패했습니다."); }, Arrays.asList("태웅", "백호", "치수", "태섭"), From c0dcb0c5f6a019b7972c5e6333829f41ba2a878a Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 21:39:17 +0900 Subject: [PATCH 17/18] =?UTF-8?q?fix=20:=20=EC=9E=AC=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20=EC=9E=AC=EB=A7=A4?= =?UTF-8?q?=EC=B9=AD=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=EC=8B=9C=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=EA=B3=BC=20=EB=A0=88=EB=B2=A8=EC=9D=B4=20?= =?UTF-8?q?=EB=A7=9E=EC=A7=80=20=EC=95=8A=EC=95=84=EC=84=9C=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8=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 --- .../domain/PairMatchingService.java | 2 +- .../pairmatching/domain/option/Mission.java | 11 +++++-- .../pairmatching/domain/pair/PairOption.java | 8 +++++ .../message/ExceptionMessage.java | 2 ++ .../java/pairmatching/ApplicationTest.java | 30 +++++++++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/main/java/pairmatching/domain/PairMatchingService.java b/src/main/java/pairmatching/domain/PairMatchingService.java index 335af2a33..151524a8f 100644 --- a/src/main/java/pairmatching/domain/PairMatchingService.java +++ b/src/main/java/pairmatching/domain/PairMatchingService.java @@ -79,7 +79,7 @@ public static boolean hasHistory(PairOption option) { public static List getHistory(Course course, Level level) { List result = new ArrayList<>(); - Mission.findAll().forEach(mission -> { + Mission.findByLevel(level).forEach(mission -> { PairOption option = new PairOption(course, level, mission); if (hasHistory(option)) { result.add(history.get(option)); diff --git a/src/main/java/pairmatching/domain/option/Mission.java b/src/main/java/pairmatching/domain/option/Mission.java index 856ad949c..a3586ef39 100644 --- a/src/main/java/pairmatching/domain/option/Mission.java +++ b/src/main/java/pairmatching/domain/option/Mission.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import pairmatching.message.ExceptionMessage; public enum Mission { @@ -32,7 +33,13 @@ public static Mission findByName(String name) { throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); } - public static List findAll() { - return new ArrayList<>(Arrays.asList(Mission.values())); + public static List findByLevel(Level level) { + return Arrays.stream(Mission.values()) + .filter(mission -> mission.level.equals(level)) + .collect(Collectors.toList()); + } + + public Level getLevel() { + return level; } } diff --git a/src/main/java/pairmatching/domain/pair/PairOption.java b/src/main/java/pairmatching/domain/pair/PairOption.java index 08bbaa458..32fe049a3 100644 --- a/src/main/java/pairmatching/domain/pair/PairOption.java +++ b/src/main/java/pairmatching/domain/pair/PairOption.java @@ -12,16 +12,24 @@ public class PairOption { public static final int LEVEL_INDEX = 1; public static final int MISSION_INDEX = 2; public static final String OPTION_DELIMITER = ", "; + private final Course course; private final Level level; private final Mission mission; public PairOption(Course course, Level level, Mission mission) { + validateMatch(level, mission); this.course = course; this.level = level; this.mission = mission; } + private void validateMatch(Level level, Mission mission) { + if (!mission.getLevel().equals(level)) { + throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); + } + } + public static PairOption createByString(String value) { validateRegex(value); String[] split = value.split(OPTION_DELIMITER); diff --git a/src/main/java/pairmatching/message/ExceptionMessage.java b/src/main/java/pairmatching/message/ExceptionMessage.java index e567c948e..af6f9b92b 100644 --- a/src/main/java/pairmatching/message/ExceptionMessage.java +++ b/src/main/java/pairmatching/message/ExceptionMessage.java @@ -2,9 +2,11 @@ public class ExceptionMessage { public static final String EXCEPTION_PREFIX = "[ERROR] : "; + public static final String INVALID_INPUT = "잘못된 입력입니다."; public static final String INVALID_MENU_INPUT = "잘못된 메뉴 입력입니다."; public static final String INVALID_REMATCH_INPUT = "잘못된 리매칭 입력입니다."; + public static final String REMATCHING_FAIL = "3번의 리매칭을 모두 실패했습니다."; public static final String NO_MATCHING_HISTORY = "매칭 기록이 없습니다."; } diff --git a/src/test/java/pairmatching/ApplicationTest.java b/src/test/java/pairmatching/ApplicationTest.java index 1b63f4333..271810999 100644 --- a/src/test/java/pairmatching/ApplicationTest.java +++ b/src/test/java/pairmatching/ApplicationTest.java @@ -60,6 +60,36 @@ class ApplicationTest extends NsTest { ); } + @Test + void 없는_코스에_대한_예외_처리() { + assertSimpleTest( + () -> { + runException("1", "안드로이드, 레벨1, 자동차경주"); + assertThat(output()).contains(ERROR_MESSAGE); + } + ); + } + + @Test + void 없는_레벨에_대한_예외_처리() { + assertSimpleTest( + () -> { + runException("1", "백엔드, 레벨6, 자동차경주"); + assertThat(output()).contains(ERROR_MESSAGE); + } + ); + } + + @Test + void 매칭되지_않는_미션에_대한_예외_처리() { + assertSimpleTest( + () -> { + runException("1", "백엔드, 레벨2, 숫자야구게임"); + assertThat(output()).contains(ERROR_MESSAGE); + } + ); + } + @Override public void runMain() { Application.main(new String[]{}); From c771c43e1ca06f017248835e1ec621a48831f605 Mon Sep 17 00:00:00 2001 From: jhon3242 Date: Mon, 27 Nov 2023 21:43:05 +0900 Subject: [PATCH 18/18] =?UTF-8?q?refactor=20:=20Pair=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/pairmatching/domain/pair/Pair.java | 2 +- .../java/pairmatching/domain/pair/Pairs.java | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/pairmatching/domain/pair/Pair.java b/src/main/java/pairmatching/domain/pair/Pair.java index 88fe9e73c..d1ab1c773 100644 --- a/src/main/java/pairmatching/domain/pair/Pair.java +++ b/src/main/java/pairmatching/domain/pair/Pair.java @@ -7,7 +7,7 @@ import pairmatching.Utils; public class Pair { - private List crews; + private final List crews; public Pair(String firstCrew, String secondCrew) { crews = new ArrayList<>(); diff --git a/src/main/java/pairmatching/domain/pair/Pairs.java b/src/main/java/pairmatching/domain/pair/Pairs.java index 22a1bdb5b..f7f07643f 100644 --- a/src/main/java/pairmatching/domain/pair/Pairs.java +++ b/src/main/java/pairmatching/domain/pair/Pairs.java @@ -4,7 +4,7 @@ import java.util.List; public class Pairs { - private List pairs; + private final List pairs; public Pairs(List pairs) { this.pairs = pairs; @@ -13,17 +13,25 @@ public Pairs(List pairs) { public static Pairs createByNameList(List names) { List pairs = new ArrayList<>(); for (int i = 0; i < names.size(); i += 2) { - if (i + 1 == names.size()) { - Pair lastPair = pairs.get(pairs.size() - 1); - lastPair.addCrew(names.get(i)); + if (isThirdPair(names, i)) { + handleThirdPair(names, pairs, i); break; } - Pair pair = new Pair(names.get(i), names.get(i + 1)); - pairs.add(pair); + Pair newPair = new Pair(names.get(i), names.get(i + 1)); + pairs.add(newPair); } return new Pairs(pairs); } + private static void handleThirdPair(List names, List pairs, int i) { + Pair lastPair = pairs.get(pairs.size() - 1); + lastPair.addCrew(names.get(i)); + } + + private static boolean isThirdPair(List names, int i) { + return i + 1 == names.size(); + } + public boolean hasSamePair(Pairs source) { for (Pair pair : source.pairs) { for (Pair thisPair : this.pairs) {