ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,38 @@
+package christmas.domain.calendar.enums;
+
+import christmas.domain.sale.enums.BenefitCategory;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+
+import static christmas.domain.sale.enums.BenefitCategory.WEEKDAY_SALE;
+import static christmas.domain.sale.enums.BenefitCategory.WEEKEND_SALE;
+import static christmas.domain.calendar.enums.YearMonthDateDefinition.*;
+
+public enum Week {
+    WEEKDAY(WEEKDAY_SALE),
+    WEEKEND(WEEKEND_SALE);
+
+
+    private final BenefitCategory benefitCategory;
+
+    Week(BenefitCategory benefitCategory) {
+        this.benefitCategory = benefitCategory;
+    }
+
+    public static Week determineWeek(int date) {
+        LocalDate localDate = LocalDate.of(YEAR.get(), MONTH.get(), date);
+        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
+        int week = dayOfWeek.getValue();
+
+        if (week >= WEEKEND_START.get() && week <= WEEKEND_END.get()) {
+            return WEEKEND;
+        }
+        return WEEKDAY;
+    }
+
+
+    public BenefitCategory getBenefitCategory() {
+        return benefitCategory;
+    }
+}

리뷰: enum 클래스의 활용도가 굉장히 높으신 것 같아요! enum 사용법 많이 배워갑니다 ㅎㅎ
@@ -0,0 +1,49 @@
+package christmas.domain;
+
+import christmas.global.view.io.EventCalendarView;
+import christmas.global.view.io.OrdersView;
+import christmas.global.view.io.BenefitDetailsView;
+import christmas.global.view.output.OutputView;
+
+import static christmas.global.view.message.OrderDynamicMessage.SHOW_EVENT;
+
+public class EventController {
+    private final EventCalendarView eventCalendarView;
+    private final OrdersView ordersView;
+    private final BenefitDetailsView benefitDetailsView;
+
+    public EventController(EventCalendarView eventCalendarView, OrdersView ordersView, BenefitDetailsView benefitDetailsView) {
+        this.eventCalendarView = eventCalendarView;
+        this.ordersView = ordersView;
+        this.benefitDetailsView = benefitDetailsView;
+    }
+
+    public void play() {
+        takeReservation();
+        showOrderedMenus();
+        showEventPreview();
+    }
+    public void takeReservation() {
+        int date = inputVisitDate();
+
+        inputOrders();
+        OutputView.println(SHOW_EVENT.get(date));
+    }
+
+    public int inputVisitDate() {
+        return eventCalendarView.inputVisitDate();
+    }
+
+    public void inputOrders() {
+        ordersView.inputOrders();
+    }
+
+    public void showOrderedMenus() {
+        ordersView.showOrderMenus();
+    }
+
+    public void showEventPreview() {
+        benefitDetailsView.showEventPreview();
+    }
+
+}

리뷰: P5: 패키징이 묘한 것이어요 ㅋㅋㅋ

어떤 목적으로 패키징을 하셨는지 궁금합니당 🤔 
(docs/README.md에 추가해주셔도 좋았을 것 같고요?!)
@@ -0,0 +1,29 @@
+package christmas.global.view.io;
+
+import christmas.domain.calendar.EventCalendar;
+import christmas.domain.calendar.dto.DateDto;
+import christmas.global.view.input.InputView;
+import christmas.global.view.output.OutputView;
+
+import static christmas.global.view.message.OrderStaticMessage.EXPECTED_VISIT_DATE;
+import static christmas.global.view.message.OrderStaticMessage.START_MESSAGE;
+
+public class EventCalendarView implements InteractionRepeatable{
+    private final EventCalendar eventCalendar;
+
+    public EventCalendarView(EventCalendar eventCalendar) {
+        this.eventCalendar = eventCalendar;
+    }
+
+    public int inputVisitDate() {
+        OutputView.println(START_MESSAGE.get());
+        OutputView.println(EXPECTED_VISIT_DATE.get());
+
+        return supplyInteraction(() -> {
+            String input = InputView.input();
+            DateDto dateDto = new DateDto(input);
+
+            return eventCalendar.takeReservation(dateDto.date());
+        });
+    }
+}

리뷰: P2: 이 뷰의 역할이 어떤 건지 명확히 해야할 것 같아요. 🤔 

지금은 뷰 계층도 여러 단계로 추상화 되어있고, 컨트롤러에서 받...을것만 같은 DTO도 도입이 되어있는데, 정작 호출한 쪽으로 돌아가는 건 `int` 타입의 값 하나란 말이죠. '전송되지 않는 전송객체(DTO)는 왜 존재하는 거지?....' 이런 생각이 충분히 들 수 있는 코드인 것 같거든요.

- 왜 `InputView`와 `EventCalendarView`가 나뉘었는가
- 왜 DateDto를 도입했는가
- 왜 반환값을 `View`가 아닌 `eventCalendar`가 만들어 반환하는가
- 왜 그 반환 타입이 `int`인가 (추상화된 뷰 계층이 단순 원시 타입을 반환하는게 적절한가?)
- 여러 클래스로 나뉘지 않았어도, InputView만 있어도 어색하지 않게 구현 가능하지 않을까?

요런 부분들을 고민해보면 좋을 것 같아요

다르게 말하면, 계층이 나눠진 목적이 드러나면 좋겠어요. 목적을 드러내기 어렵다면, 아예 계층을 나누지 않는 것도 좋고요.

시간 날 때 한번 생각해봐 주세요...! 😄
@@ -0,0 +1,49 @@
+package christmas.domain;
+
+import christmas.global.view.io.EventCalendarView;
+import christmas.global.view.io.OrdersView;
+import christmas.global.view.io.BenefitDetailsView;
+import christmas.global.view.output.OutputView;
+
+import static christmas.global.view.message.OrderDynamicMessage.SHOW_EVENT;
+
+public class EventController {
+    private final EventCalendarView eventCalendarView;
+    private final OrdersView ordersView;
+    private final BenefitDetailsView benefitDetailsView;
+
+    public EventController(EventCalendarView eventCalendarView, OrdersView ordersView, BenefitDetailsView benefitDetailsView) {
+        this.eventCalendarView = eventCalendarView;
+        this.ordersView = ordersView;
+        this.benefitDetailsView = benefitDetailsView;
+    }
+
+    public void play() {
+        takeReservation();
+        showOrderedMenus();
+        showEventPreview();
+    }
+    public void takeReservation() {
+        int date = inputVisitDate();
+
+        inputOrders();
+        OutputView.println(SHOW_EVENT.get(date));
+    }
+
+    public int inputVisitDate() {
+        return eventCalendarView.inputVisitDate();
+    }
+
+    public void inputOrders() {
+        ordersView.inputOrders();
+    }
+
+    public void showOrderedMenus() {
+        ordersView.showOrderMenus();
+    }
+
+    public void showEventPreview() {
+        benefitDetailsView.showEventPreview();
+    }
+
+}

리뷰: P4: 30라인의 코드는 뷰 객체로 이전할수 있을 거 같아요..!

엇 근데 이벤트 안내 문구 출력 코드가 `takeReservation()` 안에.... 😭
@@ -0,0 +1,92 @@
+package christmas.domain.order.enums.food;
+
+import java.util.*;
+
+import static christmas.global.exception.OrderExceptionMessage.INVALID_ORDERS;
+
+public enum Food {
+    양송이수프(FoodCategory.APPETIZER,"양송이수프", 6000),
+    타파스(FoodCategory.APPETIZER, "타파스", 5500),
+    시저샐러드(FoodCategory.APPETIZER, "시저샐러드", 8000),
+
+    티본스테이크(FoodCategory.MAIN_DISH, "티본스테이크", 55000),
+    바비큐립(FoodCategory.MAIN_DISH, "바비큐립", 54000),
+    해산물파스타(FoodCategory.MAIN_DISH, "해산물파스타",35000),
+    크리스마스파스타(FoodCategory.MAIN_DISH, "크리스마스파스타",25000),
+
+    초코케이크(FoodCategory.DESSERT, "초코케이크",15000),
+    아이스크림(FoodCategory.DESSERT, "아이스크림",5000),
+
+    제로콜라(FoodCategory.DRINK, "제로콜라",3000),
+    레드와인(FoodCategory.DRINK, "레드와인",60000),
+    샴페인(FoodCategory.DRINK, "샴페인",25000);
+
+    private final FoodCategory foodCategory;
+    private final String food;
+    private final int price;
+
+    Food(FoodCategory foodCategory, String food, int price) {
+        this.foodCategory = foodCategory;
+        this.food = food;
+        this.price = price;
+    }
+
+
+    public static Food findByFood(String food) {
+        return Arrays.stream(Food.values())
+                .filter(f -> f.food.equals(food))
+                .findFirst()
+                .orElseThrow(() -> new IllegalArgumentException(INVALID_ORDERS.get()));
+    }
+
+    public static Map<FoodCategory, Integer> sortByFoodCategory(Map<Food, Integer> foodMap) {
+        Map<FoodCategory, Integer> foodCategoryMap = new EnumMap<>(FoodCategory.class);
+
+        for (Food food : foodMap.keySet()) {
+            FoodCategory foodCategory = food.foodCategory;
+            int count = foodCategoryMap.getOrDefault(foodCategory, 0);
+            count += foodMap.get(food);
+
+            foodCategoryMap.put(foodCategory, count);
+        }
+
+        return foodCategoryMap;
+    }
+
+    public static int calculateTotalPrice(Map<Food, Integer> foodMap) {
+        int totalPrice = 0;
+
+        for (Food food : foodMap.keySet()) {
+            int price = food.price;
+            int foodCount = foodMap.get(food);
+            totalPrice += price * foodCount;
+        }
+
+        return totalPrice;
+    }
+
+    public static String generateOrderedMenu(Map<Food, Integer> foodMap) {
+        StringBuilder menu = new StringBuilder();
+
+        for (Food food : foodMap.keySet()) {
+            String foodName = food.food;
+            int count = foodMap.get(food);
+            String order = String.format("%s %s개\n",foodName, count);
+            menu.append(order);
+        }
+        return menu.toString();
+
+    }
+
+    public FoodCategory getFoodCategory() {
+        return foodCategory;
+    }
+
+    public String getFood() {
+        return food;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+}

리뷰: P3: `generateOrderedMenu()`에 파라미터로 통째로 맵을 넘겨주지 않고, 밖에서 맵을 순회하면서 `Food`에는 `getOrderedFoodName(food:Food)` 같은 메서드만 호출해서 결과를 받아보게 하면 더 좋을 것 같아요 😇 👍
@@ -0,0 +1,75 @@
+package christmas.global.view.io;
+
+import christmas.domain.badge.Enum.EventBadge;
+import christmas.domain.sale.BenefitDetails;
+import christmas.domain.sale.enums.Giveaway;
+import christmas.global.view.output.OutputView;
+
+import static christmas.global.view.message.PriceMessage.getDiscountPriceMessage;
+import static christmas.global.view.message.PriceMessage.getPriceMessage;
+import static christmas.global.view.message.TitleMessage.*;
+
+public class BenefitDetailsView implements InteractionRepeatable{
+    private final BenefitDetails benefitDetails;
+
+    public BenefitDetailsView(BenefitDetails benefitDetails) {
+        this.benefitDetails = benefitDetails;
+    }
+
+    public void showEventPreview() {
+        calculateTotalPrice();
+        showResult();
+    }
+
+    public void calculateTotalPrice() {
+        benefitDetails.calculateTotalPrice();
+        benefitDetails.calculateTotalSaleAmount();
+
+        int totalPrice = benefitDetails.getTotalPrice();
+
+        OutputView.println(BEFORE_SALE_PRICE.get());
+        OutputView.println(getPriceMessage(totalPrice));
+    }
+
+    public void showResult() {
+        showFreeGift();
+        showTotalBenefitDetails();
+        int totalBenefitAmount = showTotalBenefitAmount();
+        showFinalTotalPrice();
+        showBadge(totalBenefitAmount);
+    }
+
+    private void showFreeGift() {
+        Giveaway giveaway = benefitDetails.calculateFreeGiftPrice();
+
+        OutputView.println(GIVEAWAY_MENU.get());
+        OutputView.println(giveaway.getProduct());
+        OutputView.printNextLine();
+    }
+
+    private void showTotalBenefitDetails() {
+        OutputView.println(BENEFIT.get());
+        String benefitDetails = this.benefitDetails.getTotalBenefitMessage();
+        OutputView.println(benefitDetails);
+    }
+
+    private int showTotalBenefitAmount() {
+        int totalBenefitAmount = benefitDetails.calculateTotalBenefitAmount();
+        OutputView.println(TOTAL_BENEFIT_AMOUNT.get());
+        OutputView.println(getDiscountPriceMessage(totalBenefitAmount));
+
+        return totalBenefitAmount;
+    }
+
+    private void showFinalTotalPrice() {
+        OutputView.println(AFTER_SALE_PRICE.get());
+        int totalFinalPrice = this.benefitDetails.calculateFinalPrice();
+        OutputView.println(getPriceMessage(totalFinalPrice));
+    }
+
+    private void showBadge(int totalBenefitAmount) {
+        String badge = EventBadge.getBadge(totalBenefitAmount);
+        OutputView.println(EVENT_BADGE.get());
+        OutputView.println(badge);
+    }
+}

리뷰: P5: 25라인의 `calculateTotalPrice()`가 
-> `BenefitDetails#calculateTotalPrice()`
-> `SaleDetails#calculateTotalPrice()`
-> `Orders#calculateTotalPrice(foodMap)`
-> `Food.calculateTotalPrice(foodMap)`

이런식으로 호출이 되는데요.
BenefitDetails와 SaleDetails는 어떤 목적으로 거쳐가도록 구현하셨는지 궁금합니다!
@@ -0,0 +1,75 @@
+package christmas.global.view.io;
+
+import christmas.domain.badge.Enum.EventBadge;
+import christmas.domain.sale.BenefitDetails;
+import christmas.domain.sale.enums.Giveaway;
+import christmas.global.view.output.OutputView;
+
+import static christmas.global.view.message.PriceMessage.getDiscountPriceMessage;
+import static christmas.global.view.message.PriceMessage.getPriceMessage;
+import static christmas.global.view.message.TitleMessage.*;
+
+public class BenefitDetailsView implements InteractionRepeatable{
+    private final BenefitDetails benefitDetails;
+
+    public BenefitDetailsView(BenefitDetails benefitDetails) {
+        this.benefitDetails = benefitDetails;
+    }
+
+    public void showEventPreview() {
+        calculateTotalPrice();
+        showResult();
+    }
+
+    public void calculateTotalPrice() {
+        benefitDetails.calculateTotalPrice();
+        benefitDetails.calculateTotalSaleAmount();
+
+        int totalPrice = benefitDetails.getTotalPrice();
+
+        OutputView.println(BEFORE_SALE_PRICE.get());
+        OutputView.println(getPriceMessage(totalPrice));
+    }
+
+    public void showResult() {
+        showFreeGift();
+        showTotalBenefitDetails();
+        int totalBenefitAmount = showTotalBenefitAmount();
+        showFinalTotalPrice();
+        showBadge(totalBenefitAmount);
+    }
+
+    private void showFreeGift() {
+        Giveaway giveaway = benefitDetails.calculateFreeGiftPrice();
+
+        OutputView.println(GIVEAWAY_MENU.get());
+        OutputView.println(giveaway.getProduct());
+        OutputView.printNextLine();
+    }
+
+    private void showTotalBenefitDetails() {
+        OutputView.println(BENEFIT.get());
+        String benefitDetails = this.benefitDetails.getTotalBenefitMessage();
+        OutputView.println(benefitDetails);
+    }
+
+    private int showTotalBenefitAmount() {
+        int totalBenefitAmount = benefitDetails.calculateTotalBenefitAmount();
+        OutputView.println(TOTAL_BENEFIT_AMOUNT.get());
+        OutputView.println(getDiscountPriceMessage(totalBenefitAmount));
+
+        return totalBenefitAmount;
+    }
+
+    private void showFinalTotalPrice() {
+        OutputView.println(AFTER_SALE_PRICE.get());
+        int totalFinalPrice = this.benefitDetails.calculateFinalPrice();
+        OutputView.println(getPriceMessage(totalFinalPrice));
+    }
+
+    private void showBadge(int totalBenefitAmount) {
+        String badge = EventBadge.getBadge(totalBenefitAmount);
+        OutputView.println(EVENT_BADGE.get());
+        OutputView.println(badge);
+    }
+}

리뷰: P5: benefitDetails를 필드로 두고, 이렇게 showResult() 안에서 사용하니 코드가 깔끔해지고 좋네요 😇 👍
@@ -0,0 +1,39 @@
+package christmas.domain.badge.Enum;
+
+import static christmas.global.exception.CommonExceptionMessage.UNEXPECTED_EXCEPTION;
+
+public enum EventBadge {
+    NONE("없음", 0)
+    ,STAR("별", 5_000)
+    ,TREE("트리", 10_000)
+    ,SANTA("산타", 20_000)
+    ;
+
+    private final String badge;
+    private final int benefitPrice;
+
+    EventBadge(String badge, int benefitPrice) {
+        this.badge = badge;
+        this.benefitPrice = benefitPrice;
+    }
+
+    public static String getBadge(int benefitPrice) {
+        validateBenefitPrice(benefitPrice);
+        if(benefitPrice >= SANTA.benefitPrice) {
+            return SANTA.badge;
+        }
+        if(benefitPrice >= TREE.benefitPrice) {
+            return TREE.badge;
+        }
+        if(benefitPrice >= STAR.benefitPrice) {
+            return STAR.badge;
+        }
+        return NONE.badge;
+    }
+
+    public static void validateBenefitPrice(int benefitPrice) {
+        if (benefitPrice < 0) {
+            throw new IllegalStateException(UNEXPECTED_EXCEPTION.get());
+        }
+    }
+}

리뷰: P4: 정적메서드에서 유효성 검증을 한번 더 거치는 것 정말 꼼꼼하고 좋네요 👍 

P4: 22~31라인의 다중 if 문은 enum의 기능을 활용해서 해결 할 수 있지 않을까요? 😇
@@ -0,0 +1,38 @@
+package christmas.global.config;
+
+import christmas.domain.EventController;
+import christmas.domain.calendar.EventCalendar;
+import christmas.domain.order.Orders;
+import christmas.domain.sale.BenefitDetails;
+import christmas.domain.sale.ChristmasDDaySale;
+import christmas.domain.sale.SaleDetails;
+import christmas.global.view.io.BenefitDetailsView;
+import christmas.global.view.io.EventCalendarView;
+import christmas.global.view.io.OrdersView;
+
+public class Dependency {
+    public static EventController eventController() {
+        return new EventController(eventCalendarView(), ordersView(), benefitDetailsView());
+    }
+
+    public static BenefitDetailsView benefitDetailsView() {
+        return new BenefitDetailsView(benefitDetails());
+    }
+
+    public static OrdersView ordersView() {
+        return new OrdersView(Orders.getInstance());
+    }
+
+    public static EventCalendarView eventCalendarView() {
+        return new EventCalendarView(EventCalendar.getInstance());
+    }
+
+    public static BenefitDetails benefitDetails() {
+        return new BenefitDetails(saleDetails());
+    }
+
+    public static SaleDetails saleDetails() {
+        return new SaleDetails(Orders.getInstance(), EventCalendar.getInstance(), ChristmasDDaySale.getInstance());
+    }
+
+}

리뷰: P3: 연관관계 정보가 완전히 분리되지 않은 것 같아요..!

코드 안에서만 분리할거라면 Application쪽의 메서드로만 분리해도 충분할거 같고, 지금처럼 Dependency 파일을 아예 따로 뺄 거라면, Orders가 자신의 인스턴스가 무엇인지 전혀 알지 못하게 밖에서 주입하도록 만들어주는게 좋을 것 같아요.
@@ -1,7 +1,16 @@
 package christmas;
 
+import christmas.config.Dependency;
+
 public class Application {
     public static void main(String[] args) {
-        // TODO: 프로그램 구현
+
+        try {
+            EventPlanner eventPlanner = Dependency.eventPlannner();
+            eventPlanner.run();
+        } catch (Exception e) {
+            System.out.println();
+            throw e;
+        }
     }
 }

리뷰: P5: 요구사항이 다 구현되지 않은 것 같아요 😭 ...
@@ -1,7 +1,16 @@
 package christmas;
 
+import christmas.config.Dependency;
+
 public class Application {
     public static void main(String[] args) {
-        // TODO: 프로그램 구현
+
+        try {
+            EventPlanner eventPlanner = Dependency.eventPlannner();
+            eventPlanner.run();
+        } catch (Exception e) {
+            System.out.println();
+            throw e;
+        }
     }
 }

리뷰: P5: 진짜 사소한 건데요. 
이 공백 출력의 의미...는 뭘까요?... 🤔 ...
@@ -0,0 +1,42 @@
+package christmas.domain;
+
+import christmas.constant.Calendar;
+import christmas.constant.FoodName;
+import christmas.validator.DateValidator;
+import christmas.view.InputView;
+import christmas.view.OutputView;
+
+public class Date {
+    int date;
+
+    public void saveDate(){
+        String input = InputView.inputDate();
+        this.date = DateValidator.validateDate(input);
+    }
+
+
+
+    public int calculateChristmasEvent() {
+        if(25 < date){
+            return 0;
+        }else if(1 <= date && date <= 25){
+            return 900 + date * 100 ;
+            //christmas 이벤트 할인 값 구하는 식
+        }
+        return 0;
+    }
+
+    public boolean checkStarEvent(){
+        return Calendar.isStarByDate(this.date);
+    }
+
+    public String checkSaleSort(){
+        return Calendar.getSaleSortByDate(this.date);
+    }
+
+    public void printStartResultLine(){
+        OutputView.printResultStart(date);
+    }
+
+
+}

리뷰: P2: `Date`가 단순 값타입은 아니고 자기만의 역할을 가진 객체로 보여지는데요!
그렇다면 여기서 뷰를 호출하게 되면, 뷰와 비즈니스 로직이 강하게 연관된다는 생각이 들어요.

우테코 요구사항에 있었듯이 뷰를 분리해주려면, 승훈님께서 구현해놓으신 컨트롤러나, `EventPlanner`나, 아니면 서비스 보다 앞서있는 어떤 제3의 객체에서, 뷰를 처리하고 값만 `Date`쪽으로 넘겨주면 될 것 같아요..!
@@ -0,0 +1,33 @@
+package christmas.validator;
+
+import jdk.jshell.spi.ExecutionControl.RunException;
+
+public class DateValidator {
+
+    public static int validateDate(String input) {
+        validateInputType(input);
+
+        try {
+            if (input == null) {
+                throw new IllegalArgumentException("[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요.");
+            }
+
+            int date = Integer.parseInt(input);
+
+            if (date < 1 || date > 31) {
+                throw new IllegalArgumentException("[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요.");
+            }
+
+            return date;
+
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("[ERROR] 유효하지 않은 날짜 형식입니다. 다시 입력해 주세요.");
+        }
+    }
+
+    private static void validateInputType(String input) {
+        if (!(input instanceof String)) {
+            throw new IllegalArgumentException("[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요.");
+        }
+    }
+}
\ No newline at end of file

리뷰: P5: 타입까지 검증하시려고 노력하신 부분이 보여서 정말 좋은 것 같아요 😇 👍 

그런데 원천 input의 타입은 무조건 String이 될 수 밖에 없어요! 일부러 앞에서 타입을 변환하지 않는 이상은요(만약 그렇다면, 의도에 따라 바뀐 것이니 예외적인 상황이 아니겠죠..!)
그래서 이 부분의 코드는 제거해도 좋을 것 같습니다..!
@@ -0,0 +1,60 @@
+package christmas.constant;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+public enum FoodName {
+    MUSHROOM_SOUP("양송이수프",6000,"APPITIZER"),
+    TAPAS("타파스", 6000,"APPITIZER"),
+    CEASAR_SALAD("시저샐러드", 6000,"APPITIZER"),
+    T_BONE_STAKE("티본스테이크", 6000,"MAIN"),
+    BARBECUE_RIBS("바베큐립", 6000,"MAIN"),
+    SEAFOOD_PASTA("해산물파스타", 6000,"MAIN"),
+    CHRISTMAS_PASTA("크리스마스파스타", 6000,"MAIN"),
+    CHOCOLATE_CAKE("초코케이크", 6000,"DESSERT"),
+    ICE_CREAM("아이스크림", 6000,"DESSERT"),
+    ZERO_COLA("제로콜라", 6000,"DRINK"),
+    RED_WINE("레드와인", 6000,"DRINK"),
+    CHAMPAGNE("샴페인", 6000,"DRINK");
+
+    private final String name;
+    private final int price;
+    private final String sort;
+
+    FoodName(String name, int price, String sort) {this.name = name; this.price = price;
+        this.sort = sort;
+    }
+
+    private String getName() {
+        return name;
+    }
+
+    private int getPrice() {
+        return price;
+    }
+
+    private String getSort() {return sort;}
+
+    public static String[] getAllFoodNames() {
+        return Arrays.stream(FoodName.values())
+                .map(FoodName::getName)
+                .toArray(String[]::new);
+    }
+
+    public static int getPriceByName(String name) {
+        return Stream.of(values())
+                .filter(foodName -> foodName.getName().equals(name))
+                .findFirst()
+                .map(FoodName::getPrice)
+                .orElse(0);
+    }
+
+    public static boolean isNameAndSortMatch(String name, String sort) {
+        return Arrays.stream(values())
+                .filter(foodName -> foodName.getSort().equals(sort))
+                .anyMatch(foodName -> foodName.getName().equals(name));
+    }
+
+
+
+}

리뷰: P4: enum으로 메뉴를 구현하신 부분 정말 좋은 것 같아요 👍 

그런데 어플리케이션이 정상동작 하지 않는 이유 중 일부가 여기 숨어있었군요
가격이 전부 6000원... 😭 

한가지만 의견을 내보자면, 음식의 카테고리(`sort`)도 enum으로 관리해보면 좋을 거 같아요!
@@ -0,0 +1,27 @@
+package christmas;
+
+import christmas.controller.EventController;
+
+public class EventPlanner {
+    private final EventController eventController;
+
+    public EventPlanner(EventController eventController) {
+        this.eventController = eventController;
+    }
+
+    public void run(){
+        startRequestInfo();
+        startOrderProgram();
+        runOrderProgram();
+    }
+
+    private void startRequestInfo(){
+        eventController.requestInfo();
+    }
+
+    private void startOrderProgram(){eventController.startPrintingResult();}
+
+    private void runOrderProgram(){
+        eventController.runDecemberEvent();
+    }
+}

리뷰: P5: 질문드립니다..!
EventPlanner와 EventController의 역할이 다소 중첩되는 것 같은데요(다르게 말하면, 한 객체로 할 수 있는 역할을 둘로 쪼갠 것 같은데요)

나누신 이유가 어떤건지 궁금합니다!