Requirements


  1. The system automatically assigns a spot to a car.
    1. The system assigns a spot of appropriate size (small, medium, large)
    2. The system checks for free spots.
  2. Upon successful assigning, the system issues a ticket with the current time.
  3. When the vehicle leaves, the system charges an amount determined by the time the vehicle spent in the lot.
  4. The system notifies vehicles when no space is available.


Core Objects & Relationships

Based on the requirements and use cases, identify the main objects of the system and analyze how they interact and relate to each other...


Entities:

  • ParkingService
  • ParkingFloor
  • Ticket
  • ParkingSpot
  • VehicleSize (enum: small, medium, large)


* We could add Vehicle here, but I think all we need from a vehicle is its size, so for simplicity I ommit it.


Relationships:

  • ParkingService is the orchestrator. It holds the parking floors, tracks its own state (Full, Available_spots), and handles the ticket issuing logic for incoming vehicles, as well as the payment logic for outgoing vehicles.
  • ParkingFloor holds a grid of parking spots. It has a label to make it easy to find to clients. It tracks whether the floor is full or not. It knows how to find an available spot of a certain size.
  • ParkingSpot represents a spot where cars can be allocated. It knows its size (small, medium, large) and tracks whether it is empty or occupied.
  • Ticket holds a reference to the parking spot where the vehicle was assigned to, as well as a timestamp of entrance. Upon exit, it knows the time of exit.



APIs & Class Members

For each class, define the attributes (data) it will hold and the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation. Write your code in the code editor below.


class ParkingService:

- floors: List

- state: FULL, AVAILABLE

- map: Map

- feeStrategy: FeeStrategy

+ ParkingService(numFloors, feeStrategy)

+ assignSpot(size) -> Ticket

+ checkout(ticket) -> void


class ParkingFloor:

- floorId: string

- state: FULL, AVAILABLE

+ ParkingLot(floorId)

+ isFull() -> bool

+ getAvailableSpot(size) -> ParkingSpot


class ParkingSpot:

- size: VehicleSize

- state: EMPTY, OCCUPIED

+ markEmpty() -> void

+ markOccupied() -> void


class Ticket:

- issue: timestamp

- exit: timestamp

- parkingSpot: ParkingSpot


interface FeeStrategy:

+ calculateFee(ticket) -> double



Deep Dive

Explain design tradeoffs you considered. Check and explain whether your design adheres to SOLID principles. Explain how your design can handle changes in scale and whether it would be easy to extend with new functionalities. Identify areas for future improvement...