diff --git a/docs/README.md b/docs/README.md index e69de29..bf793d5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,46 @@ +## 페어매칭 관리 애플리케이션 + +## 기능 목록 정의서 + +## 페어 매칭 프로그램 시작시 +- **기능 목록** + - [x] 기능을 선택할 수 있는 화면을 보여준다. + - [x] 사용자는 선택할 기능을 입력한다. + - [X] 초기 사용자의 목록을 md 파일에서 가져와 저장한다. + +- **예외 목록** + - [x] 1, 2, 3, Q가 아닌 입력은 예외 처리한다. + +## 1. 페어 매칭 선택시 +- **페어 매칭 기능 목록** + - [X] 현재 과정, 미션(레벨별로)에 대한 안내를 화면에 출력한다. + - [x] 사용자에게 과정, 레벨, 미션에대한 입력을 순서대로 `입력받는다.` + - [x] 해당 과정에 맞는 크루들을 셔플하여 페어 매칭 결과를 만든다. + - [X] 페어 매칭 결과는 저장을하고, 중복된 페어매칭 검증시에 사용된다. + - [x] 같은 레벨 다른 미션에서 이미 페어로 만났다면 재매칭 한다. + - [x] 페어 매칭이 완료되면 페어 매칭 결과를 출력한다. +- **페어 재매칭 기능 목록** + - [x] 이미 `과정, 레벨`에 대해 만들어진 페어가 있다면 재 매칭 여부를 `입력한다.` + - [x] `재 페어매칭시` 각 사람들은 는 이전에 만났던 페어를 만나면 안된다. + - [x] 이전에 만났던 페어를 만나면 최대 3회 재시도를 한다. + - [x] 재페어 매칭이 완료되면 페어 매칭 결과를 출력한다. + +- **예외 목록** + - [x] `백엔드, 레벨1, 자동차경주`과 같은 포멧의 입력이 아니면 예외 처리한다. + - [X] 각 과정, 레벨, 미션이 존재하지 않으면 예외 처리한다. + - [X] 만약 미션이 없는 레벨이라면 예외 처리한다. + - [X] 재매칭 여부 입력시 네, 아니오가 아닌 입력은 예외 처리한다. + +## 2. 페어 조회 선택시 +- **조회 기능 목록** + - [x] 과정, 레벨, 미션에 대한 입력을 순서대로 `입력받는다.` + - [x] 해당 입력에 대한 페어 매칭 결과를 출력한다. +- **예외 목록** + - [x] `백엔드, 레벨1, 자동차경주`과 같은 포멧의 입력이 아니면 예외 처리한다. + - [x] 각 과정, 레벨, 미션은 모두 존재하야 한다. + - [x] 만약 미션이 없는 레벨이라면 예외 처리한다. + - [x] 조회할 매칭 결과가 없다면 예외 처리한다. + +## 3. 페어 초기화 선택시 +- **초기화 기능 목록** + - [x] 모든 레벨의 모든 페어 매칭 기록을 초기화 한다 diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index c619a21..65dc566 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -1,8 +1,10 @@ package pairmatching; +import pairmatching.controller.PairMatchingController; + public class Application { public static void main(String[] args) { - // TODO 구현 진행 - + PairMatchingController pairMatchingController = new PairMatchingController(); + pairMatchingController.run(); } } diff --git a/src/main/java/pairmatching/controller/PairMatchingController.java b/src/main/java/pairmatching/controller/PairMatchingController.java new file mode 100644 index 0000000..50c81aa --- /dev/null +++ b/src/main/java/pairmatching/controller/PairMatchingController.java @@ -0,0 +1,83 @@ +package pairmatching.controller; + +import java.util.List; +import pairmatching.exception.NoPariResultException; +import pairmatching.exception.PairAlreadyExistException; +import pairmatching.service.PairMatchingService; +import pairmatching.util.InputValidator; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; + +public class PairMatchingController { + public static final String RETRY = "네"; + private final InputView inputView = new InputView(); + private final OutputView outputView = new OutputView(); + private final PairMatchingService pairMatchingService = new PairMatchingService(); + + public void run() { + try { + determineMenuSelect(InputValidator.validateSelectMenu(inputView.inputSelectMenu())); + } catch (IllegalArgumentException exception) { + outputView.printMessage(exception.getMessage()); + run(); + } + } + + private void determineMenuSelect(final String validatedSelectMenu) { + if (validatedSelectMenu.equals(InputValidator.PAIR_MATCHING)) { + requestPairMatching(); + } + if (validatedSelectMenu.equals(InputValidator.PAIR_VIEW)) { + requestPairView(); + } + if (validatedSelectMenu.equals(InputValidator.PAIR_RESET)) { + requestPairReset(); + } + } + + private void requestPairMatching() { + List courseInformation = InputValidator.validateCourseInformation(inputView.inputCourseInformation()); + try { + outputView.printPairMatchingResult(pairMatchingService.pairMatch(courseInformation)); + run(); + } catch (PairAlreadyExistException exception) { + requestRetry(courseInformation); + } catch (IllegalArgumentException exception) { + outputView.printMessage(exception.getMessage()); + requestPairMatching(); + } + } + + private void requestRetry(final List courseInformation) { + try { + if (InputValidator.validateRetryInput(inputView.inputRetry()).equals(RETRY)) { + outputView.printPairMatchingResult(pairMatchingService.retryPairMatching(courseInformation)); + run(); + } + } catch (IllegalArgumentException exception) { + outputView.printMessage(exception.getMessage()); + requestRetry(courseInformation); + } + } + + private void requestPairView() { + try { + List courseInformation = InputValidator.validateCourseInformation( + inputView.inputCourseInformation()); + outputView.printPairMatchingResult(pairMatchingService.findPairMatchResult(courseInformation)); + run(); + } catch (NoPariResultException exception) { + outputView.printMessage(exception.getMessage()); + run(); + } catch (IllegalArgumentException exception) { + outputView.printMessage(exception.getMessage()); + requestPairView(); + } + } + + private void requestPairReset() { + outputView.printResetMessage(); + pairMatchingService.deleteAllMatchingResult(); + run(); + } +} diff --git a/src/main/java/pairmatching/domain/CourseInformation.java b/src/main/java/pairmatching/domain/CourseInformation.java new file mode 100644 index 0000000..01ae048 --- /dev/null +++ b/src/main/java/pairmatching/domain/CourseInformation.java @@ -0,0 +1,64 @@ +package pairmatching.domain; + +import java.util.List; +import java.util.Objects; +import pairmatching.domain.enums.Course; +import pairmatching.domain.enums.Level; +import pairmatching.domain.enums.Mission; +import pairmatching.message.ErrorMessage; + +public class CourseInformation { + public static final int COURSE_INDEX = 0; + public static final int LEVEL_INDEX = 1; + public static final int MISSION_INDEX = 2; + private final Course course; + private final Level level; + private final Mission mission; + + private CourseInformation(final Course course, final Level level, final Mission mission) { + this.course = course; + this.level = level; + this.mission = mission; + } + + public static CourseInformation of(final List inputInformation) { + CourseInformation courseInformation = new CourseInformation( + Course.findCourse(inputInformation.get(COURSE_INDEX)), + Level.findLevel(inputInformation.get(LEVEL_INDEX)), + Mission.findMission(inputInformation.get(MISSION_INDEX)) + ); + return validateCourseInformation(courseInformation); + } + + private static CourseInformation validateCourseInformation(final CourseInformation courseInformation) { + if (!courseInformation.level.isExistsMission(courseInformation.mission)) { + throw new IllegalArgumentException(ErrorMessage.NO_MISSION_IN_LEVEL_ERROR); + } + return courseInformation; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CourseInformation that = (CourseInformation) o; + return course == that.course && level == that.level && mission == that.mission; + } + + @Override + public int hashCode() { + return Objects.hash(course, level, mission); + } + + public Course getCourse() { + return course; + } + + public Level getLevel() { + return level; + } +} diff --git a/src/main/java/pairmatching/domain/Crew.java b/src/main/java/pairmatching/domain/Crew.java new file mode 100644 index 0000000..e567b06 --- /dev/null +++ b/src/main/java/pairmatching/domain/Crew.java @@ -0,0 +1,39 @@ +package pairmatching.domain; + +import java.util.Objects; +import pairmatching.domain.enums.Course; + +public class Crew { + private final Course course; + private final String name; + + public Crew(final Course course, final String name) { + this.course = course; + this.name = name; + } + + public boolean containsCourse(final Course course) { + return this.course == course; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Crew crew = (Crew) o; + return course == crew.course && Objects.equals(name, crew.name); + } + + @Override + public int hashCode() { + return Objects.hash(course, name); + } +} diff --git a/src/main/java/pairmatching/domain/Crews.java b/src/main/java/pairmatching/domain/Crews.java new file mode 100644 index 0000000..cc800b2 --- /dev/null +++ b/src/main/java/pairmatching/domain/Crews.java @@ -0,0 +1,50 @@ +package pairmatching.domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class Crews { + private final List crews; + + public Crews(final List crews) { + this.crews = crews; + } + + public List makePairList() { + if (crews.size() % 2 == 0) { + return createEvenPair(); + } + return createOddPair(); + } + + private List createOddPair() { + List pairs = new ArrayList<>(); + for (int index = 0; index < crews.size(); index++) { + if (index == crews.size() - 3) { + pairs.add(new Pair(List.of(crews.get(index), crews.get(index + 1), crews.get(index + 2)))); + break; + } + if (index % 2 == 1) { + pairs.add(new Pair(List.of(crews.get(index - 1), crews.get(index)))); + } + } + return pairs; + } + + private List createEvenPair() { + List pairs = new ArrayList<>(); + for (int index = 0; index < crews.size(); index++) { + if (index % 2 == 1) { + pairs.add(new Pair(List.of(crews.get(index - 1), crews.get(index)))); + } + } + return pairs; + } + + public List getCrewNameList() { + return crews.stream() + .map(Crew::getName) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/pairmatching/domain/Pair.java b/src/main/java/pairmatching/domain/Pair.java new file mode 100644 index 0000000..a636d34 --- /dev/null +++ b/src/main/java/pairmatching/domain/Pair.java @@ -0,0 +1,29 @@ +package pairmatching.domain; + +import java.util.List; + +public class Pair { + public static final String SEPARATOR = " : "; + private final List pair; + + public Pair(final List pair) { + this.pair = pair; + } + + public boolean containsPair(List pairs) { + return pairs.stream() + .map(input -> input.pair) + .anyMatch(pair -> pair.containsAll(this.pair)); + } + + @Override + public String toString() { + StringBuilder log = new StringBuilder(); + pair.stream() + .map(Crew::getName) + .limit(pair.size() - 1) + .forEach(name -> log.append(name).append(SEPARATOR)); + log.append(pair.get(pair.size() - 1).getName()); + return log.toString(); + } +} diff --git a/src/main/java/pairmatching/domain/PairMatching.java b/src/main/java/pairmatching/domain/PairMatching.java new file mode 100644 index 0000000..6c49b77 --- /dev/null +++ b/src/main/java/pairmatching/domain/PairMatching.java @@ -0,0 +1,11 @@ +package pairmatching.domain; + +public class PairMatching { + private final CourseInformation courseInformation; + private final Crews crews; + + public PairMatching(final CourseInformation courseInformation, final Crews crews) { + this.courseInformation = courseInformation; + this.crews = crews; + } +} diff --git a/src/main/java/pairmatching/domain/enums/Course.java b/src/main/java/pairmatching/domain/enums/Course.java new file mode 100644 index 0000000..f060a3d --- /dev/null +++ b/src/main/java/pairmatching/domain/enums/Course.java @@ -0,0 +1,26 @@ +package pairmatching.domain.enums; + +import java.util.Arrays; +import pairmatching.message.ErrorMessage; + +public enum Course { + BACKEND("백엔드"), + FRONTEND("프론트엔드"); + + private String name; + + Course(String name) { + this.name = name; + } + + public static Course findCourse(final String inputCourse) { + return Arrays.stream(Course.values()) + .filter(course -> course.containsName(inputCourse)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.NO_COURSE_ERROR)); + } + + private boolean containsName(final String inputCourse) { + return name.equals(inputCourse); + } +} diff --git a/src/main/java/pairmatching/domain/enums/Level.java b/src/main/java/pairmatching/domain/enums/Level.java new file mode 100644 index 0000000..f1d794f --- /dev/null +++ b/src/main/java/pairmatching/domain/enums/Level.java @@ -0,0 +1,42 @@ +package pairmatching.domain.enums; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import pairmatching.message.ErrorMessage; + +/** + * 자동차경주 | 로또 | 숫자야구게임 - 레벨2: 장바구니 | 결제 | 지하철노선도 - 레벨3: - 레벨4: 성능개선 | 배포 + */ +public enum Level { + LEVEL1("레벨1", List.of(Mission.CAR_RACING, Mission.LOTTO, Mission.BASEBALL)), + LEVEL2("레벨2", List.of(Mission.BASKET, Mission.PAYMENT, Mission.SUBWAY_PATH)), + LEVEL3("레벨3", Collections.emptyList()), + LEVEL4("레벨4", List.of(Mission.PERFORMANCE, Mission.DISTRIBUTION)), + LEVEL5("레벨5", Collections.emptyList()); + + private String name; + private List missions; + + Level(final String name, final List missions) { + this.name = name; + this.missions = missions; + } + + public static Level findLevel(final String inputLevel) { + return Arrays.stream(Level.values()) + .filter(level -> level.containsLevel(inputLevel)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.NO_LEVEL_ERROR)); + } + + private boolean containsLevel(final String inputLevel) { + return name.equals(inputLevel); + } + + public boolean isExistsMission(final Mission mission) { + return missions.contains(mission); + } + +// 추가 기능 구현 +} diff --git a/src/main/java/pairmatching/domain/enums/Mission.java b/src/main/java/pairmatching/domain/enums/Mission.java new file mode 100644 index 0000000..ae8d76f --- /dev/null +++ b/src/main/java/pairmatching/domain/enums/Mission.java @@ -0,0 +1,32 @@ +package pairmatching.domain.enums; + +import java.util.Arrays; +import pairmatching.message.ErrorMessage; + +public enum Mission { + CAR_RACING("자동차경주"), + LOTTO("로또"), + BASEBALL("숫자야구게임"), + BASKET("장바구니"), + PAYMENT("결제"), + SUBWAY_PATH("지하철노선도"), + PERFORMANCE("성능개선"), + DISTRIBUTION("배포"); + + private String name; + + Mission(final String name) { + this.name = name; + } + + public static Mission findMission(final String inputMission) { + return Arrays.stream(values()) + .filter(mission -> mission.containsMission(inputMission)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.NO_MISSION_ERROR)); + } + + private boolean containsMission(final String inputMission) { + return name.equals(inputMission); + } +} diff --git a/src/main/java/pairmatching/exception/NoPariResultException.java b/src/main/java/pairmatching/exception/NoPariResultException.java new file mode 100644 index 0000000..73eaa42 --- /dev/null +++ b/src/main/java/pairmatching/exception/NoPariResultException.java @@ -0,0 +1,7 @@ +package pairmatching.exception; + +public class NoPariResultException extends RuntimeException { + public NoPariResultException(String message) { + super(message); + } +} diff --git a/src/main/java/pairmatching/exception/PairAlreadyExistException.java b/src/main/java/pairmatching/exception/PairAlreadyExistException.java new file mode 100644 index 0000000..a332d36 --- /dev/null +++ b/src/main/java/pairmatching/exception/PairAlreadyExistException.java @@ -0,0 +1,7 @@ +package pairmatching.exception; + +public class PairAlreadyExistException extends RuntimeException { + public PairAlreadyExistException() { + super(); + } +} diff --git a/src/main/java/pairmatching/message/ErrorMessage.java b/src/main/java/pairmatching/message/ErrorMessage.java new file mode 100644 index 0000000..a47f8fd --- /dev/null +++ b/src/main/java/pairmatching/message/ErrorMessage.java @@ -0,0 +1,20 @@ +package pairmatching.message; + + +public class ErrorMessage { + + + public static final String MENU_SELECT_ERROR = "[ERROR] '1, 2, 3, Q'만 입력할 수 있습니다."; + public static final String COURSE_INFORMATION_ERROR = "[ERROR] '백엔드, 레벨1, 자동차경주'과 같이 입력해야 합니다."; + public static final String FILE_NOT_FOUND_ERROR = "[ERROR] 파일을 찾을 수 없습니다."; + public static final String NO_COURSE_ERROR = "[ERROR] 존재하지 않는 코스입니다."; + public static final String NO_LEVEL_ERROR = "[ERROR] 존재하지 않는 레벨입니다."; + public static final String NO_MISSION_ERROR = "[ERROR] 존재하지 않는 미션입니다."; + public static final String NO_MISSION_IN_LEVEL_ERROR = "[ERROR] 해당 레벨에 존재하지 않는 미션입니다."; + public static final String LIMIT_PAIR_MATCH_TRY_ERROR = "[ERROR] 중복된 페어가 존재하여 매칭할 수 없습니다."; + public static final String RETRY_INPUT_ERROR = "[ERROR] 네, 아니오만 입력해야 합니다."; + public static final String NO_PAIR_MATCHING_RESULT = "[ERROR] 매칭 이력이 없습니다."; + + private ErrorMessage() { + } +} diff --git a/src/main/java/pairmatching/repository/CrewRepository.java b/src/main/java/pairmatching/repository/CrewRepository.java new file mode 100644 index 0000000..1b8d19f --- /dev/null +++ b/src/main/java/pairmatching/repository/CrewRepository.java @@ -0,0 +1,50 @@ +package pairmatching.repository; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import pairmatching.domain.Crew; +import pairmatching.domain.Crews; +import pairmatching.domain.enums.Course; +import pairmatching.message.ErrorMessage; + +public class CrewRepository { + private static final CrewRepository instance = new CrewRepository(); + private static final List store = new ArrayList<>(); + private static final String BACKEND_PATH = "src/main/resources/backend-crew.md"; + private static final String FRONTEND_PATH = "src/main/resources/frontend-crew.md"; + + static { + initializeCrew(BACKEND_PATH, Course.BACKEND); + initializeCrew(FRONTEND_PATH, Course.FRONTEND); + } + + private CrewRepository() { + } + + public static CrewRepository getInstance() { + return instance; + } + + private static void initializeCrew(String path, Course course) { + try { + BufferedReader reader = new BufferedReader(new FileReader(path)); + store.addAll(reader.lines() + .collect(Collectors.toList()) + .stream() + .map(name -> new Crew(course, name)) + .collect(Collectors.toList())); + } catch (FileNotFoundException e) { + throw new IllegalArgumentException(ErrorMessage.FILE_NOT_FOUND_ERROR); + } + } + + public static Crews findAllByCourse(final Course course) { + return new Crews(store.stream() + .filter(crew -> crew.containsCourse(course)) + .collect(Collectors.toList())); + } +} diff --git a/src/main/java/pairmatching/repository/MatchingCrewRepository.java b/src/main/java/pairmatching/repository/MatchingCrewRepository.java new file mode 100644 index 0000000..f73600b --- /dev/null +++ b/src/main/java/pairmatching/repository/MatchingCrewRepository.java @@ -0,0 +1,58 @@ +package pairmatching.repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import pairmatching.domain.CourseInformation; +import pairmatching.domain.Pair; +import pairmatching.domain.enums.Level; +import pairmatching.exception.NoPariResultException; +import pairmatching.message.ErrorMessage; + +public class MatchingCrewRepository { + private static final MatchingCrewRepository instance = new MatchingCrewRepository(); + private static final Map> store = new HashMap<>(); + + private MatchingCrewRepository() { + } + + public static MatchingCrewRepository getInstance() { + return instance; + } + + public boolean hasMatchedBefore(CourseInformation courseInformation) { + return store.containsKey(courseInformation); + } + + public void savePairMatching(final CourseInformation courseInformation, final List pairs) { + store.remove(courseInformation); + store.put(courseInformation, pairs); + } + + public List findPairMatching(final CourseInformation courseInformation) { + if (!store.containsKey(courseInformation)) { + throw new NoPariResultException(ErrorMessage.NO_PAIR_MATCHING_RESULT); + } + return store.get(courseInformation); + } + + public void deleteAll() { + store.clear(); + } + + public boolean hasEqualMatchedCrew(final CourseInformation courseInformation, final List pairs) { + return store.keySet() + .stream() + .filter(key -> key.getLevel() == courseInformation.getLevel()) + .map(store::get) + .anyMatch(findPairs -> hasSameMatchedPair(findPairs, pairs)); + } + + private boolean hasSameMatchedPair(final List findPairs, final List pairs) { + return findPairs.stream() + .anyMatch(findPair -> findPair.containsPair(pairs)); + + } + +} diff --git a/src/main/java/pairmatching/service/PairMatchingService.java b/src/main/java/pairmatching/service/PairMatchingService.java new file mode 100644 index 0000000..62e1e4a --- /dev/null +++ b/src/main/java/pairmatching/service/PairMatchingService.java @@ -0,0 +1,64 @@ +package pairmatching.service; + +import java.util.List; +import pairmatching.domain.CourseInformation; +import pairmatching.domain.Crews; +import pairmatching.domain.Pair; +import pairmatching.exception.PairAlreadyExistException; +import pairmatching.message.ErrorMessage; +import pairmatching.repository.CrewRepository; +import pairmatching.repository.MatchingCrewRepository; +import pairmatching.util.ShuffleUtil; + +public class PairMatchingService { + public static final int MAX_TRY = 3; + private final MatchingCrewRepository matchingCrewRepository = MatchingCrewRepository.getInstance(); + + public List retryPairMatching(final List inputInformation) { + CourseInformation courseInformation = CourseInformation.of(inputInformation); + return matchCrew(courseInformation, 0); + } + + public List pairMatch(final List inputInformation) { + CourseInformation courseInformation = validateAlreadyMatch(CourseInformation.of(inputInformation)); + return matchCrew(courseInformation, 0); + } + + private List matchCrew(final CourseInformation courseInformation, final int matchTryCount) { + checkTryCount(matchTryCount); + Crews shuffledCrews = ShuffleUtil.ShuffleCrews(CrewRepository.findAllByCourse(courseInformation.getCourse()), + courseInformation.getCourse()); + List pairs = shuffledCrews.makePairList(); + if (hasSamePairInList(courseInformation, pairs)) { + matchCrew(courseInformation, matchTryCount + 1); + } + matchingCrewRepository.savePairMatching(courseInformation, pairs); + return pairs; + } + + private boolean hasSamePairInList(final CourseInformation courseInformation, final List pairs) { + return matchingCrewRepository.hasEqualMatchedCrew(courseInformation, pairs); + } + + private void checkTryCount(final int matchTryCount) { + if (matchTryCount == MAX_TRY) { + throw new IllegalArgumentException(ErrorMessage.LIMIT_PAIR_MATCH_TRY_ERROR); + } + } + + private CourseInformation validateAlreadyMatch(final CourseInformation courseInformation) { + if (matchingCrewRepository.hasMatchedBefore(courseInformation)) { + throw new PairAlreadyExistException(); + } + return courseInformation; + } + + public List findPairMatchResult(final List inputInformation) { + CourseInformation courseInformation = CourseInformation.of(inputInformation); + return matchingCrewRepository.findPairMatching(courseInformation); + } + + public void deleteAllMatchingResult() { + matchingCrewRepository.deleteAll(); + } +} diff --git a/src/main/java/pairmatching/util/InputValidator.java b/src/main/java/pairmatching/util/InputValidator.java new file mode 100644 index 0000000..aecc8e7 --- /dev/null +++ b/src/main/java/pairmatching/util/InputValidator.java @@ -0,0 +1,45 @@ +package pairmatching.util; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import pairmatching.message.ErrorMessage; + +public class InputValidator { + public static final String PAIR_MATCHING = "1"; + public static final String PAIR_VIEW = "2"; + public static final String PAIR_RESET = "3"; + public static final String QUIT = "Q"; + public static final String SEPARATOR = ", "; + public static final int NEED_SIZE_INPUT = 3; + public static final String YES = "네"; + public static final String NO = "아니오"; + + private InputValidator() { + } + + public static String validateSelectMenu(final String userInput) { + if (!userInput.equals(PAIR_MATCHING) + && !userInput.equals(PAIR_VIEW) + && !userInput.equals(PAIR_RESET) + && !userInput.equals(QUIT)) { + throw new IllegalArgumentException(ErrorMessage.MENU_SELECT_ERROR); + } + return userInput; + } + + public static List validateCourseInformation(final String userInput) { + if (userInput.split(SEPARATOR).length != NEED_SIZE_INPUT) { + throw new IllegalArgumentException(ErrorMessage.COURSE_INFORMATION_ERROR); + } + return Arrays.stream(userInput.split(SEPARATOR)) + .collect(Collectors.toList()); + } + + public static String validateRetryInput(final String userInput) { + if (!userInput.equals(YES) && !userInput.equals(NO)) { + throw new IllegalArgumentException(ErrorMessage.RETRY_INPUT_ERROR); + } + return userInput; + } +} diff --git a/src/main/java/pairmatching/util/ShuffleUtil.java b/src/main/java/pairmatching/util/ShuffleUtil.java new file mode 100644 index 0000000..b3470ce --- /dev/null +++ b/src/main/java/pairmatching/util/ShuffleUtil.java @@ -0,0 +1,20 @@ +package pairmatching.util; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; +import java.util.stream.Collectors; +import pairmatching.domain.Crew; +import pairmatching.domain.Crews; +import pairmatching.domain.enums.Course; + +public class ShuffleUtil { + private ShuffleUtil() { + } + + public static Crews ShuffleCrews(Crews crews, final Course course) { + List shuffledName = Randoms.shuffle(crews.getCrewNameList()); + return new Crews(shuffledName.stream() + .map(name -> new Crew(course, name)) + .collect(Collectors.toList())); + } +} diff --git a/src/main/java/pairmatching/view/InputView.java b/src/main/java/pairmatching/view/InputView.java new file mode 100644 index 0000000..5134a1c --- /dev/null +++ b/src/main/java/pairmatching/view/InputView.java @@ -0,0 +1,40 @@ +package pairmatching.view; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + + public String inputSelectMenu() { + System.out.println("기능을 선택하세요."); + System.out.println("1. 페어 매칭"); + System.out.println("2. 페어 조회"); + System.out.println("3. 페어 초기화"); + System.out.println("Q. 종료"); + return Console.readLine(); + } + + public String inputCourseInformation() { + printInformation(); + System.out.println("과정, 레벨, 미션을 선택하세요."); + System.out.println("ex) 백엔드, 레벨1, 자동차경주"); + return Console.readLine(); + } + + private static void printInformation() { + System.out.println("#############################################"); + System.out.println("과정: 백엔드 | 프론트엔드"); + System.out.println("미션:"); + System.out.println(" -레벨1: 자동차경주 | 로또 | 숫자야구게임"); + System.out.println(" -레벨2: 장바구니 | 결제 | 지하철노선도"); + System.out.println(" -레벨3:"); + System.out.println(" -레벨4: 성능개선 | 배포"); + System.out.println(" -레벨5:"); + System.out.println("#############################################"); + } + + public String inputRetry() { + System.out.println("매칭 정보가 있습니다. 다시 매칭하시겠습니까?"); + System.out.println("네 | 아니오"); + return Console.readLine(); + } +} diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java new file mode 100644 index 0000000..6330da9 --- /dev/null +++ b/src/main/java/pairmatching/view/OutputView.java @@ -0,0 +1,30 @@ +package pairmatching.view; + +import java.util.Arrays; +import java.util.List; +import pairmatching.domain.Pair; + +public class OutputView { + public void printMessage(final String message) { + System.out.println(message); + System.out.println(); + } + + public void printPairMatchingResult(final List pairMatch) { + System.out.println("페어 매칭 결과입니다."); + System.out.println(createPairResultMessage(pairMatch)); + } + + private String createPairResultMessage(final List pairMatch) { + StringBuilder message = new StringBuilder(); + Arrays.stream(pairMatch.toString() + .replaceAll("(?:\\[|null|\\]|)", "") + .split(",")) + .forEach(match -> message.append(match.trim()).append("\n")); + return message.toString(); + } + + public void printResetMessage() { + System.out.println("초기화 되었습니다."); + } +}