ParkingLot LLD.
Share feedback and suggestion
https://leetcode.com/discuss/interview-question/6003635/WayFair-Automated-Parking-Lot-Problem-Design/
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
import org.joda.time.DateTime;
enum VehicleType
{
TWO_WHEELER,
THREE_WHEELER,
FOUR_WHEELER
}
enum ParkingSpotType{
SMALL,
MEDIUM,
LARGE
}
enum TicketStatus
{
UNPAID,
PAID
}
class Vehicle{
int id;
VehicleType vehicleType;
}
class ParkingSpot{
int id;
ParkingSpotType parkingSpotType;
double hourlyRate;
double minRate;
boolean isAvailable;
Vehicle vehicle;
public void parkTheVehicle(Vehicle vehicle)
{
this.vehicle = vehicle;
this.isAvailable = false;
}
public void removeVehicle()
{
this.vehicle = null;
this.isAvailable = true;
}
}
class DisplayBoard
{
int id;
int freeSpots;
public void updateDisplayBoard()
{
}
}
abstract class ParkingSpotManager{
List<ParkingSpot> parkingSpots;
ParkingSpotManager(List<ParkingSpot> parkingSpots)
{
this.parkingSpots = parkingSpots;
}
public void addParkingSpot(ParkingSpot parkingSpot)
{
parkingSpots.add(parkingSpot);
}
public void removeParkingSpot(ParkingSpot parkingSpot){
for(ParkingSpot ps : parkingSpots)
{
if(ps.id == parkingSpot.id)
{
parkingSpots.remove(ps);
}
}
};
public abstract ParkingSpot findParkingSpot();
public void parkTheVehicle(Vehicle vehicle, ParkingSpot parkingSpot)
{
parkingSpot.parkTheVehicle(vehicle);
}
public void removeTheVehicle( ParkingSpot parkingSpot)
{
parkingSpot.removeVehicle();
}
}
class TwoWheelerParkingSpotManager extends ParkingSpotManager
{
TwoWheelerParkingSpotManager(List<ParkingSpot> parkingSpots)
{
super(parkingSpots);
}
public ParkingSpot findParkingSpot()
{
return parkingSpots.get(0);
}
}
class FourWheelerParkingSpotManager extends ParkingSpotManager
{
FourWheelerParkingSpotManager(List<ParkingSpot> parkingSpots)
{
super(parkingSpots);
}
public ParkingSpot findParkingSpot()
{
return parkingSpots.get(0);
}
}
class ParkingSpotFactory
{
public ParkingSpotManager getParkingSpotManager(ParkingSpotType parkingSpotType)
{
switch (parkingSpotType) {
case SMALL:
return new TwoWheelerParkingSpotManager(new ArrayList<>());
case LARGE:
return new FourWheelerParkingSpotManager(new ArrayList<>());
default:
throw new IllegalArgumentException("unrecongnized parkingspottype");
}
}
}
// whats the best place for display board;
class Floor{
Map<ParkingSpotType,ParkingSpotManager> parkingSpotManagerList;
DisplayBoard displayBoard;
ParkingSpotFactory parkingSpotFactory;
Floor()
{
parkingSpotManagerList = new HashMap<>();
parkingSpotFactory = new ParkingSpotFactory();
setParkingSpotManager();
}
private void setParkingSpotManager()
{
for(ParkingSpotType parkingSpotType : ParkingSpotType.values())
{
parkingSpotManagerList.put(parkingSpotType, parkingSpotFactory.getParkingSpotManager(parkingSpotType));
}
}
public ParkingSpotManager getParkingSpotManager(ParkingSpotType parkingSpotType)
{
return parkingSpotManagerList.get(parkingSpotType);
}
}
class Ticket
{
int id;
Vehicle vehicle;
ParkingSpot parkingSpot;
DateTime entryTime;
DateTime exitTime;
double amount;
TicketStatus ticketStatus;
Ticket(Vehicle vehicle, ParkingSpot parkingSpot)
{
this.vehicle = vehicle;
this.parkingSpot = parkingSpot;
entryTime = new DateTime();
this.ticketStatus = TicketStatus.UNPAID;
}
public double calculatePrice()
{
return (new DateTime().getHourOfDay() - entryTime.getHourOfDay())*parkingSpot.hourlyRate;
}
}
class EntryGate {
int id;
public Ticket generateTicket(Vehicle vehicle, ParkingSpot parkingSpot)
{
Ticket tick =new Ticket(vehicle, parkingSpot);
return tick;
}
}
interface CostCompute
{
public double calculatePrice(Ticket ticket);
}
class HourlyCostCompute implements CostCompute
{
public double calculatePrice(Ticket ticket)
{
return (new DateTime().getHourOfDay() - ticket.entryTime.getHourOfDay())*ticket.parkingSpot.hourlyRate;
}
}
class MinCostCompute implements CostCompute
{
public double calculatePrice(Ticket ticket)
{
return (new DateTime().getMinuteOfDay() - ticket.entryTime.getMinuteOfDay())*ticket.parkingSpot.minRate;
}
}
class ExitGate {
CostCompute compute;
ExitGate(CostCompute compute)
{
this.compute = compute;
}
public Double calculatePrice(Ticket ticket)
{
return compute.calculatePrice(ticket);
}
public void payTheTicket(Ticket ticket)
{
double price = calculatePrice(ticket);
ticket.amount = price;
}
}
class ParkingLot{
List<Floor> floors;
EntryGate entrygate;
ExitGate exitGate;
DisplayBoard displayBoard;
ParkingLot()
{
this.floors = new ArrayList<>();
this.entrygate = new EntryGate();
this.exitGate = new ExitGate( new HourlyCostCompute());
displayBoard = new DisplayBoard();
}
///getter and setter for floor
public void addParkingSpot(int floorId, ParkingSpot pSpot)
{
Floor floor = floors.get(floorId);
ParkingSpotManager parkingSpotManager = floor.getParkingSpotManager(pSpot.parkingSpotType);
parkingSpotManager.addParkingSpot(pSpot);
}
public ParkingSpot getParkingSpot(int floorId, ParkingSpotType parkingSpotType)
{
Floor floor = floors.get(floorId);
ParkingSpot parkingSpot = floor.getParkingSpotManager(parkingSpotType).findParkingSpot();
return parkingSpot;
}
public void parkTheVehicle(Vehicle vehicle, ParkingSpot spot, int floorId)
{
Floor floor = floors.get(floorId);
floor.getParkingSpotManager(spot.parkingSpotType).parkTheVehicle(vehicle, spot);
entrygate.generateTicket(vehicle, spot);
displayBoard.updateDisplayBoard();
}
public void removeTheVehicle(Ticket ticket, int floorId, int exitGateId)
{
exitGate.payTheTicket(ticket);
Floor floor = floors.get(floorId);
floor.getParkingSpotManager(ticket.parkingSpot.parkingSpotType).removeTheVehicle(ticket.parkingSpot);
displayBoard.updateDisplayBoard();
}
}
/*
API Spec
Get /parking/spot -> get parking spot input {SpotType, floorId}
DELETE /parking/spot/:{id} -> removes parking spot
POST /parking/spot -> {ParkingSpot object} ->add parking spot
POST /parking/park -> park a vehicle
POST /parking/exit -> exit the vehicle
GET /parking/price -> price
GET /parking/status:{id} ->retrieve the current status of parking spot
DB spec
Vehicle
vehicle_id, vehicle_type
ParkingSpot
parking_spot_id,spot_type, is_available,vehicle_id, floor_id
Floor
floor_id, JSON{spot_ids}
Ticket
ticket_id, vehicle_id, spot_id,entry_time,exit_time,amount, payment_id
Payment
payment_id,amount,payment_status
*/