Requirements

  1. Parking lot system must have a method to assign parking spots to users
    1. Parking spots will be assigned automatically based on the nearest available spot that fits the cars description
  2. Parking lot system must have a method to allow users to pay their ticket fee
    1. Once the ticket has been paid, the parking spot assigned to the user will be freed back into the pool of available parking spots



Define Core Objects

  1. Parking Lot Class
    1. Singleton class
    2. Holds multiple Parking Lot Floor Objects
    3. Holds a map of ticket IDs to tickets
    4. Contains two methods
      1. Assign Parking Spot(String CarType): takes in a string CarType and returns a parking spot ID and a ticket ID
  2. Parking Lot Floor Class
    1. Holds multiple Parking Spot Objects
    2. Has a method called GetFreeParkingSpot(String CarType) which returns a parking spot ID and fee per hour of the nearest open parking spot given a car type. returns -1 if no spots available
  3. Parking Spot Class
    1. contains an ID, a isAvailable property, and type
    2. The ID should contain relevant information about the spot including floor number, area code, and spot type for example an ID of 424C would be the 24th parking spot in the 4th floor for compact cars
  4. Ticket Class
    1. Contains a ticket ID, a entry time, a parking spot ID. Also contains a status for paid or unpaid
  5. Payment Manager
    1. Separate from Parking lot, manages payments given ticket Id
  6. Settings Object
    1. Singleton class that will contain various information such as valid car types, fees per car spot, etc.





Analyze Relationships

Use Cases

  1. Need to assign parking spot to new customer
    1. Customer makes request at the parking lot entrance for new available parking spot giving their car type. The parking lot class takes in the request, and loops through its parking lot floors from lowest to highest floor level making a request to each parking lot floor's GetFreeParkingSpot method. The first floor to return a free parking spot is then used to create a ticket, and the ticket id is returned to the user with parking spot ID
  2. need to pay for parking spot
    1. Customer makes a parking spot payment request. Parking Lot Sytem will make a request to the payment manager given a ticket object. Returns True/False if payment is made successfully.




Establish Hierarchy

I currently do not have any classes that derive from each other. I considered creating an abstract parking spot class and then making derived classes for other spots based on size, but I felt like this was unnecessary as the only differences between spots are the size of the spot and the name of the spot type.





Design Patterns

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

Singletons are being used here for the Parking lot, payment manager, and settings classes. The settings object will be provided to objects through dependency injection




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.


class ParkingLot: def __init__(self): self.floors = [] self.settings = Settings() self.paymentManager = PaymentManager(settings) self.tickets = {} def addFloor(self, parkingSpotAllocation): self.floors.append(len(self.floors), ParkingLotFloor(parkingSpotAllocation) def assignSpot(self, String CarType): if CarType not in settings.ValidCarTypes(): #handle error return 1 else: for floor in self.floors: parkingSpotID = floor.GetFreeParkingSpot(CarType) newTicket = Ticket(datetime.now(), parkingSpotID) self.tickets[newTicket.getID()] = newTicket return newTicket.getID() #handle no tickets available return 1 def makePayment(self, ticketID): ticket = self.tickets[ticketID] if paymentManager.makePayment(ticket) == 0: ticket.isPaid = True carFloor, spotNum, carType = ticket.parkingSpotID.split('-') self.floors[carFloor].SetSpotAvailable(ticket.parkingSpotID) class ParkingLotFloor: def init(self, floorNum, parkingSpotAllocation): self.floorNum = floorNum self.spots = {} for spotType, numSpots in parkingSpotAllocation: for I in range(numSpots): newSpot = ParkingSpot(spotType, spotNum, floorNum) self.spots[newSpot.id] = newSpot def GetFreeParkingSpot(self, carType): for spot in spots: if spot.isAvailable and carType == spot.type: spot.isAvailable = False return spot.id class SpotType(Enum): ... class ParkingSpot: def init(self, spotType, spotNum, floorNum): self.id = generateID(spotType, spotNum, floorNum) self.isAvailable = True class Ticket: def init(self, entryTime, parkingSpotID): self.entryTime = entryTime self.id = generateTicketID() self.isPaid = False self.parkingSpotID = parkingSpotID class PaymentManager: def init(self, settings): self.settings = settings def makePayment(self, ticket): carFloor, spotNum, carType = ticket.parkingSpotID.split('-') spotRate = settings.getRate(carType) payment = (datetime.now() - ticket.startTime) * spotRate #payment logic here if paymentSuccessful: return 0 else: return 1





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

Currently, every request is handled sequentially. Furthermore, there is no queueing system if multiple requests are made at the same time. I am operating under the assumption that there is one parking lot entrance system where users can queue up and request a parking spot.


In the future, a queueing system can be created to process both entrance requests and ticket payment requests. Requests can also be made to run in parallel if resources allow.


The addition of new parking spot types is relatively easy as you can just add new types to the SpotType Enum. new ways to make payments can also be added by creating new payment functions within the Payment manager.


The parking lot system is also relatively extensible as you can add a new floor easily with the add floor method




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...