ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,82 @@
+package christmas.controller;
+
+import static christmas.domain.event.EventConstants.*;
+
+import christmas.domain.restaurant.Orders;
+import christmas.domain.restaurant.VisitDate;
+import christmas.service.RestaurantCalculator;
+import christmas.view.inputview.InputValueType;
+import christmas.view.inputview.InputView;
+import christmas.view.outputview.OutputView;
+
+public class WootecoRestaurantController {
+    private final RestaurantCalculator restaurantCalculator;
+    private final EventPlanerController eventPlanerController;
+
+    public WootecoRestaurantController(RestaurantCalculator restaurantCalculator,
+                                       EventPlanerController eventPlanerController) {
+        this.restaurantCalculator = restaurantCalculator;
+        this.eventPlanerController = eventPlanerController;
+    }
+
+    public void takeReservation() {
+        VisitDate visitDate = getVisitDate();
+        Orders orders = getOrders();
+        int orderTotalAmount = getOrderTotalAmount(orders);
+
+        showEventPreviewMessage(visitDate);
+        showOrderDetails(orders, orderTotalAmount);
+        executeEvent(visitDate, orders, orderTotalAmount);
+    }
+
+    private VisitDate getVisitDate() {
+        OutputView.printHelloMessage();
+        VisitDate visitDate = inputVisitDate();
+        return visitDate;
+    }
+
+    private Orders getOrders() {
+        OutputView.printMenu();
+        Orders orders = inputOrders();
+        return orders;
+    }
+
+    private int getOrderTotalAmount(Orders orders) {
+        return restaurantCalculator.getOrderTotalAmount(orders);
+    }
+
+    private static void showEventPreviewMessage(VisitDate visitDate) {
+        OutputView.printEventPreviewMessage(visitDate);
+    }
+
+    private static void showOrderDetails(Orders orders, int orderTotalAmount) {
+        OutputView.printOrder(orders, orderTotalAmount);
+    }
+
+    private void executeEvent(VisitDate visitDate, Orders orders, int orderTotalAmount) {
+        if (canApplyEvent(orderTotalAmount)) {
+            eventPlanerController.executeEventPlaner(visitDate, orders, orderTotalAmount);
+        }
+    }
+
+    private boolean canApplyEvent(int orderTotalAmount) {
+        if (isOrderTotalAmountValidForEvent(orderTotalAmount)) {
+            return true;
+        }
+
+        eventPlanerController.notApplyEvent(orderTotalAmount);
+        return false;
+    }
+
+    private static boolean isOrderTotalAmountValidForEvent(int orderTotalAmount) {
+        return orderTotalAmount >= EVENT_MIN_PAY_AMOUNT.getValue();
+    }
+
+    private Orders inputOrders() {
+        return (Orders) InputView.inputValue(InputValueType.ORDERS);
+    }
+
+    private VisitDate inputVisitDate() {
+        return (VisitDate) InputView.inputValue(InputValueType.VISIT_DATE);
+    }
+}

리뷰: 제가 해당 부분의 기능 구현을 까먹고있다가 마지막에 하게 되었는데, 이러한 문제가 발생했네요. 

기본 MVC 패턴의 컨트롤러 역할을 생각해보면 이벤트 도메인이나 서비스에서 해당 로직을 처리하는 것이 좋아보입니다. 감사합니다!
@@ -0,0 +1,74 @@
+package christmas.controller;
+
+import christmas.domain.*;
+import christmas.message.ErrorMessage;
+import christmas.view.InputView;
+import christmas.view.OutputView;
+
+public class ChristmasPromotionController {
+    private EventCalendar eventCalendar;
+    private VisitDate visitDate;
+    private Menu menu;
+    private Event event;
+    private StarDate starDate;
+
+    public void run() {
+        eventCalendarSetting(2023, 12);
+        starDateSetting();
+        visitDate();
+        menuSetting();
+        eventSetting();
+        result();
+    }
+
+    private void eventCalendarSetting(int year, int month) {
+        this.eventCalendar = new EventCalendar(year, month);
+    }
+
+    private void starDateSetting() {
+        this.starDate = new StarDate(eventCalendar);
+    }
+
+    private void visitDate() {
+        OutputView.printStart();
+        while (true) {
+            try {
+                this.visitDate = VisitDate.of(InputView.readDate(), this.eventCalendar);
+                return;
+            } catch (IllegalArgumentException e) {
+                OutputView.printErrorMessage(ErrorMessage.INVALID_DATE.getFormattedMessage());
+                System.out.println(e.getMessage());
+                System.out.println();
+            }
+        }
+    }
+
+    private void menuSetting() {
+        while (true) {
+            try {
+                this.menu = new Menu(InputView.readMenu());
+                return;
+            } catch (IllegalArgumentException e) {
+                OutputView.printErrorMessage(ErrorMessage.INVALID_ORDER.getFormattedMessage());
+                System.out.println(e.getMessage());
+                OutputView.printAllMenu(e.getMessage());
+                System.out.println();
+            }
+        }
+    }
+
+    private void eventSetting() {
+        this.event = new Event();
+        this.event.eventSetting(visitDate, eventCalendar, starDate, menu);
+    }
+
+    private void result() {
+        OutputView.printSelectMenu(menu);
+        OutputView.printBeforeDiscountMenuTotalPrice(menu);
+        OutputView.printGift(event);
+        OutputView.printBenefitHistory(event);
+        OutputView.printBenefitsAllAmount(event);
+        OutputView.printAfterDiscount(menu, event);
+        OutputView.printBadge(event, eventCalendar);
+    }
+}

리뷰: `InputView` 에서 `CommonValidator` 를 통해서 검증을 하는것으로 보입니다. 그렇다면 `InputValidator` 에서 추가적인 검증도 함께 진행해서 예외를 처리하는 식으로 구현하는 방법은 어떻게 생각하시나요? 

저는 입력을 담당하는 클래스에서 입력을 받고 검증 클래스를 통해 검증후 예외까지 던지도록 구현했더니 깔끔하게 구현했던거 같아서 여쭤봅니다!
@@ -0,0 +1,43 @@
+package christmas.domain;
+
+import christmas.domain.constants.event.EventValue;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+
+public class EventCalendar {
+    private final LocalDate currentDate;
+
+    public EventCalendar(int year, int month) {
+        this.currentDate = LocalDate.of(year, month, 1);
+    }
+
+    public boolean isWeekend(int day) {
+        DayOfWeek dayOfWeek = currentDate.withDayOfMonth(day).getDayOfWeek();
+        return dayOfWeek == DayOfWeek.FRIDAY || dayOfWeek == DayOfWeek.SATURDAY;
+    }
+
+    public boolean isChristmasDDay(int day) {
+        return day >= EventValue.CHRISTMAS_START_DAY.getValue() && day <= EventValue.CHRISTMAS_END_DAY.getValue();
+    }
+
+    public boolean containsAllDay(int day) {
+        return day >= EventValue.DECEMBER_START_DAY.getValue() && day <= EventValue.DECEMBER_END_DAY.getValue();
+    }
+
+    public int getYear() {
+        return currentDate.getYear();
+    }
+
+    public int getMonth() {
+        return currentDate.getMonthValue();
+    }
+
+    public int getStartDate() {
+        return currentDate.getDayOfMonth();
+    }
+
+    public int getEndDate() {
+        return currentDate.lengthOfMonth();
+    }
+}

리뷰: 이벤트에 맞는 날짜를 세팅하는 방법은 정말 좋은 방법 같습니다 👍 이 방법이 훨씬 깔끔하고 사용하기도 편한방법 같아요.
@@ -0,0 +1,45 @@
+package christmas.domain;
+
+import christmas.domain.constants.event.EventDate;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.TemporalAdjusters;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class StarDate {
+    private final Set<Integer> starDates;
+
+    public StarDate(EventCalendar eventCalendar) {
+        this.starDates = new HashSet<>() {{
+            addAll(starDatesSettingWithSunday(eventCalendar));
+            addAll(starDateSettingWithSpecialDay(eventCalendar));
+        }};
+    }
+
+    public boolean visitDateContainsStarDates(int day) {
+        return starDates.contains(day);
+    }
+
+    public Set<Integer> starDatesSettingWithSunday(EventCalendar eventCalendar) {
+        LocalDate localDate = LocalDate.of(eventCalendar.getYear(), eventCalendar.getMonth(), eventCalendar.getStartDate());
+        Set<Integer> sundays = new HashSet<>();
+        LocalDate currentSunday = localDate.with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
+
+        while (!currentSunday.isAfter(localDate.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY)))) {
+            sundays.add(currentSunday.getDayOfMonth());
+            currentSunday = currentSunday.plusWeeks(1);
+        }
+        return sundays;
+    }
+
+    public Set<Integer> starDateSettingWithSpecialDay(EventCalendar eventCalendar) {
+        return Arrays.stream(EventDate.values())
+                .filter(eventDate -> eventDate.getMonth() == eventCalendar.getMonth())
+                .findFirst()
+                .map(EventDate::getEventDates)
+                .orElse(EventDate.NONE.getEventDates());
+    }
+}

리뷰: 저는 개인적으로 이번 과제는 여러가지 이벤트들을 추상화하는 것이 핵심이라고 생각해서 이벤트 객체들에만 신경을 써서 상대적으로 날짜 정보들은 조금 대충(?) 다뤘던것 같습니다. 영석님 처럼 날짜 정보들을 꼼꼼하게 다뤄야했나 하는 생각이 드네요 🥲
@@ -0,0 +1,31 @@
+package christmas.domain.constants;
+
+import java.util.function.Predicate;
+
+public enum Badge {
+    NONE("없음", (amount) -> amount >= 0 && amount < 5_000),
+    START("별", (amount) -> amount >= 5_000 && amount < 10_000),
+    TREE("트리", (amount) -> amount >= 10_000 && amount < 20_000),
+    SANTA("산타", (amount) -> amount >= 20_000 && amount < Integer.MAX_VALUE);
+
+    private final String badge;
+    private final Predicate<Integer> whichBadge;
+
+    Badge(String badge, Predicate<Integer> whichBadge) {
+        this.badge = badge;
+        this.whichBadge = whichBadge;
+    }
+
+    public String getBadge() {
+        return badge;
+    }
+
+    public boolean getWhichBadgeFromAmount(int amount) {
+        return whichBadge.test(amount);
+    }
+
+    @Override
+    public String toString() {
+        return badge;
+    }
+}
\ No newline at end of file

리뷰: 정말 좋은 방법이라고 생각합니다! `Predicate` 를 활용하면서도 미처 생각하지 못한 방법이네요 👍
@@ -0,0 +1,41 @@
+package christmas.domain.constants;
+
+import java.util.function.Function;
+
+public enum Gift {
+    CHAMPAGNE("샴페인", 25_000, 1, true, (amount) -> amount >= 120_000);
+
+    private final String name;
+    private final int price;
+    private final int count;
+    private final boolean gift;
+    private final Function<Integer, Boolean> giftApplicable;
+
+    Gift(String name, int price, int count, boolean gift, Function<Integer, Boolean> giftApplicable) {
+        this.name = name;
+        this.price = price;
+        this.count = count;
+        this.gift = gift;
+        this.giftApplicable = giftApplicable;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getPrice() {
+        return this.price;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public boolean getGift() {
+        return gift;
+    }
+
+    public boolean isGiftApplicable(int amount) {
+        return giftApplicable.apply(amount);
+    }
+}

리뷰: `Gift` enum 클래스안에 존재하는 상수들은 이미 증정품이라고 생각합니다. 어떤 이유로 구현하셨는지 궁금합니다!
@@ -0,0 +1,35 @@
+package christmas.domain.constants.event;
+
+import java.util.Set;
+
+public enum EventDate {
+    NONE(0, Set.of()),
+    JANUARY(1, Set.of(1)),
+    FEBRUARY(2, Set.of(14)),
+    MARCH(3, Set.of(1, 14)),
+    APRIL(4, Set.of()),
+    MAY(5, Set.of(5, 8, 15)),
+    JUNE(6, Set.of(6)),
+    JULY(7, Set.of()),
+    AUGUST(8, Set.of(15)),
+    SEPTEMBER(9, Set.of()),
+    OCTOBER(10, Set.of(3, 9)),
+    NOVEMBER(11, Set.of(11)),
+    DECEMBER(12, Set.of(25));
+
+    private final int month;
+    private final Set<Integer> eventDates;
+
+    EventDate(int month, Set<Integer> eventDates) {
+        this.month = month;
+        this.eventDates = eventDates;
+    }
+
+    public int getMonth() {
+        return month;
+    }
+
+    public Set<Integer> getEventDates() {
+        return eventDates;
+    }
+}

리뷰: 각 월의 특별한 날짜들을 정의해놓은 enum 으로 보입니다. 다만 그 기준이 조금 모호한 것 같습니다. 
`2월` 이나 `3월` 같은 경우는 공휴일이 아닌 발렌타인 데이 같은 날들을 포함하는 반면 공휴일만을 포함하는 달도 있습니다. 하지만 `5월 27일` (부처님 오신 날), `9월 28 ~ 30일` (추석) 은 제외되어 있고 할로윈 데이처럼 빠진 날들도 있습니다. 

기준을 세워서 공휴일만 넣는다든지 공휴일 포함 모든 의미있는 날들? 을 넣는다든지 해서 기준을 세우면 좀더 명확하게 이해할 수 있을것 같다는 생각이 들었습니다. 영석님의 생각은 어떠신지 궁금합니다 🤔
@@ -0,0 +1,12 @@
+package christmas.util.validation;
+
+import christmas.message.ErrorMessage;
+
+public class CommonValidator {
+
+    public static void isBlank(String text) {
+        if (text == null || text.isBlank()) {
+            throw new IllegalArgumentException(ErrorMessage.BLANK.getReasonFormattedMessage());
+        }
+    }
+}

리뷰: 저도 이런식으로 입력값이 공백인지 체크하는 메소드를 만들었었는데 `Console.readLine().trim();` 으로 공백 제거하는 방법도 있더라구요 😂
@@ -0,0 +1,16 @@
+package christmas.view.constants;
+
+public enum InputMessage {
+    VISIT_DATE("12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)"),
+    ORDER_MENU("주문하실 메뉴를 메뉴와 개수를 알려 주세요. (e.g. 해산물파스타-2,레드와인-1,초코케이크-1)");
+
+    private final String message;
+
+    InputMessage(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+}

리뷰: 달력 및 날짜관련 클래스에 12월 뿐만 아니라 다른 날들도 정의해두셨으니 이부분도 파라미터를 받도록 처리하면 좋을것 같습니다!
@@ -0,0 +1,53 @@
+package christmas.domain.event;
+
+import christmas.domain.calendar.Date;
+import christmas.domain.calendar.Order;
+import christmas.domain.menu.MenuGroup;
+import christmas.domain.menu.MenuType;
+
+public final class WeekdayDiscountEvent implements Event {
+
+    private static final int CHRISTMAS_EVENT_MONTH = 12;
+    private static final int CHRISTMAS_EVENT_MIN_DAY = 1;
+    private static final int CHRISTMAS_EVENT_MAX_DAY = 31;
+    private static final int CHRISTMAS_EVENT_DESERT_DISCOUNT = 2_023;
+    private static final String WEEKDAY_DISCOUNT_EVENT_TITLE = "평일 할인";
+    private int benefit;
+
+    @Override
+    public boolean isApplicable(Date date) {
+        return isEventPeriod(date) && !date.isWeekend();
+    }
+
+    private static boolean isEventPeriod(Date date) {
+        return date.getMonth() == CHRISTMAS_EVENT_MONTH &&
+                date.getDay() >= CHRISTMAS_EVENT_MIN_DAY
+                && date.getDay() <= CHRISTMAS_EVENT_MAX_DAY;
+    }
+
+    @Override
+    public int calculateDiscount(Date date, Order order) {
+        benefit = order.getMenus().menuList().stream()
+                .mapToInt(menu -> {
+                    MenuType menuType = MenuType.findByMenuName(menu.getMenuName());
+                    MenuGroup menuGroup = MenuGroup.findByMenuType(menuType);
+                    int menuQuantity = menu.getMenuQuantity();
+                    if (menuGroup == MenuGroup.DESSERT) {
+                        return CHRISTMAS_EVENT_DESERT_DISCOUNT * menuQuantity;
+                    }
+                    return 0;
+                })
+                .sum();
+        return benefit;
+    }
+
+    @Override
+    public int getBenefit() {
+        return benefit;
+    }
+
+    @Override
+    public String getEventName() {
+        return WEEKDAY_DISCOUNT_EVENT_TITLE;
+    }
+}

리뷰: 상수로 날짜를 정의한다기 보다는 java.util.Calendar 클래스를 이용하면 더 쉽게 표기가능 할것 같습니다.
@@ -0,0 +1,53 @@
+package christmas.domain.event;
+
+import christmas.domain.calendar.Date;
+import christmas.domain.calendar.Order;
+import christmas.domain.menu.MenuGroup;
+import christmas.domain.menu.MenuType;
+
+public final class WeekendDiscountEvent implements Event {
+    private static final int CHRISTMAS_EVENT_MONTH = 12;
+    private static final int CHRISTMAS_EVENT_MIN_DAY = 1;
+    private static final int CHRISTMAS_EVENT_MAX_DAY = 31;
+    private static final int CHRISTMAS_EVENT_DESERT_DISCOUNT = 2_023;
+    private static final String WEEKEND_DISCOUNT_EVENT_TITLE = "주말 할인";
+    private int benefit;
+
+    @Override
+    public boolean isApplicable(Date date) {
+        return isEventPeriod(date) &&
+                date.isWeekend();
+    }
+
+    private static boolean isEventPeriod(Date date) {
+        return date.getMonth() == CHRISTMAS_EVENT_MONTH &&
+                date.getDay() >= CHRISTMAS_EVENT_MIN_DAY
+                && date.getDay() <= CHRISTMAS_EVENT_MAX_DAY;
+    }
+
+    @Override
+    public int calculateDiscount(Date date, Order order) {
+        benefit = order.getMenus().menuList().stream()
+                .mapToInt(menu -> {
+                    MenuType menuType = MenuType.findByMenuName(menu.getMenuName());
+                    MenuGroup menuGroup = MenuGroup.findByMenuType(menuType);
+                    int menuQuantity = menu.getMenuQuantity();
+                    if (menuGroup == MenuGroup.MAIN) {
+                        return CHRISTMAS_EVENT_DESERT_DISCOUNT * menuQuantity;
+                    }
+                    return 0;
+                })
+                .sum();
+        return benefit;
+    }
+
+    @Override
+    public int getBenefit() {
+        return benefit;
+    }
+
+    @Override
+    public String getEventName() {
+        return WEEKEND_DISCOUNT_EVENT_TITLE;
+    }
+}

리뷰: 이 부분도 Calendar 클래스의 after before 함수를 사용하면 더 쉽게 비교 가능합니다!
@@ -0,0 +1,55 @@
+package christmas.domain.event;
+
+import christmas.domain.calendar.Date;
+import christmas.domain.calendar.Order;
+import christmas.domain.menu.Menu;
+import christmas.domain.menu.MenuType;
+
+public final class FreeGiftEvent implements Event {
+
+    private static final int CHRISTMAS_EVENT_MONTH = 12;
+    private static final int CHRISTMAS_EVENT_MIN_DAY = 1;
+    private static final int CHRISTMAS_EVENT_MAX_DAY = 31;
+    private static final int CHRISTMAS_EVENT_FREE_STANDARD = 120_000;
+    private static final String CHRISTMAS_EVENT_FREE_QUANTITY = "1";
+    private static final String FREE_GIFT_EVENT_TITLE = "증정 이벤트";
+    private Menu benefitGift = new Menu(MenuType.EMPTY.getTitle(), CHRISTMAS_EVENT_FREE_QUANTITY);
+    private int benefit;
+
+    @Override
+    public boolean isApplicable(Date date) {
+        return isEventPeriod(date);
+    }
+
+    private static boolean isEventPeriod(Date date) {
+        return date.getMonth() == CHRISTMAS_EVENT_MONTH &&
+                date.getDay() >= CHRISTMAS_EVENT_MIN_DAY
+                && date.getDay() <= CHRISTMAS_EVENT_MAX_DAY;
+    }
+
+    @Override
+    public int calculateDiscount(Date date, Order order) {
+        int beforeMoney = order.getBeforeMoney();
+        if (beforeMoney >= CHRISTMAS_EVENT_FREE_STANDARD) {
+            MenuType champagne = MenuType.CHAMPAGNE;
+            benefitGift = new Menu(champagne.getTitle(), CHRISTMAS_EVENT_FREE_QUANTITY);
+            benefit = champagne.getPrice();
+        }
+        return benefit;
+    }
+
+    public Menu getBenefitGift() {
+        return benefitGift;
+    }
+
+    @Override
+    public int getBenefit() {
+        return benefit;
+    }
+
+    @Override
+    public String getEventName() {
+        return FREE_GIFT_EVENT_TITLE;
+    }
+
+}

리뷰: 생성자로 DI 주입 받으시면 더 좋을 것 같습니다!
@@ -0,0 +1,51 @@
+package christmas.controller;
+
+import christmas.domain.calendar.Date;
+import christmas.domain.calendar.Order;
+import christmas.domain.calendar.Planner;
+import christmas.domain.menu.Menus;
+import christmas.view.InputView;
+import christmas.view.OutputView;
+
+public class UtecoRestaurantController {
+
+    public void startOperation() {
+        Date date = inputDate();
+        Menus menus = inputMenus();
+        Order order = new Order(menus);
+        Planner planner = new Planner(date, order);
+
+        OutputView.printBasicPreview(date, menus, order);
+        OutputView.printPlanner(order, planner);
+    }
+
+    private static Date inputDate() {
+        OutputView.printRestaurantIntro();
+        Date date = createDate();
+        return date;
+    }
+
+    private static Date createDate() {
+        try {
+            return new Date(InputView.inputDate());
+        } catch (IllegalArgumentException e) {
+            OutputView.printException(e);
+            return createDate();
+        }
+    }
+
+    private static Menus inputMenus() {
+        OutputView.printRestaurantMenu();
+        Menus menus = createMenus();
+        return menus;
+    }
+
+    private static Menus createMenus() {
+        try {
+            return InputView.inputOrderMenu();
+        } catch (IllegalArgumentException e) {
+            OutputView.printException(e);
+            return createMenus();
+        }
+    }
+}

리뷰: 저랑 비슷하게 구현하셨네요 ! 다만 View를 스태틱으로 관리하신 이유가있을까요?
@@ -0,0 +1,65 @@
+package christmas.domain.calendar;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.format.TextStyle;
+import java.util.Locale;
+
+public class Date {
+    private static final int VISIT_YEAR = 2023;
+    private static final int VISIT_MONTH = 12;
+    private Year year;
+    private Month month;
+    private Day day;
+    private String dayFormat;
+
+    public Date(int day) {
+        this.year = new Year(VISIT_YEAR);
+        this.month = new Month(VISIT_MONTH);
+        this.day = new Day(day);
+        this.dayFormat = createVisitingDayFormat();
+    }
+
+    public String createVisitingDayFormat() {
+        LocalDate visitDay = createDateTimeFormat();
+        DayOfWeek dayOfWeek = visitDay.getDayOfWeek();
+        return dayOfWeek.getDisplayName(TextStyle.FULL, Locale.KOREA);
+    }
+
+    public boolean isWeekend() {
+        LocalDate visitDay = createDateTimeFormat();
+        DayOfWeek dayOfWeek = visitDay.getDayOfWeek();
+        return dayOfWeek == DayOfWeek.FRIDAY || dayOfWeek == DayOfWeek.SATURDAY;
+    }
+
+    public boolean isSunday() {
+        LocalDate visitDay = createDateTimeFormat();
+        DayOfWeek dayOfWeek = visitDay.getDayOfWeek();
+        return dayOfWeek == DayOfWeek.SUNDAY;
+    }
+
+    public LocalDate createDateTimeFormat() {
+        return LocalDate.of(getYear(), getMonth(), getDay());
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s월 %s일", month.month(), day.day());
+    }
+
+    public int getYear() {
+        return year.year();
+    }
+
+    public int getMonth() {
+        return month.month();
+    }
+
+    public int getDay() {
+        return day.day();
+    }
+
+    public String getDayFormat() {
+        return dayFormat;
+    }
+}

리뷰: 감탄하고갑니다.. ! 날짜를 이런식으로 관리할수도있네요!
@@ -0,0 +1,48 @@
+package christmas.domain.event;
+
+import christmas.domain.calendar.Date;
+import christmas.domain.calendar.Order;
+import java.time.LocalDate;
+import java.time.Period;
+
+public final class ChristmasDailyDiscountEvent implements Event {
+
+    private static final int CHRISTMAS_EVENT_YEAR = 2023;
+    private static final int CHRISTMAS_EVENT_MONTH = 12;
+    private static final int CHRISTMAS_EVENT_MIN_DAY = 1;
+    private static final int CHRISTMAS_EVENT_MAX_DAY = 25;
+    private static final int CHRISTMAS_EVENT_START_MONEY = 1_000;
+    private static final int CHRISTMAS_EVENT_DISCOUNT_UNIT = 100;
+    private static final String CHRISTMAS_DAILY_DISCOUNT_EVENT_TITLE = "크리스마스 디데이 할인";
+    private int benefit;
+
+    @Override
+    public boolean isApplicable(Date date) {
+        return isEventPeriod(date);
+    }
+
+    private static boolean isEventPeriod(Date date) {
+        return date.getMonth() == CHRISTMAS_EVENT_MONTH &&
+                date.getDay() >= CHRISTMAS_EVENT_MIN_DAY
+                && date.getDay() <= CHRISTMAS_EVENT_MAX_DAY;
+    }
+
+    @Override
+    public int calculateDiscount(Date date, Order order) {
+        LocalDate startDay = LocalDate.of(CHRISTMAS_EVENT_YEAR, CHRISTMAS_EVENT_MONTH, CHRISTMAS_EVENT_MIN_DAY);
+        LocalDate visitDay = date.createDateTimeFormat();
+        Period period = Period.between(startDay, visitDay);
+        benefit = CHRISTMAS_EVENT_START_MONEY + CHRISTMAS_EVENT_DISCOUNT_UNIT * period.getDays();
+        return benefit;
+    }
+
+    @Override
+    public int getBenefit() {
+        return benefit;
+    }
+
+    @Override
+    public String getEventName() {
+        return CHRISTMAS_DAILY_DISCOUNT_EVENT_TITLE;
+    }
+}

리뷰: 조금 억지스러운 지적이긴 하지만, &&를 앞으로 뺴려면 모두 다 빼면 좋을것 같아요!
 date.getMonth() == CHRISTMAS_EVENT_MONTH 
                && date.getDay() >= CHRISTMAS_EVENT_MIN_DAY
                && date.getDay() <= CHRISTMAS_EVENT_MAX_DAY;
@@ -0,0 +1,18 @@
+package christmas.domain.event;
+
+import christmas.domain.calendar.Date;
+import christmas.domain.calendar.Order;
+
+public sealed interface Event permits ChristmasDailyDiscountEvent, WeekdayDiscountEvent, WeekendDiscountEvent,
+        SpecialDiscountEvent,
+        FreeGiftEvent {
+
+    boolean isApplicable(Date date);
+
+    int calculateDiscount(Date date, Order order);
+
+    int getBenefit();
+
+    String getEventName();
+
+}

리뷰: sealed 키워드를 처음봐서 신기하네요..! 저도 공부해봐야겠습니다