Defining Processes in the Simulation
00:00
In this lesson, you’re going to set up your moviegoer to move through the processes of the environment. To do this, go ahead and make a new function called go_to_movies()
, which will take in the env
(environment), a moviegoer
, and the theater
as parameters.
00:17
The first step for the moviegoer is to arrive at the theater. To keep track of this arrival time, you can go ahead and make a new variable called arrival_time
and set this equal to the env.now
property.
00:31 Now that the moviegoer is at the theater, they’re going to have to go through the processes. So they’ll need to buy a ticket, they’ll need to have that ticket checked, and then they’ll have to decide if they’re going to get food or not.
00:43
So start off with buying a ticket. Each of these processes are going to have the moviegoer
request a resource to complete that process. If all the resources are tied up, the moviegoer
will need to wait until a resource becomes free before completing that process. A way to simulate this is by making the function into a generator using the yield
keyword, which will retain state of the function as the moviegoer
waits.
01:07
Let’s see what this looks like, and then discuss what’s happening. So go ahead and say with theater.cashier.request()
, then we’ll call this as request
.
01:21
You’ll want to yield that request
and then yield the env.process()
of theater
, and then call that .purchase_ticket()
method and pass in the moviegoer
.
01:34
So, there’s quite a bit going on here, and we can break it down a little bit. In these first two lines, you’re using the cashier.request()
method, which will check to see if there’s a .cashier
resource available. And if not, then the moviegoer
will wait. Once one is available, this function will then yield the process of purchasing that ticket.
01:55
So, a big takeaway here is the moviegoer
function here is what actually links purchasing the ticket with a .cashier
. If you were to put .usher
here, then the moviegoer would be looking for .usher
resources to purchase tickets from. Once the process is completed, you could call the .release()
method, which would mark this .cashier
resource as being free, but by using with
, as soon as this code block completes, the .cashier
will be freed up.
02:21
If you’re not familiar with how the yield
keyword or generators work, this block of code probably looks like magic. You can think of yield
as a return statement, which then is returning these methods when you call go_to_movies()
, but allowing the function to continue on each time it’s called. Getting too deep into yield
is beyond the scope of this course, so feel free to check out a link to a fantastic guide in the description if you need a refresher on how these statements work. Okay!
02:49
So now that the moviegoer has the ticket, it’s time to go through the other steps of the process. And like before, the next steps are pretty similar for having the ticket checked and going to concessions. So to check the ticket, you can say with theater
and then call the .usher
and then call .request() as request
.
03:10
You’ll first yield that request
, and then you’ll yield the env.process
.
03:17
So, theater.check_ticket()
, and then pass in moviegoer
.
03:24
And I noticed an autocomplete issue here—.usher
should be singular, so I’ll get rid of that s
. Get rid of this s
, and then also .server
.
03:40
And to keep things consistent, let’s say # check ticket
.
03:45
So now for the concessions area, things are a little bit different. I’m going to say # buy food
here. And because each moviegoer is either going to decide to buy food or not to buy food, you’re going to need to add some randomness to how this works.
03:59
So you can say something like if random.choice()
and then just pass in a list of [True, False]
, and this is just assuming a 50/50 split between either buying food or not buying food. Now you can put in your with
block, so with theater.server.request() as request:
.
04:22
Go ahead and yield that request
, and then once a .server
is available, we’ll say env.process()
, and then the theater
, and then .sell_food()
to the moviegoer
.
04:36
So each time the moviegoer
gets to this step, it will decide if they’re going to buy food or not, and if they are, it’ll go through and run this block here. So, once they’ve made it past that, it’s time for them to go to their seat, and we’ll assume this happens instantly. And the wait is complete, so you can say your list of wait_times
can now append. Then here, take that env.now
property, and then subtract the arrival_time
.
05:04
And this will calculate their wait time in minutes by comparing the time it is now to the time they got there. Okay! So now that this function is defined, the moviegoer
knows what the processes for going into the theater and getting to their seat is. They have to buy the ticket, they have to have their ticket checked, and then they have to decide if they’re going to buy food—and if they are, they have to go get that food.
05:27
They have the process and they’ll also pay attention to how long it takes them to go through that process. And then append that to wait_times
. All right!
05:35 In the next lesson, you’re going to write a function that will actually run the simulation.
Become a Member to join the conversation.
gileswintle on Dec. 19, 2020
hi, I see that you are writing your classes as inheriting from object. Is this course in Python 2? If not, why do we need to inherit from object?
thank you