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
306 changes: 31 additions & 275 deletions README.md

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion src/main/java/christmas/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package christmas;

import christmas.config.AppConfig;
import christmas.controller.EventPlannerController;

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

import christmas.controller.EventPlannerController;
import christmas.service.*;
import christmas.service.SpecialDayDiscount;
import christmas.service.WeekdayDessertDiscount;
import christmas.service.WeekendMainDiscount;
import christmas.service.discountpolicy.ChristmasCountdownDiscount;
import christmas.service.discountpolicy.DiscountPolicy;
import christmas.view.InputView;
import christmas.view.OutputView;

import java.util.List;

public class AppConfig {

public EventPlannerController eventPlannerController() {
return new EventPlannerController(eventService(), inputView(), outputView());
}

public EventService eventService() {
return new EventService(discountService(), giftService());
}

public DiscountService discountService() {
return new DiscountService(discountPolicies());
}

public List<DiscountPolicy> discountPolicies() {
return List.of(
new ChristmasCountdownDiscount(),
new WeekdayDessertDiscount(),
new WeekendMainDiscount(),
new SpecialDayDiscount()
);
}

public GiftService giftService() {
return new GiftService();
}

public InputView inputView() {
return new InputView();
}

public OutputView outputView() {
return new OutputView();
}
}
89 changes: 89 additions & 0 deletions src/main/java/christmas/controller/EventPlannerController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package christmas.controller;

import christmas.domain.Menu;
import christmas.domain.Order;
import christmas.domain.OrderItem;
import christmas.domain.EventResult;
import christmas.service.EventService;
import christmas.view.InputView;
import christmas.view.OutputView;
import christmas.validator.InputValidator;

import java.util.ArrayList;
import java.util.List;

public class EventPlannerController {

private final EventService eventService;
private final OutputView outputView;
private final InputView inputView;

public EventPlannerController(EventService eventService, InputView inputView, OutputView outputView) {
this.eventService = eventService;
this.outputView = outputView;
this.inputView = inputView;
}

public void run() {

int date = readDateWithRetry();
List<OrderItem> orderItems = readOrderWithRetry();

Order order = new Order(orderItems);
EventResult eventResult = eventService.planEvent(order, date);

outputView.printEventResult(eventResult);
}

private int readDateWithRetry() {
while (true) {
try {
int date = InputValidator.validateDate(inputView.readDate());
return date;
} catch (IllegalArgumentException e) {
outputView.printErrorMessage(e.getMessage());
}
}
}

private List<OrderItem> readOrderWithRetry() {
while (true) {
try {
String input = inputView.readOrder();
return parseOrder(input);
} catch (IllegalArgumentException e) {
outputView.printErrorMessage(e.getMessage());
}
}
}

private List<OrderItem> parseOrder(String input) {
List<OrderItem> orderItems = new ArrayList<>();
String[] items = input.split(",");

for (String item : items) {
String[] details = item.split("-");
InputValidator.validateMenuFormat(details);

String menuName = details[0].trim();
String quantityStr = details[1].trim();

InputValidator.validateMenuName(menuName);
int quantity = parseQuantity(quantityStr);

InputValidator.validateQuantity(quantity);

orderItems.add(new OrderItem(Menu.fromName(menuName), quantity));
}

return orderItems;
}

private int parseQuantity(String quantityStr) {
try {
return Integer.parseInt(quantityStr);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.");
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/christmas/domain/Badge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package christmas.domain;

import java.math.BigDecimal;

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

private final String displayName;
private final BigDecimal minimumDiscount;

Badge(String displayName, BigDecimal minimumDiscount) {
this.displayName = displayName;
this.minimumDiscount = minimumDiscount;
}

public String getDisplayName() {
return displayName;
}

public BigDecimal getMinimumDiscount() {
return minimumDiscount;
}

public static Badge getBadgeForDiscount(BigDecimal discount) {
Badge assignedBadge = NONE;
for (Badge badge : Badge.values()) {
if (discount.compareTo(badge.getMinimumDiscount()) >= 0) {
assignedBadge = badge;
}
}
return assignedBadge;
}
}
119 changes: 119 additions & 0 deletions src/main/java/christmas/domain/EventResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package christmas.domain;

import java.math.BigDecimal;
import java.util.Map;

public class EventResult {

private final Order order;
private final BigDecimal totalDiscount;
private final BigDecimal discountedPrice;
private final Menu gift;
private final Badge badge;
private final Map<String, BigDecimal> discountDetails;

public EventResult(Order order, BigDecimal totalDiscount, BigDecimal discountedPrice, Menu gift, Badge badge, Map<String, BigDecimal> discountDetails) {
this.order = order;
this.totalDiscount = totalDiscount;
this.discountedPrice = discountedPrice;
this.gift = gift;
this.badge = badge;
this.discountDetails = discountDetails;
}

public Order getOrder() {
return order;
}

public BigDecimal getTotalDiscount() {
return totalDiscount;
}

public BigDecimal getDiscountedPrice() {
return discountedPrice;
}

public Menu getGift() {
return gift;
}

public Badge getBadge() {
return badge;
}

public Map<String, BigDecimal> getDiscountDetails() {
return discountDetails;
}

@Override
public String toString() {
StringBuilder result = new StringBuilder();

String lineSeparator = System.lineSeparator();

result.append("12월 이벤트 결과 미리 보기!").append(lineSeparator).append(lineSeparator);

// 주문 메뉴 출력
result.append("<주문 메뉴>").append(lineSeparator);
for (OrderItem item : order.getOrderItems()) {
result.append(item).append(lineSeparator);
}

// 할인 전 총 주문 금액 출력
result.append(lineSeparator).append("<할인 전 총주문 금액>").append(lineSeparator);
BigDecimal totalPriceBeforeDiscount = order.getTotalPriceBeforeDiscount();
result.append(formatCurrency(totalPriceBeforeDiscount)).append("원").append(lineSeparator);

// 증정 메뉴 출력
result.append(lineSeparator).append("<증정 메뉴>").append(lineSeparator);
if (gift != null) {
result.append(gift.getName()).append(" 1개").append(lineSeparator);
} else {
result.append("없음").append(lineSeparator);
}

// 혜택 내역 출력
result.append(lineSeparator).append("<혜택 내역>").append(lineSeparator);
if (discountDetails.isEmpty() && gift == null) {
result.append("없음").append(lineSeparator);
} else {
for (Map.Entry<String, BigDecimal> entry : discountDetails.entrySet()) {
result.append(entry.getKey()).append(": -").append(formatCurrency(entry.getValue())).append("원").append(lineSeparator);
}
if (gift != null) {
result.append("증정 이벤트: -").append(formatCurrency(gift.getPrice())).append("원").append(lineSeparator);
}
}

// 총 혜택 금액 출력 (0보다 큰 경우와 0인 경우 구분)
result.append(lineSeparator).append("<총혜택 금액>").append(lineSeparator);
BigDecimal totalBenefit = totalDiscount;
if (gift != null) {
totalBenefit = totalBenefit.add(gift.getPrice());
}
if (totalBenefit.compareTo(BigDecimal.ZERO) > 0) {
result.append("-").append(formatCurrency(totalBenefit)).append("원").append(lineSeparator);
} else {
result.append("0원").append(lineSeparator);
}

// 할인 후 예상 결제 금액 출력
result.append(lineSeparator).append("<할인 후 예상 결제 금액>").append(lineSeparator);
result.append(formatCurrency(discountedPrice)).append("원").append(lineSeparator);

// 이벤트 배지 출력
result.append(lineSeparator).append("<12월 이벤트 배지>").append(lineSeparator);
if (badge != Badge.NONE) {
result.append(badge.getDisplayName()).append(lineSeparator);
} else {
result.append("없음").append(lineSeparator);
}

return result.toString();
}


private String formatCurrency(BigDecimal amount) {
return String.format("%,d", amount.longValue());
}
}
57 changes: 57 additions & 0 deletions src/main/java/christmas/domain/Menu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package christmas.domain;

import java.math.BigDecimal;

public enum Menu {

MUSHROOM_SOUP("양송이수프", "애피타이저", BigDecimal.valueOf(6_000)),
TAPAS("타파스", "애피타이저", BigDecimal.valueOf(5_500)),
CAESAR_SALAD("시저샐러드", "애피타이저", BigDecimal.valueOf(8_000)),


T_BONE_STEAK("티본스테이크", "메인", BigDecimal.valueOf(55_000)),
BBQ_RIB("바비큐립", "메인", BigDecimal.valueOf(54_000)),
SEAFOOD_PASTA("해산물파스타", "메인", BigDecimal.valueOf(35_000)),
CHRISTMAS_PASTA("크리스마스파스타", "메인", BigDecimal.valueOf(25_000)),


CHOCOLATE_CAKE("초코케이크", "디저트", BigDecimal.valueOf(15_000)),
ICE_CREAM("아이스크림", "디저트", BigDecimal.valueOf(5_000)),


ZERO_COKE("제로콜라", "음료", BigDecimal.valueOf(3_000)),
RED_WINE("레드와인", "음료", BigDecimal.valueOf(60_000)),
CHAMPAGNE("샴페인", "음료", BigDecimal.valueOf(25_000));

private final String name;
private final String category;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카테고리는 분류가 정해져있으니까, Enum으로 관리하면 더 좋을 것 같아요!

private final BigDecimal price;

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

public String getName() {
return name;
}

public String getCategory() {
return category;
}

public BigDecimal getPrice() {
return price;
}


public static Menu fromName(String name) {
for (Menu menu : values()) {
if (menu.name.equals(name)) {
return menu;
}
}
throw new IllegalArgumentException("[ERROR] 유효하지 않은 메뉴 이름입니다. 다시 입력해 주세요.");
}
}
Loading