Skip to content

[점심 메뉴 추천] 김승진 미션 제출합니다. #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bf23f41
docs(README): 리드미 기능 목록 추가
ohksj77 Sep 3, 2023
d18a89f
feat: MenuController와 ComponentFactory 추가
ohksj77 Sep 3, 2023
f486801
feat: 출력 클래스 추가
ohksj77 Sep 3, 2023
01847b8
feat: 코치 이름 요청 메시지 출력 기능
ohksj77 Sep 3, 2023
dd98aee
feat(ErrorMessage): 에러 메시지 열거형 추가
ohksj77 Sep 3, 2023
6063cb2
feat(Coach): 도메인 클래스 Coach 추가
ohksj77 Sep 3, 2023
ea2ec2e
feat(CoachList): 일급컬렉션 추가
ohksj77 Sep 3, 2023
52e1848
feat(InputValidator): 입력값 검증 클래스 추가
ohksj77 Sep 3, 2023
b2d261b
feat(InputView): 입력 기능 클래스 추가
ohksj77 Sep 3, 2023
8ef65a3
feat(InputManager): 입력 관리 기능 클래스 추가
ohksj77 Sep 3, 2023
023bb0e
feat: 코치 이름 입력 기능 적용
ohksj77 Sep 3, 2023
776b09c
feat(MenuRepository): 저장소 클래스 추가
ohksj77 Sep 3, 2023
dab6327
feat(MenuService): 서비스 클래스 추가
ohksj77 Sep 3, 2023
03599f7
fix: 저장 함수 도메인 리턴하도록 수정
ohksj77 Sep 3, 2023
7841e18
feat(CoachMenu): 메뉴 도메인 추가
ohksj77 Sep 3, 2023
066f2df
feat(Category): 카테고리 열거형 추가
ohksj77 Sep 3, 2023
0226972
feat(MenuMap): 매뉴 일급 컬렉션 추가
ohksj77 Sep 3, 2023
3f5b590
feat: 일급 컬렉션 구현
ohksj77 Sep 3, 2023
84c3cfd
feat: 코치가 못먹는 음식 입력 요청 메시지 입출력
ohksj77 Sep 3, 2023
8ce087b
feat: 코치 못먹는 음식 입력 기능 연결
ohksj77 Sep 3, 2023
eadd8f2
feat(MenuGenerator): 메뉴 생성 기능
ohksj77 Sep 3, 2023
0258853
feat: 카테고리를 통한 메뉴 조회 기능
ohksj77 Sep 3, 2023
c34202a
feat(MenuGenerator): 메뉴 생성 기능
ohksj77 Sep 4, 2023
60c2276
feat: 도메인 추가
ohksj77 Sep 4, 2023
2d8c0fd
feat: 열거형 추가
ohksj77 Sep 4, 2023
6df9253
feat: 전체 기능 연결
ohksj77 Sep 4, 2023
d2e301b
refactor: 에러 메시지 및 에러 상황 검증 수정
ohksj77 Sep 4, 2023
692c793
test: 단위 테스트
ohksj77 Sep 4, 2023
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
106 changes: 106 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
## 기능 목록
- 기능 목록
- [x] 시작 메시지 출력
- [x] 코치 이름
- [x] 코치 이름 입력 요청 메시지 출력
- [x] 코치 이름 입력
- [x] 콤마로 구분해 입력했는지 검증
- [x] 코치 이름 2글자 ~ 4글자인지 검증
- [x] 코치가 2명 이상인지 검증
- [x] 잘못된 입력시 재입력
- [x] 코치가 못 먹는 메뉴
- [x] 코치 못 먹는 메뉴 입력 요청 메시지 출력
- [x] 코치 못 먹는 메뉴 입력
- [x] 콤마로 구분해 입력했는지 검증
- [x] 개수가 0 ~ 2개 인지 검증
- [x] 잘못된 입력시 재입력
- [x] 메뉴 추천
- [x] 이전에 먹은 음식은 못먹도록 필터링
- [x] 같은 카테고리 2번만 먹을 수 있도록 필터링
- [x] 못 먹는 음식은 추천하지 않도록 필터링
- [x] 랜덤으로 셔플
- [x] 메뉴 추천 메시지 출력
- [x] 추천 완료 메시지 출력

## 구현 클래스 목록
- MenuController
- start()

- ComponentFactory
- menuController()

- OutputView
- printStart()
- printCoachNameRequest()

- CoachList
- getNextCoach()
- getCoachNum()

- InputManager
- readCoach()
- readCoachMenu()

- InputValidator
- validateSplitter()
- validateCoachMenu()

- InputView
- readCoach()
- readCoachMenu()

- MenuService
- recommendMenu()
- saveCoachList()
- addHateMenu()

- MenuRepository
- saveCoachList()
- findCoachList()
- saveCoachMenuMap()
- findCoachMenuMap()

- MenuMap
- getInstance()

- MenuGenerator
- generate()

- AvailMenuList
- getMenuByCategory()

- Coach
- getName()
- addMenus()
- getAvailMenuByCategory()
- noSameRecommendMenu()
- addRecommendMenu()

- CoachList
- getAllCoaches()

- DayCategory
- getCategory()

- DayCategoryList
- isMaxCount()
- addCategory()

- HateMenuList
- getMenus()

- Menu

- MenuMap
- getInstance()
- contains()
- getExceptHateMenus()

- RecommendResult

## 열거형 목록
- ProgressMessage
- ErrorMessage
- Category
- Day
- ResultTag
5 changes: 4 additions & 1 deletion src/main/java/menu/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package menu;

import menu.factory.ComponentFactory;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
final ComponentFactory componentFactory = new ComponentFactory();
componentFactory.menuController().start();
}
}
31 changes: 31 additions & 0 deletions src/main/java/menu/constant/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package menu.constant;

import java.util.Arrays;

public enum Category {
JAPANESE_FOOD(1, "일식"),
KOREAN_FOOD(2, "한식"),
CHINESE_FOOD(3, "중식"),
ASIAN_FOOD(4, "아시안"),
WESTERN_FOOD(5, "양식");

private final int index;
private final String toKorean;

Category(final int index, final String toKorean) {
this.index = index;
this.toKorean = toKorean;
}

public static Category getByIndex(final int index) {
return Arrays.stream(values())
.filter(c -> c.index == index)
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(ErrorMessage.NO_MATCHING_INDEX.toString()));
}

@Override
public String toString() {
return this.toKorean;
}
}
23 changes: 23 additions & 0 deletions src/main/java/menu/constant/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package menu.constant;

public enum ErrorMessage {
INVALID_DELIMITER_USAGE("구분자의 사용이 잘못되었습니다."),
INVALID_COACH_NUM_ERROR("코치 수가 잘못되었습니다."),
INVALID_COACH_NAME_LENGTH("코치의 이름 길이가 잘못되었습니다."),
INVALID_MENU_NAME("잘못된 메뉴명입니다."),
NO_MATCHING_INDEX("인덱스에 해당하는 값이 없습니다."),
CANNOT_FIND_CATEGORY("카테고리를 찾을 수 없습니다."),
INVALID_HATE_MENU_NUM("잘못된 못먹는 음식 개수입니다.");

private static final String PREFIX = "[ERROR] ";
private final String message;

ErrorMessage(final String message) {
this.message = message;
}

@Override
public String toString() {
return PREFIX + this.message;
}
}
21 changes: 21 additions & 0 deletions src/main/java/menu/constant/ProgressMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package menu.constant;

public enum ProgressMessage {
START_MESSAGE("점심 메뉴 추천을 시작합니다."),
COACH_NAME_REQUEST("코치의 이름을 입력해 주세요. (, 로 구분)"),
COACH_MENU_REQUEST("%s(이)가 못 먹는 메뉴를 입력해 주세요."),
RECOMMEND_RESULT("메뉴 추천 결과입니다."),
DAY_CLASSIFIER("[ 구분 | 월요일 | 화요일 | 수요일 | 목요일 | 금요일 ]"),
RECOMMEND_FINISH("\n추천을 완료했습니다.");

private final String message;

ProgressMessage(final String message) {
this.message = message;
}

@Override
public String toString() {
return this.message;
}
}
18 changes: 18 additions & 0 deletions src/main/java/menu/constant/ResultTag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package menu.constant;

public enum ResultTag {
START_TAG("[ "),
DELIMITER(" | "),
END_TAG(" ]");

private final String tag;

ResultTag(final String tag) {
this.tag = tag;
}

@Override
public String toString() {
return this.tag;
}
}
44 changes: 44 additions & 0 deletions src/main/java/menu/controller/MenuController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package menu.controller;

import menu.domain.CoachList;
import menu.domain.RecommendResult;
import menu.io.InputManager;
import menu.io.OutputView;
import menu.service.MenuService;

public class MenuController {
private final OutputView outputView;
private final InputManager inputManager;
private final MenuService menuService;

public MenuController(final OutputView outputView, final InputManager inputManager, final MenuService menuService) {
this.outputView = outputView;
this.inputManager = inputManager;
this.menuService = menuService;
}

public void start() {
outputView.printStart();
final CoachList coachList = createCoachList();
createCoachMenuMap(coachList);
recommendMenu();
}

private void recommendMenu() {
final RecommendResult recommendResult = menuService.recommendMenu();
outputView.printRecommendResult(recommendResult);
}

private void createCoachMenuMap(final CoachList coachList) {
coachList.getAllCoaches().forEach(coach -> {
outputView.printCoachMenuRequest(coach);
menuService.addHateMenus(coach, inputManager.readCoachMenu());
});
}

private CoachList createCoachList() {
outputView.printCoachNameRequest();
final CoachList coachList = inputManager.readCoach();
return menuService.saveCoachList(coachList);
}
}
18 changes: 18 additions & 0 deletions src/main/java/menu/domain/AvailMenuList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package menu.domain;

import menu.constant.Category;

import java.util.List;
import java.util.Map;

public class AvailMenuList {
private final Map<Category, List<Menu>> coachAvailMenu;

public AvailMenuList(final Map<Category, List<Menu>> coachAvailMenu) {
this.coachAvailMenu = coachAvailMenu;
}

public List<Menu> getMenuByCategory(final Category category) {
return this.coachAvailMenu.get(category);
}
}
71 changes: 71 additions & 0 deletions src/main/java/menu/domain/Coach.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package menu.domain;

import menu.constant.Category;
import menu.constant.ErrorMessage;
import menu.constant.ResultTag;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public final class Coach {
private static final int MIN_NAME_LENGTH = 2;
private static final int MAX_NAME_LENGTH = 4;
private final String name;
private final List<Menu> recommendMenuList;
private HateMenuList hateMenuList;
private AvailMenuList availMenuList;

public Coach(final String name) {
validateName(name);
this.name = name;
recommendMenuList = new ArrayList<>();
}

private void validateName(final String name) {
if (invalidLength(name.length())) {
throw new IllegalArgumentException(ErrorMessage.INVALID_COACH_NAME_LENGTH.toString());
}
}

private boolean invalidLength(final int length) {
return length < MIN_NAME_LENGTH || length > MAX_NAME_LENGTH;
}

@Override
public String toString() {
return ResultTag.START_TAG
+ name
+ ResultTag.DELIMITER
+ recommendMenuList.stream().map(Menu::toString).collect(Collectors.joining(ResultTag.DELIMITER.toString()))
+ ResultTag.END_TAG;
}

public String getName() {
return this.name;
}

public void addHateMenus(final HateMenuList hateMenuList) {
this.hateMenuList = hateMenuList;
this.availMenuList = new AvailMenuList(getAvailMenu());
}

private Map<Category, List<Menu>> getAvailMenu() {
return MenuMap.getInstance().getExceptHateMenus(hateMenuList.getMenus());
}

public List<String> getAvailMenuByCategory(final Category category) {
return this.availMenuList.getMenuByCategory(category).stream()
.map(Menu::toString)
.collect(Collectors.toList());
}

public boolean noSameRecommendMenu(final String menu) {
return recommendMenuList.stream().noneMatch(m -> m.toString().equals(menu));
}

public void addRecommendMenu(final Menu menu) {
this.recommendMenuList.add(menu);
}
}
31 changes: 31 additions & 0 deletions src/main/java/menu/domain/CoachList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package menu.domain;

import menu.constant.ErrorMessage;

import java.util.List;
import java.util.stream.Collectors;

public class CoachList {
private static final int MIN_COACH_NUM = 2;
private final List<Coach> coaches;

public CoachList(final List<String> coaches) {
validateSize(coaches);
this.coaches = coaches.stream().map(Coach::new).collect(Collectors.toList());
}

private void validateSize(final List<String> coaches) {
if (coaches.size() < MIN_COACH_NUM) {
throw new IllegalArgumentException(ErrorMessage.INVALID_COACH_NUM_ERROR.toString());
}
}

public List<Coach> getAllCoaches() {
return this.coaches;
}

@Override
public String toString() {
return coaches.stream().map(Coach::toString).collect(Collectors.joining("\n"));
}
}
Loading