Week 2 of 8

Build: Scene Planner

A while loop, user input, and a growing list — your most ambitious script yet

Day 9 60 minutes Build Day

Day 9 of 40

What You'll Accomplish Today

The Project: Scene Planner

Yesterday's shot filter worked on hardcoded data — the shots were already in the script. Today you build the opposite: a script where the user enters the shots interactively, one at a time, until they're done. The script collects each shot as a dictionary, appends it to a list, and auto-numbers them.

This is a two-day build. Today you write the input loop — the part that collects shots. Tomorrow you add the output and platform summary.

Why Two Days?

This script is longer and more complex than anything you've built so far. Breaking it into two sessions lets you understand each piece before adding the next one. By the end of Day 10 you'll have a genuinely useful scene planning tool.

Create a new file called scene_planner.py in your Python Training folder.

Today's Code — The Input Loop

Here's the full code you'll write today. Read it through completely first.

scene_planner.py (Part 1 — today) Python
scene = []

scene_num = input("What scene number is this? ")

print(f"\n=== Planning Scene {scene_num} ===")
print("Add shots one at a time. Type 'done' when finished.\n")

while True:
    description = input("Shot description (or 'done'): ")

    if description.strip().lower() == "done":
        break

    platform = input("Platform (Kling / Runway / Veo): ")

    valid_platforms = ["kling", "runway", "veo"]

    if platform.lower() not in valid_platforms:
        print(f"  ⚠ Unknown platform '{platform}'. Defaulting to Kling.")
        platform = "Kling"

    print("  Shot types: wide, medium, close-up, aerial, tracking, slow-mo")
    shot_type = input("  Shot type: ")

    shot = {
        "number": len(scene) + 1,
        "description": description,
        "platform": platform,
        "type": shot_type,
    }
    scene.append(shot)
    print(f"  ✓ Shot {shot['number']} added.\n")
Type this fully before reading the explanations below. When you run it, you should be able to add shots one by one and see the confirmation message. Type "done" to exit the loop. At this stage the script ends after you say done — tomorrow you'll add the output section.

Breaking It Down: Section by Section

Section 1 — Setup

scene_planner.py — lines 1–6 Python
scene = []

scene_num = input("What scene number is this? ")

print(f"\n=== Planning Scene {scene_num} ===")
print("Add shots one at a time. Type 'done' when finished.\n")

scene = [] creates an empty list. This is where all the shot dictionaries will go as the user adds them. Starting empty and growing it is the pattern for building data from user input.

scene_num stores the scene number as a string. We don't convert it to an integer because we're only displaying it, never doing math with it.

The === ... === header is just decoration — it makes the terminal output easier to read at a glance.

Section 2 — The while True Loop

scene_planner.py — lines 8–12 Python
while True:
    description = input("Shot description (or 'done'): ")

    if description.strip().lower() == "done":
        break

while True: means "loop forever." On its own, this would run until you force-quit the program. The break statement is what makes it stop — it immediately exits the loop when the condition is met.

This pattern — while True: ... break — is the standard way to write "keep going until the user decides to stop." You'll use it constantly in interactive scripts.

description.strip() removes any leading or trailing whitespace the user may have accidentally typed. If someone typed " done " with spaces, .strip() turns it into "done" before the comparison.

.lower() makes the check case-insensitive. "DONE", "Done", and "done" all trigger the break.

Key Concept: while True / break

Think of while True: as saying "open a conversation loop." break says "end the conversation." Between those two lines, everything runs on repeat until the user triggers the exit condition.

This is different from a for loop, which runs a fixed number of times (once per item in a list). A while True loop runs an unknown number of times — however many times the user keeps adding shots.

# for loop: runs exactly 5 times (once per shot)
for shot in shots:
    print(shot)

# while True: runs until the user types 'done'
while True:
    answer = input("Keep going? (done to quit): ")
    if answer == "done":
        break

Section 3 — Platform Validation

scene_planner.py — lines 14–19 Python
    platform = input("Platform (Kling / Runway / Veo): ")

    valid_platforms = ["kling", "runway", "veo"]

    if platform.lower() not in valid_platforms:
        print(f"  ⚠ Unknown platform '{platform}'. Defaulting to Kling.")
        platform = "Kling"

valid_platforms is a list of allowed values (all lowercase so comparison is easy). This is a common pattern: define what's allowed, then check against it.

not in is the reverse of in. "pika" not in valid_platforms returns True because "pika" isn't in the list. If the user's input isn't valid, we print a warning and override it with a sensible default ("Kling") so the script keeps running rather than crashing.

Notice we check platform.lower() against the lowercase list — so "KLING", "Kling", and "kling" all pass validation correctly.

Key Concept: not in

The in operator checks if something is inside a collection:

"kling" in ["kling", "runway", "veo"]   # True
"sora" in ["kling", "runway", "veo"]    # False
"sora" not in ["kling", "runway", "veo"] # True

in and not in work on lists, strings, and (next week) dictionaries. They're one of Python's most readable features — the code says almost exactly what it means in English.

Section 4 — Building the Shot Dictionary

scene_planner.py — lines 21–29 Python
    print("  Shot types: wide, medium, close-up, aerial, tracking, slow-mo")
    shot_type = input("  Shot type: ")

    shot = {
        "number": len(scene) + 1,
        "description": description,
        "platform": platform,
        "type": shot_type,
    }
    scene.append(shot)
    print(f"  ✓ Shot {shot['number']} added.\n")

After collecting all inputs, we package them into a dictionary called shot. Each key is a string label; each value comes from a variable we collected with input().

"number": len(scene) + 1 — this auto-numbers each shot. Before we append the new shot, len(scene) tells us how many shots are already in the list. If there are 0 shots so far, this shot is #1. If there are 2 shots, this is #3. This is cleaner than manually tracking a counter variable.

scene.append(shot) adds the completed dictionary to the scene list. After this line, the shot is permanently stored in the list, and the loop goes back to the top to ask for the next one.

The trailing comma after shot_type, is valid Python and a common style for multiline dictionaries and lists — it makes adding a new line later easier without forgetting a comma.

Run and Test

Terminal
$ python scene_planner.py
What scene number is this? 3

=== Planning Scene 3 ===
Add shots one at a time. Type 'done' when finished.

Shot description (or 'done'): Wide establishing, golf course at dawn
Platform (Kling / Runway / Veo): Kling
  Shot types: wide, medium, close-up, aerial, tracking, slow-mo
  Shot type: wide
  ✓ Shot 1 added.

Shot description (or 'done'): Close-up on club head at impact
Platform (Kling / Runway / Veo): Sora
  ⚠ Unknown platform 'Sora'. Defaulting to Kling.
  Shot types: wide, medium, close-up, aerial, tracking, slow-mo
  Shot type: close-up
  ✓ Shot 2 added.

Shot description (or 'done'): done

The script ends cleanly after typing "done" — no output yet, because that's tomorrow's work. But the data was being collected and stored correctly the whole time.

If Your Loop Never Stops

If you accidentally created an infinite loop (you typed "done" but it didn't exit), press Ctrl + C in the terminal to force-stop the script. Then re-read the break condition — a typo in the comparison string is the most common cause.

End of Day Checklist

Tomorrow

You'll add the output section to scene_planner.py — the part that prints the final shot list with all fields, then counts how many shots are assigned to each platform. You'll also learn a clever trick for counting: the dictionary .get(key, default) pattern. Then the week wraps up with a vocabulary review.