Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- CONFIG = {
- "recipe": {
- "espresso": {
- "ingredients": {
- "water": 50,
- "milk": 0, # Added this in because "sparse" data is usually normalized before used.
- "coffee": 18,
- },
- "cost": 1.5,
- },
- "latte": {
- "ingredients": {
- "water": 200,
- "milk": 150,
- "coffee": 24,
- },
- "cost": 2.5,
- },
- "cappuccino": {
- "ingredients": {
- "water": 250,
- "milk": 100,
- "coffee": 24,
- },
- "cost": 3.0,
- }
- },
- "resources": {
- "water": 300,
- "milk": 200,
- "coffee": 100,
- },
- "money": {
- "value": 0,
- }
- }
- class CoffeeMaker:
- """A Coffee Maker."""
- def __init__(self, config: dict[str, any]) -> None:
- """Initialize a coffee maker."""
- self.config = config
- self.running = True
- def calc_ingredients(self, recipe: dict[str, int]) -> dict[str, float]:
- """Calculate the ingredients left after using recipe."""
- resources = self.config["resources"]
- return {ingredient: resources[ingredient] - recipe[ingredient] for ingredient in resources.keys()}
- def charge(self, tender: float, order: str) -> float:
- """Calculate the leftover change from tender after subtracting order cost."""
- cost = self.config["recipe"][order]["cost"]
- self.config["money"]["value"] += cost
- return tender - cost
- def get_units(self, ingredient: str) -> str:
- """Return the units used for a particular ingredient"""
- match ingredient:
- case "water" | "milk":
- return "ml"
- case "coffee":
- return "g"
- case _:
- raise TypeError(f"Units not known for ingredient. {ingredient=}")
- def is_enough_ingredients(self, ingredients: dict[str, int]) -> bool:
- """Flag whether the coffee maker has sufficient resources for a recipe."""
- return all((ingredient > 0 for ingredient in ingredients.values()))
- def is_valid_order(self, order: str) -> bool:
- """Flag whether the order is support by this machine."""
- return order in self.config["recipe"]
- def make_recipe(self, ingredients: dict[str, int]) -> None:
- """Reduce the number of resources by the recipe's ingredients."""
- self.config["resources"].update(ingredients)
- def prompt(self, typ: str) -> str | int: # Ideally, functions should only return 1 type.
- """Prompt the user with the given prompt type and return their response."""
- match typ:
- case "menu":
- if (resp := input("What would you like (espresso/latte/cappuccino): ").lower()) == "off":
- self.stop()
- return resp
- case "charge":
- quarters = int(input("How many quarters: "))
- dimes = int(input("How many dimes: "))
- nickels = int(input("How many nickels: "))
- pennies = int(input("How many pennies: "))
- return round((quarters * .25) + (dimes * .1) + (nickels * .05) + (pennies * .01), 2)
- case _:
- raise TypeError(f"Unknown prompt option. {typ=}")
- def report(self) -> None:
- """Output a summary report of ingredients leftover and money."""
- report = ""
- for ingredient, leftover in self.config["resources"].items():
- units = self.get_units(ingredient)
- report += f"{ingredient.upper()}: {leftover} {units}\n"
- money = self.config["money"]["value"]
- report += f"MONEY: {money}"
- print(report)
- def start(self):
- """Start the coffee maker."""
- try:
- while self.running:
- order = self.prompt("menu")
- if order == "report":
- self.report()
- continue
- if not self.is_valid_order(order):
- print("Sorry that command is not supported.")
- continue
- recipe = self.config["recipe"][order]['ingredients']
- ingredients = self.calc_ingredients(recipe)
- if not self.is_enough_ingredients(ingredients):
- ingredient = min(ingredients, key=ingredients.get)
- print(f"Sorry, there is not enough {ingredient}.")
- continue
- tender = self.prompt("charge")
- if (change := self.charge(tender, order)) < 0:
- print("Sorry, that's not enough money. Money refunded.")
- continue
- if change > 0:
- print(f"Your change is {change}")
- self.make_recipe(ingredients)
- except (StopIteration, KeyboardInterrupt):
- pass
- def stop(self):
- """Turn off the coffee maker."""
- # If you had to clean up anything, save a backup, stop a process.
- print("System shutting down.")
- raise StopIteration("System shutdown requested.")
- def main():
- """Main Entry Point."""
- CoffeeMaker(CONFIG).start()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment