PL with fee and level

mail@pastecode.io avatar
unknown
java
a month ago
7.8 kB
1
Indexable
Never
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class ParkingLotSystem {

    // Enum for Vehicle Size
    public enum VehicleSize {
        SMALL, COMPACT, LARGE
    }

    // Interface for Vehicle
    public interface Vehicle {
        String getLicensePlate();
        VehicleSize getSize();
    }

    // Interface for ParkingSpot
    public interface ParkingSpot {
        boolean isAvailable();
        void parkVehicle(Vehicle vehicle);
        void removeVehicle();
        Vehicle getVehicle();
        int getSpotId();
    }

    // Interface for ParkingLot
    public interface ParkingLot {
        Optional<ParkingSpot> findAvailableSpot(Vehicle vehicle);
        boolean parkVehicle(Vehicle vehicle);
        boolean leaveSpot(int spotId, int level);
        int availableSpots();
        double calculateFee(int spotId, int level, long hoursParked);
    }

    // Interface for PaymentProcessor
    public interface PaymentProcessor {
        double processPayment(int spotId, long hoursParked);
    }

    // Implementing Vehicle Classes
    public static class Car implements Vehicle {
        private String licensePlate;
        private VehicleSize size = VehicleSize.COMPACT;

        public Car(String licensePlate) {
            this.licensePlate = licensePlate;
        }

        @Override
        public String getLicensePlate() {
            return licensePlate;
        }

        @Override
        public VehicleSize getSize() {
            return size;
        }
    }

    public static class Bike implements Vehicle {
        private String licensePlate;
        private VehicleSize size = VehicleSize.SMALL;

        public Bike(String licensePlate) {
            this.licensePlate = licensePlate;
        }

        @Override
        public String getLicensePlate() {
            return licensePlate;
        }

        @Override
        public VehicleSize getSize() {
            return size;
        }
    }

    public static class Truck implements Vehicle {
        private String licensePlate;
        private VehicleSize size = VehicleSize.LARGE;

        public Truck(String licensePlate) {
            this.licensePlate = licensePlate;
        }

        @Override
        public String getLicensePlate() {
            return licensePlate;
        }

        @Override
        public VehicleSize getSize() {
            return size;
        }
    }

    // Implementing ParkingSpot Class
    public static class SimpleParkingSpot implements ParkingSpot {
        private int spotId;
        private Vehicle currentVehicle;
        private VehicleSize spotSize;

        public SimpleParkingSpot(int spotId, VehicleSize spotSize) {
            this.spotId = spotId;
            this.spotSize = spotSize;
        }

        @Override
        public boolean isAvailable() {
            return currentVehicle == null;
        }

        @Override
        public void parkVehicle(Vehicle vehicle) {
            if (vehicle.getSize().ordinal() <= spotSize.ordinal()) {
                this.currentVehicle = vehicle;
            }
        }

        @Override
        public void removeVehicle() {
            this.currentVehicle = null;
        }

        @Override
        public Vehicle getVehicle() {
            return currentVehicle;
        }

        @Override
        public int getSpotId() {
            return spotId;
        }
    }

    // Implementing Level Class
    public static class Level {
        private int levelNumber;
        private List<ParkingSpot> spots;

        public Level(int levelNumber, int numberOfSpots, VehicleSize spotSize) {
            this.levelNumber = levelNumber;
            this.spots = new ArrayList<>();
            for (int i = 1; i <= numberOfSpots; i++) {
                spots.add(new SimpleParkingSpot(i, spotSize));
            }
        }

        public int getLevelNumber() {
            return levelNumber;
        }

        public Optional<ParkingSpot> findAvailableSpot(Vehicle vehicle) {
            return spots.stream()
                    .filter(ParkingSpot::isAvailable)
                    .filter(spot -> vehicle.getSize().ordinal() <= spot.getVehicle().getSize().ordinal())
                    .findFirst();
        }

        public boolean parkVehicle(Vehicle vehicle) {
            Optional<ParkingSpot> availableSpot = findAvailableSpot(vehicle);
            if (availableSpot.isPresent()) {
                availableSpot.get().parkVehicle(vehicle);
                return true;
            }
            return false;
        }

        public boolean leaveSpot(int spotId) {
            for (ParkingSpot spot : spots) {
                if (spot.getSpotId() == spotId && !spot.isAvailable()) {
                    spot.removeVehicle();
                    return true;
                }
            }
            return false;
        }

        public int availableSpots() {
            return (int) spots.stream().filter(ParkingSpot::isAvailable).count();
        }
    }

    // Implementing MultiLevelParkingLot Class
    public static class MultiLevelParkingLot implements ParkingLot {
        private List<Level> levels;
        private PaymentProcessor paymentProcessor;

        public MultiLevelParkingLot(int numberOfLevels, int spotsPerLevel, VehicleSize spotSize, PaymentProcessor paymentProcessor) {
            this.levels = new ArrayList<>();
            this.paymentProcessor = paymentProcessor;
            for (int i = 1; i <= numberOfLevels; i++) {
                levels.add(new Level(i, spotsPerLevel, spotSize));
            }
        }

        @Override
        public Optional<ParkingSpot> findAvailableSpot(Vehicle vehicle) {
            for (Level level : levels) {
                Optional<ParkingSpot> availableSpot = level.findAvailableSpot(vehicle);
                if (availableSpot.isPresent()) {
                    return availableSpot;
                }
            }
            return Optional.empty();
        }

        @Override
        public boolean parkVehicle(Vehicle vehicle) {
            for (Level level : levels) {
                if (level.parkVehicle(vehicle)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public boolean leaveSpot(int spotId, int level) {
            return levels.get(level - 1).leaveSpot(spotId);
        }

        @Override
        public int availableSpots() {
            return levels.stream().mapToInt(Level::availableSpots).sum();
        }

        @Override
        public double calculateFee(int spotId, int level, long hoursParked) {
            return paymentProcessor.processPayment(spotId, hoursParked);
        }
    }

    // Implementing PaymentProcessor Class
    public static class FlatRatePaymentProcessor implements PaymentProcessor {
        private static final double RATE_PER_HOUR = 2.0;

        @Override
        public double processPayment(int spotId, long hoursParked) {
            return RATE_PER_HOUR * hoursParked;
        }
    }

    // Main Class for Testing
    public static void main(String[] args) {
        PaymentProcessor paymentProcessor = new FlatRatePaymentProcessor();
        ParkingLot parkingLot = new MultiLevelParkingLot(3, 10, VehicleSize.COMPACT, paymentProcessor);

        Vehicle car = new Car("ABC123");
        Vehicle bike = new Bike("XYZ456");

        parkingLot.parkVehicle(car);
        parkingLot.parkVehicle(bike);

        System.out.println("Available spots: " + parkingLot.availableSpots());

        parkingLot.leaveSpot(1, 1);
        System.out.println("Available spots after leaving: " + parkingLot.availableSpots());

        double fee = parkingLot.calculateFee(1, 1, 3);
        System.out.println("Parking fee for 3 hours: $" + fee);
    }
}
Leave a Comment