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 ]
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
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
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
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 __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 __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 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
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))
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 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
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
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))
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))
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()
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)
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()
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)
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()
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))