Пример #1
0
 def __init__(self, duration):
     """This method will create an instance of a Grocery Store"""
     self.duration = duration
     self.checkout_lock = Lock()
     self.clock = RealtimeEnvironment(initial_time=0,
                                      factor=speed,
                                      strict=False)
     self.checkout0 = CheckoutStation(lock=self.checkout_lock)
     self.checkout1 = CheckoutStation(lock=self.checkout_lock)
     self.checkout2 = CheckoutStation(lock=self.checkout_lock)
     self.controller = Controller(duration=self.duration,
                                  lock=self.checkout_lock,
                                  checkout0=self.checkout0,
                                  checkout1=self.checkout1,
                                  checkout2=self.checkout2)
     thread_checkout0 = Thread(target=self.checkout0.serve_queue)
     thread_checkout1 = Thread(target=self.checkout1.serve_queue)
     thread_checkout2 = Thread(target=self.checkout2.serve_queue)
     thread_controller = Thread(target=self.controller.simulate)
     self.threads = [
         thread_checkout0, thread_checkout1, thread_checkout2,
         thread_controller
     ]
     self.objects = [
         self.checkout0, self.checkout1, self.checkout2, self.controller
     ]
Пример #2
0
class CustomerQueue:
    """This class represents the line up of customers waiting to be put into queues.
    It will generate an instance of a customer every 50 to 100 seconds.
        """
    def __init__(self, duration):
        """This method will create an instance of a CustomerQueue"""
        self.history = []
        self.customer_queue = []
        self.customer_count = 0
        self.queue_lock = Lock()
        self.clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
        self.duration = duration
        self.status = True

    def generate_customers(self):
        """This function will generate a Customer object every 50-100 seconds"""
        arrive_time = randint(50, 100)
        while self.status:
            self.clock.run(until=arrive_time)
            c = Customer(id=self.customer_count, time=arrive_time)
            self.history.append(c)
            self.queue_lock.acquire()
            self.customer_queue.append(c)
            self.queue_lock.release()
            self.customer_count = self.customer_count + 1
            arrive_time = arrive_time + randint(50, 100)

    def change_status(self):
        """This method will halt the thread from performing any more executions of the target function"""
        self.status = False
Пример #3
0
class Window:
    """This class represents the window where the customer is served"""
    def __init__(self, id, payment):
        """This method will create an instance of a Window"""
        self.id = id
        self.queue = Queue(maxsize=3)
        self.clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
        self.payment_queue = payment
        self.status = True

    def serve_queue(self):
        """This method will serve the customers in the queue. Serving a customer will take 300 to 600 seconds"""
        serve_time = 0
        while self.status:
            if not self.queue.empty():
                time = randint(300, 600)
                serve_time = serve_time + time
                self.clock.run(until=serve_time)
                c = self.queue.get()
                print("Customer {} has finished being served".format(c.id))
                c.finished(time)
                self.payment_queue.complete(c)

    def change_status(self):
        """This method will halt the thread from performing any more executions of the target function"""
        self.status = False
Пример #4
0
class CheckoutStation:
    """This class will represent a Checkout Station at the Grocery Store"""
    def __init__(self, lock):
        """This method will create an instance of a Checkout Station"""
        self.queue = Queue(maxsize=2)
        self.clock = RealtimeEnvironment(initial_time=0,
                                         factor=speed,
                                         strict=False)
        self.status = True
        self.checkout_lock = lock

    def serve_queue(self):
        """This method will execute the simulation of a Checkout Station. This is the target function for the thread"""
        serve_time = 0
        while self.status or not self.queue.empty() or (
                not self.status and not self.queue.empty()):
            # while True:
            time = randint(300, 600)
            serve_time = serve_time + time
            # self.checkout_lock.acquire()
            c = self.queue.get()
            # self.checkout_lock.release()
            self.clock.run(until=serve_time)
            c.finished(time)
            print("Customer {} has finished being served".format(c.id))

    def change_status(self):
        """This method will halt the thread from performing any more executions of the target function"""
        self.status = False
Пример #5
0
 def __init__(self, id, payment):
     """This method will create an instance of a Window"""
     self.id = id
     self.queue = Queue(maxsize=3)
     self.clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
     self.payment_queue = payment
     self.status = True
Пример #6
0
 def __init__(self, lock):
     """This method will create an instance of a Checkout Station"""
     self.queue = Queue(maxsize=2)
     self.clock = RealtimeEnvironment(initial_time=0,
                                      factor=speed,
                                      strict=False)
     self.status = True
     self.checkout_lock = lock
Пример #7
0
 def __init__(self, duration):
     """This method will create an instance of a CustomerQueue"""
     self.history = []
     self.customer_queue = []
     self.customer_count = 0
     self.queue_lock = Lock()
     self.clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
     self.duration = duration
     self.status = True
Пример #8
0
def test_model_with_tk_process_visualization(until=0.00001,
                                             factor=0.1,
                                             flow_speed=10**10):
    env = RealtimeEnvironment(factor=factor, strict=False)
    model = Model(env)
    canvas = model.initialize_tkinter_process_visualization(
        flow_speed=flow_speed)
    env.run(until=until)
    canvas.tk_gui.destroy()
    assert True
Пример #9
0
class GroceryStore:
    """This class will simulate a Grocery Store"""
    def __init__(self, duration):
        """This method will create an instance of a Grocery Store"""
        self.duration = duration
        self.checkout_lock = Lock()
        self.clock = RealtimeEnvironment(initial_time=0,
                                         factor=speed,
                                         strict=False)
        self.checkout0 = CheckoutStation(lock=self.checkout_lock)
        self.checkout1 = CheckoutStation(lock=self.checkout_lock)
        self.checkout2 = CheckoutStation(lock=self.checkout_lock)
        self.controller = Controller(duration=self.duration,
                                     lock=self.checkout_lock,
                                     checkout0=self.checkout0,
                                     checkout1=self.checkout1,
                                     checkout2=self.checkout2)
        thread_checkout0 = Thread(target=self.checkout0.serve_queue)
        thread_checkout1 = Thread(target=self.checkout1.serve_queue)
        thread_checkout2 = Thread(target=self.checkout2.serve_queue)
        thread_controller = Thread(target=self.controller.simulate)
        self.threads = [
            thread_checkout0, thread_checkout1, thread_checkout2,
            thread_controller
        ]
        self.objects = [
            self.checkout0, self.checkout1, self.checkout2, self.controller
        ]

    def start(self):
        """This method will perform the simulation of the Grocery Store and output statistics to the terminal"""
        print("Starting Threads...")
        for thread in self.threads:
            thread.start()
        self.clock.run(until=self.duration)

        for object in self.objects:
            object.change_status()
        self.clock.run(until=self.duration + 2000)
        print("All threads have stopped...")

        time_sum = 0
        complete = 0
        for customer in self.controller.history:
            if customer.complete:
                time_sum = time_sum + customer.finish_time - customer.arrival_time
                complete = complete + 1

        print("\n************************************\n"
              "Total Customer Arrived: {}\n"
              "Total Customer Served: {}\n"
              "Average time to serve: {}\n".format(
                  len(self.controller.history), complete,
                  time_sum // complete))
Пример #10
0
 def __init__(self, time):
     """This class will create an instance of a Drive Through"""
     self.length = time
     self.clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
     self.customers = CustomerQueue(time)
     self.payment = Payment()
     self.window0 = Window(id="Jane", payment=self.payment)
     self.window1 = Window(id="John", payment=self.payment)
     self.monitor = Monitor(window0=self.window0, window1=self.window1, people=self.customers)
     people = Thread(target=self.customers.generate_customers, name="people")
     crew0 = Thread(target=self.window0.serve_queue, name="John")
     crew1 = Thread(target=self.window1.serve_queue, name="Jane")
     monitor = Thread(target=self.monitor.move_people, name="Monitor")
     self.threads = [people, crew0, crew1, monitor]
     self.objects = [self.window0, self.window1, self.monitor]
Пример #11
0
    def green_actions(self, direction):
        global error
        clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
        print("Car {} is trying to go {}".format(
            self.cars[0].id, directions[self.cars[0].direction]))
        if not error:
            # CASE: Left turn
            if int(direction) == 0:
                print("Car {} is checking if it is clear".format(
                    self.cars[0].id))
                if self.locks[str(self.left)].acquire():
                    if self.locks[str(self.id)].acquire(timeout=action_time):
                        print("It is clear for Car {} to go".format(
                            self.cars[0].id))
                        clock.run(
                            until=action_time
                        )  # Two seconds to perform actions -- arbitrary
                        car = self.cars.pop(0)
                        print("Car {} has made a left turn".format(car.id))
                        self.locks[str(self.id)].release()
                    else:
                        print("Car {} was unable to go...trying again")
                    self.locks[str(self.left)].release()

            # CASE: Straight
            elif int(direction) == 1:
                print("Car {} is checking if it is clear".format(
                    self.cars[0].id))
                if self.locks[str(self.right)].acquire():
                    if self.locks[str(
                            self.straight)].acquire(timeout=action_time):
                        print("It is clear for Car {} to go".format(
                            self.cars[0].id))
                        clock.run(until=action_time)
                        car = self.cars.pop(0)
                        print("Car {} has driven straight".format(car.id))
                        self.locks[str(self.straight)].release()
                    else:
                        print("Car {} was unable to go...trying again")
                    self.locks[str(self.right)].release()

            # CASE: Right turn
            elif int(direction) == 2:
                print("Car {} is checking if it is clear".format(
                    self.cars[0].id))
                self.locks[str(self.right)].acquire()
                print("It is clear for Car {} to go".format(self.cars[0].id))
                clock.run(until=2)
                car = self.cars.pop(0)
                print("Car {} has made a right turn".format(car.id))
                self.locks[str(self.right)].release()

            # CASE: Unknown action
            else:
                pass
Пример #12
0
    def __init__(self, duration, lock, checkout0, checkout1, checkout2):
        """This method will create an instance of the Controller

            args:
                duration -- The amount of time that the simulation will run in seconds
                lock -- The shared lock used for all checkout stations
                checkout<x> -- An instance of a checkout station
            """
        self.history = []
        self.status = False
        self.duration = duration
        self.clock = RealtimeEnvironment(initial_time=0,
                                         factor=speed,
                                         strict=False)
        self.checkout_lock = lock
        self.checkout0 = checkout0
        self.checkout1 = checkout1
        self.checkout2 = checkout2
Пример #13
0
class DriveThrough:
    """This class will simulate a Drive Through scenario"""
    def __init__(self, time):
        """This class will create an instance of a Drive Through"""
        self.length = time
        self.clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
        self.customers = CustomerQueue(time)
        self.payment = Payment()
        self.window0 = Window(id="Jane", payment=self.payment)
        self.window1 = Window(id="John", payment=self.payment)
        self.monitor = Monitor(window0=self.window0, window1=self.window1, people=self.customers)
        people = Thread(target=self.customers.generate_customers, name="people")
        crew0 = Thread(target=self.window0.serve_queue, name="John")
        crew1 = Thread(target=self.window1.serve_queue, name="Jane")
        monitor = Thread(target=self.monitor.move_people, name="Monitor")
        self.threads = [people, crew0, crew1, monitor]
        self.objects = [self.window0, self.window1, self.monitor]

    def start(self):
        """This method will start the drive though simulation"""
        for thread in self.threads:
            thread.start()
        self.clock.run(until=self.length)

        for thread in self.objects:
            thread.change_status()

        while not self.customers.customer_queue:
            pass
        self.clock.run(until=self.length + 1000)    # let each thread finish before collecting stats
        time_sum = 0
        complete = 0
        for customer in self.customers.history:
            if customer.complete:
                time_sum = time_sum + customer.finish_time - customer.arrival_time
                complete = complete + 1

        print("\n************************************\n"
              "Total Customer Arrived: {}\n"
              "Total Customer Served: {}\n"
              "Average time to serve: {}\n".format(len(self.customers.history), complete, time_sum//complete))
Пример #14
0
    def red_actions(self, direction):
        complete = False
        global active_light
        global human
        global error
        if int(direction) == 2:
            while self.id != (active_light.direction %
                              2) and not complete and not error:
                print("Car {} wants to turn right on a red light".format(
                    self.cars[0].id))
                clock = RealtimeEnvironment(initial_time=0,
                                            factor=speed,
                                            strict=False)
                clock.run(until=3)
                if self.locks[str(self.right)].acquire(False):
                    car = self.cars.pop(0)
                    print("It is clear for Car {}".format(car.id))
                    clock.run(until=5)
                    print("Car {} has made a right turn".format(car.id))
                    self.locks[str(self.right)].release()
                    complete = True
                else:
                    if human:
                        print(
                            "WARNING:Car {} has caused a crash...\n SIMULATION OVER"
                            .format(self.cars[0].id))

                        error = True
                    else:
                        print(
                            "Car {} was unable turn right on a red light, trying again"
                            .format(self.cars[0].id))
Пример #15
0
                    def waiting(customer):
                        """This is the waiting sequence for a customer who cannot be put into a queue right away"""
                        clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
                        customer.action()  # Waiting for queue to open
                        # Try to get into a queue every seconds
                        for i in range(1, 20):
                            clock.run(until=i)
                            if not (window0.full and window1.full):
                                customer.queue_action()
                                customer.add_time(i)
                                if window0.qsize() < window1.qsize():
                                    window0.put(customer)
                                    print(queue_message.format(customer.id, self.window0.id))
                                else:
                                    window1.put(customer)
                                    print(queue_message.format(customer.id, self.window1.id))
                        if not customer.in_window():
                            # leave and put them back into the queue
                            print("Customer {} has left and will try again later".format(customer.id))
                            customer.action()   # Leaving the line
                            customer.add_time(600)
                            clock.run(until=620)
                            people_lock.acquire()
                            people.append(customer)

                            customer.action() # Rejoining the line
                            people_lock.release()
                            print("Customer {} had rejoined the waiting list".format(customer.id))

                            # Leave permanently
                            clock.run(until=660)
                            people_lock.acquire()
                            if not customer.in_window():
                                customer.action() # Leaving Permanently
                                customer.add_time(40)
                                people.remove(customer)
                                print("Customer {} has left permanently".format(customer.id))
                            people_lock.release()
Пример #16
0
 def run(self):
     while self.active:
         for light in [self.light0, self.light1]:
             clock = RealtimeEnvironment(initial_time=0,
                                         factor=speed,
                                         strict=False)
             other_light = self.light1 if light == self.light0 else self.light0
             global active_light
             active_light = light
             print("*************************\n"
                   "Active Light: {} and {}\n"
                   "Inactive Light : {} and {}\n"
                   "*************************\n".format(
                       active_light.direction,
                       int(active_light.direction) + 2,
                       other_light.direction, other_light.direction + 2))
             other_light.set_colour("red")
             light.set_colour("green")
             clock.run(until=18)
             light.set_colour("yellow")
             clock.run(until=20)
Пример #17
0
                def waiting(customer):
                    """This function is the waiting sequence for a customer. It wil perform the following:
                        - Attempt to put the customer in a queue every second for 20 seconds
                        - Wait 600 seconds
                        - Attempt to put the customer in a queue every second for 40 seconds
                        - Make the customer leave

                        *NOTE* The next step is only performed if the previous one is
                        unsuccessful in placing the customer in a queue
                        """
                    clock = RealtimeEnvironment(initial_time=0,
                                                factor=speed,
                                                strict=False)
                    customer.action()  # Waiting for checkout to open

                    print("Customer {} is waiting for a queue to open".format(
                        customer.id))
                    for i in range(1, 20):
                        clock.run(until=i)
                        lock.acquire()
                        if (not customer.in_checkout() and
                            (not (checkout0.full() and checkout1.full()
                                  and checkout2.full()))):
                            key = min(checkout0.qsize(), checkout1.qsize(),
                                      checkout2.qsize())
                            customer.queue_action()
                            customer.add_time(i)
                            if checkout0.qsize() == key:
                                print(
                                    "Customer {} has been put into Checkout 0".
                                    format(customer.id))
                                checkout0.put(customer)
                            elif checkout1.qsize() == key:
                                print(
                                    "Customer {} has been put into Checkout 1".
                                    format(customer.id))
                                checkout1.put(customer)
                            else:  # self.checkout2.queue.qsize() == key:
                                print(
                                    "Customer {} has been put into Checkout 2".
                                    format(customer.id))
                                checkout2.put(customer)
                        lock.release()

                    if not customer.in_checkout():
                        print("Customer {} had left and will try again later".
                              format(customer.id))
                        customer.action()  # Leave the area
                        customer.add_time(600)
                        clock.run(until=620)

                        print("Customer {} had rejoined the checkout area".
                              format(customer.id))
                        customer.action()
                        for i in range(1, 40):
                            clock.run(until=620 + i)
                            lock.acquire()
                            if (not customer.in_checkout() and
                                (not (checkout0.full() and checkout1.full()
                                      and checkout2.full()))):
                                key = min(checkout0.qsize(), checkout1.qsize(),
                                          checkout2.qsize())
                                customer.queue_action()
                                customer.add_time(i)
                                if checkout0.qsize() == key:
                                    print(
                                        "Customer {} has been put into Checkout 0"
                                        .format(customer.id))
                                    checkout0.put(customer)
                                elif checkout1.qsize() == key:
                                    print(
                                        "Customer {} has been put into Checkout 1"
                                        .format(customer.id))
                                    checkout1.put(customer)
                                else:  # self.checkout2.queue.qsize() == key:
                                    print(
                                        "Customer {} has been put into Checkout 2"
                                        .format(customer.id))
                                    checkout2.put(customer)
                            lock.release()

                        if not customer.in_checkout():
                            print("Customer {} has left permanently".format(
                                customer.id))
                            customer.action()
Пример #18
0
    def simulate(self):
        """This method is the target function for the thread, it will do the following:
            - Generate customers every 50 to 100 seconds
            - Place the customers in a shortest checkout line
            - If no space is available, it will create a thread to perform the 'waiting' sequence
        """
        checkout0 = self.checkout0.queue
        checkout1 = self.checkout1.queue
        checkout2 = self.checkout2.queue
        lock = self.checkout_lock
        arrive_time = randint(50, 100)

        while arrive_time < self.duration:
            # Generate a person
            self.clock.run(until=arrive_time)
            c = Customer(id=len(self.history), time=arrive_time)
            # print("Customer {} has appeared".format(c.id))
            self.history.append(c)

            # Try to put them in a checkout
            lock.acquire()

            # CASE: All checkouts are full --> customer must wait
            if checkout0.full() and checkout1.full() and checkout2.full():

                def waiting(customer):
                    """This function is the waiting sequence for a customer. It wil perform the following:
                        - Attempt to put the customer in a queue every second for 20 seconds
                        - Wait 600 seconds
                        - Attempt to put the customer in a queue every second for 40 seconds
                        - Make the customer leave

                        *NOTE* The next step is only performed if the previous one is
                        unsuccessful in placing the customer in a queue
                        """
                    clock = RealtimeEnvironment(initial_time=0,
                                                factor=speed,
                                                strict=False)
                    customer.action()  # Waiting for checkout to open

                    print("Customer {} is waiting for a queue to open".format(
                        customer.id))
                    for i in range(1, 20):
                        clock.run(until=i)
                        lock.acquire()
                        if (not customer.in_checkout() and
                            (not (checkout0.full() and checkout1.full()
                                  and checkout2.full()))):
                            key = min(checkout0.qsize(), checkout1.qsize(),
                                      checkout2.qsize())
                            customer.queue_action()
                            customer.add_time(i)
                            if checkout0.qsize() == key:
                                print(
                                    "Customer {} has been put into Checkout 0".
                                    format(customer.id))
                                checkout0.put(customer)
                            elif checkout1.qsize() == key:
                                print(
                                    "Customer {} has been put into Checkout 1".
                                    format(customer.id))
                                checkout1.put(customer)
                            else:  # self.checkout2.queue.qsize() == key:
                                print(
                                    "Customer {} has been put into Checkout 2".
                                    format(customer.id))
                                checkout2.put(customer)
                        lock.release()

                    if not customer.in_checkout():
                        print("Customer {} had left and will try again later".
                              format(customer.id))
                        customer.action()  # Leave the area
                        customer.add_time(600)
                        clock.run(until=620)

                        print("Customer {} had rejoined the checkout area".
                              format(customer.id))
                        customer.action()
                        for i in range(1, 40):
                            clock.run(until=620 + i)
                            lock.acquire()
                            if (not customer.in_checkout() and
                                (not (checkout0.full() and checkout1.full()
                                      and checkout2.full()))):
                                key = min(checkout0.qsize(), checkout1.qsize(),
                                          checkout2.qsize())
                                customer.queue_action()
                                customer.add_time(i)
                                if checkout0.qsize() == key:
                                    print(
                                        "Customer {} has been put into Checkout 0"
                                        .format(customer.id))
                                    checkout0.put(customer)
                                elif checkout1.qsize() == key:
                                    print(
                                        "Customer {} has been put into Checkout 1"
                                        .format(customer.id))
                                    checkout1.put(customer)
                                else:  # self.checkout2.queue.qsize() == key:
                                    print(
                                        "Customer {} has been put into Checkout 2"
                                        .format(customer.id))
                                    checkout2.put(customer)
                            lock.release()

                        if not customer.in_checkout():
                            print("Customer {} has left permanently".format(
                                customer.id))
                            customer.action()

                # Execute waiting sequence
                lock.release()
                print("Customer {} is waiting".format(c.id))
                waiting = Thread(target=waiting, args=(c, ))
                waiting.start()
                clock = RealtimeEnvironment(initial_time=0,
                                            factor=speed,
                                            strict=False)
                clock.run(until=20)

            # CASE: A checkout station is open --> place in the shortest queue
            else:
                key = min(checkout0.qsize(), checkout1.qsize(),
                          checkout2.qsize())
                c.queue_action()
                if checkout0.qsize() == key:
                    checkout0.put(c)
                    print("Customer {} has been put into Checkout 0".format(
                        c.id))
                elif checkout1.qsize() == key:
                    checkout1.put(c)
                    print("Customer {} has been put into Checkout 1".format(
                        c.id))
                else:  # checkout2.qsize() == key:
                    checkout2.put(c)
                    print("Customer {} has been put into Checkout 2".format(
                        c.id))
                lock.release()

            arrive_time = arrive_time + randint(50, 100)
Пример #19
0
def test_model_with_tk_tilemap_visualization(until=0.00001, factor=1 / 10**10):
    env = RealtimeEnvironment(factor=factor, strict=False)
    model = Model(env)
    canvas = model.initialize_tkinter_tilemap_visualization()
    env.run(until=until)
    canvas.tk_gui.destroy()
Пример #20
0
    def move_people(self):
        """This function will place customers into a window queue if space is available"""
        people = self.people.customer_queue
        people_lock = self.people.queue_lock
        window0 = self.window0.queue
        window1 = self.window1.queue
        queue_message = "Customer {} has been put into {}'s queue"

        while self.status:
            if len(people) is not 0:
                queue_message = "Customer {} has been put into {}'s queue"
                # CASE: Both window queues are full
                if window0.full() and window1.full():
                    def waiting(customer):
                        """This is the waiting sequence for a customer who cannot be put into a queue right away"""
                        clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
                        customer.action()  # Waiting for queue to open
                        # Try to get into a queue every seconds
                        for i in range(1, 20):
                            clock.run(until=i)
                            if not (window0.full and window1.full):
                                customer.queue_action()
                                customer.add_time(i)
                                if window0.qsize() < window1.qsize():
                                    window0.put(customer)
                                    print(queue_message.format(customer.id, self.window0.id))
                                else:
                                    window1.put(customer)
                                    print(queue_message.format(customer.id, self.window1.id))
                        if not customer.in_window():
                            # leave and put them back into the queue
                            print("Customer {} has left and will try again later".format(customer.id))
                            customer.action()   # Leaving the line
                            customer.add_time(600)
                            clock.run(until=620)
                            people_lock.acquire()
                            people.append(customer)

                            customer.action() # Rejoining the line
                            people_lock.release()
                            print("Customer {} had rejoined the waiting list".format(customer.id))

                            # Leave permanently
                            clock.run(until=660)
                            people_lock.acquire()
                            if not customer.in_window():
                                customer.action() # Leaving Permanently
                                customer.add_time(40)
                                people.remove(customer)
                                print("Customer {} has left permanently".format(customer.id))
                            people_lock.release()

                    # Execute waiting sequence
                    people_lock.acquire()
                    if people:
                        if people[0].in_window() is False and people[0].actions == 0:
                            customer = people.pop(0)
                            customer.action()
                            people_lock.release()

                            # Execute waiting sequence
                            waiting = Thread(target=waiting, args=(customer,))
                            waiting.start()
                            clock = RealtimeEnvironment(initial_time=0, factor=speed, strict=False)
                            clock.run(until=20)
                        else:
                            people_lock.release()
                    else:
                        people_lock.release()

                # CASE: There is available space in a window queue
                else:
                    people_lock.acquire()
                    customer = people.pop(0)
                    customer.queue_action()
                    people_lock.release()
                    if window0.qsize() < window1.qsize():
                        window0.put(customer)
                        print(queue_message.format(customer.id, self.window0.id))
                    else:
                        window1.put(customer)
                        print(queue_message.format(customer.id, self.window1.id))