diff --git a/SOLUTION.md b/SOLUTION.md new file mode 100644 index 000000000..8cb45df0e --- /dev/null +++ b/SOLUTION.md @@ -0,0 +1,202 @@ +# 페어 매칭 관리 모델링 + +## 용어 정리 + +### 크루 +| 용어 | 설명 | +|-------------|----------------| +| Crew | 우테코에서 학습하는 사람들 | +| Crew Name | 크루 이름 | +| Crew Course | 크루가 참여하는 분야 | + +### 미션 +| 용어 | 설명 | +|---------|-----------------------| +| Mission | 학습 레벨마다 구분되어 존재하는 미션들 | + +### 레벨 +| 용어 | 설명 | +|---------|------------------------| +| Level | 우테코 학습 단계를 구분한 것 1~5단계 존재 | +| Mission | 각 단계마다 미션이 존재 | + +### 분야 +| 용어 | 설명 | +|--------|----------------------------| +| Course | 크루가 참가하는 분야로 백엔드 프론트엔드가 있음 | + + +## 개발 요구사항 + +### 페어 매칭 기능 +- 페어 매칭 조건 + - [ ] 미션을 함께 수행할 페어를 두명씩 매칭한다. + - [ ] 페어 매칭 대상이 홀수인 경우 한 페어는 3인으로 구성한다. + - [ ] 같은 레벨에서 이미 페어를 맺은 크루와는 다시 페어로 매칭될 수 없다. + +- 페어 매칭 구현 방법 + - [ ] 크루들의 이름 목록을 List 형태로 준비한다. + - [ ] 크루 목록의 순서를 랜덤으로 섞는다. 이 때 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드를 활용해야 한다. + - [ ] 랜덤으로 섞인 페어 목록에서 페어 매칭을 할 때 앞에서부터 순서대로 두명씩 페어를 맺는다. + - [ ] 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다. + - [ ] 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다. + - [ ] 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다. + +### 파일 입출력 +- [ ] 페어 매칭에 필요한 크루들의 이름을 파일 입출력을 통해 불러온다. +- [ ] `src/main/resources/backend-crew.md`과 `src/main/resources/frontend-crew.md` 파일을 이용한다. +- [ ] 두 파일의 내용은 수정이 가능하다. 수정 시 크루들의 이름은 중복될 수 없다. +- [ ] 파일 입출력 방법은 `자바 파일 읽기`나 `자바 파일 입출력`과 같은 키워드로 구글링해서 찾을 수 있다. + +### 에러 처리 +- [ ] 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`를 발생시키고, `[ERROR]`로 시작하는 에러 메시지를 출력 후 해당 부분부터 다시 입력을 받는다. +- [ ] 아래의 프로그래밍 실행 결과 예시와 동일하게 입력과 출력이 이루어져야 한다. + +### 기능 선택 +- [ ] 프로그램을 시작하면 기능의 종류를 출력하고 그 중 하나의 입력을 받는다. + +``` +기능을 선택하세요. +1. 페어 매칭 +2. 페어 조회 +3. 페어 초기화 +Q. 종료 +``` + +### 페어 매칭 +- [ ] 과정와 미션을 출력하고 매칭하고자 하는 과정, 레벨, 미션을 입력 받는다. + +``` +############################################# +과정: 백엔드 | 프론트엔드 +미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: +############################################ +과정, 레벨, 미션을 선택하세요. +ex) 백엔드, 레벨1, 자동차경주 +``` + +- [ ] 매칭이 정상적으로 수행되면 결과가 출력된다. +- [ ] 출력되는 페어의 순서는 `camp.nextstep.edu.missionutils.Randoms`의 shuffle 메서드의 결과 순서로 정렬한다. + +### 프로그래밍 실행 결과 예시 + +``` +기능을 선택하세요. +1. 페어 매칭 +2. 페어 조회 +3. 페어 초기화 +Q. 종료 +1 + +############################################# +과정: 백엔드 | 프론트엔드 +미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: +############################################ +과정, 레벨, 미션을 선택하세요. +ex) 백엔드, 레벨1, 자동차경주 +프론트엔드, 레벨1, 자동차경주 + +페어 매칭 결과입니다. +다비 : 신디 +쉐리 : 덴버 +제키 : 로드 +라라 : 윌터 +니콜 : 이브 +린다 : 시저 +보노 : 제시 : 제키 + +기능을 선택하세요. +1. 페어 매칭 +2. 페어 조회 +3. 페어 초기화 +Q. 종료 +1 + +############################################# +과정: 백엔드 | 프론트엔드 +미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: +############################################ +과정, 레벨, 미션을 선택하세요. +ex) 백엔드, 레벨1, 자동차경주 +프론트엔드, 레벨1, 자동차경주 + +매칭 정보가 있습니다. 다시 매칭하시겠습니까? +네 | 아니오 +아니오 + +과정, 레벨, 미션을 선택하세요. +ex) 백엔드, 레벨1, 자동차경주 +프론트엔드, 레벨1, 자동차경주 +매칭 정보가 있습니다. 다시 매칭하시겠습니까? +네 | 아니오 +네 + +페어 매칭 결과입니다. +이브 : 윌터 +보노 : 제키 +신디 : 로드 +제시 : 린다 +시저 : 라라 +니콜 : 다비 +리사 : 덴버 : 제키 + +기능을 선택하세요. +1. 페어 매칭 +2. 페어 조회 +3. 페어 초기화 +Q. 종료 +2 + +############################################# +과정: 백엔드 | 프론트엔드 +미션: + - 레벨1: 자동차경주 | 로또 | 숫자야구게임 + - 레벨2: 장바구니 | 결제 | 지하철노선도 + - 레벨3: + - 레벨4: 성능개선 | 배포 + - 레벨5: +############################################ +과정, 레벨, 미션을 선택하세요. +ex) 백엔드, 레벨1, 자동차경주 +프론트엔드, 레벨1, 자동차경주 + +페어 매칭 결과입니다. +이브 : 윌터 +보노 : 제키 +신디 : 로드 +제시 : 린다 +시저 : 라라 +니콜 : 다비 +리사 : 덴버 : 제키 + +기능을 선택하세요. +1. 페어 매칭 +2. 페어 조회 +3. 페어 초기화 +Q. 종료 +3 + +초기화 되었습니다. + +기능을 선택하세요. +1. 페어 매칭 +2. 페어 조회 +3. 페어 초기화 +Q. 종료 +Q +``` diff --git a/src/main/java/pairmatching/Application.java b/src/main/java/pairmatching/Application.java index 6f56e741c..8f9c97441 100644 --- a/src/main/java/pairmatching/Application.java +++ b/src/main/java/pairmatching/Application.java @@ -1,7 +1,14 @@ package pairmatching; +import pairmatching.config.AppConfig; +import pairmatching.controller.Controller; + public class Application { + public static void main(String[] args) { - // TODO 구현 진행 + AppConfig appConfig = new AppConfig(); + Controller controller = appConfig.controller(); + controller.run(); } + } diff --git a/src/main/java/pairmatching/config/AppConfig.java b/src/main/java/pairmatching/config/AppConfig.java new file mode 100644 index 000000000..38910c85a --- /dev/null +++ b/src/main/java/pairmatching/config/AppConfig.java @@ -0,0 +1,37 @@ +package pairmatching.config; + +import pairmatching.controller.Controller; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; + +public class AppConfig { + + private InputView inputView; + private OutputView outputView; + private Controller controller; + + public AppConfig() { + } + + private InputView inputView() { + if (inputView == null) { + return inputView = new InputView(); + } + return inputView; + } + + private OutputView outputView() { + if (outputView == null) { + return outputView = new OutputView(); + } + return outputView; + } + + public Controller controller() { + if (controller == null) { + return controller = new Controller(inputView(), outputView()); + } + return controller; + } + +} diff --git a/src/main/java/pairmatching/controller/Controller.java b/src/main/java/pairmatching/controller/Controller.java new file mode 100644 index 000000000..e564d5c75 --- /dev/null +++ b/src/main/java/pairmatching/controller/Controller.java @@ -0,0 +1,127 @@ +package pairmatching.controller; + +import static pairmatching.service.FileReaderService.BACKEND_CREW_DIR; +import static pairmatching.service.FileReaderService.FRONTEND_CREW_DIR; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; +import pairmatching.model.Course; +import pairmatching.model.Crew; +import pairmatching.model.Crews; +import pairmatching.model.InputInformation; +import pairmatching.model.Result; +import pairmatching.service.FileReaderService; +import pairmatching.service.InputParser; +import pairmatching.view.InputView; +import pairmatching.view.OutputView; + +public class Controller { + + private final InputView inputView; + private final OutputView outputView; + + public Controller(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + List backendCrews = readCrews(BACKEND_CREW_DIR, Course.BACKEND); + List frontendCrews = readCrews(FRONTEND_CREW_DIR, Course.FRONTEND); + Crews crews = new Crews(backendCrews, frontendCrews); + + Result result = Result.init(); + String function; + while (!"Q".equals(function = inputView.readFunctionSelect())) { + if ("3".equals(function)) { + result = Result.init(); + outputView.printInitMsg(); + continue; + } + + if ("1".equals(function)) { + handlePairMatchingProcess(result, crews); + } + if ("2".equals(function)) { + InputInformation courseAndLevelAndMission = readCourseAndLevelAndMission(); + handlePrintPairMatching(result, courseAndLevelAndMission); + } + } + } + + private List readCrews(String dir, Course course) { + return retryUntilValid(() -> { + List names = FileReaderService.readFile(dir); + List crews = new ArrayList<>(); + for (String name : names) { + crews.add(Crew.from(course, name)); + } + return crews; + }); + } + + private InputInformation readCourseAndLevelAndMission() { + return retryUntilValid(() -> + InputParser.parseCourseAndLevelAndMission(inputView.readCourseAndLevelAndMission()) + ); + } + + private Object handlePairMatchingProcess(Result result, Crews crews) { + return retryUntilValid(() -> { + InputInformation courseAndLevelAndMission = readCourseAndLevelAndMission(); + handlePairMatching(result, courseAndLevelAndMission, crews); + handlePrintPairMatching(result, courseAndLevelAndMission); + return null; + }); + } + + private void handlePairMatching(Result result, InputInformation information, Crews crews) { + // 이미 생성된 정보가 있을 때 + if (result.isExist(information)) { + String rematching = readRematching(); + if ("아니오".equals(rematching)) { + throw new IllegalStateException(); + } + } + + int retry = 0; + while (retry < 3) { + try { + // 정보 생성 및 저장 + List> pairs = crews.pairMatching(information.getCourse()); + result.put(information, pairs); + // 같은 레벨에서 같은 크루가 두 번 이상 만나는지 검사 + result.isAlreadyMatched(); + return; + } catch (IllegalArgumentException e) { + retry++; + } + } + throw new IllegalArgumentException("3회 시도까지 매칭이 되지 않았습니다."); + } + + private String readRematching() { + return retryUntilValid(() -> + InputParser.parseYesOrNo(inputView.readRematching()) + ); + } + + private void handlePrintPairMatching(Result result, InputInformation courseAndLevelAndMission) { + List> pairs = result.getPairs(courseAndLevelAndMission); + outputView.printPairMatching(pairs); + } + + private T retryUntilValid(Supplier supplier) { + while (true) { + try { + return supplier.get(); + } catch (IllegalArgumentException e) { + outputView.printErrorMsg(e.getMessage()); + } catch (IllegalStateException e) { + continue; + } + } + } + +} diff --git a/src/main/java/pairmatching/model/Course.java b/src/main/java/pairmatching/model/Course.java new file mode 100644 index 000000000..f7f538f31 --- /dev/null +++ b/src/main/java/pairmatching/model/Course.java @@ -0,0 +1,27 @@ +package pairmatching.model; + +public enum Course { + + BACKEND("백엔드"), + FRONTEND("프론트엔드"); + + private final String name; + + Course(String name) { + this.name = name; + } + + public static Course from(String name) { + for (Course course : Course.values()) { + if (course.name.equals(name)) { + return course; + } + } + throw new IllegalArgumentException("없는 과정입니다."); + } + + public String getName() { + return name; + } + +} diff --git a/src/main/java/pairmatching/model/Crew.java b/src/main/java/pairmatching/model/Crew.java new file mode 100644 index 000000000..3cbdb7fbc --- /dev/null +++ b/src/main/java/pairmatching/model/Crew.java @@ -0,0 +1,21 @@ +package pairmatching.model; + +public class Crew { + + private final Course course; + private final String name; + + private Crew(Course course, String name) { + this.course = course; + this.name = name; + } + + public static Crew from(Course course, String name) { + return new Crew(course, name); + } + + public String getName() { + return name; + } + +} diff --git a/src/main/java/pairmatching/model/Crews.java b/src/main/java/pairmatching/model/Crews.java new file mode 100644 index 000000000..3ecf55bb8 --- /dev/null +++ b/src/main/java/pairmatching/model/Crews.java @@ -0,0 +1,44 @@ +package pairmatching.model; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Crews { + + private final Map> crews; + + public Crews(List backends, List frontends) { + this.crews = new HashMap<>(); + crews.put(Course.BACKEND, backends); + crews.put(Course.FRONTEND, frontends); + } + + public List> pairMatching(Course course) { + List crewNames = new ArrayList<>(); + for (Crew crew : crews.get(course)) { + crewNames.add(crew.getName()); + } + + return makePair(Randoms.shuffle(crewNames)); + } + + private List> makePair(List crewNames) { + List> pairs = new ArrayList<>(); + for (int i = 1; i < crewNames.size(); i += 2) { + List pair = new ArrayList<>(); + pair.add(crewNames.get(i - 1)); + pair.add(crewNames.get(i)); + pairs.add(pair); + } + + if (crewNames.size() % 2 != 0) { + pairs.get(pairs.size() - 1).add(crewNames.get(crewNames.size() - 1)); + } + + return pairs; + } + +} diff --git a/src/main/java/pairmatching/model/InputInformation.java b/src/main/java/pairmatching/model/InputInformation.java new file mode 100644 index 000000000..1cfb8677c --- /dev/null +++ b/src/main/java/pairmatching/model/InputInformation.java @@ -0,0 +1,35 @@ +package pairmatching.model; + +public class InputInformation { + + private final Course course; + private final Level level; + private final Mission mission; + + private InputInformation(Course course, Level level, Mission mission) { + this.course = course; + this.level = level; + this.mission = mission; + } + + public static InputInformation from(String course, String level, String mission) { + return new InputInformation( + Course.from(course.trim()), + Level.from(level.trim()), + Mission.from(mission.trim()) + ); + } + + public Course getCourse() { + return course; + } + + public Level getLevel() { + return level; + } + + public Mission getMission() { + return mission; + } + +} diff --git a/src/main/java/pairmatching/model/Level.java b/src/main/java/pairmatching/model/Level.java new file mode 100644 index 000000000..147817eec --- /dev/null +++ b/src/main/java/pairmatching/model/Level.java @@ -0,0 +1,26 @@ +package pairmatching.model; + +public enum Level { + + LEVEL1("레벨1"), + LEVEL2("레벨2"), + LEVEL3("레벨3"), + LEVEL4("레벨4"), + LEVEL5("레벨5"); + + private final String name; + + Level(String name) { + this.name = name; + } + + public static Level from(String name) { + for (Level level : Level.values()) { + if (level.name.equals(name)) { + return level; + } + } + throw new IllegalArgumentException("없는 레벨입니다."); + } + +} diff --git a/src/main/java/pairmatching/model/Mission.java b/src/main/java/pairmatching/model/Mission.java new file mode 100644 index 000000000..9b4c7e5b3 --- /dev/null +++ b/src/main/java/pairmatching/model/Mission.java @@ -0,0 +1,66 @@ +package pairmatching.model; + +import java.util.ArrayList; +import java.util.List; + +public enum Mission { + + RACING_CAR("자동차경주", Level.LEVEL1), + LOTTO("로또", Level.LEVEL1), + NUMBER_BASEBALL("숫자야구게임", Level.LEVEL1), + + SHOPPING_CART("장바구니", Level.LEVEL2), + PAYMENT("결제", Level.LEVEL2), + SUBWAY("지하철노선도", Level.LEVEL2), + + IMPROVEMENT("성능개선", Level.LEVEL4), + DEPLOY("배포", Level.LEVEL4); + + private final String name; + private final Level level; + + Mission(String name, Level level) { + this.name = name; + this.level = level; + } + + public static List values(Level level) { + List missions = new ArrayList<>(); + for (Mission mission : Mission.values()) { + if (mission.level == level) { + missions.add(mission); + } + } + return missions; + } + + public static Mission from(String name) { + for (Mission mission : Mission.values()) { + if (mission.name.equals(name)) { + return mission; + } + } + throw new IllegalArgumentException("없는 미션입니다."); + } + + public static String level1() { + return RACING_CAR.name + " | " + LOTTO.name + " | " + NUMBER_BASEBALL.name; + } + + public static String level2() { + return SHOPPING_CART.name + " | " + PAYMENT.name + " | " + SUBWAY.name; + } + + public static String level3() { + return ""; + } + + public static String level4() { + return IMPROVEMENT.name + " | " + DEPLOY.name; + } + + public static String level5() { + return ""; + } + +} diff --git a/src/main/java/pairmatching/model/Result.java b/src/main/java/pairmatching/model/Result.java new file mode 100644 index 000000000..46d21538a --- /dev/null +++ b/src/main/java/pairmatching/model/Result.java @@ -0,0 +1,99 @@ +package pairmatching.model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Result { + + private Map>>>> result; + + private Result() { + Map>>> temp = new HashMap<>(); + for (Level level : Level.values()) { + temp.put(level, new HashMap<>()); + for (Mission mission : Mission.values(level)) { + temp.get(level).put(mission, null); + } + } + this.result = new HashMap<>(); + for (Course course : Course.values()) { + result.put(course, temp); + } + } + + public static Result init() { + return new Result(); + } + + public List> getPairs(InputInformation information) { + return result.get(information.getCourse()) + .get(information.getLevel()) + .get(information.getMission()); + } + + public boolean isExist(InputInformation information) { + return getPairs(information) != null; + } + + public void put(InputInformation information, List> pairs) { + result.get(information.getCourse()) + .get(information.getLevel()) + .put(information.getMission(), pairs); + } + + public void isAlreadyMatched() { + for (Course course : Course.values()) { + for (Level level : Level.values()) { + validateAlreadyMatched(result.get(course).get(level), level); + } + } + } + + private void validateAlreadyMatched(Map>> sameLevelPairs, Level level) { + if (sameLevelPairs.isEmpty()) { + return; + } + + for (Mission x : Mission.values(level)) { + for (Mission y : Mission.values(level)) { + checkSameLevel(sameLevelPairs, x, y); + } + } + } + + private void checkSameLevel(Map>> sameLevelPairs, Mission x, Mission y) { + if (x == y) { + return; + } + + List> pairsX = sameLevelPairs.get(x); + List> pairsY = sameLevelPairs.get(y); + if (pairsX == null || pairsY == null) { + return; + } + + for (int i = 0; i < pairsX.size(); i++) { + for (int j = i + 1; j < pairsY.size(); j++) { + check(pairsX.get(i), pairsY.get(j)); + } + } + } + + private void check(List pairX, List pairY) { + if (pairX.size() != pairY.size()) { + return; + } + + pairX.sort(String::compareTo); + pairY.sort(String::compareTo); + + for (int i = 0; i < pairX.size(); i++) { + if (!pairX.get(i).equals(pairY.get(i))) { + return; + } + } + throw new IllegalArgumentException("중복되는 페어가 있으므로 다시 섞습니다."); + } + +} diff --git a/src/main/java/pairmatching/service/FileReaderService.java b/src/main/java/pairmatching/service/FileReaderService.java new file mode 100644 index 000000000..70bd9bf2c --- /dev/null +++ b/src/main/java/pairmatching/service/FileReaderService.java @@ -0,0 +1,22 @@ +package pairmatching.service; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +public class FileReaderService { + + public static final String BACKEND_CREW_DIR = "src/main/resources/backend-crew.md"; + public static final String FRONTEND_CREW_DIR = "src/main/resources/frontend-crew.md"; + + public static List readFile(String filePath) { + try (BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath))) { + return bufferedReader.lines().collect(Collectors.toList()); + } catch (IOException e) { + throw new IllegalArgumentException("읽을 수 없는 파일 입니다."); + } + } + +} diff --git a/src/main/java/pairmatching/service/InputParser.java b/src/main/java/pairmatching/service/InputParser.java new file mode 100644 index 000000000..c14c13704 --- /dev/null +++ b/src/main/java/pairmatching/service/InputParser.java @@ -0,0 +1,26 @@ +package pairmatching.service; + +import pairmatching.model.InputInformation; + +public class InputParser { + + private InputParser() { + } + + public static InputInformation parseCourseAndLevelAndMission(String input) { + try { + String[] split = input.split(","); + return InputInformation.from(split[0], split[1], split[2]); + } catch (Exception e) { + throw new IllegalArgumentException("잘못된 입력입니다. 다시 입력해주세요."); + } + } + + public static String parseYesOrNo(String input) { + if ("네".equals(input.trim()) || "아니오".equals(input.trim())) { + return input.trim(); + } + 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..e2a49d676 --- /dev/null +++ b/src/main/java/pairmatching/view/InputView.java @@ -0,0 +1,45 @@ +package pairmatching.view; + +import camp.nextstep.edu.missionutils.Console; +import pairmatching.model.Course; +import pairmatching.model.Mission; + +public class InputView { + + public String readFunctionSelect() { + System.out.println("기능을 선택하세요."); + System.out.println("1. 페어 매칭"); + System.out.println("2. 페어 조회"); + System.out.println("3. 페어 초기화"); + System.out.println("Q. 종료"); + return Console.readLine(); + } + + public String readCourseAndLevelAndMission() { + System.out.println(); + printWooWaInformation(); + System.out.println("과정, 레벨, 미션을 선택하세요."); + System.out.println("ex) 백엔드, 레벨1, 자동차경주"); + return Console.readLine(); + } + + public String readRematching() { + System.out.println(); + System.out.println("매칭 정보가 있습니다. 다시 매칭하시겠습니까?"); + System.out.println("네 | 아니오"); + return Console.readLine(); + } + + private void printWooWaInformation() { + System.out.println("#############################################"); + System.out.println("과정: " + Course.BACKEND.getName() + " | " + Course.FRONTEND.getName()); + System.out.println("미션: "); + System.out.println(" - 레벨1: " + Mission.level1()); + System.out.println(" - 레벨2: " + Mission.level2()); + System.out.println(" - 레벨3: " + Mission.level3()); + System.out.println(" - 레벨4: " + Mission.level4()); + System.out.println(" - 레벨5: " + Mission.level5()); + System.out.println("#############################################"); + } + +} diff --git a/src/main/java/pairmatching/view/OutputView.java b/src/main/java/pairmatching/view/OutputView.java new file mode 100644 index 000000000..00e400e0c --- /dev/null +++ b/src/main/java/pairmatching/view/OutputView.java @@ -0,0 +1,36 @@ +package pairmatching.view; + +import java.util.List; +import java.util.StringJoiner; + +public class OutputView { + + public void printErrorMsg(String msg) { + System.out.println("[ERROR] " + msg); + } + + public void printInitMsg() { + System.out.println(); + System.out.println("초기화 되었습니다."); + System.out.println(); + } + + public void printPairMatching(List> pairs) { + System.out.println(); + if (pairs == null) { + System.out.println("페어 매칭 결과가 없습니다."); + return; + } + + System.out.println("페어 매칭 결과입니다."); + for (List pair : pairs) { + StringJoiner stringJoiner = new StringJoiner(" : "); + for (String name : pair) { + stringJoiner.add(name); + } + System.out.println(stringJoiner); + } + System.out.println(); + } + +}