forked from realpython/materials
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimulate.py
More file actions
110 lines (80 loc) · 3.03 KB
/
Copy pathsimulate.py
File metadata and controls
110 lines (80 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""Companion code to https://realpython.com/simulation-with-simpy/
'Simulating Real-World Processes With SimPy'
Python version: 3.7.3
SimPy version: 3.0.11
"""
import simpy
import random
import statistics
wait_times = []
class Theater(object):
def __init__(self, env, num_cashiers, num_servers, num_ushers):
self.env = env
self.cashier = simpy.Resource(env, num_cashiers)
self.server = simpy.Resource(env, num_servers)
self.usher = simpy.Resource(env, num_ushers)
def purchase_ticket(self, moviegoer):
yield self.env.timeout(random.randint(1, 3))
def check_ticket(self, moviegoer):
yield self.env.timeout(3 / 60)
def sell_food(self, moviegoer):
yield self.env.timeout(random.randint(1, 5))
def go_to_movies(env, moviegoer, theater):
# Moviegoer arrives at the theater
arrival_time = env.now
with theater.cashier.request() as request:
yield request
yield env.process(theater.purchase_ticket(moviegoer))
with theater.usher.request() as request:
yield request
yield env.process(theater.check_ticket(moviegoer))
if random.choice([True, False]):
with theater.server.request() as request:
yield request
yield env.process(theater.sell_food(moviegoer))
# Moviegoer heads into the theater
wait_times.append(env.now - arrival_time)
def run_theater(env, num_cashiers, num_servers, num_ushers):
theater = Theater(env, num_cashiers, num_servers, num_ushers)
for moviegoer in range(3):
env.process(go_to_movies(env, moviegoer, theater))
while True:
yield env.timeout(0.20) # Wait a bit before generating a new person
moviegoer += 1
env.process(go_to_movies(env, moviegoer, theater))
def get_average_wait_time(wait_times):
average_wait = statistics.mean(wait_times)
# Pretty print the results
minutes, frac_minutes = divmod(average_wait, 1)
seconds = frac_minutes * 60
return round(minutes), round(seconds)
def get_user_input():
num_cashiers = input("Input # of cashiers working: ")
num_servers = input("Input # of servers working: ")
num_ushers = input("Input # of ushers working: ")
params = [num_cashiers, num_servers, num_ushers]
if all(str(i).isdigit() for i in params): # Check input is valid
params = [int(x) for x in params]
else:
print(
"Could not parse input. Simulation will use default values:",
"\n1 cashier, 1 server, 1 usher.",
)
params = [1, 1, 1]
return params
def main():
# Setup
random.seed(42)
num_cashiers, num_servers, num_ushers = get_user_input()
# Run the simulation
env = simpy.Environment()
env.process(run_theater(env, num_cashiers, num_servers, num_ushers))
env.run(until=90)
# View the results
mins, secs = get_average_wait_time(wait_times)
print(
"Running simulation...",
f"\nThe average wait time is {mins} minutes and {secs} seconds.",
)
if __name__ == "__main__":
main()