Skip to content

Sde105 api

Parking Lot x Electric Vehicle

The Parking Lot Problem is a well-known design challenge in system architecture, typically involving vehicle parking, spot management, and space allocation. In this modified version, we enhance the problem by introducing Electric Vehicle (EV) chargers integrated into the parking spots, creating a more complex and realistic system.

In this parking lot system: 1. Vehicles can be either electric (EV) or non-electric (NonEV). 2. Parking spots are either equipped with an EV charger or do not have a charger. Only EVs can use chargers. 3. The parking lot should handle different operations like reserving spots, parking vehicles, and managing the charging process for electric vehicles.

The system must support:

  • EV Charger Integration: Parking spots equipped with chargers should support starting and stopping charging sessions for electric vehicles.
  • Pricing Calculation: The charging cost should be calculated based on the time an EV has been charging.
  • Efficient Spot Management: The parking lot must be able to efficiently manage and track parking spots, ensuring that spots with chargers are correctly allocated to electric vehicles and that no non-EV vehicle can occupy these spots.

UML Line Types

Line Type Relationship Description Example
Solid Line (Association) Association Represents a simple connection between classes. Can be unidirectional or bidirectional. ClassA -- ClassB
Dashed Line (Dependency) Dependency Indicates that one class depends on another. The dependent class uses services from another class. ClassA ..> ClassB
Solid Diamond Line (Aggregation) Aggregation A whole-part relationship where the part can exist independently of the whole. ClassA o-- ClassB
Filled Diamond Line (Composition) Composition A whole-part relationship where the part cannot exist without the whole (strong aggregation). ClassA *-- ClassB
Arrow Line (Generalization) Generalization (Inheritance) Represents inheritance, where a subclass extends a superclass. The arrow points from the subclass to the superclass. ClassB --\|> ClassA (ClassB is a subclass of ClassA)
Dashed Line with Arrow (Realization) Realization (Interface Implementation) Indicates that a class implements an interface. The dashed line with an arrow points from the class to the interface. ClassB ..\|> InterfaceA (ClassB implements InterfaceA)
Association with Role Names and Multiplicity Association with Role and Multiplicity Association can include role names and multiplicity, specifying the number of instances involved. ClassA "1" -- "*" ClassB

UML diagram image

Fast API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@startuml

enum VehicleType {
  EV
  NonEV
}

interface ParkingVehicle {
  + vehicle_type: VehicleType
  + license_plate: str
  + is_ev(): bool
}

class Charger {
  - start_time: Optional[datetime]
  - end_time: Optional[datetime]
  + start_charge(): void
  + end_charge(): void
  + calculate_price(): float
}

class ParkingSpot {
  - spot_number: int
  - vehicle: Optional<ParkingVehicle>
  - charger: Optional<Charger>
  + reserve_spot(vehicle: ParkingVehicle): void
  + release_spot(): void
  + is_available(): bool
  + start_charging(): void
  + stop_charging(): void
  + calculate_price(): float
}

class ParkingLot {
  - spots: Dict<int, ParkingSpot>
  + find_available_spot(): Optional<ParkingSpot>
  + park_vehicle(vehicle: ParkingVehicle): ParkingSpot
  + unpark_vehicle(vehicle: ParkingVehicle): void
}

ParkingLot "1" *-- "*" ParkingSpot : contains
ParkingSpot "1" o-- "0..1" ParkingVehicle : occupies
ParkingSpot "1" o-- "0..1" Charger : has

ParkingVehicle <|.. EV
ParkingVehicle <|.. NonEV

@enduml
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import random
from enum import Enum
from pydantic import BaseModel
from datetime import datetime
from typing import Dict, Optional
from fastapi import FastAPI, HTTPException

# Define the vehicle types
class VehicleType(str, Enum):
    EV = "EV"
    NonEV = "NonEV"

# Define the ParkingVehicle interface
class ParkingVehicle(BaseModel):
    vehicle_type: VehicleType
    license_plate: str

    def is_ev(self) -> bool:
        return self.vehicle_type == VehicleType.EV

# Charger class to handle charging logic
class Charger(BaseModel):
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None

    def start_charge(self):
        self.start_time = datetime.now()

    def end_charge(self):
        self.end_time = datetime.now()

    def calculate_price(self) -> float:
        if self.start_time and self.end_time:
            # For simplicity, assuming $0.10 per minute of charge
            duration = (self.end_time - self.start_time).total_seconds() / 60
            return 1 + round(duration * 0.10, 2)  # Calculate price based on duration
        return 0.0

    def reset_charge(self):
        self.start_time = None
        self.end_time = None

# Define the ParkingSpot class
class ParkingSpot(BaseModel):
    spot_number: int
    vehicle: Optional[ParkingVehicle] = None
    charger: Optional[Charger] = None

    def reserve_spot(self, vehicle: ParkingVehicle):
        if self.is_available():
            self.vehicle = vehicle
            if vehicle.is_ev() and not self.charger:
                raise HTTPException(status_code=400, detail="EV charger is required but not available")
        else:
            raise HTTPException(status_code=400, detail="Parking spot is already occupied")

    def release_spot(self):
        self.vehicle = None
        if self.charger:
            self.charger.reset_charge()

    def is_available(self) -> bool:
        return self.vehicle is None

    def start_charging(self):
        if self.vehicle and self.vehicle.is_ev() and self.charger:
            self.charger.start_charge()

    def stop_charging(self):
        if self.charger:
            self.charger.end_charge()

    def calculate_price(self) -> float:
        if self.charger:
            return self.charger.calculate_price()
        return 0.0

# Define the ParkingLot class using a dictionary for spots
class ParkingLot:
    spots: Dict[int, ParkingSpot]

    def __init__(self, spots: Dict[int, ParkingSpot]):
        self.spots = spots

    def find_available_spot(self, is_ev=False) -> Optional[ParkingSpot]:
        for spot in self.spots.values():
            if spot.is_available():
                if is_ev:
                    if spot.charger:
                        return spot
                    else:
                        continue
                else:
                    return spot
        return None

    def park_vehicle(self, vehicle: ParkingVehicle) -> ParkingSpot:
        spot = self.find_available_spot(is_ev=vehicle.is_ev())
        if spot:
            spot.reserve_spot(vehicle)
            return spot
        else:
            raise HTTPException(status_code=400, detail="No available parking spots")

    def unpark_vehicle(self, vehicle: ParkingVehicle):
        for spot in self.spots.values():
            if spot.vehicle == vehicle:
                spot.release_spot()
                return
        raise HTTPException(status_code=400, detail="Vehicle not found in parking lot")

# FastAPI app initialization
app = FastAPI()

# Create parking lot and spots, with half having chargers
total_spots = 10
spots = {}

for i in range(1, total_spots + 1):
    spot = ParkingSpot(spot_number=i)
    # Randomly assign chargers
    if random.choice([True, False]):
        spot.charger = Charger()  # Assign charger to this spot
    spots[i] = spot

parking_lot = ParkingLot(spots=spots)

# FastAPI endpoints
@app.post("/park/")
async def park_vehicle(vehicle: ParkingVehicle):
    spot = parking_lot.park_vehicle(vehicle)
    return {"spot_number": spot.spot_number, "vehicle": vehicle}

@app.post("/unpark/")
async def unpark_vehicle(vehicle: ParkingVehicle):
    parking_lot.unpark_vehicle(vehicle)
    return {"message": f"Vehicle {vehicle.license_plate} has been unparked"}

@app.post("/start_charging/{spot_number}")
async def start_charging(spot_number: int):
    spot = parking_lot.spots.get(spot_number)
    if spot:
        if spot.vehicle and spot.vehicle.is_ev() and spot.charger:
            spot.start_charging()
            return {"message": f"Charging started for vehicle at spot {spot_number}"}
        raise HTTPException(status_code=400, detail="Spot is not suitable for charging")
    raise HTTPException(status_code=404, detail="Spot not found")

@app.post("/stop_charging/{spot_number}")
async def stop_charging(spot_number: int):
    spot = parking_lot.spots.get(spot_number)
    if spot:
        if spot.charger:
            spot.stop_charging()
            return {"message": f"Charging stopped at spot {spot_number}. Total charge: ${spot.calculate_price()}"}
        raise HTTPException(status_code=400, detail="Charging not started or spot not found")
    raise HTTPException(status_code=404, detail="Spot not found")

@app.get("/available_spot/")
async def get_available_spot():
    spot = parking_lot.find_available_spot()
    if spot:
        return {"spot_number": spot.spot_number}
    return {"message": "No available parking spots"}

@app.get("/list_parking_lot_spots/")
async def list_parking_lot_spots():
    return parking_lot.spots

Key Takeaways

  1. EV Charger Integration: The system integrates chargers with parking spots, and charging is only applicable to EV vehicles.

  2. Efficient Parking Spot Management: The system uses a dictionary to store parking spots, allowing for quick lookups and efficient spot management.

  3. Charging Process: Charging for EV vehicles is managed through the Charger class, which calculates the total cost based on the duration of the charging session.

  4. Vehicle Type Handling: The VehicleType enum differentiates between EV and non-EV vehicles, with additional logic in the system to ensure that only EV vehicles can use charging spots.

  5. Extensibility and Scalability: The system is designed to be scalable and easily extensible. New features, such as adding more vehicle types or different pricing mechanisms, can be added with minimal changes to the current design.

This enhanced Parking Lot system with EV chargers provides a real-world solution to managing parking spaces with added complexity from EVs and their charging requirements. It can be further extended to support more sophisticated features like reservation systems or dynamic pricing.