76. Design Peer to Peer Parcel Delivery System

Design Peer to Peer Parcel Delivery System
Design a Peer-to-Peer Delivery System that can be used to deliver a parcel from one customer to another.

Implement a class named PeerToPeerDeliverySystem. The deliverable item list is preconfigured and fixed. Customers and drivers are considered already onboarded based on totalUsers and totalDrivers.


Below are the expected features of the system.
  • Drivers are pre-created with ids: dv-0, dv-1, ... dv-(totalDrivers-1).
  • Customers are pre-created with ids: user-0, user-1, ... user-(totalUsers-1).
  • The list of items that can be delivered is preconfigured in the system and is fixed.
  • Customers should be able to place an order for the delivery of a parcel and also be able to cancel it.
  • One driver can pickup only one order at a time.
  • Orders should be auto-assigned to drivers based on availability. Even If no driver is available, the system should accept the order and assign it to a driver when the driver becomes free. The number of ongoing orders can exceed the number of drivers.
  • If multiple drivers are available then assign the lexicographically lowest driver id among AVAILABLE drivers.
  • Pending orders will be assigned to drivers in the order in which they were created.
  • Once an order is assigned to a driver, the driver should be able to pick up the order and also mark the order as delivered after delivery.
  • The system should be able to show the status of orders and drivers.
  • Canceled orders shouldn’t be assigned to the driver. If an assigned order gets canceled the driver shouldn’t be able to pick up the order, the driver should be available for other orders.
  • Once a driver picks up an order the order cannot be canceled by the user nor system.
  • Assume driver is available 24*7. Ignore the travel time.

Constructor

PeerToPeerDeliverySystem(int totalUsers, int totalDrivers, List<String> deliverableItemIds)
  • Pre-created customers with ids: user-0, user-1, ... user-(totalUsers-1).
  • Pre-created drivers with ids: dv-0, dv-1, ... dv-(totalDrivers-1).
  • deliverableItemIds is fixed for the lifetime of the system.

Methods

1) Create Order

String createOrder(String orderId, String customerId, String itemId)
  • customerId must be one of: user-0 ... user-(totalUsers-1).
  • itemId must be one of the preconfigured deliverable items.
  • Order should be accepted even if no driver is available. If a driver is available, auto-assign immediately; otherwise keep the order pending for assignment when a driver becomes free.
  • Returns "ACCEPTED", "PENDING" or "INVALID" based on whether driver was assigned or order is in waiting queue or if the request was invalid.

2) Cancel Order

String cancelOrder(String orderId)
  • Returns the updated order status : CANCELED or ERROR if the order can't be cancelled.
  • Canceled orders must never be assigned or picked up.
  • If an order is assigned but not picked up, it can be canceled and the assigned driver becomes available for other orders.
  • Once an order is picked up, it cannot be canceled and this method should return "ERROR".

3) Pick Up Order

String pickUpOrder(String driverId, String orderId)
  • driverId must be one of: dv-0 ... dv-(totalDrivers-1).
  • orderId must exist and must be currently assigned to this driver.
  • Returns the updated order status : PICKED_UP or ERROR if the order is not picked.
  • If the order is canceled, the driver must not be able to pick it up.
  • One driver can pick up only one order at a time.

4) Deliver / Complete Order

String deliverOrder(String driverId, String orderId)
  • Order must be picked up by the same driver before it can be delivered.
  • Returns the updated order status : DELIVERED or ERROR.
  • After delivery, the driver becomes available and the next pending order (if any) should be auto-assigned.

5) String getOrderStatus(String orderId)

  • Returns order statuses: CREATED, ASSIGNED, PICKED_UP, DELIVERED, CANCELED.

6) String getDriverStatus(String driverId)

  • Returns driver statuses: AVAILABLE, or BUSY:<orderId>.

Constraints

  • No external database (use only in-memory data structures).
  • All IDs are case-sensitive strings.
  • totalUsers and totalDrivers are both greater than or equal to 1
  • Valid customer ids: user-0 ... user-(totalUsers-1).
  • Valid driver ids: dv-0 ... dv-(totalDrivers-1).
  • One driver can handle only one ongoing order at a time.
  • Valid order transitions :
    • CREATED -> ASSIGNED -> PICKED_UP -> DELIVERED
    • CREATED/ASSIGNED -> CANCELED
  • Once PICKED_UP, the order cannot be canceled.
  • Canceled orders must never be picked up or delivered.
  • Ignore travel time; availability is purely state-based.
  • Ensure application is thread safe and handles concurrency scenarios.

Examples

Example 1: Basic flow with immediate assignment (lexicographically lowest available driver)

  • PeerToPeerDeliverySystem system = new PeerToPeerDeliverySystem(totalUsers = 3, totalDrivers = 2, deliverableItemIds = List.of("ITEM_1", "ITEM_2"))  => system
  • system.createOrder(orderId = "O1", customerId = "user-0", itemId = "ITEM_1")  => ACCEPTED (a driver was available, so the order was assigned immediately)
  • system.getOrderStatus(orderId = "O1")  => ASSIGNED
  • system.getDriverStatus(driverId = "dv-0")  => BUSY:O1 (dv-0 is the lexicographically lowest available driver)
  • system.getDriverStatus(driverId = "dv-1")  => AVAILABLE
  • system.pickUpOrder(driverId = "dv-0", orderId = "O1")  => PICKED_UP
  • system.cancelOrder(orderId = "O1")  => ERROR (once PICKED_UP, the order cannot be canceled)
  • system.deliverOrder(driverId = "dv-0", orderId = "O1")  => DELIVERED
  • system.getDriverStatus(driverId = "dv-0")  => AVAILABLE

Example 2: Cancel before pickup frees driver + invalid createOrder

  • PeerToPeerDeliverySystem system = new PeerToPeerDeliverySystem(totalUsers = 2, totalDrivers = 1, deliverableItemIds = List.of("ITEM_A"))  => system
  • system.createOrder(orderId = "O1", customerId = "user-0", itemId = "ITEM_A")  => ACCEPTED
  • system.getDriverStatus(driverId = "dv-0")  => BUSY:O1
  • system.cancelOrder(orderId = "O1")  => CANCELED (order was ASSIGNED but not PICKED_UP, so it can be canceled)
  • system.getDriverStatus(driverId = "dv-0")  => AVAILABLE (canceling an assigned-but-not-picked order frees the driver)
  • system.pickUpOrder(driverId = "dv-0", orderId = "O1")  => ERROR (canceled orders cannot be picked up)
  • system.createOrder(orderId = "BAD1", customerId = "user-0", itemId = "UNKNOWN_ITEM")  => INVALID (itemId is not in the preconfigured deliverableItemIds list)
  • system.createOrder(orderId = "O2", customerId = "user-1", itemId = "ITEM_A")  => ACCEPTED (dv-0 is available again, so O2 is assigned immediately)
  • system.getOrderStatus(orderId = "O2")  => ASSIGNED
  • system.getDriverStatus(driverId = "dv-0")  => BUSY:O2

Example 3: Pending orders when drivers are busy + FIFO assignment of pending queue

  • PeerToPeerDeliverySystem system = new PeerToPeerDeliverySystem(totalUsers = 3, totalDrivers = 1, deliverableItemIds = List.of("X", "Y"))  => system
  • system.createOrder(orderId = "O1", customerId = "user-0", itemId = "X")  => ACCEPTED
  • system.pickUpOrder(driverId = "dv-0", orderId = "O1")  => PICKED_UP (driver is now busy with O1)
  • system.createOrder(orderId = "O2", customerId = "user-1", itemId = "Y")  => PENDING (no driver available, so the order waits in the pending queue)
  • system.createOrder(orderId = "O3", customerId = "user-2", itemId = "X")  => PENDING (also queued after O2)
  • system.getOrderStatus(orderId = "O2")  => CREATED (created but not yet assigned)
  • system.getOrderStatus(orderId = "O3")  => CREATED
  • system.cancelOrder(orderId = "O3")  => CANCELED (a CREATED/pending order can be canceled)
  • system.deliverOrder(driverId = "dv-0", orderId = "O1")  => DELIVERED (driver becomes available; next pending order is auto-assigned)
  • system.getOrderStatus(orderId = "O2")  => ASSIGNED (O2 was first in the pending queue, so it gets assigned before O3)
  • system.getDriverStatus(driverId = "dv-0")  => BUSY:O2
  • system.pickUpOrder(driverId = "dv-0", orderId = "O3")  => ERROR (O3 is canceled and also not assigned to dv-0)




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