Requirements


Parking lot that contains multiple floor and spots suitable for different size of vehicles.


Calculate fees of a vehicle using a spot depending on parking duration

-> minutes -> UNIX minutes


Find a suitable spot for a vehicle to fit, preferring an exact size spot



Questions:

Is there a time limit of a vehicle using a spot?








Define Core Objects


Enum SpotSize:

SMALL

MEDIUM

LARGE



// vehicle

// find spot and get parking ticket

// vehicle leaving and paying ticket



FeeCalculator:

MinuteFee : Map int

PenaltyFee: Map int

TimeLimit: int

int VehicleFee(parkingTicket)


Parking Lot:


feeCalculator: FeeCalculator

floors: Floor[]


parkingTicket FindSpotForVehicle(vehicle)

int VehicleLeaving(parkingTicket, date: Minutes UNIX)


Floor:

floorNumber

spots: Spots[]



Spot:

Size: SpotSize

Available: Bool


ParkingTicket:

EnteringDate: Int

Spot: Spot

Vehicle: Vehicle


Vehicle:

Plate: string

size: SpotSize

parkingTicket


  • Motorbike:

SpotSize = SMALL

  • Car:
    • SpotSize = MEDIUM
  • Truck:
    • SpotSize = LARGE





Analyze Relationships

The inreractions are already defined





Establish Hierarchy

vehicle have already define hierarchy





Design Patterns

Consider using design patterns (e.g., Factory, Singleton, Observer, Strategy) that fit the problem...






Define Class Members (write code)

Attributes: For each class, define the attributes (data) it will hold...

Methods: Define the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation.


from enum import Enum from typing import List, Dict, Tuple, Optional from abc import ABC, abstractmethod class SpotSize(Enum): SMALL = 1 MEDIUM = 2 LARGE = 3 class Floor: def init(self, floorNumber: int, spotsAvailable: Dict[SpotSize, int] ): self.floorNumber = floorNumber self.spotsAvailable = spotsAvailable def isSpotForVehicleSizeAvailable(self, vehicleSize: SpotSize) -> bool: return self.spotsAvailable[vehicleSize] > 0 def useSpot(self, vehicleSize: SpotSize) -> bool: self.spotsAvailable[vehicleSize] -= 1 def freeSpot(self, vehicleSize: SpotSize) -> bool: self.spotsAvailable[vehicleSize] += 1 class ParkingTicket: def init(self, enteringDate: int, spotSize: SpotSize, spotFloor: Floor): self.enteringDate = enteringDate self.spotSize = spotSize self.spotFloor = spotFloor class Vehicle: def init(self, plate: str, size: SpotSize): self.plate = plate self.size = size self.parkingTicket = None class Motorbike(Vehicle): def init(self, plate: str): super().init(plate, SpotSize.SMALL) class Car(Vehicle): def init(self, plate: str): super().init(plate, SpotSize.MEDIUM) class Truck(Vehicle): def init(self, plate: str): super().init(plate, SpotSize.LARGE) def vehicleFactory(plate: str, vehicleType: str) -> Vehicle: if(vehicleType == "motorbike"): return Motorbike(plate) if(vehicleType == "car"): return Car(plate) if(vehicleType == "truck"): return Truck(plate) class FeeCalculator: def init(self, timeLimit: int, minuteFee: Dict[SpotSize, int], penaltyFee: Dict[SpotSize, int]): self.timeLimit = timeLimit self.minuteFee = minuteFee self.penaltyFee = penaltyFee def vehicleFee(self, vehicle: Vehicle, leavingDate: int) -> int: parkingTicket = vehicle.parkingTicket minutesUsingSpot = leavingDate - parkingTicket.enteringDate fee = minutesUsingSpot * self.minuteFee[vehicle.size] if minutesUsingSpot > self.timeLimit: fee += self.penaltyFee[vehicle.size] return fee class ParkingLot: _instance = None def new(cls, feeCalculator: FeeCalculator, floors: List[Floor]): if cls._instance is None: cls._instance = super().new(cls) cls._instance.feeCaclulator = feeCalculator cls._instance.floors = floors return cls._instance def enterParkingSlot(self, vehicle: Vehicle, enteringDate: int) -> ParkingTicket: spotSize, spotFloor = self.findSpotForVehicle(vehicle.size) if not spotSize: return None parkingTicket = ParkingTicket(enteringDate, spotSize, spotFloor) vehicle.parkingTicket = parkingTicket return parkingTicket def leaveParkingSlot(self, vehicle: Vehicle, leavingDate: int) -> Optional[int]: if not vehicle.parkingTicket: return None parkingTicket = vehicle.parkingTicket parkingTicket.spotFloor.freeSpot(parkingTicket.spotSize) return self.feeCaclulator.vehicleFee(vehicle, leavingDate) def findSpotForVehicle(self, vehicleSize: SpotSize) -> Tuple[Optional[bool], Optional[Floor]]: spotSizeAvailable = None spotFloor = None for spotSize in SpotSize: if spotSize.value < vehicleSize.value: continue if spotSizeAvailable != None: break for floor in self.floors: if floor.isSpotForVehicleSizeAvailable(spotSize): spotSizeAvailable = spotSize spotFloor = floor break if spotSizeAvailable == None: return None, None spotFloor.useSpot(spotSizeAvailable) return spotSizeAvailable, spotFloor if name == "main": car = vehicleFactory("abc123", "car") car2 = vehicleFactory("abc124", "car") car3 = vehicleFactory("abc125", "car") check if no spot found floor1 = Floor(1, { SpotSize.MEDIUM: 1, SpotSize.LARGE: 1 }) floors = [floor1] minuteFee = {SpotSize.SMALL: 1, SpotSize.MEDIUM: 2, SpotSize.LARGE: 3} penaltyFee = {SpotSize.SMALL: 10, SpotSize.MEDIUM: 20, SpotSize.LARGE: 30} feeCalculator =FeeCalculator(120, minuteFee, penaltyFee) parkingLot = ParkingLot(feeCalculator, floors) ticket1 = parkingLot.enterParkingSlot(car, 1) print(ticket1.spotSize) ticket2 = parkingLot.enterParkingSlot(car2, 2) print(ticket2.spotSize) ticket3 = parkingLot.enterParkingSlot(car3, 3) print(ticket3) print(parkingLot.leaveParkingSlot(car, 10)) print(parkingLot.leaveParkingSlot(car2, 12)) print(parkingLot.leaveParkingSlot(car3, 12))





Adhere to SOLID Guidelines

Yes





Consider Scalability and Flexibility

It is flexible, since accepts more types of cars with sizes defined already

It is scalable since each parking slot can handle its own parking spots inside its class




Create/Explain your diagram(s)

Try creating a class, flow, state and/or sequence diagram using the diagramming tool. Mermaid flow diagrams can be used to represent system use cases. You can ask the interviewer bot to create a starter diagram if unfamiliar with the tool. Briefly explain your diagrams if necessary...






Future improvements



Add parking SPot class

Add location of pot, and heap that orders spots in a floor depending on location

Add lock so only one car enters and uses a spot at the time