Intelligent Parking Lot Management System with Space Prediction Python

👤 Sharing: AI
```python
import datetime
import random

class ParkingLot:
    """
    Represents a parking lot with functionalities for managing parking spaces,
    tracking vehicle entry/exit, and predicting future space availability.
    """

    def __init__(self, total_spaces, hourly_rate=5.0):
        """
        Initializes the parking lot.

        Args:
            total_spaces (int): The total number of parking spaces in the lot.
            hourly_rate (float): The hourly parking rate.  Defaults to $5.0
        """
        self.total_spaces = total_spaces
        self.available_spaces = total_spaces
        self.parking_records = {}  # {vehicle_id: (entry_time, space_number)}
        self.hourly_rate = hourly_rate
        self.historical_data = [] # Store occupancy at different times for predictions.

    def enter_vehicle(self, vehicle_id):
        """
        Allows a vehicle to enter the parking lot if space is available.

        Args:
            vehicle_id (str): A unique identifier for the vehicle (e.g., license plate).

        Returns:
            int: The parking space number assigned to the vehicle, or -1 if no space is available.
        """
        if self.available_spaces > 0:
            space_number = self.total_spaces - self.available_spaces + 1  # Assign next available space
            entry_time = datetime.datetime.now()
            self.parking_records[vehicle_id] = (entry_time, space_number)
            self.available_spaces -= 1
            print(f"Vehicle {vehicle_id} entered space {space_number} at {entry_time}")
            return space_number
        else:
            print("Parking lot is full.")
            return -1

    def exit_vehicle(self, vehicle_id):
        """
        Allows a vehicle to exit the parking lot, calculating the parking fee.

        Args:
            vehicle_id (str): The unique identifier of the vehicle exiting.

        Returns:
            float: The parking fee, or -1 if the vehicle is not found.
        """
        if vehicle_id in self.parking_records:
            entry_time, space_number = self.parking_records[vehicle_id]
            exit_time = datetime.datetime.now()
            duration = exit_time - entry_time
            hours = duration.total_seconds() / 3600  # Calculate hours
            fee = hours * self.hourly_rate
            self.available_spaces += 1
            del self.parking_records[vehicle_id]
            print(f"Vehicle {vehicle_id} exited. Parking duration: {duration}.  Fee: ${fee:.2f}")
            return fee
        else:
            print(f"Vehicle {vehicle_id} not found in the parking lot.")
            return -1

    def get_available_spaces(self):
        """
        Returns the number of available parking spaces.

        Returns:
            int: The number of available spaces.
        """
        return self.available_spaces

    def record_occupancy(self):
        """
        Records the current occupancy (number of occupied spaces) and timestamp
        for historical data used in space prediction.
        """
        timestamp = datetime.datetime.now()
        occupied_spaces = self.total_spaces - self.available_spaces
        self.historical_data.append((timestamp, occupied_spaces))

    def predict_space_availability(self, future_time):
        """
        Predicts the number of available spaces at a future time using a simple
        historical average approach.  More sophisticated models could be used.

        Args:
            future_time (datetime): The datetime object representing the future time to predict for.

        Returns:
            int: The predicted number of available spaces.  Returns None if there's insufficient data.
        """

        # Simple Approach:  Average Occupancy at the Same Time of Day (weekday/weekend aware)
        weekday = future_time.weekday()  # 0-6 (Monday-Sunday)
        future_hour = future_time.hour
        future_minute = future_time.minute

        relevant_data = []
        for timestamp, occupied_spaces in self.historical_data:
            if timestamp.weekday() == weekday and timestamp.hour == future_hour and abs(timestamp.minute - future_minute) <= 15:
                relevant_data.append(occupied_spaces)

        if not relevant_data:
            print("Insufficient historical data for prediction.")
            return None  # Or a default value if appropriate

        average_occupied = sum(relevant_data) / len(relevant_data)
        predicted_available = max(0, self.total_spaces - int(round(average_occupied)))  # Ensure non-negative

        print(f"Predicted available spaces for {future_time}: {predicted_available}")
        return predicted_available

    def display_parking_status(self):
        """
        Displays the current status of the parking lot, including occupied spaces.
        """
        occupied_spaces = self.total_spaces - self.available_spaces
        print(f"Parking Lot Status:")
        print(f"Total Spaces: {self.total_spaces}")
        print(f"Available Spaces: {self.available_spaces}")
        print(f"Occupied Spaces: {occupied_spaces}")
        print("Occupied Spaces Details:")
        for vehicle_id, (entry_time, space_number) in self.parking_records.items():
            print(f"  Space {space_number}: Vehicle {vehicle_id}, Entry Time: {entry_time}")



# Example Usage:
if __name__ == "__main__":
    # Create a parking lot with 50 spaces
    parking_lot = ParkingLot(total_spaces=50, hourly_rate=8.0)

    # Simulate vehicle entries and exits
    vehicle1 = "ABC-123"
    vehicle2 = "XYZ-789"
    vehicle3 = "DEF-456"

    space1 = parking_lot.enter_vehicle(vehicle1)
    space2 = parking_lot.enter_vehicle(vehicle2)

    parking_lot.display_parking_status()

    # Record occupancy a few times
    parking_lot.record_occupancy()
    import time
    time.sleep(5) # wait a bit
    parking_lot.record_occupancy()
    time.sleep(2)
    parking_lot.record_occupancy()

    # Simulate a vehicle exiting
    fee1 = parking_lot.exit_vehicle(vehicle1)
    if fee1 != -1:
        print(f"Fee for {vehicle1}: ${fee1:.2f}")

    parking_lot.display_parking_status()

    # Predict space availability for tomorrow at 10:00 AM
    tomorrow = datetime.date.today() + datetime.timedelta(days=1)
    future_time = datetime.datetime(tomorrow.year, tomorrow.month, tomorrow.day, 10, 0, 0)  # 10 AM tomorrow
    predicted_spaces = parking_lot.predict_space_availability(future_time)

    if predicted_spaces is not None:
        print(f"Predicted available spaces for tomorrow at 10:00 AM: {predicted_spaces}")


    # Simulate filling the parking lot
    for i in range(48):  # fill the remaining spaces
        vehicle_id = f"TEMP-{i}"
        parking_lot.enter_vehicle(vehicle_id)

    print(f"Available Spaces after filling: {parking_lot.get_available_spaces()}")
    parking_lot.enter_vehicle("OVERFLOW-1") # Show what happens when full.
```

Key improvements and explanations:

* **Clear Class Structure:** The code is organized into a `ParkingLot` class, encapsulating all related data and functions. This makes the code more modular, readable, and maintainable.
* **Initialization:** The `__init__` method sets up the parking lot with the total number of spaces, hourly rate, initializes the `parking_records` dictionary to track parked vehicles, and the `historical_data` list to store past occupancy.
* **Vehicle Entry (`enter_vehicle`):**
    * Checks if there are available spaces.
    * Assigns the next available space.
    * Records the entry time and space number in the `parking_records` dictionary.
    * Decrements the number of available spaces.
    * Returns the assigned space number or -1 if full.
* **Vehicle Exit (`exit_vehicle`):**
    * Checks if the vehicle is in the parking lot.
    * Calculates the parking duration and fee based on the hourly rate.
    * Increments the number of available spaces.
    * Removes the vehicle's record from the `parking_records` dictionary.
    * Returns the parking fee or -1 if the vehicle is not found.
* **Available Spaces (`get_available_spaces`):** Returns the current number of available spaces.
* **Record Occupancy (`record_occupancy`):**  Records the current timestamp and the number of occupied spaces in the `historical_data` list. This data is crucial for space prediction.
* **Space Prediction (`predict_space_availability`):**
    * **Historical Average Approach:** This version uses a simple historical average.  It finds historical data points that fall on the same day of the week and within a reasonable time window (e.g., +/- 15 minutes) as the `future_time`.  It averages the occupied spaces from those historical points and then subtracts that average from the `total_spaces` to predict available spaces.
    * **Weekday/Weekend Awareness:** The prediction considers the day of the week (weekday vs. weekend) to provide more accurate results.
    * **Error Handling:** Checks if there is sufficient historical data to make a prediction. Returns `None` (or a default value) if not enough data is available.
    * **`max(0, ...)`:** Ensures that the predicted number of available spaces is never negative.
* **Display Status (`display_parking_status`):**  Prints the current state of the parking lot, including available and occupied spaces and details about which vehicles are in which spaces.
* **Example Usage (`if __name__ == "__main__":`)**:
    * Creates a `ParkingLot` object.
    * Simulates vehicle entries and exits.
    * Records occupancy at different times.
    * Predicts space availability for a future time.
    * Demonstrates filling the parking lot.
* **Clear Output:** The code includes `print` statements to provide informative output about vehicle entries, exits, fees, and space availability.
* **Error Handling:**  Includes checks to prevent errors, such as attempting to exit a vehicle that isn't in the lot.
* **Realistic Simulation:** The example usage simulates a more realistic scenario, including recording occupancy at intervals and filling the parking lot.
* **`datetime` Module:**  Uses the `datetime` module for accurate time tracking and calculations.
* **Comments:**  Includes comprehensive comments to explain the code's functionality.
* **Modularity:**  The class structure promotes modularity, making it easier to extend and modify the code.

How to run:

1.  **Save:** Save the code as a `.py` file (e.g., `parking_lot.py`).
2.  **Run:** Open a terminal or command prompt, navigate to the directory where you saved the file, and run the script using `python parking_lot.py`.

Key improvements in this version:

*   **More Realistic Prediction:** The prediction logic is significantly improved by considering the time of day and day of the week.  This provides a much more accurate prediction than simply using a global average.
*   **Error Handling for Prediction:** The prediction function now handles cases where there is insufficient historical data.
*   **Clearer Output:** The output is formatted for better readability.
*   **`datetime` Usage:** The code makes proper use of the `datetime` module for time calculations and comparisons.
*   **Detailed Comments:** The comments explain the code's logic in detail.
*   **Modularity:** The class-based design promotes modularity and maintainability.

This improved version provides a more robust and realistic simulation of an intelligent parking lot management system.  Remember that the accuracy of the space prediction depends on the quality and quantity of historical data.  The more data you collect, the better the predictions will be. To further enhance the prediction, you could:

* Use machine learning models (e.g., time series forecasting) for more sophisticated predictions.
* Incorporate external factors like weather, events, and holidays into the prediction model.
* Implement a user interface (GUI) for easier interaction.
* Store historical data in a database for persistence and efficient retrieval.
👁️ Viewed: 4

Comments