CSC110 / lectures / CourseNote / Discrete-Event Simulation.py
Discrete-Event Simulation.py
Raw
# Some are wrong. Not fully implemented.

def run_simulation(initial_events: list[Event], system: FoodDeliverySystem) -> None:
    events = EventQueueList()  # Initialize an empty priority queue of events
    for event in initial_events:
        events.enqueue(event)

    # Repeatedly remove and process the next event
    while not events.is_empty():
        event = events.dequeue()

        new_events = event.handle_event(system)
        for new_event in new_events:
            events.enqueue(new_event)

class FoodDeliverySimulation:
    """A simulation of the food delivery system.
    """
    # Private Instance Attributes:
    #   - _system: The FoodDeliverySystem instance that this simulation uses.
    #   - _events: A collection of the events to process during the simulation.
    _system: FoodDeliverySystem
    _events: EventQueue

    def __init__(self, start_time: datetime.datetime, num_days: int,
                 num_couriers: int, num_customers: int,
                 num_restaurants: int) -> None:
        """Initialize a new simulation with the given simulation parameters.

        start_time: the starting time of the simulation
        num_days: the number of days that the simulation runs
        num_couriers: the number of couriers in the system
        num_customers: the number of customers in the system
        num_restaurants: the number of restaurants in the system
        """
        self._events = EventQueueList()
        self._system = FoodDeliverySystem()

        self._populate_initial_events(start_time, num_days)
        self._generate_system(num_couriers, num_customers, num_restaurants)

    def _populate_initial_events(self, start_time: datetime.datetime, num_days: int) -> None:
        """Populate this simulation's Event priority queue with GenerateOrdersEvents.

        One new GenerateOrderEvent is generated per day, starting with start_time and
        repeating num_days times.
        """

    def _generate_system(self, num_couriers: int, num_customers: int, num_restaurants: int) -> None:
        """Populate this simulation's FoodDeliverySystem with the specified number of entities.
        """

    def run(self) -> None:
        """Run this simulation.
        """
        while not self._events.is_empty():
            event = self._events.dequeue()

            new_events = event.handle_event(self._system)
            for new_event in new_events:
                self._events.enqueue(new_event)

# >>> simulation = FoodDeliverySimulation(datetime.datetime(2022, 11, 30), 7, 4, 100, 50)
# >>> simulation.run()


    def _populate_initial_events(self, start_time: datetime.datetime, num_days: int) -> None:
        """Populate this simulation's Event priority queue with GenerateOrdersEvents.

        One new GenerateOrderEvent is generated per day, starting with start_time and
        repeating num_days times.

        Preconditions:
        - num_days >= 0
        """
        for day in range(0, num_days):
            # 1. Create a GenerateOrderEvent for the given day after the start time.

            # 2. Enqueue the new event.

            def _generate_system(self, num_couriers: int, num_customers: int, num_restaurants: int) -> None:
                """Populate this simulation's FoodDeliverySystem with the specified number of entities.
                """
                for i in range(0, num_customers):
                    location = _generate_location()
                    customer = Customer(f'Customer {i}', location)
                    self._system.add_customer(customer)

                # Couriers and Restaurants are similar
                ...

            # Outside the class: helper for generating random locations in Toronto
        TORONTO_COORDS = (43.747743, 43.691170, -79.633951, -79.176646)

        def _generate_location() -> tuple[float, float]:
            """Return a randomly-generated location (latitude, longitude) within the Toronto bounds.
            """
            return (random.uniform(TORONTO_COORDS[0], TORONTO_COORDS[1]),
                    random.uniform(TORONTO_COORDS[2], TORONTO_COORDS[3]))

# >>> simulation = FoodDeliverySimulation(datetime.datetime(2022, 11, 30), 7, 4, 100, 50)
# >>> simulation.run()