Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# 기능 구현 목록
- [X] : 페어 이름을 초기화 받는다.
- [X] : 기능 선택 목록을 출력한다.
- [X] : 기능을 선택 받는다.
- [X] `예외 처리` : 빈 값을 입력한 경우
- [X] `예외 처리` : 1~3, Q 이외의 값을 입력한 경우.

## 페어 매칭 기능
- [X] : 페어 매칭 안내 문자열을 출력한다.
```
#############################################
과정: 백엔드 | 프론트엔드
미션:
- 레벨1: 자동차경주 | 로또 | 숫자야구게임
- 레벨2: 장바구니 | 결제 | 지하철노선도
- 레벨3:
- 레벨4: 성능개선 | 배포
- 레벨5:
############################################
과정, 레벨, 미션을 선택하세요.
ex) 백엔드, 레벨1, 자동차경주
```
- [X] : 과정, 레벨, 미션을 `, `기준으로 구분되어 입력 받는다. (ex `백엔드, 레벨1, 자동차경주`)
- [X] `예외 처리` : 빈 값을 입력한 경우
- [X] `예외 처리` : 구분자를 잘못 입력한 경우
- [X] `예외 처리` : 일치하는 값이 없는 경우

- [X] 페어를 매칭한다.
- [X] : 두명씩 매칭한다.
- [X] : 매칭 대상이 홀수인 경우 한 페어는 3인으로 구성된다.
- [X] : 같은 레벨에서 이미 페어를 맺은 크루와는 다시 매칭되지 않는다.

- [X] : 크루들 이름 목록을 List<String> 형태로 준비한다.
- [X] : 크루 목록의 순서를 랜덤으로 섞는다. (shuffle 메서드를 활용해야 한다.)
- [X] : 홀수인 경우 마지막 남은 크루는 마지막 페어에 포함시킨다.

- [X] : 같은 레벨에서 이미 페어로 만난적이 있는 크루끼리 다시 페어로 매칭 된다면 크루 목록의 순서를 다시 랜덤으로 섞어서 매칭을 시도한다.
- [X] : 안내 문구를 출력 후 사용자에게 네, 아니오를 입력받는다.
- [X] `예외 처리` : 빈 값을 입력한 경우
- [X] `예외 처리` : 네, 아니오가 아닌 값을 입력 받은 경우
```text
매칭 정보가 있습니다. 다시 매칭하시겠습니까?
네 | 아니오
```
- [X] : 아니오를 선택할 경우 코스, 레벨, 미션을 다시 선택한다.
- [X] : 3회 시도까지 매칭이 되지 않거나 매칭을 할 수 있는 경우의 수가 없으면 에러 메시지를 출력한다.

- [X] : 매칭 결과를 출력한다.
```text
페어 매칭 결과입니다.
용팔 : 대만
대협 : 덕규
치수 : 준호
태웅 : 백호
달재 : 태산
한나 : 수겸
태섭 : 대남
준섭 : 소연
현준 : 호열
구식 : 경태
```

## 페어 조회 기능
- [X] : 과정, 레벨, 미션을 선택하면 해당 미션의 페어 정보를 출력한다.
- [X] : 매칭 이력이 없으면 매칭 이력이 없다고 안내한다. ( `[ERROR] 매칭 이력이 없습니다.` )


## 페어 초기화 기능
- [X] : 페어를 초기화한다.

4 changes: 3 additions & 1 deletion src/main/java/pairmatching/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package pairmatching;

import pairmatching.domain.PairMatchingController;

public class Application {
public static void main(String[] args) {
// TODO 구현 진행
PairMatchingController.run();
}
}
25 changes: 25 additions & 0 deletions src/main/java/pairmatching/Utils.java
Original file line number Diff line number Diff line change
@@ -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<String> list1, List<String> list2) {
Map<String, Integer> 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;
}
}
42 changes: 42 additions & 0 deletions src/main/java/pairmatching/domain/CrewRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
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 final List<String> backend = new ArrayList<>();
private final List<String> 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<String> 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<String> findByCourse(Course course) {
if (course == Course.FRONTEND) {
return new ArrayList<>(frontend);
}
if (course == Course.BACKEND) {
return new ArrayList<>(backend);
}
return null;
}
}
111 changes: 111 additions & 0 deletions src/main/java/pairmatching/domain/PairMatchingController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package pairmatching.domain;

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;

public class PairMatchingController {

public static void run() {
PairMatchingService.initCrews();
proceed();
}

private static void proceed() {
while (true) {
String validateMenu = getValidateMenu();
if (validateMenu.equals(ProgramOption.QUIT)) {
break;
}
handleByMenu(validateMenu);
}
}

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)) {
handlePairSearch();
return;
}
if (validateMenu.equals(ProgramOption.PAIR_RESET)) {
handlePairReset();
return;
}
throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT);
}

private static void handlePairMatching() {
try {
PairOption pairOption = InputView.readOption();
pairMatching(pairOption);
} catch (IllegalArgumentException error) {
OutputView.printException(error);
handlePairMatching();
}
}

private static void pairMatching(PairOption pairOption) {
if (PairMatchingService.hasHistory(pairOption)) {
handleRematch(pairOption);
return;
}
Pairs matchingResult = PairMatchingService.createNewPairMatching(pairOption);
PairMatchingService.addPairsToHistory(pairOption, matchingResult);
OutputView.printMatchingResult(matchingResult);
}

private static void handleRematch(PairOption pairOption) {
if (getValidateRematch().equals(ProgramOption.YES)) {
// 3번 리매칭
List<Pairs> history = PairMatchingService.getHistory(pairOption.getCourse(), pairOption.getLevel());
Pairs matchingResult = PairMatchingService.createNoDuplicatePairMatching(pairOption, history);
OutputView.printMatchingResult(matchingResult);
return;
}
// 아니오를 선택한 경우 다시 코스, 레벨, 미션을 선택한다.
handlePairMatching();
}

private static String getValidateRematch() {
try {
return PairMatchingService.getValidateRematch(InputView.readRematch());
} catch (IllegalArgumentException error) {
OutputView.printException(error);
return getValidateRematch();
}
}

private static void handlePairSearch() {
try {
PairOption pairOption = InputView.readOption();
if (!PairMatchingService.hasHistory(pairOption)) {
throw new IllegalArgumentException(ExceptionMessage.NO_MATCHING_HISTORY);
}
Pairs matchedPairs = PairMatchingService.findHistory(pairOption);
OutputView.printMatchingResult(matchedPairs);
} catch (IllegalArgumentException error) {
OutputView.printException(error);
handlePairSearch();
}
}

private static void handlePairReset() {
PairMatchingService.reset();
}
}
118 changes: 118 additions & 0 deletions src/main/java/pairmatching/domain/PairMatchingService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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;
import pairmatching.message.ExceptionMessage;
import pairmatching.message.ProgramOption;

public class PairMatchingService {
private static CrewRepository crewRepository = new CrewRepository();
private static Map<PairOption, Pairs> history = new HashMap<>();

public static void initCrews() {
crewRepository = new CrewRepository();
history = new HashMap<>();
crewRepository.initBackend(ProgramOption.BACKEND_FILE_PATH);
crewRepository.initFrontend(ProgramOption.FRONTEND_FILE_PATH);
}

public static String getValidateMenu(String input) {
validateMenu(input);
return input;
}

private static void validateMenu(String input) {
if (input.length() != 1) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT);
}
if (!ProgramOption.MENU_INPUT_OPTIONS.contains(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 createNoDuplicatePairMatching(PairOption option, List<Pairs> 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<String> shuffleCrew = getShuffleCrew(option.getCourse());
return Pairs.createByNameList(shuffleCrew);
}

public static void addPairsToHistory(PairOption option, Pairs pairs) {
history.put(option, pairs);
}

private static List<String> getShuffleCrew(Course course) {
List<String> crewNames = crewRepository.findByCourse(course);
if (crewNames == null) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_MENU_INPUT);
}
return Randoms.shuffle(crewNames);
}

public static boolean hasHistory(PairOption option) {
return history.containsKey(option);
}

public static List<Pairs> getHistory(Course course, Level level) {
List<Pairs> result = new ArrayList<>();
Mission.findByLevel(level).forEach(mission -> {
PairOption option = new PairOption(course, level, mission);
if (hasHistory(option)) {
result.add(history.get(option));
}
});
return result;
}

public static String getValidateRematch(String input) {
validateRematch(input);
return input;
}

private static void validateRematch(String input) {
if (!input.equals(ProgramOption.YES) && !input.equals(ProgramOption.NO)) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_REMATCH_INPUT);
}
}

public static boolean hasSamePair(List<Pairs> history, Pairs rematch) {
for (Pairs pairs : history) {
if (pairs.hasSamePair(rematch)) {
return true;
}
}
return false;
}

public static Pairs findHistory(PairOption option) {
return history.get(option);
}

public static void reset() {
history = new HashMap<>();
}
}
Loading