From bf23f41cbdcec3f10205dc80b1cd1ff4b2690cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 00:18:49 +0900 Subject: [PATCH 01/28] =?UTF-8?q?docs(README):=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 리드미 내용 추가 - 기능 목록 --- docs/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/README.md b/docs/README.md index e69de29bb..15984e4f7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,20 @@ +## 기능 목록 +- 기능 목록 +- [ ] 시작 메시지 출력 +- [ ] 코치 이름 + - [ ] 코치 이름 입력 요청 메시지 출력 + - [ ] 코치 이름 입력 + - [ ] 콤마로 구분해 입력했는지 검증 + - [ ] 코치 이름 2글자 ~ 4글자인지 검증 + - [ ] 코치가 2명 이상인지 검증 +- [ ] 코치가 못 먹는 메뉴 + - [ ] 코치 못 먹는 메뉴 입력 요청 메시지 출력 + - [ ] 코치 못 먹는 메뉴 입력 + - [ ] 콤마로 구분해 입력했는지 검증 +- [ ] 메뉴 추천 + - [ ] 이전에 먹은 음식은 못먹도록 필터링 + - [ ] 같은 카테고리 2번만 먹을 수 있도록 필터링 + - [ ] 못 먹는 음식은 추천하지 않도록 필터링 + - [ ] 랜덤으로 셔플 + - [ ] 메뉴 추천 메시지 출력 +- [ ] 추천 완료 메시지 출력 From d18a89f4bedf7dcd780ed270a9506623737754d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 01:07:24 +0900 Subject: [PATCH 02/28] =?UTF-8?q?feat:=20MenuController=EC=99=80=20Compone?= =?UTF-8?q?ntFactory=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - MenuController - ComponenetFactory --- docs/README.md | 7 +++++++ src/main/java/menu/Application.java | 5 ++++- src/main/java/menu/controller/MenuController.java | 8 ++++++++ src/main/java/menu/factory/ComponentFactory.java | 10 ++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/main/java/menu/controller/MenuController.java create mode 100644 src/main/java/menu/factory/ComponentFactory.java diff --git a/docs/README.md b/docs/README.md index 15984e4f7..2d8b22eeb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,3 +18,10 @@ - [ ] 랜덤으로 셔플 - [ ] 메뉴 추천 메시지 출력 - [ ] 추천 완료 메시지 출력 + +## 구현 클래스 목록 +- MenuController + - startRecommend() + +- ComponentFactory + - menuController() diff --git a/src/main/java/menu/Application.java b/src/main/java/menu/Application.java index 6340b6f33..bc4fcc903 100644 --- a/src/main/java/menu/Application.java +++ b/src/main/java/menu/Application.java @@ -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().startRecommend(); } } diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java new file mode 100644 index 000000000..f0ed9fd31 --- /dev/null +++ b/src/main/java/menu/controller/MenuController.java @@ -0,0 +1,8 @@ +package menu.controller; + +public class MenuController { + + public void startRecommend() { + + } +} diff --git a/src/main/java/menu/factory/ComponentFactory.java b/src/main/java/menu/factory/ComponentFactory.java new file mode 100644 index 000000000..095f4fc1b --- /dev/null +++ b/src/main/java/menu/factory/ComponentFactory.java @@ -0,0 +1,10 @@ +package menu.factory; + +import menu.controller.MenuController; + +public class ComponentFactory { + + public MenuController menuController() { + return new MenuController(); + } +} From f4868018872d1ab0aaca78f839dbacbcee25a263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 01:14:12 +0900 Subject: [PATCH 03/28] =?UTF-8?q?feat:=20=EC=B6=9C=EB=A0=A5=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - OutputView - 열거형 ProgressMessage --- docs/README.md | 3 +++ src/main/java/menu/constant/ProgressMessage.java | 16 ++++++++++++++++ .../java/menu/controller/MenuController.java | 7 +++++++ src/main/java/menu/factory/ComponentFactory.java | 7 ++++++- src/main/java/menu/io/OutputView.java | 10 ++++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/main/java/menu/constant/ProgressMessage.java create mode 100644 src/main/java/menu/io/OutputView.java diff --git a/docs/README.md b/docs/README.md index 2d8b22eeb..872155882 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,3 +25,6 @@ - ComponentFactory - menuController() + +- OutputView + - printStart() \ No newline at end of file diff --git a/src/main/java/menu/constant/ProgressMessage.java b/src/main/java/menu/constant/ProgressMessage.java new file mode 100644 index 000000000..ec1a4a9cb --- /dev/null +++ b/src/main/java/menu/constant/ProgressMessage.java @@ -0,0 +1,16 @@ +package menu.constant; + +public enum ProgressMessage { + START_MESSAGE("점심 메뉴 추천을 시작합니다."); + + private final String message; + + ProgressMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return this.message; + } +} diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index f0ed9fd31..54be959b2 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -1,6 +1,13 @@ package menu.controller; +import menu.io.OutputView; + public class MenuController { + private final OutputView outputView; + + public MenuController(final OutputView outputView) { + this.outputView = outputView; + } public void startRecommend() { diff --git a/src/main/java/menu/factory/ComponentFactory.java b/src/main/java/menu/factory/ComponentFactory.java index 095f4fc1b..d20caea63 100644 --- a/src/main/java/menu/factory/ComponentFactory.java +++ b/src/main/java/menu/factory/ComponentFactory.java @@ -1,10 +1,15 @@ package menu.factory; import menu.controller.MenuController; +import menu.io.OutputView; public class ComponentFactory { public MenuController menuController() { - return new MenuController(); + return new MenuController(outputView()); + } + + private OutputView outputView() { + return new OutputView(); } } diff --git a/src/main/java/menu/io/OutputView.java b/src/main/java/menu/io/OutputView.java new file mode 100644 index 000000000..82bb66b06 --- /dev/null +++ b/src/main/java/menu/io/OutputView.java @@ -0,0 +1,10 @@ +package menu.io; + +import menu.constant.ProgressMessage; + +public class OutputView { + + public void printStart() { + System.out.println(ProgressMessage.START_MESSAGE); + } +} From 01847b84d3440daa1f629781cdb8d5069770a6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 01:21:05 +0900 Subject: [PATCH 04/28] =?UTF-8?q?feat:=20=EC=BD=94=EC=B9=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=9A=94=EC=B2=AD=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 코치 이름 입력 요청 메시지 출력 --- docs/README.md | 12 ++++++++---- src/main/java/menu/Application.java | 2 +- src/main/java/menu/constant/ProgressMessage.java | 3 ++- src/main/java/menu/controller/MenuController.java | 7 ++++++- src/main/java/menu/io/OutputView.java | 4 ++++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/README.md b/docs/README.md index 872155882..10a31f196 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,8 +1,8 @@ ## 기능 목록 - 기능 목록 -- [ ] 시작 메시지 출력 +- [x] 시작 메시지 출력 - [ ] 코치 이름 - - [ ] 코치 이름 입력 요청 메시지 출력 + - [x] 코치 이름 입력 요청 메시지 출력 - [ ] 코치 이름 입력 - [ ] 콤마로 구분해 입력했는지 검증 - [ ] 코치 이름 2글자 ~ 4글자인지 검증 @@ -21,10 +21,14 @@ ## 구현 클래스 목록 - MenuController - - startRecommend() + - start() - ComponentFactory - menuController() - OutputView - - printStart() \ No newline at end of file + - printStart() + - printCoachNameRequest() + +## 열거형 목록 +- ProgressMessage diff --git a/src/main/java/menu/Application.java b/src/main/java/menu/Application.java index bc4fcc903..53f559e86 100644 --- a/src/main/java/menu/Application.java +++ b/src/main/java/menu/Application.java @@ -5,6 +5,6 @@ public class Application { public static void main(String[] args) { final ComponentFactory componentFactory = new ComponentFactory(); - componentFactory.menuController().startRecommend(); + componentFactory.menuController().start(); } } diff --git a/src/main/java/menu/constant/ProgressMessage.java b/src/main/java/menu/constant/ProgressMessage.java index ec1a4a9cb..ee69f9559 100644 --- a/src/main/java/menu/constant/ProgressMessage.java +++ b/src/main/java/menu/constant/ProgressMessage.java @@ -1,7 +1,8 @@ package menu.constant; public enum ProgressMessage { - START_MESSAGE("점심 메뉴 추천을 시작합니다."); + START_MESSAGE("점심 메뉴 추천을 시작합니다."), + COACH_NAME_REQUEST("코치의 이름을 입력해 주세요. (, 로 구분)"); private final String message; diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index 54be959b2..52af9200a 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -9,7 +9,12 @@ public MenuController(final OutputView outputView) { this.outputView = outputView; } - public void startRecommend() { + public void start() { + outputView.printStart(); + createCoach(); + } + private void createCoach() { + outputView.printCoachNameRequest(); } } diff --git a/src/main/java/menu/io/OutputView.java b/src/main/java/menu/io/OutputView.java index 82bb66b06..dd6c775d2 100644 --- a/src/main/java/menu/io/OutputView.java +++ b/src/main/java/menu/io/OutputView.java @@ -7,4 +7,8 @@ public class OutputView { public void printStart() { System.out.println(ProgressMessage.START_MESSAGE); } + + public void printCoachNameRequest() { + System.out.println(ProgressMessage.COACH_NAME_REQUEST); + } } From dd98aee0e3b4f5f9949970ea6f63d34ea2e9c670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:01:11 +0900 Subject: [PATCH 05/28] =?UTF-8?q?feat(ErrorMessage):=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=97=B4=EA=B1=B0=ED=98=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 열거형 추가 - ErrorMessage --- docs/README.md | 26 ++++++++++++++++--- src/main/java/menu/constant/ErrorMessage.java | 19 ++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 src/main/java/menu/constant/ErrorMessage.java diff --git a/docs/README.md b/docs/README.md index 10a31f196..b815f6b1c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,14 +3,17 @@ - [x] 시작 메시지 출력 - [ ] 코치 이름 - [x] 코치 이름 입력 요청 메시지 출력 - - [ ] 코치 이름 입력 - - [ ] 콤마로 구분해 입력했는지 검증 - - [ ] 코치 이름 2글자 ~ 4글자인지 검증 - - [ ] 코치가 2명 이상인지 검증 + - [x] 코치 이름 입력 + - [x] 콤마로 구분해 입력했는지 검증 + - [x] 코치 이름 2글자 ~ 4글자인지 검증 + - [x] 코치가 2명 이상인지 검증 + - [x] 잘못된 입력시 재입력 - [ ] 코치가 못 먹는 메뉴 - [ ] 코치 못 먹는 메뉴 입력 요청 메시지 출력 - [ ] 코치 못 먹는 메뉴 입력 - [ ] 콤마로 구분해 입력했는지 검증 + - [ ] 개수가 0 ~ 2개 인지 검증 + - [ ] 잘못된 입력시 재입력 - [ ] 메뉴 추천 - [ ] 이전에 먹은 음식은 못먹도록 필터링 - [ ] 같은 카테고리 2번만 먹을 수 있도록 필터링 @@ -30,5 +33,20 @@ - printStart() - printCoachNameRequest() +- Coach + +- CoachList + +- InputManager + - readCoach() + +- InputValidator + - validateCoach() + +- InputView + - readCoach() + + ## 열거형 목록 - ProgressMessage +- ErrorMessage diff --git a/src/main/java/menu/constant/ErrorMessage.java b/src/main/java/menu/constant/ErrorMessage.java new file mode 100644 index 000000000..a9871a85c --- /dev/null +++ b/src/main/java/menu/constant/ErrorMessage.java @@ -0,0 +1,19 @@ +package menu.constant; + +public enum ErrorMessage { + COACH_NAME_INPUT_ERROR("잘못된 코치 이름 입력입니다."), + INVALID_COACH_NUM_ERROR("코치 수가 잘못되었습니다."), + INVALID_COACH_NAME_LENGTH("코치의 이름 길이가 잘못되었습니다."); + + 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; + } +} From 6063cb25b4e9e99552d0cd342c3f0c537f7996d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:02:00 +0900 Subject: [PATCH 06/28] =?UTF-8?q?feat(Coach):=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20Coach=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - Coach --- src/main/java/menu/domain/Coach.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/menu/domain/Coach.java diff --git a/src/main/java/menu/domain/Coach.java b/src/main/java/menu/domain/Coach.java new file mode 100644 index 000000000..bddf5449d --- /dev/null +++ b/src/main/java/menu/domain/Coach.java @@ -0,0 +1,25 @@ +package menu.domain; + +import menu.constant.ErrorMessage; + +public class Coach { + private static final int MIN_NAME_LENGTH = 2; + private static final int MAX_NAME_LENGTH = 4; + private final String name; + + public Coach(final String name) { + validateName(name); + this.name = name; + } + + private void validateName(final String name) { + final int length = name.length(); + if (invalidLength(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; + } +} From ea2ec2e45c4d1f9842fa405e0788f5ada5598d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:02:22 +0900 Subject: [PATCH 07/28] =?UTF-8?q?feat(CoachList):=20=EC=9D=BC=EA=B8=89?= =?UTF-8?q?=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - CoachList --- src/main/java/menu/domain/CoachList.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/menu/domain/CoachList.java diff --git a/src/main/java/menu/domain/CoachList.java b/src/main/java/menu/domain/CoachList.java new file mode 100644 index 000000000..5c0ff050c --- /dev/null +++ b/src/main/java/menu/domain/CoachList.java @@ -0,0 +1,22 @@ +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 coaches; + + public CoachList(final List coaches) { + validateSize(coaches); + this.coaches = coaches.stream().map(Coach::new).collect(Collectors.toList()); + } + + private void validateSize(final List coaches) { + if (coaches.size() < MIN_COACH_NUM) { + throw new IllegalArgumentException(ErrorMessage.INVALID_COACH_NUM_ERROR.toString()); + } + } +} From 52e1848fb2033f6108cec371701eff5f1e6ed451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:03:46 +0900 Subject: [PATCH 08/28] =?UTF-8?q?feat(InputValidator):=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EA=B0=92=20=EA=B2=80=EC=A6=9D=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - InputValidator --- src/main/java/menu/io/InputValidator.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/menu/io/InputValidator.java diff --git a/src/main/java/menu/io/InputValidator.java b/src/main/java/menu/io/InputValidator.java new file mode 100644 index 000000000..d0c27b155 --- /dev/null +++ b/src/main/java/menu/io/InputValidator.java @@ -0,0 +1,16 @@ +package menu.io; + +import menu.constant.ErrorMessage; + +public class InputValidator { + private static final String SPLITTER = ","; + public void validateSplitter(final String input) { + if (invalidSplitterUsage(input)) { + throw new IllegalArgumentException(ErrorMessage.COACH_NAME_INPUT_ERROR.toString()); + } + } + + private boolean invalidSplitterUsage(final String input) { + return !input.contains(SPLITTER) || input.startsWith(SPLITTER) || input.endsWith(SPLITTER); + } +} From b2d261b04ca954ebc8db871a35a1225737dc5d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:04:29 +0900 Subject: [PATCH 09/28] =?UTF-8?q?feat(InputView):=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - InputView 추가 --- src/main/java/menu/io/InputView.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/menu/io/InputView.java diff --git a/src/main/java/menu/io/InputView.java b/src/main/java/menu/io/InputView.java new file mode 100644 index 000000000..29ea49a55 --- /dev/null +++ b/src/main/java/menu/io/InputView.java @@ -0,0 +1,17 @@ +package menu.io; + +import camp.nextstep.edu.missionutils.Console; + +public class InputView { + private final InputValidator inputValidator; + + public InputView(final InputValidator inputValidator) { + this.inputValidator = inputValidator; + } + + public String readCoach() { + final String input = Console.readLine(); + inputValidator.validateSplitter(input); + return input; + } +} From 8ef65a3cf13898a19c8baa78b518955898cc06a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:04:52 +0900 Subject: [PATCH 10/28] =?UTF-8?q?feat(InputManager):=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20=EA=B4=80=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - InputManager --- src/main/java/menu/io/InputManager.java | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/menu/io/InputManager.java diff --git a/src/main/java/menu/io/InputManager.java b/src/main/java/menu/io/InputManager.java new file mode 100644 index 000000000..5e1617964 --- /dev/null +++ b/src/main/java/menu/io/InputManager.java @@ -0,0 +1,29 @@ +package menu.io; + +import menu.domain.CoachList; + +import java.util.Arrays; +import java.util.function.Supplier; + +public class InputManager { + private static final String SPLITTER = ","; + private final InputView inputView; + + public InputManager(final InputView inputView) { + this.inputView = inputView; + } + + public CoachList readCoach() { + return read(() -> new CoachList(Arrays.asList(inputView.readCoach().split(SPLITTER)))); + } + + private T read(final Supplier supplier) { + while (true) { + try { + return supplier.get(); + } catch (final IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } +} From 023bb0e1e5e02be0c331a7cc5d70a4ce7e05d499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:05:22 +0900 Subject: [PATCH 11/28] =?UTF-8?q?feat:=20=EC=BD=94=EC=B9=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 코치 이름 입력 --- .../java/menu/constant/ProgressMessage.java | 2 +- .../java/menu/controller/MenuController.java | 7 ++++++- .../java/menu/factory/ComponentFactory.java | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/main/java/menu/constant/ProgressMessage.java b/src/main/java/menu/constant/ProgressMessage.java index ee69f9559..e6d4988f0 100644 --- a/src/main/java/menu/constant/ProgressMessage.java +++ b/src/main/java/menu/constant/ProgressMessage.java @@ -6,7 +6,7 @@ public enum ProgressMessage { private final String message; - ProgressMessage(String message) { + ProgressMessage(final String message) { this.message = message; } diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index 52af9200a..cbf59a936 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -1,12 +1,16 @@ package menu.controller; +import menu.domain.CoachList; +import menu.io.InputManager; import menu.io.OutputView; public class MenuController { private final OutputView outputView; + private final InputManager inputManager; - public MenuController(final OutputView outputView) { + public MenuController(final OutputView outputView, final InputManager inputManager) { this.outputView = outputView; + this.inputManager = inputManager; } public void start() { @@ -16,5 +20,6 @@ public void start() { private void createCoach() { outputView.printCoachNameRequest(); + final CoachList coachList = inputManager.readCoach(); } } diff --git a/src/main/java/menu/factory/ComponentFactory.java b/src/main/java/menu/factory/ComponentFactory.java index d20caea63..6c5df5d44 100644 --- a/src/main/java/menu/factory/ComponentFactory.java +++ b/src/main/java/menu/factory/ComponentFactory.java @@ -1,12 +1,27 @@ package menu.factory; import menu.controller.MenuController; +import menu.io.InputManager; +import menu.io.InputValidator; +import menu.io.InputView; import menu.io.OutputView; public class ComponentFactory { public MenuController menuController() { - return new MenuController(outputView()); + return new MenuController(outputView(), inputManager()); + } + + private InputManager inputManager() { + return new InputManager(inputView()); + } + + private InputView inputView() { + return new InputView(inputValidator()); + } + + private InputValidator inputValidator() { + return new InputValidator(); } private OutputView outputView() { From 776b09c362e4802a7eefc0afa92de42ed615d4bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:10:11 +0900 Subject: [PATCH 12/28] =?UTF-8?q?feat(MenuRepository):=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=EC=86=8C=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - MenuRepository --- docs/README.md | 6 ++++++ src/main/java/menu/repository/MenuRepository.java | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/main/java/menu/repository/MenuRepository.java diff --git a/docs/README.md b/docs/README.md index b815f6b1c..027ffa188 100644 --- a/docs/README.md +++ b/docs/README.md @@ -46,6 +46,12 @@ - InputView - readCoach() +- MenuService + - saveCoachList() + +- MenuRepository + - saveCoachList() + - findCoachList() ## 열거형 목록 - ProgressMessage diff --git a/src/main/java/menu/repository/MenuRepository.java b/src/main/java/menu/repository/MenuRepository.java new file mode 100644 index 000000000..07819df2a --- /dev/null +++ b/src/main/java/menu/repository/MenuRepository.java @@ -0,0 +1,15 @@ +package menu.repository; + +import menu.domain.CoachList; + +public class MenuRepository { + private CoachList coachList; + + public void saveCoachList(final CoachList coachList) { + this.coachList = coachList; + } + + public CoachList findCoachList() { + return this.coachList; + } +} From dab632754050783ced0eba1cf7a20952cd9ed2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:10:33 +0900 Subject: [PATCH 13/28] =?UTF-8?q?feat(MenuService):=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - MenuService --- src/main/java/menu/service/MenuService.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/menu/service/MenuService.java diff --git a/src/main/java/menu/service/MenuService.java b/src/main/java/menu/service/MenuService.java new file mode 100644 index 000000000..578a382b5 --- /dev/null +++ b/src/main/java/menu/service/MenuService.java @@ -0,0 +1,16 @@ +package menu.service; + +import menu.domain.CoachList; +import menu.repository.MenuRepository; + +public class MenuService { + private final MenuRepository menuRepository; + + public MenuService(final MenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + public void saveCoachList(final CoachList coachList) { + menuRepository.saveCoachList(coachList); + } +} From 03599f7161cd370368507c530b6e46c860bb70fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 02:19:32 +0900 Subject: [PATCH 14/28] =?UTF-8?q?fix:=20=EC=A0=80=EC=9E=A5=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=A6=AC=ED=84=B4?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코드 수정 - 리턴 타입 수정 --- docs/README.md | 2 +- src/main/java/menu/controller/MenuController.java | 11 ++++++++--- src/main/java/menu/factory/ComponentFactory.java | 12 +++++++++++- src/main/java/menu/repository/MenuRepository.java | 3 ++- src/main/java/menu/service/MenuService.java | 4 ++-- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/docs/README.md b/docs/README.md index 027ffa188..e13677afa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,7 @@ ## 기능 목록 - 기능 목록 - [x] 시작 메시지 출력 -- [ ] 코치 이름 +- [x] 코치 이름 - [x] 코치 이름 입력 요청 메시지 출력 - [x] 코치 이름 입력 - [x] 콤마로 구분해 입력했는지 검증 diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index cbf59a936..1662a572b 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -3,23 +3,28 @@ import menu.domain.CoachList; 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) { + 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(); - createCoach(); + final CoachList coachList = createCoachList(); + } - private void createCoach() { + private CoachList createCoachList() { outputView.printCoachNameRequest(); final CoachList coachList = inputManager.readCoach(); + return menuService.saveCoachList(coachList); } } diff --git a/src/main/java/menu/factory/ComponentFactory.java b/src/main/java/menu/factory/ComponentFactory.java index 6c5df5d44..9202912f7 100644 --- a/src/main/java/menu/factory/ComponentFactory.java +++ b/src/main/java/menu/factory/ComponentFactory.java @@ -5,11 +5,21 @@ import menu.io.InputValidator; import menu.io.InputView; import menu.io.OutputView; +import menu.repository.MenuRepository; +import menu.service.MenuService; public class ComponentFactory { public MenuController menuController() { - return new MenuController(outputView(), inputManager()); + return new MenuController(outputView(), inputManager(), menuService()); + } + + private MenuService menuService() { + return new MenuService(menuRepository()); + } + + private MenuRepository menuRepository() { + return new MenuRepository(); } private InputManager inputManager() { diff --git a/src/main/java/menu/repository/MenuRepository.java b/src/main/java/menu/repository/MenuRepository.java index 07819df2a..12c4c2737 100644 --- a/src/main/java/menu/repository/MenuRepository.java +++ b/src/main/java/menu/repository/MenuRepository.java @@ -5,8 +5,9 @@ public class MenuRepository { private CoachList coachList; - public void saveCoachList(final CoachList coachList) { + public CoachList saveCoachList(final CoachList coachList) { this.coachList = coachList; + return this.coachList; } public CoachList findCoachList() { diff --git a/src/main/java/menu/service/MenuService.java b/src/main/java/menu/service/MenuService.java index 578a382b5..3fd2d1f97 100644 --- a/src/main/java/menu/service/MenuService.java +++ b/src/main/java/menu/service/MenuService.java @@ -10,7 +10,7 @@ public MenuService(final MenuRepository menuRepository) { this.menuRepository = menuRepository; } - public void saveCoachList(final CoachList coachList) { - menuRepository.saveCoachList(coachList); + public CoachList saveCoachList(final CoachList coachList) { + return menuRepository.saveCoachList(coachList); } } From 7841e18fd56ac60db4360ad664b1e16c4d62df1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:01:53 +0900 Subject: [PATCH 15/28] =?UTF-8?q?feat(CoachMenu):=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - CoachMenu --- docs/README.md | 21 +++++++++++++++------ src/main/java/menu/domain/CoachMenu.java | 9 +++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 src/main/java/menu/domain/CoachMenu.java diff --git a/docs/README.md b/docs/README.md index e13677afa..fad0288b2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,12 +8,12 @@ - [x] 코치 이름 2글자 ~ 4글자인지 검증 - [x] 코치가 2명 이상인지 검증 - [x] 잘못된 입력시 재입력 -- [ ] 코치가 못 먹는 메뉴 - - [ ] 코치 못 먹는 메뉴 입력 요청 메시지 출력 - - [ ] 코치 못 먹는 메뉴 입력 - - [ ] 콤마로 구분해 입력했는지 검증 - - [ ] 개수가 0 ~ 2개 인지 검증 - - [ ] 잘못된 입력시 재입력 +- [x] 코치가 못 먹는 메뉴 + - [x] 코치 못 먹는 메뉴 입력 요청 메시지 출력 + - [x] 코치 못 먹는 메뉴 입력 + - [x] 콤마로 구분해 입력했는지 검증 + - [x] 개수가 0 ~ 2개 인지 검증 + - [x] 잘못된 입력시 재입력 - [ ] 메뉴 추천 - [ ] 이전에 먹은 음식은 못먹도록 필터링 - [ ] 같은 카테고리 2번만 먹을 수 있도록 필터링 @@ -53,6 +53,15 @@ - saveCoachList() - findCoachList() +- CoachMenu + +- CoachMenuList + +- CoachMenuMap + +- MenuMap + ## 열거형 목록 - ProgressMessage - ErrorMessage +- Category diff --git a/src/main/java/menu/domain/CoachMenu.java b/src/main/java/menu/domain/CoachMenu.java new file mode 100644 index 000000000..77e0abc62 --- /dev/null +++ b/src/main/java/menu/domain/CoachMenu.java @@ -0,0 +1,9 @@ +package menu.domain; + +public final class CoachMenu { + private final String name; + + public CoachMenu(final String name) { + this.name = name; + } +} From 066f2df73f505ab0607c0b9a40f177763e9fd380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:02:38 +0900 Subject: [PATCH 16/28] =?UTF-8?q?feat(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=97=B4=EA=B1=B0=ED=98=95=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 열거형 추가 - Category --- src/main/java/menu/constant/Category.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/menu/constant/Category.java diff --git a/src/main/java/menu/constant/Category.java b/src/main/java/menu/constant/Category.java new file mode 100644 index 000000000..4f1bedd2a --- /dev/null +++ b/src/main/java/menu/constant/Category.java @@ -0,0 +1,20 @@ +package menu.constant; + +public enum Category { + JAPANESE_FOOD("일식"), + KOREAN_FOOD("한식"), + CHINESE_FOOD("중식"), + ASIAN_FOOD("아시안"), + WESTERN_FOOD("양식"); + + private final String toKorean; + + Category(final String toKorean) { + this.toKorean = toKorean; + } + + @Override + public String toString() { + return this.toKorean; + } +} From 022697221a71f625dc1db36f60524f45bdf8d67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:03:15 +0900 Subject: [PATCH 17/28] =?UTF-8?q?feat(MenuMap):=20=EB=A7=A4=EB=89=B4=20?= =?UTF-8?q?=EC=9D=BC=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - MenuMap --- src/main/java/menu/collection/MenuMap.java | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/menu/collection/MenuMap.java diff --git a/src/main/java/menu/collection/MenuMap.java b/src/main/java/menu/collection/MenuMap.java new file mode 100644 index 000000000..91388b5b3 --- /dev/null +++ b/src/main/java/menu/collection/MenuMap.java @@ -0,0 +1,32 @@ +package menu.collection; + +import menu.constant.Category; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MenuMap { + private final Map> menuMap; + private static MenuMap instance; + + private MenuMap() { + menuMap = new HashMap<>(); + initializeMap(); + } + + public static MenuMap getInstance() { + if (instance == null) { + instance = new MenuMap(); + } + return instance; + } + + private void initializeMap() { + menuMap.put(Category.JAPANESE_FOOD, List.of("규동", "우동", "미소시루", "스시", "가츠동", "오니기리", "하이라이스", "라멘", "오코노미야끼")); + menuMap.put(Category.KOREAN_FOOD, List.of("김밥", "김치찌개", "쌈밥", "된장찌개", "비빔밥", "칼국수", "불고기", "떡볶이", "제육볶음")); + menuMap.put(Category.CHINESE_FOOD, List.of("깐풍기", "볶음면", "동파육", "짜장면", "짬뽕", "마파두부", "탕수육", "토마토 달걀볶음", "고추잡채")); + menuMap.put(Category.ASIAN_FOOD, List.of("팟타이", "카오 팟", "나시고렝", "파인애플 볶음밥", "쌀국수", "똠얌꿍", "반미", "월남쌈", "분짜")); + menuMap.put(Category.WESTERN_FOOD, List.of("라자냐", "그라탱", "뇨끼", "끼슈", "프렌치 토스트", "바게트", "스파게티", "피자", "파니니")); + } +} From 3f5b59003bf1be0dbe923662ff7b42bf77f316bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:04:03 +0900 Subject: [PATCH 18/28] =?UTF-8?q?feat:=20=EC=9D=BC=EA=B8=89=20=EC=BB=AC?= =?UTF-8?q?=EB=A0=89=EC=85=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - CoachMenuMap - CoachMenuList --- .../java/menu/collection/CoachMenuList.java | 22 +++++++++++++++++++ .../java/menu/collection/CoachMenuMap.java | 13 +++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/main/java/menu/collection/CoachMenuList.java create mode 100644 src/main/java/menu/collection/CoachMenuMap.java diff --git a/src/main/java/menu/collection/CoachMenuList.java b/src/main/java/menu/collection/CoachMenuList.java new file mode 100644 index 000000000..0f6d3584c --- /dev/null +++ b/src/main/java/menu/collection/CoachMenuList.java @@ -0,0 +1,22 @@ +package menu.collection; + +import menu.domain.CoachMenu; + +import java.util.List; +import java.util.stream.Collectors; + +public class CoachMenuList { + private static final int MIN_SIZE = 2; + private final List coachMenus; + + public CoachMenuList(final List menus) { + validateSize(menus); + this.coachMenus = menus.stream().map(CoachMenu::new).collect(Collectors.toList()); + } + + private void validateSize(final List menus) { + if (menus.size() > MIN_SIZE) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/menu/collection/CoachMenuMap.java b/src/main/java/menu/collection/CoachMenuMap.java new file mode 100644 index 000000000..d6227ed4f --- /dev/null +++ b/src/main/java/menu/collection/CoachMenuMap.java @@ -0,0 +1,13 @@ +package menu.collection; + +import menu.domain.Coach; + +import java.util.Map; + +public class CoachMenuMap { + private final Map coachMenuMap; + + public CoachMenuMap(final Map coachMenuMap) { + this.coachMenuMap = coachMenuMap; + } +} From 84c3cfdb49d8274ba2847185f1bcfb5567cfcdc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:05:05 +0900 Subject: [PATCH 19/28] =?UTF-8?q?feat:=20=EC=BD=94=EC=B9=98=EA=B0=80=20?= =?UTF-8?q?=EB=AA=BB=EB=A8=B9=EB=8A=94=20=EC=9D=8C=EC=8B=9D=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EC=9A=94=EC=B2=AD=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=9E=85=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 코치 못먹는 음식 입력 요청 메시지 출력 - 코치 못먹는 음식 입력 --- .../{domain => collection}/CoachList.java | 21 ++++++++++++++++++- .../java/menu/constant/ProgressMessage.java | 3 ++- src/main/java/menu/domain/Coach.java | 5 +++++ src/main/java/menu/io/InputManager.java | 7 ++++++- src/main/java/menu/io/InputValidator.java | 8 +++++++ src/main/java/menu/io/InputView.java | 6 ++++++ src/main/java/menu/io/OutputView.java | 5 +++++ .../java/menu/repository/MenuRepository.java | 2 +- src/main/java/menu/service/MenuService.java | 2 +- 9 files changed, 54 insertions(+), 5 deletions(-) rename src/main/java/menu/{domain => collection}/CoachList.java (59%) diff --git a/src/main/java/menu/domain/CoachList.java b/src/main/java/menu/collection/CoachList.java similarity index 59% rename from src/main/java/menu/domain/CoachList.java rename to src/main/java/menu/collection/CoachList.java index 5c0ff050c..27d25c0a2 100644 --- a/src/main/java/menu/domain/CoachList.java +++ b/src/main/java/menu/collection/CoachList.java @@ -1,6 +1,7 @@ -package menu.domain; +package menu.collection; import menu.constant.ErrorMessage; +import menu.domain.Coach; import java.util.List; import java.util.stream.Collectors; @@ -8,10 +9,12 @@ public class CoachList { private static final int MIN_COACH_NUM = 2; private final List coaches; + private Integer index; public CoachList(final List coaches) { validateSize(coaches); this.coaches = coaches.stream().map(Coach::new).collect(Collectors.toList()); + this.index = 0; } private void validateSize(final List coaches) { @@ -19,4 +22,20 @@ private void validateSize(final List coaches) { throw new IllegalArgumentException(ErrorMessage.INVALID_COACH_NUM_ERROR.toString()); } } + + public Coach getNextCoach() { + final Coach coach = this.coaches.get(index++); + checkIndex(); + return coach; + } + + private void checkIndex() { + if (index >= getCoachNum()) { + index = 0; + } + } + + public int getCoachNum() { + return coaches.size(); + } } diff --git a/src/main/java/menu/constant/ProgressMessage.java b/src/main/java/menu/constant/ProgressMessage.java index e6d4988f0..0c76a368d 100644 --- a/src/main/java/menu/constant/ProgressMessage.java +++ b/src/main/java/menu/constant/ProgressMessage.java @@ -2,7 +2,8 @@ public enum ProgressMessage { START_MESSAGE("점심 메뉴 추천을 시작합니다."), - COACH_NAME_REQUEST("코치의 이름을 입력해 주세요. (, 로 구분)"); + COACH_NAME_REQUEST("코치의 이름을 입력해 주세요. (, 로 구분)"), + COACH_MENU_REQUEST("%s(이)가 못 먹는 메뉴를 입력해 주세요."); private final String message; diff --git a/src/main/java/menu/domain/Coach.java b/src/main/java/menu/domain/Coach.java index bddf5449d..558410feb 100644 --- a/src/main/java/menu/domain/Coach.java +++ b/src/main/java/menu/domain/Coach.java @@ -22,4 +22,9 @@ private void validateName(final String name) { private boolean invalidLength(final int length) { return length < MIN_NAME_LENGTH || length > MAX_NAME_LENGTH; } + + @Override + public String toString() { + return this.name; + } } diff --git a/src/main/java/menu/io/InputManager.java b/src/main/java/menu/io/InputManager.java index 5e1617964..8013b1de5 100644 --- a/src/main/java/menu/io/InputManager.java +++ b/src/main/java/menu/io/InputManager.java @@ -1,6 +1,7 @@ package menu.io; -import menu.domain.CoachList; +import menu.collection.CoachList; +import menu.collection.CoachMenuList; import java.util.Arrays; import java.util.function.Supplier; @@ -17,6 +18,10 @@ public CoachList readCoach() { return read(() -> new CoachList(Arrays.asList(inputView.readCoach().split(SPLITTER)))); } + public CoachMenuList readCoachMenu() { + return read(() -> new CoachMenuList(Arrays.asList(inputView.readCoachMenu().split(SPLITTER)))); + } + private T read(final Supplier supplier) { while (true) { try { diff --git a/src/main/java/menu/io/InputValidator.java b/src/main/java/menu/io/InputValidator.java index d0c27b155..188a16d02 100644 --- a/src/main/java/menu/io/InputValidator.java +++ b/src/main/java/menu/io/InputValidator.java @@ -4,6 +4,14 @@ public class InputValidator { private static final String SPLITTER = ","; + + public void validateCoachMenu(final String input) { + if (input.isEmpty()) { + return; + } + validateSplitter(input); + } + public void validateSplitter(final String input) { if (invalidSplitterUsage(input)) { throw new IllegalArgumentException(ErrorMessage.COACH_NAME_INPUT_ERROR.toString()); diff --git a/src/main/java/menu/io/InputView.java b/src/main/java/menu/io/InputView.java index 29ea49a55..0a626ae3b 100644 --- a/src/main/java/menu/io/InputView.java +++ b/src/main/java/menu/io/InputView.java @@ -14,4 +14,10 @@ public String readCoach() { inputValidator.validateSplitter(input); return input; } + + public String readCoachMenu() { + final String input = Console.readLine(); + inputValidator.validateCoachMenu(input); + return input; + } } diff --git a/src/main/java/menu/io/OutputView.java b/src/main/java/menu/io/OutputView.java index dd6c775d2..d26a252fd 100644 --- a/src/main/java/menu/io/OutputView.java +++ b/src/main/java/menu/io/OutputView.java @@ -1,6 +1,7 @@ package menu.io; import menu.constant.ProgressMessage; +import menu.domain.Coach; public class OutputView { @@ -11,4 +12,8 @@ public void printStart() { public void printCoachNameRequest() { System.out.println(ProgressMessage.COACH_NAME_REQUEST); } + + public void printCoachMenuRequest(final Coach coach) { + System.out.println(String.format(ProgressMessage.COACH_MENU_REQUEST.toString(), coach)); + } } diff --git a/src/main/java/menu/repository/MenuRepository.java b/src/main/java/menu/repository/MenuRepository.java index 12c4c2737..0e9cdab7d 100644 --- a/src/main/java/menu/repository/MenuRepository.java +++ b/src/main/java/menu/repository/MenuRepository.java @@ -1,6 +1,6 @@ package menu.repository; -import menu.domain.CoachList; +import menu.collection.CoachList; public class MenuRepository { private CoachList coachList; diff --git a/src/main/java/menu/service/MenuService.java b/src/main/java/menu/service/MenuService.java index 3fd2d1f97..7abdecb2d 100644 --- a/src/main/java/menu/service/MenuService.java +++ b/src/main/java/menu/service/MenuService.java @@ -1,6 +1,6 @@ package menu.service; -import menu.domain.CoachList; +import menu.collection.CoachList; import menu.repository.MenuRepository; public class MenuService { From 8ce087ba638711d33876b4429311ef37d329f567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:05:53 +0900 Subject: [PATCH 20/28] =?UTF-8?q?feat:=20=EC=BD=94=EC=B9=98=20=EB=AA=BB?= =?UTF-8?q?=EB=A8=B9=EB=8A=94=20=EC=9D=8C=EC=8B=9D=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 코치의 못먹는 음식 입력 기능 연결 --- .../java/menu/controller/MenuController.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index 1662a572b..c026bd14a 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -1,11 +1,17 @@ package menu.controller; -import menu.domain.CoachList; +import menu.collection.CoachList; +import menu.collection.CoachMenuMap; import menu.io.InputManager; import menu.io.OutputView; import menu.service.MenuService; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + public class MenuController { + private static final int START_INDEX = 0; private final OutputView outputView; private final InputManager inputManager; private final MenuService menuService; @@ -19,7 +25,14 @@ public MenuController(final OutputView outputView, final InputManager inputManag public void start() { outputView.printStart(); final CoachList coachList = createCoachList(); - + final CoachMenuMap coachMenuMap = coachMenuInput(coachList); + } + + private CoachMenuMap coachMenuInput(final CoachList coachList) { + return new CoachMenuMap(IntStream.range(START_INDEX, coachList.getCoachNum()) + .mapToObj(i -> coachList.getNextCoach()) + .peek(outputView::printCoachMenuRequest) + .collect(Collectors.toMap(Function.identity(), coach -> inputManager.readCoachMenu()))); } private CoachList createCoachList() { From eadd8f21320e5537fb2b8520212ba2ea2283bcff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:29:37 +0900 Subject: [PATCH 21/28] =?UTF-8?q?feat(MenuGenerator):=20=EB=A9=94=EB=89=B4?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 메뉴 생성 --- docs/README.md | 14 +++++++++++++- src/main/java/menu/utils/MenuGenerator.java | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/main/java/menu/utils/MenuGenerator.java diff --git a/docs/README.md b/docs/README.md index fad0288b2..c14928c4f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,22 +36,30 @@ - Coach - CoachList + - getNextCoach() + - getCoachNum() - InputManager - readCoach() + - readCoachMenu() - InputValidator - - validateCoach() + - validateSplitter() + - validateCoachMenu() - InputView - readCoach() + - readCoachMenu() - MenuService - saveCoachList() + - saveCoachMenuMap() - MenuRepository - saveCoachList() - findCoachList() + - saveCoachMenuMap() + - findCoachMenuMap() - CoachMenu @@ -60,6 +68,10 @@ - CoachMenuMap - MenuMap + - getInstance() + +- MenuGenerator + - generate() ## 열거형 목록 - ProgressMessage diff --git a/src/main/java/menu/utils/MenuGenerator.java b/src/main/java/menu/utils/MenuGenerator.java new file mode 100644 index 000000000..a81852388 --- /dev/null +++ b/src/main/java/menu/utils/MenuGenerator.java @@ -0,0 +1,18 @@ +package menu.utils; + +import camp.nextstep.edu.missionutils.Randoms; +import menu.collection.MenuMap; +import menu.constant.Category; + +import java.util.List; + +public class MenuGenerator { + private static final int MIN_INDEX = 1; + private static final int MAX_INDEX = 5; + + public String generate() { + final Category category = Category.getByIndex(Randoms.pickNumberInRange(MIN_INDEX, MAX_INDEX)); + final List menuByCategory = MenuMap.getInstance().getByCategory(category); + return Randoms.shuffle(menuByCategory).get(0); + } +} From 02588538232cfe39c58565f0ded23b6fb42f12e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 03:30:21 +0900 Subject: [PATCH 22/28] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=ED=86=B5=ED=95=9C=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 카테고리를 통한 메뉴 조회 --- src/main/java/menu/collection/MenuMap.java | 14 ++++++++--- src/main/java/menu/constant/Category.java | 23 ++++++++++++++----- src/main/java/menu/constant/ErrorMessage.java | 4 +++- .../java/menu/controller/MenuController.java | 5 ++++ src/main/java/menu/domain/CoachMenu.java | 6 +++++ .../java/menu/factory/ComponentFactory.java | 7 +++++- .../java/menu/repository/MenuRepository.java | 10 ++++++++ src/main/java/menu/service/MenuService.java | 10 +++++++- 8 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/main/java/menu/collection/MenuMap.java b/src/main/java/menu/collection/MenuMap.java index 91388b5b3..32d275645 100644 --- a/src/main/java/menu/collection/MenuMap.java +++ b/src/main/java/menu/collection/MenuMap.java @@ -2,9 +2,7 @@ import menu.constant.Category; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class MenuMap { private final Map> menuMap; @@ -22,6 +20,16 @@ public static MenuMap getInstance() { return instance; } + public boolean contains(final String name) { + return this.menuMap.values().stream() + .flatMap(Collection::stream) + .anyMatch(name::equals); + } + + public List getByCategory(final Category category) { + return new ArrayList<>(menuMap.get(category)); + } + private void initializeMap() { menuMap.put(Category.JAPANESE_FOOD, List.of("규동", "우동", "미소시루", "스시", "가츠동", "오니기리", "하이라이스", "라멘", "오코노미야끼")); menuMap.put(Category.KOREAN_FOOD, List.of("김밥", "김치찌개", "쌈밥", "된장찌개", "비빔밥", "칼국수", "불고기", "떡볶이", "제육볶음")); diff --git a/src/main/java/menu/constant/Category.java b/src/main/java/menu/constant/Category.java index 4f1bedd2a..4468fa42d 100644 --- a/src/main/java/menu/constant/Category.java +++ b/src/main/java/menu/constant/Category.java @@ -1,18 +1,29 @@ package menu.constant; +import java.util.Arrays; + public enum Category { - JAPANESE_FOOD("일식"), - KOREAN_FOOD("한식"), - CHINESE_FOOD("중식"), - ASIAN_FOOD("아시안"), - WESTERN_FOOD("양식"); + 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 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; diff --git a/src/main/java/menu/constant/ErrorMessage.java b/src/main/java/menu/constant/ErrorMessage.java index a9871a85c..48760ead0 100644 --- a/src/main/java/menu/constant/ErrorMessage.java +++ b/src/main/java/menu/constant/ErrorMessage.java @@ -3,7 +3,9 @@ public enum ErrorMessage { COACH_NAME_INPUT_ERROR("잘못된 코치 이름 입력입니다."), INVALID_COACH_NUM_ERROR("코치 수가 잘못되었습니다."), - INVALID_COACH_NAME_LENGTH("코치의 이름 길이가 잘못되었습니다."); + INVALID_COACH_NAME_LENGTH("코치의 이름 길이가 잘못되었습니다."), + INVALID_MENU_NAME("잘못된 메뉴명입니다."), + NO_MATCHING_INDEX("인덱스에 해당하는 값이 없습니다."); private static final String PREFIX = "[ERROR] "; private final String message; diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index c026bd14a..de4374aaf 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -25,7 +25,12 @@ public MenuController(final OutputView outputView, final InputManager inputManag public void start() { outputView.printStart(); final CoachList coachList = createCoachList(); + createCoachMenuMap(coachList); + } + + private void createCoachMenuMap(final CoachList coachList) { final CoachMenuMap coachMenuMap = coachMenuInput(coachList); + menuService.saveCoachMenuMap(coachMenuMap); } private CoachMenuMap coachMenuInput(final CoachList coachList) { diff --git a/src/main/java/menu/domain/CoachMenu.java b/src/main/java/menu/domain/CoachMenu.java index 77e0abc62..1c90372d0 100644 --- a/src/main/java/menu/domain/CoachMenu.java +++ b/src/main/java/menu/domain/CoachMenu.java @@ -1,9 +1,15 @@ package menu.domain; +import menu.collection.MenuMap; +import menu.constant.ErrorMessage; + public final class CoachMenu { private final String name; public CoachMenu(final String name) { + if (!MenuMap.getInstance().contains(name)) { + throw new IllegalArgumentException(ErrorMessage.INVALID_MENU_NAME.toString()); + } this.name = name; } } diff --git a/src/main/java/menu/factory/ComponentFactory.java b/src/main/java/menu/factory/ComponentFactory.java index 9202912f7..2fcfc3aff 100644 --- a/src/main/java/menu/factory/ComponentFactory.java +++ b/src/main/java/menu/factory/ComponentFactory.java @@ -7,6 +7,7 @@ import menu.io.OutputView; import menu.repository.MenuRepository; import menu.service.MenuService; +import menu.utils.MenuGenerator; public class ComponentFactory { @@ -15,7 +16,11 @@ public MenuController menuController() { } private MenuService menuService() { - return new MenuService(menuRepository()); + return new MenuService(menuRepository(), menuGenerator()); + } + + private MenuGenerator menuGenerator() { + return new MenuGenerator(); } private MenuRepository menuRepository() { diff --git a/src/main/java/menu/repository/MenuRepository.java b/src/main/java/menu/repository/MenuRepository.java index 0e9cdab7d..fda12ef02 100644 --- a/src/main/java/menu/repository/MenuRepository.java +++ b/src/main/java/menu/repository/MenuRepository.java @@ -1,9 +1,11 @@ package menu.repository; import menu.collection.CoachList; +import menu.collection.CoachMenuMap; public class MenuRepository { private CoachList coachList; + private CoachMenuMap coachMenuMap; public CoachList saveCoachList(final CoachList coachList) { this.coachList = coachList; @@ -13,4 +15,12 @@ public CoachList saveCoachList(final CoachList coachList) { public CoachList findCoachList() { return this.coachList; } + + public void saveCoachMenuMap(final CoachMenuMap coachMenuMap) { + this.coachMenuMap = coachMenuMap; + } + + public CoachMenuMap findCoachMenuMap() { + return this.coachMenuMap; + } } diff --git a/src/main/java/menu/service/MenuService.java b/src/main/java/menu/service/MenuService.java index 7abdecb2d..4826624c4 100644 --- a/src/main/java/menu/service/MenuService.java +++ b/src/main/java/menu/service/MenuService.java @@ -1,16 +1,24 @@ package menu.service; import menu.collection.CoachList; +import menu.collection.CoachMenuMap; import menu.repository.MenuRepository; +import menu.utils.MenuGenerator; public class MenuService { private final MenuRepository menuRepository; + private final MenuGenerator menuGenerator; - public MenuService(final MenuRepository menuRepository) { + public MenuService(final MenuRepository menuRepository, final MenuGenerator menuGenerator) { this.menuRepository = menuRepository; + this.menuGenerator = menuGenerator; } public CoachList saveCoachList(final CoachList coachList) { return menuRepository.saveCoachList(coachList); } + + public void saveCoachMenuMap(final CoachMenuMap coachMenuMap) { + menuRepository.saveCoachMenuMap(coachMenuMap); + } } From c34202a91642a973830b3532a4ddcde11e7b3697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 20:46:09 +0900 Subject: [PATCH 23/28] =?UTF-8?q?feat(MenuGenerator):=20=EB=A9=94=EB=89=B4?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 메뉴 생성 기능 --- docs/README.md | 57 +++++++++++++++------ src/main/java/menu/utils/MenuGenerator.java | 43 +++++++++++++--- 2 files changed, 79 insertions(+), 21 deletions(-) diff --git a/docs/README.md b/docs/README.md index c14928c4f..8f01e3a7b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,13 +14,13 @@ - [x] 콤마로 구분해 입력했는지 검증 - [x] 개수가 0 ~ 2개 인지 검증 - [x] 잘못된 입력시 재입력 -- [ ] 메뉴 추천 - - [ ] 이전에 먹은 음식은 못먹도록 필터링 - - [ ] 같은 카테고리 2번만 먹을 수 있도록 필터링 - - [ ] 못 먹는 음식은 추천하지 않도록 필터링 - - [ ] 랜덤으로 셔플 - - [ ] 메뉴 추천 메시지 출력 -- [ ] 추천 완료 메시지 출력 +- [x] 메뉴 추천 + - [x] 이전에 먹은 음식은 못먹도록 필터링 + - [x] 같은 카테고리 2번만 먹을 수 있도록 필터링 + - [x] 못 먹는 음식은 추천하지 않도록 필터링 + - [x] 랜덤으로 셔플 + - [x] 메뉴 추천 메시지 출력 + - [x] 추천 완료 메시지 출력 ## 구현 클래스 목록 - MenuController @@ -33,8 +33,6 @@ - printStart() - printCoachNameRequest() -- Coach - - CoachList - getNextCoach() - getCoachNum() @@ -52,8 +50,9 @@ - readCoachMenu() - MenuService + - recommendMenu() - saveCoachList() - - saveCoachMenuMap() + - addHateMenu() - MenuRepository - saveCoachList() @@ -61,19 +60,47 @@ - saveCoachMenuMap() - findCoachMenuMap() -- CoachMenu +- MenuMap + - getInstance() -- CoachMenuList +- MenuGenerator + - generate() -- CoachMenuMap +- AvailMenuList + - getMenuByCategory() + +- Coach + - getName() + - addMenus() + - getAvailMenuByCategory() + - noSameRecommendMenu() + - addRecommendMenu() + +- CoachList + - getAllCoaches() + +- DayCategory + - getCategory() + +- DayCategoryList + - isMaxCount() + - addCategory() + +- HateMenuList + - getMenus() + +- Menu - MenuMap - getInstance() + - contains() + - getExceptHateMenus() -- MenuGenerator - - generate() +- RecommendResult ## 열거형 목록 - ProgressMessage - ErrorMessage - Category +- Day +- ResultTag diff --git a/src/main/java/menu/utils/MenuGenerator.java b/src/main/java/menu/utils/MenuGenerator.java index a81852388..ca9ed9cd5 100644 --- a/src/main/java/menu/utils/MenuGenerator.java +++ b/src/main/java/menu/utils/MenuGenerator.java @@ -1,18 +1,49 @@ package menu.utils; import camp.nextstep.edu.missionutils.Randoms; -import menu.collection.MenuMap; +import menu.domain.*; import menu.constant.Category; import java.util.List; +import java.util.stream.IntStream; public class MenuGenerator { - private static final int MIN_INDEX = 1; + private static final int MIN_INDEX = 0; private static final int MAX_INDEX = 5; + private static final int MIN_RANGE = 1; + private static final int MAX_RANGE = 5; - public String generate() { - final Category category = Category.getByIndex(Randoms.pickNumberInRange(MIN_INDEX, MAX_INDEX)); - final List menuByCategory = MenuMap.getInstance().getByCategory(category); - return Randoms.shuffle(menuByCategory).get(0); + public DayCategoryList generate(final DayCategoryList dayCategoryList, final CoachList coachList) { + IntStream.range(MIN_INDEX, MAX_INDEX).forEach(i -> addOneDayRecommend(dayCategoryList, coachList)); + return dayCategoryList; + } + + private void addOneDayRecommend(final DayCategoryList dayCategoryList, final CoachList coachList) { + final Category category = generateCategory(dayCategoryList); + + dayCategoryList.addCategory(category); + coachList.getAllCoaches().forEach(coach -> recommendMenu(coach, category)); + } + + private Menu recommendMenu(final Coach coach, final Category category) { + final List menus = coach.getAvailMenuByCategory(category); + while (true) { + final String menu = Randoms.shuffle(menus).get(0); + if (coach.noSameRecommendMenu(menu)) { + final Menu recommendMenu = new Menu(menu); + coach.addRecommendMenu(recommendMenu); + return recommendMenu; + } + } + } + + private Category generateCategory(final DayCategoryList dayCategoryList) { + while (true) { + final Category category = Category.getByIndex(Randoms.pickNumberInRange(MIN_RANGE, MAX_RANGE)); + if (dayCategoryList.isMaxCount(category)) { + continue; + } + return category; + } } } From 60c227678d2d6e3e3a269887365d81c72f219816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 20:46:47 +0900 Subject: [PATCH 24/28] =?UTF-8?q?feat:=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - 도메인 클래스 --- .../java/menu/collection/CoachMenuMap.java | 13 ------ src/main/java/menu/constant/Day.java | 31 +++++++++++++ src/main/java/menu/domain/Coach.java | 44 ++++++++++++++++++- .../{collection => domain}/CoachList.java | 22 +++------- src/main/java/menu/domain/CoachMenu.java | 15 ------- src/main/java/menu/domain/DayCategory.java | 38 ++++++++++++++++ .../java/menu/domain/DayCategoryList.java | 35 +++++++++++++++ .../HateMenuList.java} | 16 ++++--- src/main/java/menu/domain/Menu.java | 23 ++++++++++ .../menu/{collection => domain}/MenuMap.java | 28 ++++++++++-- .../java/menu/domain/RecommendResult.java | 19 ++++++++ 11 files changed, 229 insertions(+), 55 deletions(-) delete mode 100644 src/main/java/menu/collection/CoachMenuMap.java create mode 100644 src/main/java/menu/constant/Day.java rename src/main/java/menu/{collection => domain}/CoachList.java (60%) delete mode 100644 src/main/java/menu/domain/CoachMenu.java create mode 100644 src/main/java/menu/domain/DayCategory.java create mode 100644 src/main/java/menu/domain/DayCategoryList.java rename src/main/java/menu/{collection/CoachMenuList.java => domain/HateMenuList.java} (51%) create mode 100644 src/main/java/menu/domain/Menu.java rename src/main/java/menu/{collection => domain}/MenuMap.java (58%) create mode 100644 src/main/java/menu/domain/RecommendResult.java diff --git a/src/main/java/menu/collection/CoachMenuMap.java b/src/main/java/menu/collection/CoachMenuMap.java deleted file mode 100644 index d6227ed4f..000000000 --- a/src/main/java/menu/collection/CoachMenuMap.java +++ /dev/null @@ -1,13 +0,0 @@ -package menu.collection; - -import menu.domain.Coach; - -import java.util.Map; - -public class CoachMenuMap { - private final Map coachMenuMap; - - public CoachMenuMap(final Map coachMenuMap) { - this.coachMenuMap = coachMenuMap; - } -} diff --git a/src/main/java/menu/constant/Day.java b/src/main/java/menu/constant/Day.java new file mode 100644 index 000000000..3a6845bca --- /dev/null +++ b/src/main/java/menu/constant/Day.java @@ -0,0 +1,31 @@ +package menu.constant; + +import java.util.Arrays; + +public enum Day { + MONDAY("월요일", 0), + TUESDAY("화요일", 1), + WEDNESDAY("수요일", 2), + THURSDAY("목요일", 3), + FRIDAY("금요일", 4); + + private final String day; + private final Integer order; + + Day(final String day, final Integer order) { + this.day = day; + this.order = order; + } + + public static Day getByOrder(final int order) { + return Arrays.stream(values()) + .filter(d -> d.order == order) + .findAny() + .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.INVALID_INDEX.toString())); + } + + @Override + public String toString() { + return this.day; + } +} diff --git a/src/main/java/menu/domain/Coach.java b/src/main/java/menu/domain/Coach.java index 558410feb..c5d0de9c1 100644 --- a/src/main/java/menu/domain/Coach.java +++ b/src/main/java/menu/domain/Coach.java @@ -1,15 +1,26 @@ package menu.domain; +import menu.constant.Category; import menu.constant.ErrorMessage; +import menu.constant.ResultTag; -public class Coach { +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 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) { @@ -25,6 +36,37 @@ private boolean invalidLength(final int 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 addMenus(final HateMenuList hateMenuList) { + this.hateMenuList = hateMenuList; + this.availMenuList = new AvailMenuList(getAvailMenu()); + } + + private Map> getAvailMenu() { + return MenuMap.getInstance().getExceptHateMenus(hateMenuList.getMenus()); + } + + public List 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); + } } diff --git a/src/main/java/menu/collection/CoachList.java b/src/main/java/menu/domain/CoachList.java similarity index 60% rename from src/main/java/menu/collection/CoachList.java rename to src/main/java/menu/domain/CoachList.java index 27d25c0a2..7133017b3 100644 --- a/src/main/java/menu/collection/CoachList.java +++ b/src/main/java/menu/domain/CoachList.java @@ -1,7 +1,6 @@ -package menu.collection; +package menu.domain; import menu.constant.ErrorMessage; -import menu.domain.Coach; import java.util.List; import java.util.stream.Collectors; @@ -9,12 +8,10 @@ public class CoachList { private static final int MIN_COACH_NUM = 2; private final List coaches; - private Integer index; public CoachList(final List coaches) { validateSize(coaches); this.coaches = coaches.stream().map(Coach::new).collect(Collectors.toList()); - this.index = 0; } private void validateSize(final List coaches) { @@ -23,19 +20,12 @@ private void validateSize(final List coaches) { } } - public Coach getNextCoach() { - final Coach coach = this.coaches.get(index++); - checkIndex(); - return coach; + public List getAllCoaches() { + return this.coaches; } - private void checkIndex() { - if (index >= getCoachNum()) { - index = 0; - } - } - - public int getCoachNum() { - return coaches.size(); + @Override + public String toString() { + return coaches.stream().map(Coach::toString).collect(Collectors.joining("\n")); } } diff --git a/src/main/java/menu/domain/CoachMenu.java b/src/main/java/menu/domain/CoachMenu.java deleted file mode 100644 index 1c90372d0..000000000 --- a/src/main/java/menu/domain/CoachMenu.java +++ /dev/null @@ -1,15 +0,0 @@ -package menu.domain; - -import menu.collection.MenuMap; -import menu.constant.ErrorMessage; - -public final class CoachMenu { - private final String name; - - public CoachMenu(final String name) { - if (!MenuMap.getInstance().contains(name)) { - throw new IllegalArgumentException(ErrorMessage.INVALID_MENU_NAME.toString()); - } - this.name = name; - } -} diff --git a/src/main/java/menu/domain/DayCategory.java b/src/main/java/menu/domain/DayCategory.java new file mode 100644 index 000000000..d0876cb06 --- /dev/null +++ b/src/main/java/menu/domain/DayCategory.java @@ -0,0 +1,38 @@ +package menu.domain; + +import menu.constant.Category; +import menu.constant.Day; + +import java.util.Objects; + +public class DayCategory { + private final Day day; + private final Category category; + + public DayCategory(final Day day, final Category category) { + this.day = day; + this.category = category; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final DayCategory that = (DayCategory) o; + return day == that.day && category == that.category; + } + + @Override + public int hashCode() { + return Objects.hash(day, category); + } + + @Override + public String toString() { + return this.category.toString(); + } + + public Category getCategory() { + return this.category; + } +} diff --git a/src/main/java/menu/domain/DayCategoryList.java b/src/main/java/menu/domain/DayCategoryList.java new file mode 100644 index 000000000..116af938e --- /dev/null +++ b/src/main/java/menu/domain/DayCategoryList.java @@ -0,0 +1,35 @@ +package menu.domain; + +import menu.constant.Category; +import menu.constant.Day; +import menu.constant.ResultTag; + +import java.util.*; +import java.util.stream.Collectors; + +public class DayCategoryList { + private static final String CATEGORY_TAG = "카테고리"; + private final List dayCategoryList; + + public DayCategoryList() { + this.dayCategoryList = new ArrayList<>(); + } + + public boolean isMaxCount(final Category category) { + return dayCategoryList.stream().filter(d -> d.getCategory() == category).count() == 2; + } + + public void addCategory(final Category category) { + final DayCategory dayCategory = new DayCategory(Day.getByOrder(dayCategoryList.size()), category); + dayCategoryList.add(dayCategory); + } + + @Override + public String toString() { + return ResultTag.START_TAG + + CATEGORY_TAG + + ResultTag.DELIMITER + + dayCategoryList.stream().map(DayCategory::toString).collect(Collectors.joining(ResultTag.DELIMITER.toString())) + + ResultTag.END_TAG; + } +} diff --git a/src/main/java/menu/collection/CoachMenuList.java b/src/main/java/menu/domain/HateMenuList.java similarity index 51% rename from src/main/java/menu/collection/CoachMenuList.java rename to src/main/java/menu/domain/HateMenuList.java index 0f6d3584c..88ec26e1e 100644 --- a/src/main/java/menu/collection/CoachMenuList.java +++ b/src/main/java/menu/domain/HateMenuList.java @@ -1,17 +1,15 @@ -package menu.collection; - -import menu.domain.CoachMenu; +package menu.domain; import java.util.List; import java.util.stream.Collectors; -public class CoachMenuList { +public class HateMenuList { private static final int MIN_SIZE = 2; - private final List coachMenus; + private final List menus; - public CoachMenuList(final List menus) { + public HateMenuList(final List menus) { validateSize(menus); - this.coachMenus = menus.stream().map(CoachMenu::new).collect(Collectors.toList()); + this.menus = menus.stream().map(Menu::new).collect(Collectors.toList()); } private void validateSize(final List menus) { @@ -19,4 +17,8 @@ private void validateSize(final List menus) { throw new IllegalArgumentException(); } } + + public List getMenus() { + return this.menus; + } } diff --git a/src/main/java/menu/domain/Menu.java b/src/main/java/menu/domain/Menu.java new file mode 100644 index 000000000..a7294a23a --- /dev/null +++ b/src/main/java/menu/domain/Menu.java @@ -0,0 +1,23 @@ +package menu.domain; + +import menu.constant.ErrorMessage; + +public final class Menu { + private final String name; + + public Menu(final String name) { + if (!name.isEmpty() && notContainsName(name)) { + throw new IllegalArgumentException(ErrorMessage.INVALID_MENU_NAME.toString()); + } + this.name = name; + } + + private boolean notContainsName(final String name) { + return !MenuMap.getInstance().contains(name); + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/src/main/java/menu/collection/MenuMap.java b/src/main/java/menu/domain/MenuMap.java similarity index 58% rename from src/main/java/menu/collection/MenuMap.java rename to src/main/java/menu/domain/MenuMap.java index 32d275645..5dbac5865 100644 --- a/src/main/java/menu/collection/MenuMap.java +++ b/src/main/java/menu/domain/MenuMap.java @@ -1,8 +1,10 @@ -package menu.collection; +package menu.domain; import menu.constant.Category; +import menu.constant.ErrorMessage; import java.util.*; +import java.util.stream.Collectors; public class MenuMap { private final Map> menuMap; @@ -26,8 +28,28 @@ public boolean contains(final String name) { .anyMatch(name::equals); } - public List getByCategory(final Category category) { - return new ArrayList<>(menuMap.get(category)); + private Category getCategoryByMenu(final Menu menu) { + return menuMap.entrySet().stream() + .filter(entry -> entry.getValue().contains(menu.toString())) + .findAny() + .map(Map.Entry::getKey) + .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.CANNOT_FIND_CATEGORY.toString())); + } + + public Map> getExceptHateMenus(final List hateMenus) { + final List hateMenuString = getHateMenuString(hateMenus); + + return this.menuMap.values().stream() + .flatMap(Collection::stream) + .filter(menu -> !hateMenuString.contains(menu)) + .map(Menu::new) + .collect(Collectors.groupingBy(this::getCategoryByMenu)); + } + + private List getHateMenuString(final List hateMenus) { + return hateMenus.stream() + .map(Menu::toString) + .collect(Collectors.toList()); } private void initializeMap() { diff --git a/src/main/java/menu/domain/RecommendResult.java b/src/main/java/menu/domain/RecommendResult.java new file mode 100644 index 000000000..db4bd45f4 --- /dev/null +++ b/src/main/java/menu/domain/RecommendResult.java @@ -0,0 +1,19 @@ +package menu.domain; + +public class RecommendResult { + private static final String LINE_DELIMITER = "\n"; + private final CoachList coachList; + private final DayCategoryList dayCategoryList; + + public RecommendResult(final CoachList coachList, final DayCategoryList dayCategoryList) { + this.coachList = coachList; + this.dayCategoryList = dayCategoryList; + } + + @Override + public String toString() { + return dayCategoryList + + LINE_DELIMITER + + coachList; + } +} From 2d8c0fdbe3c1f9c2152c8fd7311416c354c0bc57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 20:47:18 +0900 Subject: [PATCH 25/28] =?UTF-8?q?feat:=20=EC=97=B4=EA=B1=B0=ED=98=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 클래스 추가 - 열거형 --- src/main/java/menu/constant/ErrorMessage.java | 4 +++- .../java/menu/constant/ProgressMessage.java | 5 ++++- src/main/java/menu/constant/ResultTag.java | 18 ++++++++++++++++++ src/main/java/menu/domain/AvailMenuList.java | 18 ++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/main/java/menu/constant/ResultTag.java create mode 100644 src/main/java/menu/domain/AvailMenuList.java diff --git a/src/main/java/menu/constant/ErrorMessage.java b/src/main/java/menu/constant/ErrorMessage.java index 48760ead0..cde53967a 100644 --- a/src/main/java/menu/constant/ErrorMessage.java +++ b/src/main/java/menu/constant/ErrorMessage.java @@ -5,7 +5,9 @@ public enum ErrorMessage { INVALID_COACH_NUM_ERROR("코치 수가 잘못되었습니다."), INVALID_COACH_NAME_LENGTH("코치의 이름 길이가 잘못되었습니다."), INVALID_MENU_NAME("잘못된 메뉴명입니다."), - NO_MATCHING_INDEX("인덱스에 해당하는 값이 없습니다."); + NO_MATCHING_INDEX("인덱스에 해당하는 값이 없습니다."), + CANNOT_FIND_CATEGORY("카테고리를 찾을 수 없습니다."), + INVALID_INDEX("잘못된 인덱스 번호입니다."); private static final String PREFIX = "[ERROR] "; private final String message; diff --git a/src/main/java/menu/constant/ProgressMessage.java b/src/main/java/menu/constant/ProgressMessage.java index 0c76a368d..e44f19c92 100644 --- a/src/main/java/menu/constant/ProgressMessage.java +++ b/src/main/java/menu/constant/ProgressMessage.java @@ -3,7 +3,10 @@ public enum ProgressMessage { START_MESSAGE("점심 메뉴 추천을 시작합니다."), COACH_NAME_REQUEST("코치의 이름을 입력해 주세요. (, 로 구분)"), - COACH_MENU_REQUEST("%s(이)가 못 먹는 메뉴를 입력해 주세요."); + COACH_MENU_REQUEST("%s(이)가 못 먹는 메뉴를 입력해 주세요."), + RECOMMEND_RESULT("메뉴 추천 결과입니다."), + DAY_CLASSIFIER("[ 구분 | 월요일 | 화요일 | 수요일 | 목요일 | 금요일 ]"), + RECOMMEND_FINISH("\n추천을 완료했습니다."); private final String message; diff --git a/src/main/java/menu/constant/ResultTag.java b/src/main/java/menu/constant/ResultTag.java new file mode 100644 index 000000000..0ffce5c43 --- /dev/null +++ b/src/main/java/menu/constant/ResultTag.java @@ -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; + } +} diff --git a/src/main/java/menu/domain/AvailMenuList.java b/src/main/java/menu/domain/AvailMenuList.java new file mode 100644 index 000000000..82a32f27a --- /dev/null +++ b/src/main/java/menu/domain/AvailMenuList.java @@ -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> coachAvailMenu; + + public AvailMenuList(final Map> coachAvailMenu) { + this.coachAvailMenu = coachAvailMenu; + } + + public List getMenuByCategory(final Category category) { + return this.coachAvailMenu.get(category); + } +} From 6df92538eb1c160ce30f112aaeefc7a16ece9748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 20:48:11 +0900 Subject: [PATCH 26/28] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 추가 - 전체 기능 연결 및 완료 --- .../java/menu/controller/MenuController.java | 26 ++++++++----------- src/main/java/menu/io/InputManager.java | 8 +++--- src/main/java/menu/io/OutputView.java | 10 ++++++- .../java/menu/repository/MenuRepository.java | 12 +-------- src/main/java/menu/service/MenuService.java | 14 +++++++--- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/main/java/menu/controller/MenuController.java b/src/main/java/menu/controller/MenuController.java index de4374aaf..b54f514b1 100644 --- a/src/main/java/menu/controller/MenuController.java +++ b/src/main/java/menu/controller/MenuController.java @@ -1,17 +1,12 @@ package menu.controller; -import menu.collection.CoachList; -import menu.collection.CoachMenuMap; +import menu.domain.CoachList; +import menu.domain.RecommendResult; import menu.io.InputManager; import menu.io.OutputView; import menu.service.MenuService; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - public class MenuController { - private static final int START_INDEX = 0; private final OutputView outputView; private final InputManager inputManager; private final MenuService menuService; @@ -26,18 +21,19 @@ public void start() { outputView.printStart(); final CoachList coachList = createCoachList(); createCoachMenuMap(coachList); + recommendMenu(); } - private void createCoachMenuMap(final CoachList coachList) { - final CoachMenuMap coachMenuMap = coachMenuInput(coachList); - menuService.saveCoachMenuMap(coachMenuMap); + private void recommendMenu() { + final RecommendResult recommendResult = menuService.recommendMenu(); + outputView.printRecommendResult(recommendResult); } - private CoachMenuMap coachMenuInput(final CoachList coachList) { - return new CoachMenuMap(IntStream.range(START_INDEX, coachList.getCoachNum()) - .mapToObj(i -> coachList.getNextCoach()) - .peek(outputView::printCoachMenuRequest) - .collect(Collectors.toMap(Function.identity(), coach -> inputManager.readCoachMenu()))); + private void createCoachMenuMap(final CoachList coachList) { + coachList.getAllCoaches().forEach(coach -> { + outputView.printCoachMenuRequest(coach); + menuService.addHateMenus(coach, inputManager.readCoachMenu()); + }); } private CoachList createCoachList() { diff --git a/src/main/java/menu/io/InputManager.java b/src/main/java/menu/io/InputManager.java index 8013b1de5..1f6cda16c 100644 --- a/src/main/java/menu/io/InputManager.java +++ b/src/main/java/menu/io/InputManager.java @@ -1,7 +1,7 @@ package menu.io; -import menu.collection.CoachList; -import menu.collection.CoachMenuList; +import menu.domain.CoachList; +import menu.domain.HateMenuList; import java.util.Arrays; import java.util.function.Supplier; @@ -18,8 +18,8 @@ public CoachList readCoach() { return read(() -> new CoachList(Arrays.asList(inputView.readCoach().split(SPLITTER)))); } - public CoachMenuList readCoachMenu() { - return read(() -> new CoachMenuList(Arrays.asList(inputView.readCoachMenu().split(SPLITTER)))); + public HateMenuList readCoachMenu() { + return read(() -> new HateMenuList(Arrays.asList(inputView.readCoachMenu().split(SPLITTER)))); } private T read(final Supplier supplier) { diff --git a/src/main/java/menu/io/OutputView.java b/src/main/java/menu/io/OutputView.java index d26a252fd..41a752a18 100644 --- a/src/main/java/menu/io/OutputView.java +++ b/src/main/java/menu/io/OutputView.java @@ -2,6 +2,7 @@ import menu.constant.ProgressMessage; import menu.domain.Coach; +import menu.domain.RecommendResult; public class OutputView { @@ -14,6 +15,13 @@ public void printCoachNameRequest() { } public void printCoachMenuRequest(final Coach coach) { - System.out.println(String.format(ProgressMessage.COACH_MENU_REQUEST.toString(), coach)); + System.out.println(String.format(ProgressMessage.COACH_MENU_REQUEST.toString(), coach.getName())); + } + + public void printRecommendResult(final RecommendResult recommendResult) { + System.out.println(ProgressMessage.RECOMMEND_RESULT); + System.out.println(ProgressMessage.DAY_CLASSIFIER); + System.out.println(recommendResult); + System.out.println(ProgressMessage.RECOMMEND_FINISH); } } diff --git a/src/main/java/menu/repository/MenuRepository.java b/src/main/java/menu/repository/MenuRepository.java index fda12ef02..12c4c2737 100644 --- a/src/main/java/menu/repository/MenuRepository.java +++ b/src/main/java/menu/repository/MenuRepository.java @@ -1,11 +1,9 @@ package menu.repository; -import menu.collection.CoachList; -import menu.collection.CoachMenuMap; +import menu.domain.CoachList; public class MenuRepository { private CoachList coachList; - private CoachMenuMap coachMenuMap; public CoachList saveCoachList(final CoachList coachList) { this.coachList = coachList; @@ -15,12 +13,4 @@ public CoachList saveCoachList(final CoachList coachList) { public CoachList findCoachList() { return this.coachList; } - - public void saveCoachMenuMap(final CoachMenuMap coachMenuMap) { - this.coachMenuMap = coachMenuMap; - } - - public CoachMenuMap findCoachMenuMap() { - return this.coachMenuMap; - } } diff --git a/src/main/java/menu/service/MenuService.java b/src/main/java/menu/service/MenuService.java index 4826624c4..a69a8bd0d 100644 --- a/src/main/java/menu/service/MenuService.java +++ b/src/main/java/menu/service/MenuService.java @@ -1,7 +1,7 @@ package menu.service; -import menu.collection.CoachList; -import menu.collection.CoachMenuMap; +import menu.domain.*; +import menu.domain.RecommendResult; import menu.repository.MenuRepository; import menu.utils.MenuGenerator; @@ -14,11 +14,17 @@ public MenuService(final MenuRepository menuRepository, final MenuGenerator menu this.menuGenerator = menuGenerator; } + public RecommendResult recommendMenu() { + final CoachList coachList = menuRepository.findCoachList(); + final DayCategoryList dayCategoryList = menuGenerator.generate(new DayCategoryList(), coachList); + return new RecommendResult(coachList, dayCategoryList); + } + public CoachList saveCoachList(final CoachList coachList) { return menuRepository.saveCoachList(coachList); } - public void saveCoachMenuMap(final CoachMenuMap coachMenuMap) { - menuRepository.saveCoachMenuMap(coachMenuMap); + public void addHateMenus(final Coach coach, final HateMenuList hateMenuList) { + coach.addMenus(hateMenuList); } } From d2e301b5de3540151a6b24af3da5e351fbe789f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 20:55:09 +0900 Subject: [PATCH 27/28] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B0=8F=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=83=81=ED=99=A9=20=EA=B2=80=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 리팩토링 - 에러 메시지 수정 - 에러 검증 수정 --- src/main/java/menu/constant/ErrorMessage.java | 2 +- src/main/java/menu/io/InputValidator.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/menu/constant/ErrorMessage.java b/src/main/java/menu/constant/ErrorMessage.java index cde53967a..dda9e75d1 100644 --- a/src/main/java/menu/constant/ErrorMessage.java +++ b/src/main/java/menu/constant/ErrorMessage.java @@ -1,7 +1,7 @@ package menu.constant; public enum ErrorMessage { - COACH_NAME_INPUT_ERROR("잘못된 코치 이름 입력입니다."), + INVALID_DELIMITER_USAGE("구분자의 사용이 잘못되었습니다."), INVALID_COACH_NUM_ERROR("코치 수가 잘못되었습니다."), INVALID_COACH_NAME_LENGTH("코치의 이름 길이가 잘못되었습니다."), INVALID_MENU_NAME("잘못된 메뉴명입니다."), diff --git a/src/main/java/menu/io/InputValidator.java b/src/main/java/menu/io/InputValidator.java index 188a16d02..487486067 100644 --- a/src/main/java/menu/io/InputValidator.java +++ b/src/main/java/menu/io/InputValidator.java @@ -3,7 +3,7 @@ import menu.constant.ErrorMessage; public class InputValidator { - private static final String SPLITTER = ","; + private static final String DELIMETER = ","; public void validateCoachMenu(final String input) { if (input.isEmpty()) { @@ -14,11 +14,11 @@ public void validateCoachMenu(final String input) { public void validateSplitter(final String input) { if (invalidSplitterUsage(input)) { - throw new IllegalArgumentException(ErrorMessage.COACH_NAME_INPUT_ERROR.toString()); + throw new IllegalArgumentException(ErrorMessage.INVALID_DELIMITER_USAGE.toString()); } } private boolean invalidSplitterUsage(final String input) { - return !input.contains(SPLITTER) || input.startsWith(SPLITTER) || input.endsWith(SPLITTER); + return input.startsWith(DELIMETER) || input.endsWith(DELIMETER); } } From 692c793f44ad368caabddd81863c5fa7d35c00bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 4 Sep 2023 21:51:39 +0900 Subject: [PATCH 28/28] =?UTF-8?q?test:=20=EB=8B=A8=EC=9C=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 테스트 추가 - 기능 단위 테스트 --- src/main/java/menu/constant/Day.java | 31 ---------- src/main/java/menu/constant/ErrorMessage.java | 2 +- src/main/java/menu/domain/Coach.java | 5 +- src/main/java/menu/domain/DayCategory.java | 20 +------ .../java/menu/domain/DayCategoryList.java | 3 +- src/main/java/menu/domain/HateMenuList.java | 8 ++- src/main/java/menu/domain/Menu.java | 6 +- src/main/java/menu/service/MenuService.java | 4 +- src/main/java/menu/utils/MenuGenerator.java | 3 +- src/test/java/menu/ApplicationTest.java | 43 ++++++++++++++ src/test/java/menu/domain/CoachListTest.java | 7 +++ src/test/java/menu/domain/CoachTest.java | 7 +++ .../menu/domain/DomainValidationTest.java | 47 +++++++++++++++ .../java/menu/domain/HateMenuListTest.java | 7 +++ src/test/java/menu/domain/MenuTest.java | 7 +++ src/test/java/menu/io/InputValidatorTest.java | 25 ++++++++ .../java/menu/service/MenuServiceTest.java | 59 +++++++++++++++++++ .../java/menu/utils/MenuGeneratorTest.java | 31 ++++++++++ 18 files changed, 252 insertions(+), 63 deletions(-) delete mode 100644 src/main/java/menu/constant/Day.java create mode 100644 src/test/java/menu/domain/CoachListTest.java create mode 100644 src/test/java/menu/domain/CoachTest.java create mode 100644 src/test/java/menu/domain/DomainValidationTest.java create mode 100644 src/test/java/menu/domain/HateMenuListTest.java create mode 100644 src/test/java/menu/domain/MenuTest.java create mode 100644 src/test/java/menu/io/InputValidatorTest.java create mode 100644 src/test/java/menu/service/MenuServiceTest.java create mode 100644 src/test/java/menu/utils/MenuGeneratorTest.java diff --git a/src/main/java/menu/constant/Day.java b/src/main/java/menu/constant/Day.java deleted file mode 100644 index 3a6845bca..000000000 --- a/src/main/java/menu/constant/Day.java +++ /dev/null @@ -1,31 +0,0 @@ -package menu.constant; - -import java.util.Arrays; - -public enum Day { - MONDAY("월요일", 0), - TUESDAY("화요일", 1), - WEDNESDAY("수요일", 2), - THURSDAY("목요일", 3), - FRIDAY("금요일", 4); - - private final String day; - private final Integer order; - - Day(final String day, final Integer order) { - this.day = day; - this.order = order; - } - - public static Day getByOrder(final int order) { - return Arrays.stream(values()) - .filter(d -> d.order == order) - .findAny() - .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.INVALID_INDEX.toString())); - } - - @Override - public String toString() { - return this.day; - } -} diff --git a/src/main/java/menu/constant/ErrorMessage.java b/src/main/java/menu/constant/ErrorMessage.java index dda9e75d1..6b7826961 100644 --- a/src/main/java/menu/constant/ErrorMessage.java +++ b/src/main/java/menu/constant/ErrorMessage.java @@ -7,7 +7,7 @@ public enum ErrorMessage { INVALID_MENU_NAME("잘못된 메뉴명입니다."), NO_MATCHING_INDEX("인덱스에 해당하는 값이 없습니다."), CANNOT_FIND_CATEGORY("카테고리를 찾을 수 없습니다."), - INVALID_INDEX("잘못된 인덱스 번호입니다."); + INVALID_HATE_MENU_NUM("잘못된 못먹는 음식 개수입니다."); private static final String PREFIX = "[ERROR] "; private final String message; diff --git a/src/main/java/menu/domain/Coach.java b/src/main/java/menu/domain/Coach.java index c5d0de9c1..b22ff568d 100644 --- a/src/main/java/menu/domain/Coach.java +++ b/src/main/java/menu/domain/Coach.java @@ -24,8 +24,7 @@ public Coach(final String name) { } private void validateName(final String name) { - final int length = name.length(); - if (invalidLength(length)) { + if (invalidLength(name.length())) { throw new IllegalArgumentException(ErrorMessage.INVALID_COACH_NAME_LENGTH.toString()); } } @@ -47,7 +46,7 @@ public String getName() { return this.name; } - public void addMenus(final HateMenuList hateMenuList) { + public void addHateMenus(final HateMenuList hateMenuList) { this.hateMenuList = hateMenuList; this.availMenuList = new AvailMenuList(getAvailMenu()); } diff --git a/src/main/java/menu/domain/DayCategory.java b/src/main/java/menu/domain/DayCategory.java index d0876cb06..207f781bc 100644 --- a/src/main/java/menu/domain/DayCategory.java +++ b/src/main/java/menu/domain/DayCategory.java @@ -1,32 +1,14 @@ package menu.domain; import menu.constant.Category; -import menu.constant.Day; - -import java.util.Objects; public class DayCategory { - private final Day day; private final Category category; - public DayCategory(final Day day, final Category category) { - this.day = day; + public DayCategory(final Category category) { this.category = category; } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final DayCategory that = (DayCategory) o; - return day == that.day && category == that.category; - } - - @Override - public int hashCode() { - return Objects.hash(day, category); - } - @Override public String toString() { return this.category.toString(); diff --git a/src/main/java/menu/domain/DayCategoryList.java b/src/main/java/menu/domain/DayCategoryList.java index 116af938e..999bb92da 100644 --- a/src/main/java/menu/domain/DayCategoryList.java +++ b/src/main/java/menu/domain/DayCategoryList.java @@ -1,7 +1,6 @@ package menu.domain; import menu.constant.Category; -import menu.constant.Day; import menu.constant.ResultTag; import java.util.*; @@ -20,7 +19,7 @@ public boolean isMaxCount(final Category category) { } public void addCategory(final Category category) { - final DayCategory dayCategory = new DayCategory(Day.getByOrder(dayCategoryList.size()), category); + final DayCategory dayCategory = new DayCategory(category); dayCategoryList.add(dayCategory); } diff --git a/src/main/java/menu/domain/HateMenuList.java b/src/main/java/menu/domain/HateMenuList.java index 88ec26e1e..70462003a 100644 --- a/src/main/java/menu/domain/HateMenuList.java +++ b/src/main/java/menu/domain/HateMenuList.java @@ -1,10 +1,12 @@ package menu.domain; +import menu.constant.ErrorMessage; + import java.util.List; import java.util.stream.Collectors; public class HateMenuList { - private static final int MIN_SIZE = 2; + private static final int MAX_SIZE = 2; private final List menus; public HateMenuList(final List menus) { @@ -13,8 +15,8 @@ public HateMenuList(final List menus) { } private void validateSize(final List menus) { - if (menus.size() > MIN_SIZE) { - throw new IllegalArgumentException(); + if (menus.size() > MAX_SIZE) { + throw new IllegalArgumentException(ErrorMessage.INVALID_HATE_MENU_NUM.toString()); } } diff --git a/src/main/java/menu/domain/Menu.java b/src/main/java/menu/domain/Menu.java index a7294a23a..056ee02d5 100644 --- a/src/main/java/menu/domain/Menu.java +++ b/src/main/java/menu/domain/Menu.java @@ -6,10 +6,14 @@ public final class Menu { private final String name; public Menu(final String name) { + validateName(name); + this.name = name; + } + + private void validateName(final String name) { if (!name.isEmpty() && notContainsName(name)) { throw new IllegalArgumentException(ErrorMessage.INVALID_MENU_NAME.toString()); } - this.name = name; } private boolean notContainsName(final String name) { diff --git a/src/main/java/menu/service/MenuService.java b/src/main/java/menu/service/MenuService.java index a69a8bd0d..74e5a7cd1 100644 --- a/src/main/java/menu/service/MenuService.java +++ b/src/main/java/menu/service/MenuService.java @@ -16,7 +16,7 @@ public MenuService(final MenuRepository menuRepository, final MenuGenerator menu public RecommendResult recommendMenu() { final CoachList coachList = menuRepository.findCoachList(); - final DayCategoryList dayCategoryList = menuGenerator.generate(new DayCategoryList(), coachList); + final DayCategoryList dayCategoryList = menuGenerator.generate(coachList); return new RecommendResult(coachList, dayCategoryList); } @@ -25,6 +25,6 @@ public CoachList saveCoachList(final CoachList coachList) { } public void addHateMenus(final Coach coach, final HateMenuList hateMenuList) { - coach.addMenus(hateMenuList); + coach.addHateMenus(hateMenuList); } } diff --git a/src/main/java/menu/utils/MenuGenerator.java b/src/main/java/menu/utils/MenuGenerator.java index ca9ed9cd5..e5513abaa 100644 --- a/src/main/java/menu/utils/MenuGenerator.java +++ b/src/main/java/menu/utils/MenuGenerator.java @@ -13,7 +13,8 @@ public class MenuGenerator { private static final int MIN_RANGE = 1; private static final int MAX_RANGE = 5; - public DayCategoryList generate(final DayCategoryList dayCategoryList, final CoachList coachList) { + public DayCategoryList generate(final CoachList coachList) { + final DayCategoryList dayCategoryList = new DayCategoryList(); IntStream.range(MIN_INDEX, MAX_INDEX).forEach(i -> addOneDayRecommend(dayCategoryList, coachList)); return dayCategoryList; } diff --git a/src/test/java/menu/ApplicationTest.java b/src/test/java/menu/ApplicationTest.java index a757e7813..4a1190d59 100644 --- a/src/test/java/menu/ApplicationTest.java +++ b/src/test/java/menu/ApplicationTest.java @@ -71,6 +71,49 @@ class AllFeatureTest { ); }); } + + @Test + void 커스텀_기능_테스트() { + assertTimeoutPreemptively(RANDOM_TEST_TIMEOUT, () -> { + final Executable executable = () -> { + runException("구구,제임스", "김밥", "떡볶이"); + + assertThat(output()).contains( + "점심 메뉴 추천을 시작합니다.", + "코치의 이름을 입력해 주세요. (, 로 구분)", + "구구(이)가 못 먹는 메뉴를 입력해 주세요.", + "제임스(이)가 못 먹는 메뉴를 입력해 주세요.", + "메뉴 추천 결과입니다.", + "[ 구분 | 월요일 | 화요일 | 수요일 | 목요일 | 금요일 ]", + "추천을 완료했습니다." + ); + }; + assertRandomTest(executable, + Mocking.ofRandomNumberInRange(2, 2, 2, 5, 1, 3, 4), // 숫자는 카테고리 번호를 나타낸다. + Mocking.ofShuffle( + // 월요일 + List.of("김치찌개", "김밥", "쌈밥", "된장찌개", "비빔밥", "칼국수", "불고기", "떡볶이", "제육볶음"), // 구구 + List.of("제육볶음", "김밥", "김치찌개", "쌈밥", "된장찌개", "비빔밥", "칼국수", "불고기", "떡볶이"), // 제임스 + + // 화요일 + List.of("김치찌개", "김밥", "쌈밥", "된장찌개", "비빔밥", "칼국수", "불고기", "떡볶이", "제육볶음"), // 구구 + List.of("라자냐", "그라탱", "뇨끼", "끼슈", "프렌치 토스트", "바게트", "스파게티", "피자", "파니니"), // 제임스 + + // 수요일 + List.of("규동", "우동", "미소시루", "스시", "가츠동", "오니기리", "하이라이스", "라멘", "오코노미야끼"), // 구구 + List.of("가츠동", "규동", "우동", "미소시루", "스시", "오니기리", "하이라이스", "라멘", "오코노미야끼"), // 제임스 + + // 목요일 + List.of("짜장면", "깐풍기", "볶음면", "동파육", "짬뽕", "마파두부", "탕수육", "토마토 달걀볶음", "고추잡채"), // 구구 + List.of("짬뽕", "깐풍기", "볶음면", "동파육", "짜장면", "마파두부", "탕수육", "토마토 달걀볶음", "고추잡채"), // 제임스 + + // 금요일 + List.of("카오 팟", "팟타이", "나시고렝", "파인애플 볶음밥", "쌀국수", "똠얌꿍", "반미", "월남쌈", "분짜"), // 구구 + List.of("파인애플 볶음밥", "팟타이", "카오 팟", "나시고렝", "쌀국수", "똠얌꿍", "반미", "월남쌈", "분짜") // 제임스 + ) + ); + }); + } } @Override diff --git a/src/test/java/menu/domain/CoachListTest.java b/src/test/java/menu/domain/CoachListTest.java new file mode 100644 index 000000000..06e20c25e --- /dev/null +++ b/src/test/java/menu/domain/CoachListTest.java @@ -0,0 +1,7 @@ +package menu.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class CoachListTest { + +} \ No newline at end of file diff --git a/src/test/java/menu/domain/CoachTest.java b/src/test/java/menu/domain/CoachTest.java new file mode 100644 index 000000000..22d7e6aa9 --- /dev/null +++ b/src/test/java/menu/domain/CoachTest.java @@ -0,0 +1,7 @@ +package menu.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class CoachTest { + +} \ No newline at end of file diff --git a/src/test/java/menu/domain/DomainValidationTest.java b/src/test/java/menu/domain/DomainValidationTest.java new file mode 100644 index 000000000..cdd54465c --- /dev/null +++ b/src/test/java/menu/domain/DomainValidationTest.java @@ -0,0 +1,47 @@ +package menu.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("도메인 생성시 검증 로직 중") +class DomainValidationTest { + + @Test + @DisplayName("코치의 이름의 길이가 2 미만인 경우 예외를 던진다.") + void coachValidation1() { + assertThatThrownBy(() -> new Coach("a")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("코치의 이름의 길이가 4 초과인 경우 예외를 던진다.") + void coachValidation2() { + assertThatThrownBy(() -> new Coach("aaaaa")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("코치가 2명 미만인 경우 예외를 던진다.") + void coachListValidation() { + assertThatThrownBy(() -> new CoachList(List.of("aa"))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("코치의 이름의 길이가 4 초과인 경우 예외를 던진다.") + void hateMenuListValidation() { + assertThatThrownBy(() -> new HateMenuList(List.of("aa", "bb", "cc"))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("정해진 이름의 메뉴가 아닌 경우 예외를 던진다.") + void menuValidation() { + assertThatThrownBy(() -> new Menu("aa")) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/menu/domain/HateMenuListTest.java b/src/test/java/menu/domain/HateMenuListTest.java new file mode 100644 index 000000000..e30906b54 --- /dev/null +++ b/src/test/java/menu/domain/HateMenuListTest.java @@ -0,0 +1,7 @@ +package menu.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class HateMenuListTest { + +} \ No newline at end of file diff --git a/src/test/java/menu/domain/MenuTest.java b/src/test/java/menu/domain/MenuTest.java new file mode 100644 index 000000000..b9a2e20a5 --- /dev/null +++ b/src/test/java/menu/domain/MenuTest.java @@ -0,0 +1,7 @@ +package menu.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class MenuTest { + +} \ No newline at end of file diff --git a/src/test/java/menu/io/InputValidatorTest.java b/src/test/java/menu/io/InputValidatorTest.java new file mode 100644 index 000000000..876cbddec --- /dev/null +++ b/src/test/java/menu/io/InputValidatorTest.java @@ -0,0 +1,25 @@ +package menu.io; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("InputValidator 의 검증로직에서") +class InputValidatorTest { + private final InputValidator inputValidator = new InputValidator(); + + @Test + @DisplayName("콤마로 끝나는 입력값에 대해 예외를 던진다.") + void validateSplitter1() { + assertThatThrownBy(() -> inputValidator.validateCoachMenu("aa,")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("콤마로 시작하는 입력값에 대해 예외를 던진다.") + void validateSplitter2() { + assertThatThrownBy(() -> inputValidator.validateCoachMenu(",aa")) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/menu/service/MenuServiceTest.java b/src/test/java/menu/service/MenuServiceTest.java new file mode 100644 index 000000000..be4d12e3f --- /dev/null +++ b/src/test/java/menu/service/MenuServiceTest.java @@ -0,0 +1,59 @@ +package menu.service; + +import menu.domain.*; +import menu.repository.MenuRepository; +import menu.utils.MenuGenerator; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("MenuService의") +class MenuServiceTest { + private final MenuRepository menuRepository = new MenuRepository(); + private final MenuService menuService = new MenuService(menuRepository, new MenuGenerator()); + + @Test + @DisplayName("메뉴 추천이 수행되는가") + void recommendMenu() { + //given + final CoachList coachList = menuRepository.saveCoachList(new CoachList(List.of("aa", "bb"))); + final String 짜장면 = "짜장면"; + coachList.getAllCoaches().forEach(c -> c.addHateMenus(new HateMenuList(List.of(짜장면)))); + + //when + final RecommendResult recommendResult = menuService.recommendMenu(); + + //then + assertThat(recommendResult.toString()).doesNotContain(짜장면); + } + + @Test + @DisplayName("코치 리스트 저장이 수행되는가") + void saveCoachList() { + //given + + //when + final CoachList expected = new CoachList(List.of("aa", "bb")); + final CoachList coachList = menuService.saveCoachList(expected); + + //then + assertThat(coachList).isEqualTo(expected); + } + + @Test + @DisplayName("못먹는 음식 추가가 수행되는가") + void addHateMenus() { + //given + menuRepository.saveCoachList(new CoachList(List.of("aa", "bb"))); + + //when + final Coach coach = menuRepository.findCoachList().getAllCoaches().get(0); + menuService.addHateMenus(coach, new HateMenuList(List.of("탕수육", "짜장면"))); + + //then + + } +} diff --git a/src/test/java/menu/utils/MenuGeneratorTest.java b/src/test/java/menu/utils/MenuGeneratorTest.java new file mode 100644 index 000000000..79e87f7a2 --- /dev/null +++ b/src/test/java/menu/utils/MenuGeneratorTest.java @@ -0,0 +1,31 @@ +package menu.utils; + +import menu.domain.CoachList; +import menu.domain.DayCategoryList; +import menu.domain.HateMenuList; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +@DisplayName("MenuGenerator의") +class MenuGeneratorTest { + private final MenuGenerator menuGenerator = new MenuGenerator(); + + @Test + @DisplayName("메뉴 생성 로직이 수행되는가") + void generate() { + //given + final CoachList coachList = new CoachList(List.of("aa", "bb")); + final String 탕수육 = "탕수육"; + coachList.getAllCoaches().forEach(c -> c.addHateMenus(new HateMenuList(List.of(탕수육)))); + + //when + final DayCategoryList dayCategoryList = menuGenerator.generate(coachList); + + //then + assertThat(dayCategoryList.toString()).doesNotContain(탕수육); + } +}