Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pizza Pricing System

Design the pricing engine for a chain of pizza stores. Customers build pizzas from a base and toppings, add drinks, and the store totals the order — applying whatever promotional deals are running. The problem grows in three parts, each raising the bar on your object-oriented design — by Part 3 you'll be expected to apply SOLID and the Strategy and Factory patterns so new deals slot in without editing the store.

Everything lives under src/main/java/io/coderpass/pizza/. All monetary amounts are integer cents (int). Prices are store-specific — the same base or topping can cost a different amount at a different store — so every price is looked up against a Store catalog, never baked into the item.

The domain

  • A base is the foundation (THIN, REGULAR, THICK, STUFFED).
  • A topping is an add-on (CHEESE, PEPPERONI, MUSHROOM, …). A pizza may repeat a topping (double cheese) and each repeat is charged again.
  • A drink (WATER, COLA, …) is another kind of order item.
  • A Store holds its own catalog: a price for each base, topping and drink it stocks. Asking for something it doesn't stock throws UnknownItemError.
import io.coderpass.pizza.*;
import java.util.Map;

Store store = new Store(
        "Mario's",
        Map.of(Base.THIN, 800, Base.REGULAR, 1000),
        Map.of(Topping.CHEESE, 150, Topping.PEPPERONI, 250),
        Map.of(DrinkType.COLA, 200));

Part 1 — Store catalog & pizza pricing

Price a single pizza against a store's catalog.

public class Store {
    public int basePrice(Base base) { ... }
    public int toppingPrice(Topping topping) { ... }
}

public class Pizza implements OrderItem {
    public int price(Store store) { ... }
}
  • basePrice / toppingPrice return the catalog price, or throw UnknownItemError if the store doesn't stock that item.
  • new Pizza(base, toppings).price(store) is the base price plus the price of every topping (repeats included).
new Pizza(Base.THIN, List.of(Topping.CHEESE, Topping.PEPPERONI)).price(store); // 800+150+250 = 1200

Part 2 — Orders with mixed items

An order holds any mix of pizzas, drinks and other items — each an OrderItem that prices itself against the store.

public class Drink implements OrderItem {   // wraps a DrinkType
    public int price(Store store) { ... }
}

public class Order {
    public void add(OrderItem item) { ... }
    public int subtotal(Store store) { ... }
}
  • new Drink(DrinkType.COLA).price(store) looks the drink up in the catalog (UnknownItemError if unstocked).
  • Order.subtotal(store) sums every item's price. An empty order is 0.
Order order = new Order();
order.add(new Pizza(Base.THIN, List.of(Topping.PEPPERONI)));  // 1050
order.add(new Drink(DrinkType.COLA));                         // 200
order.subtotal(store);                                        // 1250

Part 3 — Promotional deals (Strategy + Factory)

Make deals pluggable without touching Store. A Promotion is a Strategy that reports how many cents to knock off an order.

public interface Promotion {
    int discount(Order order, Store store);
}

public class Store {
    public int priceOrder(Order order, List<Promotion> promotions) { ... }
}

Implement three deals:

  • BogoPizzaPromotion — buy-one-get-one-free on pizzas: pair them most-expensive-first, the cheaper of each pair is free. An odd pizza out is not free.
  • FreeDrinkWithPizzaPromotion — one free drink per pizza; when drinks outnumber pizzas the cheapest drinks are the free ones.
  • MostExpensiveToppingFreePromotion — each pizza's single dearest topping is free.

And a PromotionFactory.create(PromotionType) that builds a deal from its enum.

priceOrder returns the subtotal minus every promotion's discount. Promotions stack additively and the total never drops below zero.

store.priceOrder(order, List.of(PromotionFactory.create(PromotionType.BOGO_PIZZA)));

Running the tests

With Docker (matches CI):

docker compose -f docker-compose.yaml run --rm test

Or locally:

mvn -q -B test

Skills tested

  • Object-oriented modelling of a small domain (stores, catalogs, pizzas, orders)
  • SOLID: single-responsibility split of catalog / item / order / promotion, and Open/Closed + Dependency-Inversion via injected promotion strategies
  • Design patterns: Strategy (promotions) and Factory (promotion creation)
  • Careful edge-case handling: store-specific prices, repeated toppings, deal pairing rules, additive stacking and the zero floor

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages