Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

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 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 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.

Avatar image for gileswintle

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

Become a Member to join the conversation.