Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/main/java/christmas/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package christmas;

import christmas.config.AppConfig;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
AppConfig app = new AppConfig();
app.run();
}
}
}
18 changes: 18 additions & 0 deletions src/main/java/christmas/config/AppConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package christmas.config;

import christmas.controller.EventController;
import christmas.view.InputView;
import christmas.view.OutputView;

public class AppConfig {
private final EventController eventController;

public AppConfig() {
this.eventController = new EventController(new InputView(), new OutputView());
}

public void run() {
eventController.init();
eventController.run();
}
}
21 changes: 21 additions & 0 deletions src/main/java/christmas/config/MenuConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package christmas.config;

import christmas.model.domain.Menu;
import christmas.repository.MenuRepository;

public class MenuConfig {
public static void initMenus() {
MenuRepository.addMenu(new Menu("양송이수프", 6_000, "애피타이저"));
MenuRepository.addMenu(new Menu("타파스", 5_500, "애피타이저"));
MenuRepository.addMenu(new Menu("시저샐러드", 8_000, "애피타이저"));
MenuRepository.addMenu(new Menu("티본스테이크", 55_000, "메인"));
MenuRepository.addMenu(new Menu("바비큐립", 54_000, "메인"));
MenuRepository.addMenu(new Menu("해산물파스타", 35_000, "메인"));
MenuRepository.addMenu(new Menu("크리스마스파스타", 25_000, "메인"));
MenuRepository.addMenu(new Menu("초코케이크", 15_000, "디저트"));
MenuRepository.addMenu(new Menu("아이스크림", 5_000, "디저트"));
MenuRepository.addMenu(new Menu("제로콜라", 3_000, "음료"));
MenuRepository.addMenu(new Menu("레드와인", 60_000, "음료"));
MenuRepository.addMenu(new Menu("샴페인", 25_000, "음료"));
}
}
116 changes: 116 additions & 0 deletions src/main/java/christmas/controller/EventController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package christmas.controller;

import christmas.config.MenuConfig;
import christmas.model.domain.*;
import christmas.repository.MenuRepository;
import christmas.service.DiscountCalculator;
import christmas.view.InputView;
import christmas.view.OutputView;

import java.time.LocalDate;

public class EventController {

private static final String GIFT_CHAMPAGNE = "샴페인 1개";
private static final String NO_GIFT = "없음";
private static final String ORDER_DELIMITER = ",";
private static final String DETAIL_DELIMITER = "-";
private static final int GIFT_DISCOUNT_AMOUNT = 25000;
private static final int EVENT_YEAR = 2023;
private static final int EVENT_MONTH = 12;

private final InputView inputView;
private final OutputView outputView;
private final DiscountCalculator discountCalculator;

public EventController(InputView inputView, OutputView outputView) {
this.inputView = inputView;
this.outputView = outputView;
this.discountCalculator = new DiscountCalculator();
}

public void init() {
MenuConfig.initMenus();
}

public void run() {
while (true) {
try {
int visitDay = readValidVisitDate();
LocalDate visitDate = LocalDate.of(EVENT_YEAR, EVENT_MONTH, visitDay);

Order order = createOrderFromInput();
processOrder(order, visitDay, visitDate);
break;
} catch (IllegalArgumentException e) {
outputView.printError(e.getMessage());
}
}
}

private int readValidVisitDate() {
while (true) {
try {
return inputView.readVisitDate();
} catch (IllegalArgumentException e) {
outputView.printError(e.getMessage());
}
}
}

private Order createOrderFromInput() {
Order order = new Order();
String[] orderDetails = readValidOrderDetails();
for (String detail : orderDetails) {
String[] parts = detail.split(DETAIL_DELIMITER);
Menu menu = MenuRepository.findByName(parts[0].trim());
int quantity = Integer.parseInt(parts[1].trim());
order.addMenu(menu, quantity);
}
return order;
}

private String[] readValidOrderDetails() {
while (true) {
try {
return inputView.readOrderDetails().split(ORDER_DELIMITER);
} catch (IllegalArgumentException e) {
outputView.printError(e.getMessage());
}
}
}

private void processOrder(Order order, int visitDay, LocalDate visitDate) {
int totalPrice = order.calculateTotalPrice();

int dailyDiscount = discountCalculator.calculateDailyDiscount(visitDay);
int weekdayDiscount = discountCalculator.calculateWeekdayDiscount(order, visitDate);
int weekendDiscount = discountCalculator.calculateWeekendDiscount(order, visitDate);
int specialDayDiscount = discountCalculator.calculateSpecialDayDiscount(visitDate);

boolean eligibleForGift = discountCalculator.isEligibleForGift(totalPrice);
String gift = getGiftBasedOnEligibility(eligibleForGift);

int totalDiscount = calculateTotalDiscount(dailyDiscount, weekdayDiscount, weekendDiscount, specialDayDiscount, eligibleForGift);
int finalPrice = totalPrice - (dailyDiscount + weekdayDiscount + weekendDiscount + specialDayDiscount);

String badge = Badge.getBadgeByBenefit(totalDiscount).getName();

outputView.printOrderSummary(order, totalPrice, totalDiscount, finalPrice, gift, dailyDiscount, weekdayDiscount, weekendDiscount, specialDayDiscount, badge);
}

private String getGiftBasedOnEligibility(boolean eligibleForGift) {
if (eligibleForGift) {
return GIFT_CHAMPAGNE;
}
return NO_GIFT;
}

private int calculateTotalDiscount(int dailyDiscount, int weekdayDiscount, int weekendDiscount, int specialDayDiscount, boolean eligibleForGift) {
int giftDiscount = 0;
if (eligibleForGift) {
giftDiscount = GIFT_DISCOUNT_AMOUNT;
}
return dailyDiscount + weekdayDiscount + weekendDiscount + specialDayDiscount + giftDiscount;
}
}
28 changes: 28 additions & 0 deletions src/main/java/christmas/model/domain/Badge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package christmas.model.domain;
import java.util.Arrays;

public enum Badge {
SANTA("산타", 20000),
TREE("트리", 10000),
STAR("별", 5000),
NONE("없음", 0);

private final String name;
private final int minBenefit;

Badge(String name, int minBenefit) {
this.name = name;
this.minBenefit = minBenefit;
}

public String getName() {
return name;
}

public static Badge getBadgeByBenefit(int totalBenefit) {
return Arrays.stream(values())
.filter(badge -> totalBenefit >= badge.minBenefit)
.findFirst()
.orElse(NONE);
}
}
25 changes: 25 additions & 0 deletions src/main/java/christmas/model/domain/Menu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package christmas.model.domain;

public class Menu {
private final String name;
private final int price;
private final String category;

public Menu(String name, int price, String category) {
this.name = name;
this.price = price;
this.category = category;
}

public String getName() {
return name;
}

public int getPrice() {
return price;
}

public String getCategory() {
return category;
}
}
22 changes: 22 additions & 0 deletions src/main/java/christmas/model/domain/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package christmas.model.domain;

import java.util.HashMap;
import java.util.Map;

public class Order {
private final Map<Menu, Integer> orderDetails = new HashMap<>();

public void addMenu(Menu menu, int quantity) {
orderDetails.put(menu, orderDetails.getOrDefault(menu, 0) + quantity);
}

public Map<Menu, Integer> getOrderDetails() {
return orderDetails;
}

public int calculateTotalPrice() {
return orderDetails.entrySet().stream()
.mapToInt(entry -> entry.getKey().getPrice() * entry.getValue())
.sum();
}
}
17 changes: 17 additions & 0 deletions src/main/java/christmas/repository/MenuRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package christmas.repository;

import christmas.model.domain.Menu;
import java.util.HashMap;
import java.util.Map;

public class MenuRepository {
private static final Map<String, Menu> menus = new HashMap<>();

public static void addMenu(Menu menu) {
menus.put(menu.getName(), menu);
}

public static Menu findByName(String name) {
return menus.get(name);
}
}
77 changes: 77 additions & 0 deletions src/main/java/christmas/service/DiscountCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package christmas.service;

import christmas.model.domain.Order;

import java.time.DayOfWeek;
import java.time.LocalDate;

public class DiscountCalculator {

private static final int DAILY_DISCOUNT_START = 1000;
private static final int DAILY_DISCOUNT_INCREMENT = 100;
private static final int CATEGORY_DISCOUNT_AMOUNT = 2023;
private static final int SPECIAL_DAY_DISCOUNT = 1000;
private static final int GIFT_ELIGIBILITY_THRESHOLD = 120000;
private static final String MAIN_CATEGORY = "메인";
private static final String DESSERT_CATEGORY = "디저트";
private static final int CHRISTMAS_DAY = 25;

public int calculateDailyDiscount(int day) {
if (isInvalidDiscountDay(day)) {
return 0;
}
return DAILY_DISCOUNT_START + ((day - 1) * DAILY_DISCOUNT_INCREMENT);
}

public int calculateWeekdayDiscount(Order order, LocalDate visitDate) {
if (isWeekday(visitDate.getDayOfWeek())) {
return calculateCategoryDiscount(order, DESSERT_CATEGORY);
}
return 0;
}

public int calculateWeekendDiscount(Order order, LocalDate visitDate) {
if (isWeekend(visitDate.getDayOfWeek())) {
return calculateCategoryDiscount(order, MAIN_CATEGORY);
}
return 0;
}

public int calculateSpecialDayDiscount(LocalDate visitDate) {
if (isSpecialDay(visitDate)) {
return SPECIAL_DAY_DISCOUNT;
}
return 0;
}

public boolean isEligibleForGift(int totalPrice) {
return totalPrice >= GIFT_ELIGIBILITY_THRESHOLD;
}

private boolean isInvalidDiscountDay(int day) {
return day < 1 || day > 25;
}

private int calculateCategoryDiscount(Order order, String category) {
return order.getOrderDetails().entrySet().stream()
.filter(entry -> entry.getKey().getCategory().equals(category))
.mapToInt(entry -> CATEGORY_DISCOUNT_AMOUNT * entry.getValue())
.sum();
}

private boolean isWeekday(DayOfWeek dayOfWeek) {
return dayOfWeek == DayOfWeek.MONDAY ||
dayOfWeek == DayOfWeek.TUESDAY ||
dayOfWeek == DayOfWeek.WEDNESDAY ||
dayOfWeek == DayOfWeek.THURSDAY ||
dayOfWeek == DayOfWeek.SUNDAY;
}

private boolean isWeekend(DayOfWeek dayOfWeek) {
return dayOfWeek == DayOfWeek.FRIDAY || dayOfWeek == DayOfWeek.SATURDAY;
}

private boolean isSpecialDay(LocalDate date) {
return date.getDayOfWeek() == DayOfWeek.SUNDAY || date.getDayOfMonth() == CHRISTMAS_DAY;
}
}
Loading