Skip to content

Balick/coffee-machine-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Coffee Machine (Python)

A simple coffee machine simulator written in Python — a small stateful program that models a real coffee vending machine: it stores resources (water, milk, coffee beans, disposable cups, money), serves three coffee types (espresso, latte, cappuccino), notifies when resources are insufficient and accepts buy, fill, take, remaining, and exit commands.

This project was originally created while working through a Hyperskill exercise. Project: https://hyperskill.org/projects/68 Profile: https://hyperskill.org/profile/386978127


Table of contents


Overview

The coffee machine program models:

  • an inventory of resources (water, milk, beans, cups, money),
  • a set of recipes for drinks (espresso, latte, cappuccino),
  • a simple state machine to drive user interaction: picking actions, buying, filling incremental resources, taking money, printing remaining resources, and exiting.

It is an educational project suitable for practicing:

  • object-oriented design,
  • simple state machines,
  • defensive input handling,
  • small CLI interactions.

Features

  • Three predefined recipes with resource consumption and prices.
  • Track of machine resources and money collected.
  • Interactive mode with step-by-step prompts.
  • Fill action walks through adding water → milk → beans → cups.
  • Clear user prompts and friendly messages when resources are insufficient.
  • Easy to extend (add recipes, commands, or tests).

How it works (quick)

  1. Program instantiates a CoffeeMachine with an Inventory.

  2. It repeatedly prints a prompt (based on the current internal state) and reads user input.

  3. Input is processed by the machine's handle method which:

    • changes state when starting buy or fill,
    • makes coffee if enough resources exist,
    • performs take / remaining / exit.
  4. The fill command advances through sub-states (fill_water, fill_milk, fill_coffee.beans, fill_disposable.cups) to add resources in sequence.


Requirements

  • Python 3.9+ (uses modern typing such as tuple[bool, str]; for older Python versions replace with Tuple[...] from typing).
  • No external dependencies.

Run the program

Save your Python file (e.g. coffee_machine.py) and run:

python coffee_machine.py

The program runs in the terminal until you type exit (or the machine enters the exit state).


Interactive commands & prompts

Top-level actions (when machine is in action state):

Write action (buy, fill, take, remaining, exit):
  • buy → moves to buy state and prompts:

    What do you want to buy? 1 - espresso, 2 - latte, 3 - cappuccino, back - to main menu:
    

    Enter 1, 2, 3, or back.

  • fill → begins the fill sequence:

    1. Write how many ml of water you want to add:
    2. Write how many ml of milk you want to add:
    3. Write how many grams of coffee beans you want to add:
    4. Write how many disposable cups you want to add: After the last entry, the state returns to action.
  • take → empties the money and prints how much was given:

    I gave you $X
    
  • remaining → prints current resources (multi-line).

  • exit → exits the program loop.


Example session

Below is a short example interaction illustrating behavior.

Write action (buy, fill, take, remaining, exit):
> remaining
The coffee machine has:
400 ml of water
540 ml of milk
120 g of coffee beans
9 disposable cups
$550 of money

Write action (buy, fill, take, remaining, exit):
> buy
What do you want to buy? 1 - espresso, 2 - latte, 3 - cappuccino, back - to main menu:
> 1
I have enough resources, making you a coffee!

Write action (buy, fill, take, remaining, exit):
> buy
What do you want to buy? 1 - espresso, 2 - latte, 3 - cappuccino, back - to main menu:
> 2
Sorry, not enough water!

Write action (buy, fill, take, remaining, exit):
> fill
Write how many ml of water you want to add:
> 200
Write how many ml of milk you want to add:
> 100
Write how many grams of coffee beans you want to add:
> 50
Write how many disposable cups you want to add:
> 5

Write action (buy, fill, take, remaining, exit):
> take
I gave you $554

Write action (buy, fill, take, remaining, exit):
> exit

Project structure & code walkthrough

Main classes and responsibilities:

  • Recipe

    • Wraps a recipe entry from CoffeeMachine.RECIPES.
    • Holds name, water, milk, beans, and price.
    • Instantiated with a recipe key ('1', '2', '3').
  • Inventory

    • Stores resource amounts as attributes: water, milk, beans, cups, money.
    • Provides has_enough_for(recipe) returning (True, "") or (False, "<resource>").
    • Provides helper methods to adjust resources (add_water, add_milk, ...), and withdraw_money which sets money to 0.
  • CoffeeMachine

    • RECIPES static mapping of recipe keys to tuples: (name, water, milk, beans, price).
    • Maintains inventory and state.
    • get_prompt() chooses which prompt to display according to state.
    • handle(line) processes a single line of input depending on state.
    • define_action, fill_resources, buy_coffee provide the logic for actions.
    • __str__ prints a human-readable description of the inventory.

Note about current code: The code is functional and implements the required behavior. There are some design choices that can be addressed for clarity (see the "Possible improvements" section).


Testing & validation ideas

  • Unit tests for Inventory.has_enough_for with edge cases (exact resources, zero, negative).
  • Unit tests for fill_resources sequence to ensure state transitions happen correctly.
  • Integration test for a full interactive session simulated by a sequence of inputs.
  • Test error handling when non-integer values are entered during fill.

Possible improvements

If you want to iterate or polish the project, consider:

  • Move initial resource defaults into Inventory.__init__ (currently class attributes). This avoids resource sharing between instances and fits typical OOP practices.
  • Improve Recipe to accept the recipe tuple on construction instead of instantiating CoffeeMachine() inside Recipe.__init__ (creating a new CoffeeMachine there is wasteful/unexpected).
  • Add persistence (save/load inventory to disk) so the machine keeps state between runs.
  • Add CLI flags to run scripted sessions or to run tests automatically.
  • Add more drinks, configurable recipes loaded from a JSON/YAML file.
  • Add better input validation and explicit error messages.
  • Add localization or language support for prompts.
  • Add logging (instead of prints) to facilitate debugging and testing.
  • Replace tuple[bool, str] typing for older Python compatibility with Tuple from typing if you need to support Python < 3.9.

Contributing

  1. Fork the repository and create a feature branch.
  2. Create tests for any new behaviors.
  3. Open a pull request describing the change and why it's useful.

If you're using this repository as a learning exercise, try refactoring with the suggestions in the previous section and run through unit tests.


Credits & Links

About

simple coffee machine simulator written in Python

Topics

Resources

Stars

Watchers

Forks

Languages