One stub is left. The flight director wants to know how the crew spends its time. How many build entries, test entries and ideas are there?
Rocket grins. "Counting with a dictionary," he says. "We did that in week 5 with tags. It is almost the same code."
Raven checks the plan on the whiteboard and ticks off four boxes. "What do you notice?" she asks. "When this one is done, every box is ticked. Then we test the whole tool from start to finish."
Nova dims her lights for a moment, like a theater before the curtain. "Interesting," she says. "The first full run of a program you built yourself is a special moment. Go slowly and watch everything."
Rocket types the last two functions.
count_tags returns a dictionary of tag counts. Type it below search_entries.
def count_tags(entries):
"""A dictionary of how many entries have each tag."""
counts = {}
for entry in entries:
tag = entry["tag"]
counts[tag] = counts.get(tag, 0) + 1
return counts show_stats prints the total and each count. Type it below run_search.
def show_stats(entries):
"""Print the number of entries and a count for each tag."""
print(f"Entries in total: {len(entries)}")
for tag, count in count_tags(entries).items():
print(f" {tag}: {count}") In main, add the choice 4 branch below choice 3, and delete the stub lines completely. Here is the whole program, ready to compare with yours:
# mission_log.py
# Mission Log: keep dated notes about your missions.
# Entries are saved in mission_log.json, in the same folder.
import json
from datetime import date
LOG_FILE = "mission_log.json"
def load_entries():
"""Read saved entries, or start an empty list on the first run."""
try:
with open(LOG_FILE) as f:
return json.load(f)
except FileNotFoundError:
return []
def save_entries(entries):
"""Write every entry to the JSON file."""
with open(LOG_FILE, "w") as f:
json.dump(entries, f, indent=2)
def make_entry(text, tag, day):
"""Build one entry as a dictionary."""
return {"date": day, "tag": tag, "text": text}
def format_entry(number, entry):
"""One entry as a line of text."""
return f"{number}. {entry['date']} [{entry['tag']}] {entry['text']}"
def search_entries(entries, word):
"""Entries whose text or tag contains word, ignoring capitals."""
word = word.lower()
found = []
for entry in entries:
if word in entry["text"].lower() or word in entry["tag"]:
found.append(entry)
return found
def count_tags(entries):
"""A dictionary of how many entries have each tag."""
counts = {}
for entry in entries:
tag = entry["tag"]
counts[tag] = counts.get(tag, 0) + 1
return counts
def add_entry(entries):
"""Ask for a new entry, add it to the list and save."""
text = input("What happened? ").strip()
if text == "":
print("Nothing typed, so nothing saved.")
return
tag = input("Tag (build, test, idea): ").strip().lower()
if tag == "":
tag = "note"
entries.append(make_entry(text, tag, date.today().isoformat()))
save_entries(entries)
print(f"Saved entry {len(entries)}.")
def show_entries(entries):
"""Print every entry with its number."""
if len(entries) == 0:
print("No entries yet.")
return
for number, entry in enumerate(entries, start=1):
print(format_entry(number, entry))
def run_search(entries):
"""Ask for a word and print the matching entries."""
word = input("Search for: ").strip()
found = search_entries(entries, word)
for number, entry in enumerate(found, start=1):
print(format_entry(number, entry))
print(f"Matches found: {len(found)}")
def show_stats(entries):
"""Print the number of entries and a count for each tag."""
print(f"Entries in total: {len(entries)}")
for tag, count in count_tags(entries).items():
print(f" {tag}: {count}")
def main():
"""Load the log, then show the menu until the user quits."""
entries = load_entries()
print(f"Mission Log ready. Entries loaded: {len(entries)}")
while True:
print()
print("1 Add 2 List 3 Search 4 Stats 5 Quit")
choice = input("Choose 1 to 5: ").strip()
if choice == "1":
add_entry(entries)
elif choice == "2":
show_entries(entries)
elif choice == "3":
run_search(entries)
elif choice == "4":
show_stats(entries)
elif choice == "5":
print("Log saved. See you next mission!")
break
else:
print("Please type a number from 1 to 5.")
if __name__ == "__main__":
main() Delete mission_log.json, then run Mission Log twice. In the first run, add three entries and quit:
Mission Log ready. Entries loaded: 0 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 1 What happened? Built the launch clock Tag (build, test, idea): build Saved entry 1. 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 1 What happened? Tested the clock Tag (build, test, idea): TEST Saved entry 2. 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 1 What happened? Sound when it ends Tag (build, test, idea): idea Saved entry 3. 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 5 Log saved. See you next mission!
In the second run, the entries are loaded from the file. List, search, stats, a wrong choice, and quit. Your dates will be the day you run it:
Mission Log ready. Entries loaded: 3 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 2 1. 2026-04-12 [build] Built the launch clock 2. 2026-04-12 [test] Tested the clock 3. 2026-04-12 [idea] Sound when it ends 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 3 Search for: clock 1. 2026-04-12 [build] Built the launch clock 2. 2026-04-12 [test] Tested the clock Matches found: 2 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 4 Entries in total: 3 build: 1 test: 1 idea: 1 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 9 Please type a number from 1 to 5. 1 Add 2 List 3 Search 4 Stats 5 Quit Choose 1 to 5: 5 Log saved. See you next mission!
Mission Log is complete, and you built every line of it. Next week you will test it, polish it, save a snapshot and demo it. Tomorrow is a Crew Quest.