enum VehicleType {
CAR, BIKE, TRUCK
}
abstract class Vehicle {
private String licenseNumber;
private VehicleType type;
public Vehicle(String licenseNumber, VehicleType type) {
this.licenseNumber = licenseNumber;
this.type = type;
}
public VehicleType getType() {
return type;
}
public String getLicenseNumber() {
return licenseNumber;
}
}
class Car extends Vehicle {
public Car(String licenseNumber) {
super(licenseNumber, VehicleType.CAR);
}
}
class Bike extends Vehicle {
public Bike(String licenseNumber) {
super(licenseNumber, VehicleType.BIKE);
}
}
class Truck extends Vehicle {
public Truck(String licenseNumber) {
super(licenseNumber, VehicleType.TRUCK);
}
}
class ParkingSpot {
private final int spotNumber;
private final VehicleType supportedType;
private boolean isOccupied;
private Vehicle parkedVehicle;
public ParkingSpot(int spotNumber, VehicleType supportedType) {
this.spotNumber = spotNumber;
this.supportedType = supportedType;
this.isOccupied = false;
}
public boolean canPark(Vehicle vehicle) {
return !isOccupied && vehicle.getType() == supportedType;
}
public void park(Vehicle vehicle) {
if (canPark(vehicle)) {
this.parkedVehicle = vehicle;
this.isOccupied = true;
}
}
public void vacate() {
this.parkedVehicle = null;
this.isOccupied = false;
}
public boolean isOccupied() {
return isOccupied;
}
public int getSpotNumber() {
return spotNumber;
}
}
class ParkingFloor {
private final int floorNumber;
private List spots;
public ParkingFloor(int floorNumber, List spots) {
this.floorNumber = floorNumber;
this.spots = spots;
}
public ParkingSpot findAvailableSpot(Vehicle vehicle) {
for (ParkingSpot spot : spots) {
if (spot.canPark(vehicle)) {
return spot;
}
}
return null;
}
public int getFloorNumber() {
return floorNumber;
}
public List getSpots() {
return spots;
}
}
class Ticket {
private Vehicle vehicle;
private int floorNumber;
private int spotNumber;
private LocalDateTime entryTime;
private LocalDateTime exitTime;
private double costPerHour = 10.0;
public Ticket(Vehicle vehicle, int floorNumber, int spotNumber) {
this.vehicle = vehicle;
this.floorNumber = floorNumber;
this.spotNumber = spotNumber;
this.entryTime = LocalDateTime.now();
}
public void markExit() {
this.exitTime = LocalDateTime.now();
}
public double calculateBill() {
if (exitTime == null) {
throw new IllegalStateException("Vehicle has not exited yet!");
}
long durationInHours = Math.max(1, Duration.between(entryTime, exitTime).toHours());
return durationInHours * costPerHour;
}
public Vehicle getVehicle() {
return vehicle;
}
public int getFloorNumber() {
return floorNumber;
}
public int getSpotNumber() {
return spotNumber;
}
}
class ParkingLot {
private List floors;
private Map activeTickets = new HashMap<>();
public ParkingLot(List floors) {
this.floors = floors;
}
public Ticket parkVehicle(Vehicle vehicle) {
for (ParkingFloor floor : floors) {
ParkingSpot spot = floor.findAvailableSpot(vehicle);
if (spot != null) {
spot.park(vehicle);
Ticket ticket = new Ticket(vehicle, floor.getFloorNumber(), spot.getSpotNumber());
activeTickets.put(vehicle.getLicenseNumber(), ticket);
System.out.println("Vehicle parked at floor " + floor.getFloorNumber() + " in spot " + spot.getSpotNumber());
return ticket;
}
}
System.out.println("No available spot for vehicle type: " + vehicle.getType());
return null;
}
public double vacateSpot(String licenseNumber) {
Ticket ticket = activeTickets.get(licenseNumber);
if (ticket == null) {
System.out.println("No active ticket found for vehicle: " + licenseNumber);
return 0.0;
}
ParkingFloor floor = floors.get(ticket.getFloorNumber());
ParkingSpot spot = floor.getSpots().get(ticket.getSpotNumber());
spot.vacate();
ticket.markExit();
double bill = ticket.calculateBill();
activeTickets.remove(licenseNumber);
System.out.println("Vehicle with license " + licenseNumber + " exited. Bill: $" + bill);
return bill;
}
}
public class ParkingLotDemo {
public static void main(String[] args) throws InterruptedException {
List floor1Spots = new ArrayList<>();
floor1Spots.add(new ParkingSpot(0, VehicleType.CAR));
floor1Spots.add(new ParkingSpot(1, VehicleType.BIKE));
List floor2Spots = new ArrayList<>();
floor2Spots.add(new ParkingSpot(0, VehicleType.TRUCK));
floor2Spots.add(new ParkingSpot(1, VehicleType.CAR));
ParkingFloor floor1 = new ParkingFloor(0, floor1Spots);
ParkingFloor floor2 = new ParkingFloor(1, floor2Spots);
ParkingLot parkingLot = new ParkingLot(Arrays.asList(floor1, floor2));
Vehicle car1 = new Car("CAR123");
Vehicle bike1 = new Bike("BIKE456");
Vehicle truck1 = new Truck("TRUCK789");
Ticket ticket1 = parkingLot.parkVehicle(car1);
Ticket ticket2 = parkingLot.parkVehicle(bike1);
Ticket ticket3 = parkingLot.parkVehicle(truck1);
Thread.sleep(2000); // Simulate time spent in parking
parkingLot.vacateSpot(car1.getLicenseNumber());
parkingLot.vacateSpot(bike1.getLicenseNumber());
parkingLot.vacateSpot(truck1.getLicenseNumber());
}
}
/*
UML Diagram
visit to visualize: https://www.planttext.com/
@startuml
enum VehicleType {
CAR
BIKE
TRUCK
}
abstract class Vehicle {
- licenseNumber: String
- type: VehicleType
+ getLicenseNumber(): String
+ getType(): VehicleType
}
class Car
class Bike
class Truck
Vehicle <|-- Car
Vehicle <|-- Bike
Vehicle <|-- Truck
class ParkingSpot {
- spotNumber: int
- supportedType: VehicleType
- isOccupied: boolean
- parkedVehicle: Vehicle
+ canPark(Vehicle): boolean
+ park(Vehicle): void
+ vacate(): void
}
class ParkingFloor {
- floorNumber: int
- spots: List
+ findAvailableSpot(Vehicle): ParkingSpot
+ getFloorNumber(): int
+ getSpots(): List
}
class Ticket {
- vehicle: Vehicle
- floorNumber: int
- spotNumber: int
- entryTime: LocalDateTime
- exitTime: LocalDateTime
- costPerHour: double
+ markExit(): void
+ calculateBill(): double
}
class ParkingLot {
- floors: List
- activeTickets: Map
+ parkVehicle(Vehicle): Ticket
+ vacateSpot(String): double
}
Vehicle --> VehicleType
ParkingFloor "1" *-- "*" ParkingSpot
ParkingLot "1" o-- "*" ParkingFloor
ParkingLot --> Ticket
Ticket --> Vehicle
@enduml
*/