← Back to Blog

Calories Tracker Project — Round 3

We have a function that adds food entries. It validates the data. It timestamps automatically. It works.

What it doesn't do yet is loop. At breakfast alone you might log eggs, cheese, bread, and butter — four separate entries. So we wrap everything in a menu.

while True:
    option = input("Choose option (1-Add, q-Quit): ")
    # input always returns a string
    if option == "1":
        add_food_item()
        print("Food log added successfully!")
    elif option == "q":
        break
    else:
        print("Invalid option!")

Simple. Clean. We can now add as many entries as we want — or as many as we actually consumed. The dictionary grows with each call. We can always come back to it.

Before we think about persistence — saving data so it survives after the program closes — we want to understand what we actually need from this data. Persistence without purpose is just storage. So first, let's think about reports.

Three come to mind naturally:

  • A full history — everything logged, useful to share with a trainer, doctor, or nutritionist
  • A 7-day summary — calories only, to check against a personal target
  • A 7-day detailed view — what we actually ate, not just the numbers, useful for planning tomorrow's meals

We'll build all three. But we start with the one that feels most useful right now — the detailed 7-day view. And we start even simpler than that: today only.

# def add_food_item(): [...]

def last_days_details():
    pass

pass keeps the function valid without doing anything. No errors, no output — just a placeholder we can build on.

def last_days_details():
    # isolate today as a string — same format as the key, so we can compare
    today_string = datetime.datetime.now().strftime("%Y-%m-%d")
    for key in food_dict:
        # the key format is "2025-04-02,14:32:11"
        # split(",")[0] gives us just the date part
        if today_string == key.split(",")[0]:
            pass

The logic is there. Now we collect the matching entries into a new dictionary and return it.

def last_days_details():
    today_string = datetime.datetime.now().strftime("%Y-%m-%d")
    last_days_dict = {}
    for key in food_dict:
        if today_string == key.split(",")[0]:
            last_days_dict[key] = food_dict[key]
    return last_days_dict

Good. Now we extend it to 7 days. For that we need timedelta — also from the datetime module.

timedelta represents a duration — a difference between two dates. timedelta(days=1) is one day. Subtract it from today and you get yesterday. Subtract timedelta(days=6) and you get six days ago. It lets you move forward or backward in time by any amount, without manually calculating dates.

def last_days_details():
    today = datetime.datetime.now()
    last_days_dict = {}

    for n in range(0, 8):
        reference_day = (today - datetime.timedelta(days=n)).strftime("%Y-%m-%d")
        for key in food_dict:
            if reference_day == key.split(",")[0]:
                last_days_dict[key] = food_dict[key]

    return last_days_dict

range(0, 8) gives us 0 through 7 — today plus the previous 6 days. For each, we build the date string and check it against every key in the dictionary. Matches go into last_days_dict.

Now we need to display it. We build a print function:

def print_details(food_log):
    for key in food_log:
        print(f"{key.split(',')[0]} - {food_log[key][0]} - {food_log[key][1]}{food_log[key][2]} - {food_log[key][3]} kcal")

Let's unpack what's happening here. key.split(',')[0] gives us the date — we drop the time, we don't need it for display. food_log[key] is the list of values: index 0 is the name, index 1 is the quantity, index 2 is the measure, index 3 is the calories. We stitch them together with an f-string — one readable line per entry. Something like:

2025-04-02 - Chicken Breast - 200.0g - 175 kcal

We can call them separately — or we can fold last_days_details() inside print_details() to keep the call simple:

def print_details():
    food_log = last_days_details()
    for key in food_log:
        print(f"{key.split(',')[0]} - {food_log[key][0]} - {food_log[key][1]}{food_log[key][2]} - {food_log[key][3]} kcal")

This goes into the menu as option 2:

while True:
    option = input("Choose option (1-Add, 2-Show food details, q-Quit): ")
    if option == "1":
        add_food_item()
        print("Food log added successfully!")
    elif option == "2":
        if len(last_days_details()):
            print_details()
        else:
            print("No data available.")
    elif option == "q":
        break
    else:
        print("Invalid option!")

if len(last_days_details())len() returns the number of entries in the dictionary. If it's 0, the condition is False and we print "No data available." instead of running the print function on an empty result. It's a simple guard — don't try to display what isn't there.

The structure now looks like this:

# def add_food_item(): [...]
# def last_days_details(): [...]
# def print_details(): [...]

while True:
    option = input("Choose option (1-Add, 2-Show food details, q-Quit): ")
    if option == "1":
        add_food_item()
        print("Food log added successfully!")
    elif option == "2":
        if len(last_days_details()):
            print_details()
        else:
            print("No data available.")
    elif option == "q":
        break
    else:
        print("Invalid option!")

Here's what a populated log looks like after a few entries:

2025-04-02 - Chicken Breast - 200.0g - 175 kcal
2025-04-02 - White Rice - 100.0g - 130 kcal
2025-04-02 - Greek Yogurt - 150.0g - 88 kcal
2025-04-03 - Oats - 80.0g - 297 kcal
2025-04-03 - Banana - 1.0pcs - 89 kcal

Date, name, quantity with measure, calories. Everything we decided mattered — nothing we decided didn't.

We take data in. We filter it. We display it. All by our own rules.

In survival training, there's a moment after you light your first fire. Not the moment you strike the spark. The moment the flame holds on its own. That's where we are.

We didn't just write code. We built something that works. Next, we make it last.

[ login to bookmark ] // copied! 7 views · 4 min
// resources
Exercise calories_tracker_r3.py
← prev Calories Tracker Project — Round 2 next → Calories Tracker Project — Round 4
// 0 comments
// No comments yet. Be the first.
// leave a comment

// Your comment will appear after approval.