74. Design Food Order Management System using Commands

Food order management system using commands
Implement a simplified food order management system. This system simulates food ordering from restaurants with in-memory data structures.

You have to implement functionalities like add restaurant, update menu, place order, dispatch order etc as a set of commands.
Orders are placed to restaurants based on a restaurant selection strategy.

Data Encoding

  • All command inputs are provided as strings.
  • Menu items are encoded as strings: "itemName:price" (example: "burger:120").
  • Item lists are encoded as comma-separated strings inside a command (example: "burger,pizza").

Methods

1) Process Commands

List<String> processCommands(List<String> commands)
  • commands.size() >= 0
  • Each command parameter is separated by |
  • Each command must start with a numeric timestamp.
  • All commands must be executed in increasing timestamp order.
  • If two commands have the same timestamp, preserve their relative input order.
  • The return value is a list of outputs, one output per input command (same length as commands).

2) Get Items Served Per Restaurant

List<String> getRestaurantItemCounts()
  • Returns aggregated counts of items served (i.e. dispatched) per restaurant in food orders.
  • Each row is encoded as: "restaurantId|itemName|count"
  • Ordering of rows: sort lexicographically in ascending order.

3) Get All Dispatched Orders

List<String> getDispatchedOrders(String restaurantId)
  • Returns all dispatched orders in the exact order they were dispatched.
  • Each row is encoded as: "dispatchTimestamp|orderId|customerId|items"
  • items is a comma-separated list (example: "burger,pizza").

Command Format

Each command is a single string with parameters separated by |.

A) Add / Onboard Restaurant

timestamp|ADD_RESTAURANT|restaurantId|capacity|menu
  • capacity is the maximum number of concurrent open (not yet dispatched) orders the restaurant can hold.
  • menu is a comma-separated list of "item:price" entries.
  • Example: 101|ADD_RESTAURANT|R1|2|burger:120,pizza:200
  • Output: OK if added, else RESTAURANT_ALREADY_EXISTS.

B) Update Restaurant Menu / Prices

timestamp|UPDATE_MENU|restaurantId|menuUpdates
  • menuUpdates is a comma-separated list of "item:price" entries.
  • If price >= 0, upsert (add or update) the item price.
  • If price < 0, remove the item from existing menu (if present).
  • If an item is present in existing menu but not in menuUpdates then it will remain unaffected.
  • Example: 105|UPDATE_MENU|R1|burger:130,pasta:150,salad:-1
  • Output: OK if updated, else RESTAURANT_NOT_FOUND.

C) Place Order

timestamp|PLACE_ORDER|orderId|customerId|strategy|items
  • items is a comma-separated list of item names (example: "burger,pizza").
  • An order is accepted only if we can chose a restaurant based on strategy and:
    • Restaurant has all requested items on its menu at that time, and
    • Restaurant has available capacity (openOrders < capacity).
  • Output: ACCEPTED, else REJECTED if no restaurant can be found or INVALID_STRATEGY if strategy doesn't exist.

Restaurant Selection Strategy

When multiple restaurants can fulfill the order, choose based on strategy:
  • LOWEST_TOTAL_PRICE: pick the restaurant with minimum total price of requested items. Tie-breakers (in order):
    • Higher remaining capacity (capacity - openOrders)
    • Lexicographically smaller restaurantId
  • MAX_REMAINING_CAPACITY: pick the restaurant with maximum remaining capacity. Tie-breakers:
    • Lower total price
    • Lexicographically smaller restaurantId
  • If strategy is unknown: output INVALID_STRATEGY.

D) Dispatch Order

timestamp|DISPATCH_ORDER|orderId
  • Dispatching completes the order, frees up 1 capacity slot for that restaurant, and increments item served counts.
  • Output: DISPATCHED, or INVALID_ORDER, or ALREADY_DISPATCHED.

Output Rules

  • processCommands must return exactly one output string per command, in the same order as the input command list.
  • Even though commands are executed after sorting by timestamp, outputs are returned aligned to the original input positions.

Constraints

  • 0 <= timestamp <= 10^12
  • 0 <= commands.size() <= 100000
  • 1 <= capacity <= 100000
  • 0 <= price <= 10^9 (negative price only allowed in UPDATE_MENU to remove an item)
  • Restaurant and item names are non-empty and do not contain | or , characters.
  • No database, no UI: store everything in memory using appropriate data structures.

Examples

Example 1: Commands given in random timestamp order

Method Call
FoodCart foodCart = new FoodCart();
foodCart.processCommands(commands = List.of(
  • "200|PLACE_ORDER|O1|C1|LOWEST_TOTAL_PRICE|burger,pizza"
  • "100|ADD_RESTAURANT|R1|2|burger:120,pizza:200"
  • "150|ADD_RESTAURANT|R2|1|burger:110,pizza:220"
  • "210|PLACE_ORDER|O2|C2|LOWEST_TOTAL_PRICE|burger"
  • "220|DISPATCH_ORDER|O1"
  • "205|UPDATE_MENU|R2|pizza:180"
  • "230|PLACE_ORDER|O3|C3|LOWEST_TOTAL_PRICE|pizza"
)
Execution (sorted by timestamp)
  • 100: add R1
  • 150: add R2
  • 200: place order O1 for C1 (burger,pizza) with LOWEST_TOTAL_PRICE
    • R1 total = 120 + 200 = 320, remaining capacity = 2
    • R2 total = 110 + 220 = 330, remaining capacity = 1
    • Choose R1 (lower total) and accept O1 → output ACCEPTED
  • 205: update R2 pizza price to 180
  • 210: place order O2 for C2 (burger) with LOWEST_TOTAL_PRICE
    • R1 burger = 120, remaining capacity = 1 (since O1 is open at R1)
    • R2 burger = 110, remaining capacity = 1
    • Choose R2 (lower total) and accept O2 → output ACCEPTED
  • 220: dispatch order O1
    • Marks O1 dispatched, frees 1 slot in R1, and increments served counts for R1: burger +1, pizza +1
    • Output: DISPATCHED
  • 230: place order O3 for C3 (pizza) with LOWEST_TOTAL_PRICE
    • R2 pizza = 180 but R2 capacity = 1 and it already has O2 open → cannot accept new order
    • R1 pizza = 200 and R1 has capacity available → accept at R1
    • Accept O3 → output ACCEPTED
Expected Output
List.of(
  • "ACCEPTED"
  • "OK"
  • "OK"
  • "ACCEPTED"
  • "DISPATCHED"
  • "OK"
  • "ACCEPTED"
)

Example 2: Query items served per restaurant

Method Call
foodCart.getRestaurantItemCounts()
Expected Output
  • "R1|burger|1"
  • "R1|pizza|1"
Explanation: only order O1 was dispatched, and it belonged to restaurant R1 with items burger and pizza. Rows are already in lexicographic ascending order.

Example 3: Show all dispatched orders for a restaurant

Method Call
foodCart.getDispatchedOrders(restaurantId = "R1")
Expected Output
  • "220|O1|C1|burger,pizza"




Please use Laptop/Desktop or any other large screen to add/edit code.