If you got stuck or if you had any problems completing this project, the first port of call is to review
the lessons you learned today.
It might just be that you need to see some of the theory a few more times and listen to it a few more
times and practice it a few more times before you're ready to tackle this final challenge.
But if you have completed it and you just want to see the solution, then I'm going to go through it
with you right now.
Again, we're going to complete all of the program requirements step by step.
So the first thing is to print a report for all of the current resources in the coffee machine. Back
in PyCharm,
I'm actually going to collapse this entire project folder because I'm not going to be writing any code
other than inside main.py.
Now you can see up here, we've got access to four classes. And if we take a look inside the documentation,
you can see that both the coffeemaker class and the money machine class have a method called report.
And this is going to print a report of all of the resources like water, milk, coffee,
and this is going to print a report of the current profit.
So our final report is going to be both a report from the money machine as well as the coffee maker.
Let's go ahead and start off by creating some objects from these classes.
For example, the money machine is going to be just called money_machine
or you could call it my_money_machine.
You can actually name your objects anything you like.
But I'm just going to use the default Python snake case to create a new variable money_machine, which
is going to hold my object. And my object is going to be created, of course, from the money machine
class.
And the construction happens when I add the parentheses.
So now I have a object created and stored inside this variable money_machine.
Now, if I want this money machine to create a report, then all I have to do is tap into the object
and then write a dot and then call the method that I need, which is report.
So now if I go ahead and run my code,
you can see it prints out the current amount of money in the machine.
Now let's do the same thing for our coffee maker.
Again, I'm going to call it coffee_maker, and you see this frequently.
The object naming tends to be the lower case and snake case, so separated by underscores, version of the
name of the class.
So the name of the class is CoffeeMaker, and usually you'll see people name the object exactly the
same, but in lowercase.
And now that I have my coffee _maker, then I can go ahead and call the report method on that object
as well.
And now, if I run my code once more, you can see that I've got everything now being reported and printed
out.
So in this case, we don't actually have to care how report is implementing all of this functionality.
All we have to do is read the documentation, find the method that does the thing that we want, and
then trust that it will carry out the functionality as described.
Now that we've completed step 1, the next one is to check that resources are sufficient.
My first port of call is going to be going over to the documentation.
And you can see that the coffeemaker class actually has a method called is _resource_efficient.
And all we have to do is pass in the drink, which is a menu item, and then it's going to check and
give us true, if that drink order can be made, and false if the ingredients are insufficient.
So how do we get hold of this drink menu item to pass over to this method?
Well, if we take a look at the menu class, you can see it has a method called get_items and this is
where you really see reading the documentation properly,
actually absorbing everything that's in here becomes really, really helpful.
This menu class has two methods that are really useful.
One, It's able to get a hold of the names of all the items that are available on the menu.
And it returns it as a string separated by forward slashes.
It's also able to find a drink based on the order name.
So if we passed in one of these names to this function find_drink, then it's going to return a menu
item object if it actually exists.
Otherwise, it's going to return none.
We're going to need both of these in order to ask the user what they want.
Let's go ahead and set up our while loop. As we had previously
I'm going to create a new variable called is_on and it's going to start off being true.
And then while coffee machine is on, well then we're going to get hold of all the options that we
can offer the user. And we get that by calling that method get_items.
But of course, because this is a method, it's associated with an object.
So we have to create an object from this menu blueprint.
So let's do that next to all the other objects being created.
So let's create a menu object and it's going to be created from the menu class,
and then we add the parentheses.
And now we have access to that object by the name menu.
The options are going to be equal to the menu object and then we're going to call the get_items method.
And then when this method returns, it's going to save the string and all the options into this variable
called options.
Now we can get the user's choice by asking them for what would you like?
And then inside a set of parenthesis we'll offer them all the options. And then, of course, I need
to turn this into an fstring.
And the code highlighting immediately tells me that this is actually now working.
So once I've got the user's choice, then I can incorporate the reporting behaviour into this choice.
Remember, previously we said if the choice was equal to off, then that means the is_on is going
to be equal to false, and elif
the choice is equal to report,
well, in this case, we're going to get the coffeemaker and the money machine to make their reports
into the console.
Finally, we're ready to tackle the next problem, which is how do we check that we have enough resources?
And this is going to require us to find the drink given the order name that the user chose from the
choice and then get hold of the menu item which comes as the output from this method call.
So else, we're going to save our drink as a variable called drink, and then we're going to tap into
the menu.find_drink. And find_drink, you'll notice, takes a order name as the input.
So this is a string and this is going to be equal to whatever the user chose inside this choice.
So let's put the choice in here as the input.
And now, once we've got hold of this drink, let's go ahead and print it.
Remember, we're expecting a menu item object at this stage.
So let's click run, and let's make sure that we can hit report to get the report,
we can say off to switch off the machine and exit the code, and we can also get hold of a latte by
passing in latte as the drink that we want.
And we now get printed a menu item object at this particular location in the computer's memory.
Perfect.
Everything is working as expected.
Now, instead of printing the drink, I'm going to tackle this step 2, which is to check that the
resources are sufficient.
Again, that's going to require us to look through our documentation. And you'll see that the coffee
maker class has
that method is_resource _sufficient, and it expects a menu item object as the input.
And then it's going to return true when it can be made and false if it can't.
So let's get hold of our coffee maker object and then get it to check if the resources are sufficient
to make the current drink that we're interested in.
And let's go ahead and print the results here
and run our code.
Let's say that we wanted to make a latte. That's going to be resource sufficient, so true. Espresso,
also true, and a Cappuccino is also true.
So we can make all three drinks, basically.
Now, instead of printing this, what we want to do is we want to check if this is true and then proceed
to the next step if there are enough resources.
Now the next step is to take payment from the user and to process the coins and check the transaction
is successful.
Notice how in our coffee machine documentation for the money machine, we don't actually have a way
of processing the coins. But it what it does have is it allows us to make payments passing in the cost
of the drink and then it will return true when the payment is accepted or false, if insufficient.
So let's see what happens if we actually try to make payment.
Let's tap into our money machine object and then call the make_payment method and we have to pass in
the cost of the drink that the user ordered.
So we've got the drink object here, which remember is a menu item, and each of the menu items have
three attributes that we care about: the name of the drink, the cost of the drink and the ingredient
list.
So this is what we're interested in at the moment. So we can pass in the drink.cost which is the
attribute that's associated with the drink object,
and that cost is going to be processed by this make_payment method from the money machine.
And then finally, it's going to tell us whether if this was successful or not.
So let's see what happens when we run this code as it is.
Let's say I wanted a latte,
notice how it's asking me to insert coins:
how many quarters, how many dimes, how many nickels and how many pennies. A the coffee machine,
I don't actually need to care about how the money and the coins are processed.
All I had to do is call make_payment and it deals with all of this automatically.
Finally, it gives me the change and it returns true, telling me that this make_payment was indeed
successful.
If you actually look inside the money_machine code, then you can see that it has a method called process_
coins, but it's called when make payment is triggered.
This class is going to process coins, and then it's going to decide whether if it was successful
or not. And if it was successful, it's going to add the cost to the profit,
and if not, it's going to tell you that that was not enough money and your money is refunded.
Coming back over here, if this is successful, then that means the user has managed to pay and we fulfilled
step 3 and 4 just using one method.
The final thing we have to do is to actually make the coffee.
And that, of course, happens right at the end here.
And all we have to do to make the coffee is get hold of the coffee maker object and then call the make_
coffee method and we can pass in the order, which is our drink.
Because remember that the make_coffee method expects a menu item as the input parameter.
We can actually simplify this code even more by saying, well, if the coffee maker is_resource_sufficient
and the money machine was able to take payment, well then we can get the coffee_maker to make coffee.
So now let's go ahead and run our code.
And let's report to begin with, to see how much resources we have to begin with.
And then let's order a coffee.
Insert lots of money and we've got our coffee back.
So now let's go ahead and order a different coffee, latte, and let's go ahead and insert lots of money.
And you can see, here's my latte.
But now, if I hit report, you can see that the objects, the coffee maker has been managing our resources
and the money_machine has been managing our profit.
Now, if I decided to order another latte, then it should actually tell me, sorry, there's not enough
water and there's not enough milk. So it can't make me that drink.
And we've managed to achieve all of this functionality by writing very few lines of code, and the code
itself is actually very, very easy to understand.
Even if you came to this completely fresh, you've never seen how each of the methods are implemented,
you don't know how the coffee maker works,
you don't know how the money machine works,
you can see quite easily what it's trying to do.
And so if you only have to write this kind of code, then it would make it so much easier to create
even more complex functionality in your coffee machine, right?
So have a play around with these classes:
the coffeeMaker, the moneyMachine, the menu, the menu item, etc. And see what else it is that
you can do with this code
while not touching any of the blueprints for each of these classes.
Now, in the next lesson, I'm going to be showing you how to create your own classes so that you can
actually start structuring your code using full object-oriented programming.
And we're going to learn about these things like the initialization and how classes are declared and
why there's all this self all over the place.
That's all yet to come on tomorrow's lessons.