Skip to content
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

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

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2d95a43
docs: 기능 목록 작성
homebdy Sep 10, 2023
433f4ef
feat(OutputView): 추천 시작 안내 메시지 출력 기능 구현
homebdy Sep 10, 2023
053ca07
feat(InputView): 코치의 이름 입력 기능 구현
homebdy Sep 10, 2023
fd1af1b
feat(InputValidator): `,`로 나누지 않은 경우 예외 발생
homebdy Sep 10, 2023
943a93d
feat(Name): 각 이름은 2~4글자가 아닐 경우 예외 발생
homebdy Sep 10, 2023
9de3574
feat(Names): 코치 수가 2명~5명이 아닐 경우 예외 발생
homebdy Sep 10, 2023
52d611a
feat(Coaches): 입력한 이름으로 코치 생성
homebdy Sep 10, 2023
f5d4021
feat(InputView): 각 코치마다 못 먹는 음식 입력
homebdy Sep 10, 2023
0de4f81
feat(ExcludedMenu): 못 먹는 음식 등록
homebdy Sep 10, 2023
8b6f5ca
feat(MenuController): 메서드 분리
homebdy Sep 10, 2023
9d5dcfc
feat(Days): 메뉴 추천 요일 관리
homebdy Sep 10, 2023
6481fb4
feat(Categories): 요일별 카테고리 추천 기능 구현
homebdy Sep 10, 2023
3c816eb
feat(Categories): 이미 2번 추천된 카테고리일 경우 재추천
homebdy Sep 10, 2023
49eb086
feat(Names): 예외 발생 메시지 추가
homebdy Sep 10, 2023
1812ba3
feat(Menu): 등록된 카테고리별 메뉴 관리
homebdy Sep 10, 2023
efbfa2b
feat(Menu): 카테고리의 전체 메뉴 가져오기
homebdy Sep 10, 2023
465dd49
feat(RecommendMenu): 메뉴 추천 기능 구현
homebdy Sep 10, 2023
9e4fba2
feat(MenuService): 카테고리별 코치 메뉴 추천 기능 구현
homebdy Sep 10, 2023
284dc55
feat(RecommendMenu): 이미 한 번 먹은 음식일 경우 재추천
homebdy Sep 10, 2023
3cd0b3e
fix(ExcludedMenu): 저장 위치 변경
homebdy Sep 10, 2023
148b32c
feat(RecommendMenu): 코치가 못먹는 음식일 경우 재추천
homebdy Sep 10, 2023
5acef53
feat(OutputView): 결과 안내 메시지 출력
homebdy Sep 10, 2023
a03c0ee
feat(OutputView): 추천 요일 출력
homebdy Sep 10, 2023
d1923b9
feat(OutputView): 추천 카테고리 출력
homebdy Sep 10, 2023
1238c62
feat(OutputView): 추천 결과 출력
homebdy Sep 10, 2023
a53173a
feat(OutputView): 추천 완료 안내
homebdy Sep 10, 2023
e1a07ba
docs: 구현 완료 기능 체크
homebdy Sep 10, 2023
f95d828
feat(ExcludedMenu): 못먹는 음식 2개 이상 입력 시 예외 발생
homebdy Sep 10, 2023
89a204d
test(Name): 이름 생성 테스트
homebdy Sep 10, 2023
d61cd32
test(Names): 이름 예외 테스트
homebdy Sep 10, 2023
3b8141d
feat: 예외 발생 지점부터 다시 입력 기능 구현
homebdy Sep 10, 2023
3702089
fix(ExcludedMenu): 못먹는 음식 추가 방식 변경
homebdy Sep 10, 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
23 changes: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## 기능 목록

- [x] 추천 시작 안내 메시지 출력

- [x] 코치의 이름 입력
- [x] `,`로 나누지 않은 경우 예외 발생
- [x] 각 이름은 2~4글자가 아닐 경우 예외 발생
- [x] 코치 수가 2명~5명이 아닐 경우 예외 발생

- [x] 각 코치마다 못 먹는 음식 입력
- [x] 0~2개가 아닐 경우 예외

- [x] 카테고리 추천
- [x] 월~금까지 먹을 카테고리를 추천한다.
- [x] 이미 2번 추천된 카테고리일 경우 재추천

- [x] 코치 별 음식 추천
- [x] 요일마다 코치가 먹을 음식을 추천한다.
- [x] 이미 한 번 먹은 음식일 경우 재추천
- [x] 코치가 못먹는 음식일 경우 재추천

- [x] 추천 결과 출력
- [x] 추천 완료 안내
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.controller.MenuController;

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

public enum Days {

MONDAY("월요일"),
TUESDAY("화요일"),
WEDNESDAY("수요일"),
THURSDAY("목요일"),
FRIDAY("금요일");

private final String day;

Days(String day) {
this.day = day;
}

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

public enum ExceptionMessage {

INCORRECT_DELIMITER("','로 구분하여 입력해야합니다."),
INCORRECT_NAME_RANGE("코치의 이름은 2~4자까지 입력할 수 있습니다."),
INCORRECT_COACH_NUMBER("코치는 2명 이상, 5명 이하만 입력할 수 있습니다."),
INCORRECT_RECOMMEND("등록되지 않은 카테고리입니다."),
EXCLUDED_FOOD_SIZE("못먹는 음식은 0~2개까지 입력가능합니다.");

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

ExceptionMessage(String message) {
this.message = message;
}

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

public enum OutputMessage {

START_RECOMMEND("점심 메뉴 추천을 시작합니다."),
READ_NAMES("코치의 이름을 입력해 주세요. (, 로 구분)"),
READ_EXCLUDED_MENU("%s(이)가 못 먹는 메뉴를 입력해 주세요."),
RECOMMEND_RESULT("메뉴 추천 결과입니다."),
COMPLETE_RECOMMEND("추천을 완료했습니다."),
DAYS("구분"),
CATEGORIES("카테고리");

private final String message;

OutputMessage(String message) {
this.message = message;
}

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

public enum ResultElement {

START("[ "),
END(" ]"),
DELIMITER(" | "),
NEW_LINE("\n");


private final String element;

ResultElement(String element) {
this.element = element;
}

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

import menu.domain.Coaches;
import menu.service.MenuService;
import menu.view.InputView;
import menu.view.OutputView;

public class MenuController {

private final OutputView outputView = new OutputView();
private final InputView inputView = new InputView();

public void start() {
outputView.printStart();
MenuService menuService = new MenuService(readCoaches());
menuService.recommend();
outputView.printRecommendResult(menuService.getCategories(), menuService.getCoaches());
}

private Coaches readCoaches() {
Coaches coaches = readNames();
readExcludedFood(coaches);
return coaches;
}

private Coaches readNames() {
outputView.printCoachNames();
return inputView.readNames();
}

private void readExcludedFood(Coaches coaches) {
coaches.getCoaches()
.forEach(coach -> {
outputView.printExcludedMenu(coach.getName());
coach.addExcludedMenu(inputView.readExcludedMenu());
});
}
}
60 changes: 60 additions & 0 deletions src/main/java/menu/domain/Categories.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package menu.domain;

import camp.nextstep.edu.missionutils.Randoms;
import menu.constant.OutputMessage;
import menu.constant.ResultElement;

import java.util.*;

public class Categories {

private static final int RECOMMEND_COUNT = 5;
private static final int MAX_RECOMMEND_COUNT = 2;
private static final int START_RANDOM_NUMBER = 1;
private static final int END_RANDOM_NUMBER = 5;

private final List<Category> elements;

public Categories() {
this.elements = recommendCategory();
}

private List<Category> recommendCategory() {
List<Category> categories = new ArrayList<>();
while (categories.size() < RECOMMEND_COUNT) {
Category category = randomRecommend();
if (isDuplicateRecommend(categories, category)) {
continue;
}
categories.add(category);
}
return categories;
}

private Category randomRecommend() {
int random = Randoms.pickNumberInRange(START_RANDOM_NUMBER, END_RANDOM_NUMBER);
return Category.getRecommendFood(random);
}

private boolean isDuplicateRecommend(List<Category> categories, Category recommendCategory) {
return categories.stream()
.filter(category -> category == recommendCategory)
.count() >= MAX_RECOMMEND_COUNT;
}

public List<Category> getElements() {
return Collections.unmodifiableList(elements);
}

public String getCategories() {
String delimiter = ResultElement.DELIMITER.toString();
String start = ResultElement.START.toString();
String end = ResultElement.END.toString();

StringJoiner stringJoiner = new StringJoiner(delimiter, start, end);

stringJoiner.add(OutputMessage.CATEGORIES.getMessage());
elements.forEach(element -> stringJoiner.add(element.toString()));
return stringJoiner.toString();
}
}
34 changes: 34 additions & 0 deletions src/main/java/menu/domain/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package menu.domain;

import menu.constant.ExceptionMessage;

import java.util.Arrays;

public enum Category {

JAPANESE(1, "일식"),
KOREAN(2, "한식"),
CHINESE(3, "중식"),
ASIAN(4, "아시안"),
WESTERN(5, "양식");

private final int index;
private final String type;

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

public static Category getRecommendFood(int randomNumber) {
return Arrays.stream(Category.values())
.filter(category -> category.index == randomNumber)
.findAny()
.orElseThrow(() -> new IllegalArgumentException(ExceptionMessage.INCORRECT_RECOMMEND.toString()));
}

@Override
public String toString() {
return type;
}
}
40 changes: 40 additions & 0 deletions src/main/java/menu/domain/Coach.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package menu.domain;

import menu.constant.ResultElement;

import java.util.StringJoiner;

public class Coach {

private final Name name;

private final RecommendMenu recommendMenu = new RecommendMenu();

public Coach(Name name) {
this.name = name;
}

public void recommendMenu(Category category) {
recommendMenu.recommend(category);
}

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

public String getRecommendMenu() {
String delimiter = ResultElement.DELIMITER.toString();
String start = ResultElement.START.toString();
String end = ResultElement.END.toString();

StringJoiner stringJoiner = new StringJoiner(delimiter, start, end);

stringJoiner.add(name.getValue());
stringJoiner.add(recommendMenu.getMenus());
return stringJoiner.toString();
}

public void addExcludedMenu(ExcludedMenu excludedMenu) {
recommendMenu.addExcludedMenu(excludedMenu);
}
}
35 changes: 35 additions & 0 deletions src/main/java/menu/domain/Coaches.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package menu.domain;

import menu.constant.ResultElement;

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

public class Coaches {

private final List<Coach> coaches;

public Coaches(Names names) {
this.coaches = names.getElements()
.stream()
.map(Coach::new)
.collect(Collectors.toList());
}

public void recommendByCategory(Category category) {
coaches.forEach(coach -> coach.recommendMenu(category));
}

public List<Coach> getCoaches() {
return Collections.unmodifiableList(coaches);
}

public String getRecommend() {
StringBuilder stringBuilder = new StringBuilder();
coaches.forEach(coach ->
stringBuilder.append(coach.getRecommendMenu())
.append(ResultElement.NEW_LINE));
return stringBuilder.toString();
}
}
28 changes: 28 additions & 0 deletions src/main/java/menu/domain/ExcludedMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package menu.domain;

import menu.constant.ExceptionMessage;

import java.util.ArrayList;
import java.util.List;

public class ExcludedMenu {

private static final int MAX_SIZE = 2;

private final List<String> elements;

public ExcludedMenu(List<String> elements) {
validateSize(elements);
this.elements = new ArrayList<>(elements);
}

private void validateSize(List<String> menus) {
if (!(menus.size() <= MAX_SIZE)) {
throw new IllegalArgumentException(ExceptionMessage.EXCLUDED_FOOD_SIZE.toString());
}
}

public boolean canEat(String menu) {
return !(elements.contains(menu));
}
}
Loading