diff --git a/README.md b/README.md index 5c31c2f3d..9075649cb 100644 --- a/README.md +++ b/README.md @@ -208,3 +208,171 @@ String menu = Randoms.shuffle(menus).get(0); - 과제 진행 및 제출 방법은 [프리코스 과제 제출](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 문서를 참고한다. - 소감은 간소하게 입력해도 된다. 예를 들어, "."만 입력해도 좋다. + + +# 주의 사항 리마인더 + +- 월, 화, 수, 목 ,금 +- 요일 별 추천 카테고리 지정 +- → 코치가 해당 요일에 먹을 메뉴 추천 +- 코치 이름 입력 값 + - 최소 2글자 최대 4글자 +- 코치는 2~5명 동시 식사 +- 랜덤 생성기에서 + - 1 → 일식 + - 2 → 한식 + - 3 → 중식 + - 4 → 아시안 + - 5 → 양식 + +메뉴 + +- 한 주에 같은 카테고리는 최대 2회 +- 한 주 동안 중복되지 않은 메뉴를 추천 +- 못먹는 음식이면 추천 불가 + + → 다시 난수 생성해서 카테고리 생성 + + +예상 되는 기능 목록 + +- 코치 이름 입력 받기 +- 못 먹는 메뉴 입력 받기 +- 카테고리 추천하기 +- 메뉴 추천하기 +- 메뉴 출력하기 + +# 서비스 흐름 + +1. 코치 이름 입력 받기 + 1. List로 갖고 있기 +2. 못 먹는 메뉴 입력 받기 + 1. List로 갖고 있기 +3. 카테고리 추천 돌리기 +4. 카테고리에 따라서 메뉴 추천 돌리기 + 1. List로 반환하기 +5. 이름, 메뉴, 리스트로 객체 생성하기 +6. 출력하기 + +# 기능 목록 + +### 코치 이름 입력 + +입력 + +- 이름 입력 받기 + 1. 형식 에러 + 1. 최소 2글자 최대 4글자 + 2. 최소 2명 이상 + +로직 + +출력 + +- 없음 + +반환 + +- 데이터 자료형 : String + +### 못 먹는 메뉴 입력 + +입력 + +- 메뉴 입력 받기 + 1. 형식 에러 + +로직 + +- 코치에 해당 메뉴 저장하기 + +출력 + +- 없음 + +반환 + +- List + +### 카테고리 추천 + +입력 + +- 없음 + +로직 + +- 랜덤 함수를 통해서 카테고리 생성 +- 월,화,수,목,금 → 5개 생성 + - 같은 값이 2개 이상이면 에러 + - + +출력 + +- 없음 + +반환 + +- 데이터 자료형 : List + +### 메뉴 추천 + +1. 코치별로 카테고리 순서에 맞게 메뉴 추천(선택) +2. 카테고리별로 메뉴 추천후 코치별 배정 + +입력 + +- + +로직 + +- 카테고리 에 따른 메뉴 목록 전달 받기 +- 랜덤 함수로 메뉴 가져오기 + - 해당 메뉴가 금지 메뉴이면 다시 생성 +- 코치별 메뉴 리스트 저장 + +출력 + +- 없음 + +반환 + +- 코치별 메뉴 리스트 반환 +- 데이터 자료형 : List + +### 결과 출력 + +입력 + +- + +로직 + +- 객체에서 이름, 메뉴 받아오기 + +출력 + +- 이름 +- 메뉴 출력 + +반환 + +- 없음 + +# 데이터 + +### 코치 + +- 코치 이름 +- 못 먹는 메뉴 + - List +- 추천 받은 메뉴 + - List + +### 메뉴 + +enum + +### 카테고리 + +enum \ No newline at end of file diff --git a/src/main/java/menu/Application.java b/src/main/java/menu/Application.java index 6340b6f33..8aeb7dfcb 100644 --- a/src/main/java/menu/Application.java +++ b/src/main/java/menu/Application.java @@ -1,7 +1,120 @@ -package menu; - -public class Application { - public static void main(String[] args) { - // TODO: 프로그램 구현 - } -} +//package menu; +// +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.List; +//import javax.swing.SwingUtilities; +//import menu.domain.Coach; +//import menu.domain.Menu; +//import menu.domain.RandomCategoryNumberGenerator; +//import menu.domain.RandomNumberGenerator; +//import menu.service.CategoryRecommendService; +//import menu.service.MenuRecommendService; +//import menu.view.InputView; +//import menu.view.OutputView; +// +//public class Application { +// public static void main(String[] args) { +// // TODO: 프로그램 구현 +// RandomNumberGenerator RandomCategoryNumberGenerator = new RandomCategoryNumberGenerator(); +// CategoryRecommendService categoryRecommendService = new CategoryRecommendService(RandomCategoryNumberGenerator); +// MenuRecommendService menuRecommendService = new MenuRecommendService(); +// InputView inputView = new InputView(); +// OutputView outputView = new OutputView(); +// +// +// // 코치 이름 입력 +// outputView.printStartMessage(); +// String[] coachNames = inputView.readCoachNames(); +// +// // 카테고리 추천 돌리기 +// int[] categories = categoryRecommendService.recommendCategory(); +// +// List categoryNames = categoryRecommendService.recommendCategoryList(); +// +// +// // 디버그 코드 +//// System.out.println("카테고리 넘버 확인용"); +//// for(int i = 0 ; i < categories.length; i++){ +//// System.out.println( categories[i] ); +//// } +//// System.out.println("카테고리 넘버 확인 끝"); +// +// // 디버그 코드 +// System.out.println("카테고리 "); +// for(String categoryName : categoryNames) { +// System.out.println(categoryName); +// } +// +// +// +// // 코치 정보 리스트 +// List coachList = new ArrayList<>(); +// +// // 코치 수 만큼 반복 +// // 순서대로 계속 뽑음 그러니까 한마디로 +// // 한 코치당 한번 끝나는게 아니었음 +// +// for (String coachName : coachNames) { +// System.out.println("코치이름 : " + coachName); +// // 못 먹는 메뉴 입력 받기 +// String[] rejectedMenu = inputView.readRejectedMenu(coachName); +// +// // 디버그 코드 +// // 못 먹는 메뉴 출력 +// System.out.println("못 먹는 메뉴 출력"); +// for (String rejectedMenuName : rejectedMenu) { +// System.out.println(rejectedMenuName); +// } +// System.out.println("출력 완료"); +// +// // 메뉴 추천 정보를 저장하기 위한 새로운 리스트 +// List recommendedMenuList = new ArrayList<>(); +// // +// // 월,화,수,목,금 총 5회 메뉴 추천 +// for (int categoryNum : categories) { +// +// // 카테고리에 해당하는 메뉴 리스트 조회 +// List menus = Arrays.stream(Menu.values()) +// .filter(val -> val.getId() == categoryNum) +// .findFirst() +// .orElse(null) +// .getMenu(); +// +// // 메뉴 중에서 랜덤 메뉴 추천 +// String recommendedMenu = menuRecommendService.recommendMenu(menus); +// System.out.println(categoryNum + " 카테고리 음식 추천 " + recommendedMenu); +// // 메뉴에 저장 +// recommendedMenuList.add(recommendedMenu); +// } +// +// // 정보를 통해 코치 객체 생성 +// Coach coach = new Coach(coachName, recommendedMenuList); +// +// // 리스트에 저장 +// coachList.add(coach); +// } +// +// +// List categoryList = new ArrayList<>(); +// for(int categoryNum : categories) { +// String category = Arrays.stream(Menu.values()) +// .filter(val -> val.getId() == categoryNum) +// .findFirst() +// .orElse(null) +// .getCategory(); +// categoryList.add(category); +// } +// +// // 결과 출력 부 +// outputView.printResult(); +// outputView.printCategory(categoryList); +// for(Coach coach : coachList) { +// String name = coach.getName(); +// List menu = coach.getRecommendedMenu(); +// outputView.printMenu(name, menu); +// } +// System.out.println(); +// outputView.printEndMessage(); +// } +//} diff --git a/src/main/java/menu/Application2.java b/src/main/java/menu/Application2.java new file mode 100644 index 000000000..3d9a3ba84 --- /dev/null +++ b/src/main/java/menu/Application2.java @@ -0,0 +1,78 @@ +package menu; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import menu.domain.Coach; +import menu.domain.Menu; +import menu.domain.RandomCategoryNumberGenerator; +import menu.domain.RandomNumberGenerator; +import menu.service.CategoryRecommendService; +import menu.service.MenuRecommendService; +import menu.util.InputHandler; +import menu.view.InputView; +import menu.view.OutputView; +import org.mockito.exceptions.misusing.CannotVerifyStubOnlyMock; + +public class Application2 { + public static void main(String[] args) { + // TODO: 프로그램 구현 + RandomNumberGenerator RandomCategoryNumberGenerator = new RandomCategoryNumberGenerator(); + CategoryRecommendService categoryRecommendService = new CategoryRecommendService(RandomCategoryNumberGenerator); + OutputView outputView = new OutputView(); + + // 코치 이름 입력 + outputView.printStartMessage(); + List coachNames = InputHandler.retry(InputView::readCoachNames); + + // 카테고리 추천 돌리기 + List categoryNames = categoryRecommendService.recommendCategoryList(); + + // 코치 정보 리스트 + List coachList = new ArrayList<>(); + for(String coachName : coachNames) { + List rejectedMenu = InputView.readRejectedMenu(coachName); + Coach coach = new Coach(coachName, rejectedMenu); + coachList.add(coach); + } + + // 요일(카테고리) 별로 반복 + for(String categoryName : categoryNames) { + + // 코치 별로 추천하기 + for(Coach coach : coachList) { + + // 카테고리 메뉴 조회 + List menus = Arrays.stream(Menu.values()) + .filter(val -> val.getCategory().equals(categoryName)) + .findFirst() + .orElse(null) + .getMenu(); + + while(true){ + String recommendMenu = Randoms.shuffle(menus).get(0); + //이미 추천 한 경우 + if(coach.getRejectedMenu().contains(recommendMenu) + || coach.getRecommendedMenu().contains(recommendMenu)){ + continue; + } + coach.addRecommendedMenu(recommendMenu); + break; + } + } + } + + + // 결과 출력 부 + outputView.printResult(); + outputView.printCategory(categoryNames); + for(Coach coach : coachList) { + String name = coach.getName(); + List menu = coach.getRecommendedMenu(); + outputView.printMenu(name, menu); + } + System.out.println(); + outputView.printEndMessage(); + } +} diff --git a/src/main/java/menu/constant/ErrorMessage.java b/src/main/java/menu/constant/ErrorMessage.java new file mode 100644 index 000000000..850132248 --- /dev/null +++ b/src/main/java/menu/constant/ErrorMessage.java @@ -0,0 +1,20 @@ +package menu.constant; + +public enum ErrorMessage { + COACH_NAME_ERROR("코치 이름은 한글, 최소 2글자, 최대 4글자 입니다."), + COACH_COUNT_ERROR("코치는 최소 2명 이상 입력해야 합니다."), + MENU_NOT_EXIST("목록에 존재하지 않는 메뉴입니다.") + ; + + private String message; + + private static String prefix = "[ERROR]"; + + private ErrorMessage(String message) { + this.message = message; + } + + public String getMessage() { + return prefix + message; + } +} diff --git a/src/main/java/menu/domain/Coach.java b/src/main/java/menu/domain/Coach.java new file mode 100644 index 000000000..752b4a8f3 --- /dev/null +++ b/src/main/java/menu/domain/Coach.java @@ -0,0 +1,31 @@ +package menu.domain; + +import java.util.ArrayList; +import java.util.List; + +public class Coach { + private String name; + private List rejectedMenu; + private List recommendedMenu = new ArrayList(); + + public Coach(String name, List rejectedMenu) { + this.rejectedMenu = rejectedMenu; + this.name = name; + } + + public String getName() { + return name; + } + + public List getRejectedMenu() { + return rejectedMenu; + } + + public List getRecommendedMenu() { + return recommendedMenu; + } + + public void addRecommendedMenu(String recommendedMenu) { + this.recommendedMenu.add(recommendedMenu); + } +} diff --git a/src/main/java/menu/domain/Menu.java b/src/main/java/menu/domain/Menu.java new file mode 100644 index 000000000..36557b433 --- /dev/null +++ b/src/main/java/menu/domain/Menu.java @@ -0,0 +1,32 @@ +package menu.domain; + +import java.util.List; + +public enum Menu{ + + JAPANESE(1,"일식",List.of("규동", "우동", "미소시루", "스시", "가츠동", "오니기리", "하이라이스", "라멘", "오코노미야끼")), + KOREAN(2,"한식",List.of("김밥", "김치찌개", "쌈밥", "된장찌개", "비빔밥", "칼국수", "불고기", "떡볶이", "제육볶음")), + CHINESE(3,"중식",List.of("깐풍기", "볶음면", "동파육", "짜장면", "짬뽕", "마파두부", "탕수육", "토마토 달걀볶음", "고추잡채")), + ASIAN(4,"아시안",List.of("팟타이", "카오 팟", "나시고렝", "파인애플 볶음밥", "쌀국수", "똠얌꿍", "반미", "월남쌈", "분짜")), + ITALIAN(5,"양식",List.of("라자냐", "그라탱", "뇨끼", "끼슈", "프렌치 토스트", "바게트", "스파게티", "피자", "파니니")); + + private int id; + private String category; + private List menu; + + private Menu(int id,String category, List menu){ + this.id = id; + this.category = category; + this.menu = menu; + } + public int getId(){ + return id; + } + public String getCategory(){ + return category; + } + + public List getMenu(){ + return menu; + } +} \ No newline at end of file diff --git a/src/main/java/menu/domain/RandomCategoryNumberGenerator.java b/src/main/java/menu/domain/RandomCategoryNumberGenerator.java new file mode 100644 index 000000000..d02395552 --- /dev/null +++ b/src/main/java/menu/domain/RandomCategoryNumberGenerator.java @@ -0,0 +1,20 @@ +package menu.domain; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; + +public class RandomCategoryNumberGenerator implements RandomNumberGenerator{ + private final static int RANDOM_LOWER_INCLUSIVE = 1; + private final static int RANDOM_UPPER_INCLUSIVE = 5; + + + @Override + public int generate() { + return Randoms.pickNumberInRange(RANDOM_LOWER_INCLUSIVE, RANDOM_UPPER_INCLUSIVE); + } + +// @Override +// public String generateString(List menu){ +// return ""; +// } +} diff --git a/src/main/java/menu/domain/RandomMenuGenerator.java b/src/main/java/menu/domain/RandomMenuGenerator.java new file mode 100644 index 000000000..3b65b962f --- /dev/null +++ b/src/main/java/menu/domain/RandomMenuGenerator.java @@ -0,0 +1,18 @@ +package menu.domain; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; + +public class RandomMenuGenerator implements RandomNumberGenerator{ + + @Override + public int generate() { + return 0; + } + +// @Override +// public String generateString(List menus){ +// String menu = Randoms.shuffle(menus).get(0); +// return menu; +// }; +} diff --git a/src/main/java/menu/domain/RandomNumberGenerator.java b/src/main/java/menu/domain/RandomNumberGenerator.java new file mode 100644 index 000000000..4139565ac --- /dev/null +++ b/src/main/java/menu/domain/RandomNumberGenerator.java @@ -0,0 +1,8 @@ +package menu.domain; + +import java.util.List; + +public interface RandomNumberGenerator { + int generate(); +// String generateString(List menu); +} diff --git a/src/main/java/menu/service/CategoryRecommendService.java b/src/main/java/menu/service/CategoryRecommendService.java new file mode 100644 index 000000000..d1cfcdff8 --- /dev/null +++ b/src/main/java/menu/service/CategoryRecommendService.java @@ -0,0 +1,50 @@ +package menu.service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import menu.domain.Menu; +import menu.domain.RandomNumberGenerator; + +public class CategoryRecommendService { + private final RandomNumberGenerator randomNumberGenerator; + + public CategoryRecommendService(RandomNumberGenerator randomNumberGenerator) { + this.randomNumberGenerator = randomNumberGenerator; + } + + public List recommendCategoryList() { + List categoryList = new ArrayList<>(); + int[] status = new int[6]; + + while(categoryList.size() < 5) { + int random = randomNumberGenerator.generate(); + if(status[random] <2) { + String category = Arrays.stream(Menu.values()) + .filter(val -> val.getId() == random) + .findFirst() + .orElse(null) + .getCategory(); + categoryList.add(category); + } + } + return categoryList; + } + +// public List recommendCategoryList() { +// List categoryList = new ArrayList<>(); +// int[] status = new int[5]; +// +// for(int i = 0 ; i < 5 ; i++){ +// int random = randomNumberGenerator.generate(); +// String category = Arrays.stream(Menu.values()) +// .filter(val -> val.getId() == random) +// .findFirst() +// .orElse(null) +// .getCategory(); +// categoryList.add(category); +// } +// return categoryList; +// } + +} diff --git a/src/main/java/menu/service/MenuRecommendService.java b/src/main/java/menu/service/MenuRecommendService.java new file mode 100644 index 000000000..1d3fd7c46 --- /dev/null +++ b/src/main/java/menu/service/MenuRecommendService.java @@ -0,0 +1,12 @@ +package menu.service; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.List; + +public class MenuRecommendService { + + public String recommendMenu(List menus){ + String menu = Randoms.shuffle(menus).get(0); + return menu; + } +} diff --git a/src/main/java/menu/util/InputHandler.java b/src/main/java/menu/util/InputHandler.java new file mode 100644 index 000000000..27a087cf8 --- /dev/null +++ b/src/main/java/menu/util/InputHandler.java @@ -0,0 +1,15 @@ +package menu.util; + +import java.util.function.Supplier; + +public class InputHandler { + public static T retry(Supplier supplier){ + while(true){ + try{ + return supplier.get(); + }catch(IllegalStateException | IllegalArgumentException e){ + System.out.println(e.getMessage()); + } + } + } +} diff --git a/src/main/java/menu/util/Validator.java b/src/main/java/menu/util/Validator.java new file mode 100644 index 000000000..e9c900d2b --- /dev/null +++ b/src/main/java/menu/util/Validator.java @@ -0,0 +1,35 @@ +package menu.util; + +import java.util.List; +import java.util.regex.Pattern; +import menu.constant.ErrorMessage; +import menu.domain.Menu; + +public class Validator { + private final static String NAME_REGEX = "^[ㄱ-ㅎ가-힣]{2,4}$"; + + public static void checkNameType(String name){ + String[] names = name.split(","); + for(String s : names){ + if(!Pattern.matches(NAME_REGEX,s)){ + throw new IllegalArgumentException(ErrorMessage.COACH_NAME_ERROR.getMessage()); + } + } + } + + public static void checkLength(List names){ + if(names.isEmpty() || names.size() < 2){ + throw new IllegalArgumentException(ErrorMessage.COACH_COUNT_ERROR.getMessage()); + } + } + + public static boolean checkMenu(String menu){ + + for(Menu m : Menu.values()){ + if(m.getMenu().stream().anyMatch(val -> val.equals(menu))){ + return true; + } + } + throw new IllegalArgumentException(ErrorMessage.MENU_NOT_EXIST.getMessage()); + } +} diff --git a/src/main/java/menu/view/InputView.java b/src/main/java/menu/view/InputView.java new file mode 100644 index 000000000..8d25b2f12 --- /dev/null +++ b/src/main/java/menu/view/InputView.java @@ -0,0 +1,40 @@ +package menu.view; + +import camp.nextstep.edu.missionutils.Console; +import java.util.Arrays; +import java.util.List; +import menu.util.Validator; + +public class InputView { + public static List readCoachNames(){ + System.out.println("코치의 이름을 입력해 주세요. (, 로 구분)"); + + try{ + String inputNames = Console.readLine(); + Validator.checkNameType(inputNames); + + List names = Arrays.asList(inputNames.split(",")); + Validator.checkLength(names); + System.out.println(); + return names; + + }catch(IllegalArgumentException e){ + throw new IllegalArgumentException(e.getMessage()); + } + } + + public static List readRejectedMenu(String name){ + System.out.println(name + "(이)가 못 먹는 메뉴를 입력해 주세요."); + try{ + String inputMenu = Console.readLine(); + List names = Arrays.asList(inputMenu.split(",")); + for(String menu : names){ + Validator.checkMenu(menu); + } + System.out.println(); + return names; + }catch(IllegalArgumentException e){ + throw new IllegalArgumentException(e.getMessage()); + } + } +} diff --git a/src/main/java/menu/view/OutputView.java b/src/main/java/menu/view/OutputView.java new file mode 100644 index 000000000..b9be211d2 --- /dev/null +++ b/src/main/java/menu/view/OutputView.java @@ -0,0 +1,27 @@ +package menu.view; + +import java.util.List; + +public class OutputView { + + public void printStartMessage(){ + System.out.println("점심 메뉴 추천을 시작합니다."); + } + + public void printCategory(List categories){ + System.out.println("[ 구분 | 월요일 | 화요일 | 수요일 | 목요일 | 금요일 ]"); + System.out.println("[ 카테고리 | "+ String.join(" | ", categories) + " ]"); + } + + public void printMenu(String name, List menus){ + System.out.println("[ " + name + " | " + String.join(" | ", menus) + " ]"); + } + + public void printResult(){ + System.out.println("메뉴 추천 결과입니다."); + } + + public void printEndMessage(){ + System.out.println("추천을 완료했습니다."); + } +} diff --git a/src/test/java/menu/ApplicationTest.java b/src/test/java/menu/ApplicationTest.java index a757e7813..22b3982ae 100644 --- a/src/test/java/menu/ApplicationTest.java +++ b/src/test/java/menu/ApplicationTest.java @@ -75,7 +75,7 @@ class AllFeatureTest { @Override protected void runMain() { - Application.main(new String[]{}); + Application2.main(new String[]{}); } private static void assertRandomTest(