My Solution for Design a Parking Lot with Score: 4/10

by pulse_alchemy255

Requirements

The parking lot caters to different vehicles. It has multiple spots available based on size of the vehicle(bike , car , semi trcuk etc. The main functionalities will include:

  1. Parking spot assignment
  2. Multiple floor support
  3. Spot availability
  4. User or Admin
  5. Ticketing
  6. Paymet




Define Core Objects






Analyze Relationships





Establish Hierarchy

Design inheritance trees where applicable to promote code reuse and polymorphism. This step involves identifying common attributes and behaviors that can be abstracted into parent classes...






Design Patterns

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






#include <iostream> #include <vector> #include <string> #include <ctime> #include <mutex> using namespace std; // Enumeration for Vehicle Size enum VehicleSize { SMALL, MEDIUM, LARGE }; // Abstract Vehicle class class Vehicle { public: virtual VehicleSize getSize() const = 0; virtual double calculateFee(int hoursParked) const = 0; virtual ~Vehicle() = default; }; // Car class derived from Vehicle class Car : public Vehicle { public: VehicleSize getSize() const override { return SMALL; } double calculateFee(int hoursParked) const override { return hoursParked * 2.0; } }; // Truck class derived from Vehicle class Truck : public Vehicle { public: VehicleSize getSize() const override { return LARGE; } double calculateFee(int hoursParked) const override { return hoursParked * 5.0; } }; // ParkingSpot class class ParkingSpot { private: VehicleSize size; string identifier; int floorNumber; bool isOccupied; Vehicle* v; time_t checkInTime; time_t checkOutTime; std::mutex spotMutex; // Mutex for thread safety public: // Constructor ParkingSpot(VehicleSize sz, string id, int floor) : size(sz), identifier(id), floorNumber(floor), isOccupied(false), v(nullptr) {} // Accessor methods VehicleSize getSize() const { return size; } string getIdentifier() const { return identifier; } int getFloorNumber() const { return floorNumber; } bool getIsOccupied() const { return isOccupied; } // Assign a vehicle to the parking spot void assignVehicle(Vehicle* vehicle) { std::lock_guard<std::mutex> lock(spotMutex); if (!isOccupied && vehicle->getSize() == size) { v = vehicle; checkInTime = time(nullptr); // Record check-in time isOccupied = true; } } // Remove the vehicle from the parking spot void removeVehicle() { std::lock_guard<std::mutex> lock(spotMutex); if (isOccupied) { v = nullptr; isOccupied = false; } } // Calculate fee based on parking time double calculateFee() { std::lock_guard<std::mutex> lock(spotMutex); checkOutTime = time(nullptr); // Record check-out time int hoursParked = difftime(checkOutTime, checkInTime) / 3600; // Calculate hours parked return v->calculateFee(hoursParked); // Delegate fee calculation to the vehicle } }; // ParkingFloor class class ParkingFloor { private: int floorNumber; vector<ParkingSpot> spots; public: // Constructor ParkingFloor(int floorNum, int totalSpots) : floorNumber(floorNum) { for (int i = 0; i < totalSpots; i++) { spots.push_back(ParkingSpot(SMALL, "S" + to_string(i), floorNum)); // Example: all small spots } } // Find available spot for a vehicle ParkingSpot* findAvailableSpot(Vehicle* v) { for (auto& spot : spots) { if (!spot.getIsOccupied() && spot.getSize() == v->getSize()) { return &spot; } } return nullptr; } }; // ParkingLot class class ParkingLot { private: vector<ParkingFloor> floors; int totalFloors; int spotsPerFloor; public: // Constructor ParkingLot(int totalFloors, int spotsPerFloor) : totalFloors(totalFloors), spotsPerFloor(spotsPerFloor) { for (int i = 0; i < totalFloors; i++) { floors.push_back(ParkingFloor(i, spotsPerFloor)); // Initialize each floor } } // Assign a spot for a vehicle void assignSpot(Vehicle* v) { for (auto& floor : floors) { ParkingSpot* availableSpot = floor.findAvailableSpot(v); if (availableSpot != nullptr) { availableSpot->assignVehicle(v); cout << "Assigned vehicle to spot " << availableSpot->getIdentifier() << " on floor " << availableSpot->getFloorNumber() << endl; return; } } cout << "No available spot for vehicle." << endl; } // Release a spot occupied by a vehicle void releaseSpot(Vehicle* v) { for (auto& floor : floors) { for (auto& spot : floor.spots) { if (spot.getIsOccupied() && spot.getSize() == v->getSize()) { double fee = spot.calculateFee(); // Calculate parking fee spot.removeVehicle(); cout << "Released spot " << spot.getIdentifier() << " on floor " << spot.getFloorNumber() << ". Parking fee: $" << fee << endl; return; } } } cout << "Vehicle not found." << endl; } }; int main() { // Create a parking lot with 2 floors and 5 spots per floor ParkingLot lot(2, 5); // Create vehicles Car car1; Truck truck1; // Assign spots lot.assignSpot(&car1); lot.assignSpot(&truck1); // Release spots lot.releaseSpot(&car1); lot.releaseSpot(&truck1); return 0; }


Adhere to SOLID Guidelines

Check and explain whether your design adheres to solid principles (Ask interviewer what SOLID principle is if you can not recall it.)...






Consider Scalability and Flexibility

Explain how your design can handle changes in scale and whether it would be easily to extend with new functionalities...






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

Critically examine your design for any flaws or areas for future improvement...