269. Design Cab Booking Service
Asked in
Design Cab Booking Service
Design a simplified cab booking service in which passengers can request and cancel rides, while drivers can accept and complete them. Each ride contains a supplied ride ID, pickup location, destination, ride type, estimated distance, estimated travel time, and calculated fare.
All passenger IDs, driver IDs, and ride IDs are supplied as input. The service must not generate any identifiers.

Constructor

CabBookingService(List<String> passengerIds, List<String> driverIds)
  • Initializes the service with all existing passenger and driver IDs.
  • Every passenger ID and driver ID is supplied as input.
  • Every driver is initially available.

Methods

Request Ride

String requestRide(String rideId, String passengerId, String pickupLocation, String destination, double distanceKm, String rideType, int rideTimeMinutes)
  • Creates a new ride using the supplied rideId.
  • The service does not generate the ride ID.
  • The supplied passenger must not currently have another active ride.
  • The new ride has status REQUESTED.
  • The new ride initially has no assigned driver.
  • Calculates the fare using the distance, ride type, and estimated travel time.
  • The calculated fare is truncated to an integer.
  • Returns the created ride in the specified ride format.

Accept Ride

String acceptRide(String driverId, String rideId)
  • Assigns the supplied available driver to the requested ride.
  • The ride must currently have status REQUESTED.
  • The supplied driver must currently be available.
  • Changes the ride status from REQUESTED to ACCEPTED.
  • The assigned driver becomes unavailable until the ride is completed or cancelled.
  • Returns the updated ride.

Complete Ride

String completeRide(String driverId, String rideId)
  • Completes a ride previously accepted by the supplied driver.
  • The ride must currently have status ACCEPTED.
  • The supplied driverId must be the driver assigned to the ride.
  • Changes the ride status from ACCEPTED to COMPLETED.
  • The driver becomes available again.
  • Returns the updated ride.

Cancel Ride

String cancelRide(String passengerId, String rideId)
  • Cancels a ride belonging to the supplied passenger.
  • The supplied passengerId must be the passenger who requested the ride.
  • A ride may be cancelled while its status is REQUESTED or ACCEPTED.
  • If an accepted ride is cancelled, its assigned driver becomes available again.
  • Changes the ride status to CANCELLED.
  • Returns the updated ride.

Ride Format

Every returned ride is represented as:
"rideId,status,passengerId,driverId,pickupLocation,destination,rideType,fare"
  • status is REQUESTED, ACCEPTED, COMPLETED, or CANCELLED.
  • driverId is none until a driver accepts the ride.
  • fare is represented as an integer.
  • fare does not contain a decimal point.
  • A cancelled ride retains its assigned driver ID if it had already been accepted.

Fare Calculation

The fare before truncation is calculated as:
baseFare + distanceKm × distanceRate + rideTimeMinutes × timeRate
  • STANDARD: base fare = 40.0, distance rate = 12.0 per kilometre, time rate = 2.0 per minute.
  • PREMIUM: base fare = 80.0, distance rate = 20.0 per kilometre, time rate = 3.0 per minute.
  • The complete fare expression is evaluated before truncation.
  • The final fare is truncated to an integer by removing the fractional part.
  • The fare is not rounded to the nearest integer.
  • For example, a calculated fare of 42.75 becomes 42.
  • Because all fare values are positive, truncation is equivalent to rounding down.

Ride Lifecycle

  • REQUESTED → ACCEPTED → COMPLETED
  • REQUESTED → CANCELLED
  • REQUESTED → ACCEPTED → CANCELLED
  • A ride with status COMPLETED or CANCELLED cannot change status again.

Active Ride

  • A ride is active when its status is REQUESTED or ACCEPTED.
  • A ride with status COMPLETED or CANCELLED is no longer active.
  • A passenger cannot request another ride while the passenger already has an active ride.
  • After a passenger's active ride is completed or cancelled, the passenger may request another ride.

Identifier Rules

  • All passenger IDs and driver IDs are supplied to the constructor.
  • Every ride ID is supplied to requestRide.
  • The service does not generate passenger IDs, driver IDs, or ride IDs.
  • Each passenger ID is unique.
  • Each driver ID is unique.
  • Each ride ID is unique across all requested rides.
  • A ride ID cannot be reused after its ride is completed or cancelled.

Constraints

  • 1 ≤ passengerIds.size() ≤ 10,000
  • 1 ≤ driverIds.size() ≤ 10,000
  • passengerIds contains no duplicate values.
  • driverIds contains no duplicate values.
  • 1 ≤ rideId.length(), passengerId.length(), driverId.length() ≤ 100
  • 1 ≤ pickupLocation.length(), destination.length() ≤ 100
  • 0.1 ≤ distanceKm ≤ 10,000.0
  • 1 ≤ rideTimeMinutes ≤ 10,000
  • rideType is either STANDARD or PREMIUM.
  • IDs contain only lowercase English letters, digits, and hyphens.
  • Locations do not contain commas.
  • No parameter value is null.
  • Every passengerId passed to a method exists in passengerIds.
  • Every driverId passed to a method exists in driverIds.
  • Every rideId passed to requestRide is unique.
  • Every rideId passed to another method refers to an existing ride.
  • Every method call satisfies the required ride status, passenger ownership, driver assignment, and driver availability conditions.
  • A passenger has at most one active ride at a time.
  • A driver accepts at most one active ride at a time.

Examples

Parameter names are shown in method calls only for readability.

Example 1: Request, Accept, and Complete a Standard Ride

CabBookingService service = new CabBookingService(passengerIds = List.of("passenger-7", "passenger-9"), driverIds = List.of("driver-2", "driver-5"));
service.requestRide(rideId = "booking-101", passengerId = "passenger-7", pickupLocation = "airport", destination = "city-center", distanceKm = 8.5, rideType = "STANDARD", rideTimeMinutes = 24)
Output: "booking-101,REQUESTED,passenger-7,none,airport,city-center,STANDARD,190"
The fare before truncation is 40.0 + 8.5 × 12.0 + 24 × 2.0 = 190.0. The returned integer fare is 190.
service.acceptRide(driverId = "driver-2", rideId = "booking-101")
Output: "booking-101,ACCEPTED,passenger-7,driver-2,airport,city-center,STANDARD,190"
service.completeRide(driverId = "driver-2", rideId = "booking-101")
Output: "booking-101,COMPLETED,passenger-7,driver-2,airport,city-center,STANDARD,190"

Example 2: Cancel a Premium Ride Before Acceptance

service.requestRide(rideId = "booking-205", passengerId = "passenger-9", pickupLocation = "railway-station", destination = "technology-park", distanceKm = 12.0, rideType = "PREMIUM", rideTimeMinutes = 30)
Output: "booking-205,REQUESTED,passenger-9,none,railway-station,technology-park,PREMIUM,410"
The fare before truncation is 80.0 + 12.0 × 20.0 + 30 × 3.0 = 410.0. The returned integer fare is 410.
service.cancelRide(passengerId = "passenger-9", rideId = "booking-205")
Output: "booking-205,CANCELLED,passenger-9,none,railway-station,technology-park,PREMIUM,410"

Example 3: Cancel an Accepted Ride with a Truncated Fare

service.requestRide(rideId = "trip-88", passengerId = "passenger-7", pickupLocation = "museum", destination = "university", distanceKm = 5.27, rideType = "STANDARD", rideTimeMinutes = 15)
Output: "trip-88,REQUESTED,passenger-7,none,museum,university,STANDARD,133"
The fare before truncation is 40.0 + 5.27 × 12.0 + 15 × 2.0 = 133.24. The fractional part is removed, so the returned fare is 133.
service.acceptRide(driverId = "driver-5", rideId = "trip-88")
Output: "trip-88,ACCEPTED,passenger-7,driver-5,museum,university,STANDARD,133"
service.cancelRide(passengerId = "passenger-7", rideId = "trip-88")
Output: "trip-88,CANCELLED,passenger-7,driver-5,museum,university,STANDARD,133"

Example 4: Fractional Fare Is Truncated

service.requestRide(rideId = "trip-99", passengerId = "passenger-9", pickupLocation = "market", destination = "library", distanceKm = 4.23, rideType = "STANDARD", rideTimeMinutes = 8)
Output: "trip-99,REQUESTED,passenger-9,none,market,library,STANDARD,106"
The fare before truncation is 40.0 + 4.23 × 12.0 + 8 × 2.0 = 106.76. The fractional part is removed, so the returned fare is 106.


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