Classroom Glossary Public page

FND-102 Capstone Specification

1,584 words

Automate something in your actual life. The student selects a real, repeated, tedious task they face, then ships the tool that automates it.


The brief

Pick one task you actually repeat. Not a hypothetical example from a textbook; not a tutorial exercise. Something you, the student, would do again next week if the tool did not exist. Build a Python CLI tool that does that task. Ship it with tests, documentation, and a Git history. Present it to the cohort in five minutes plus Q&A.

The constraint is the only one that matters: the tool must be something you would actually use after this course ends. If you would not run it next month, pick a different task.


What you ship

A Git repository containing:

  1. The tool itself: one or more .py files implementing your automation
  2. argparse interface: every program option is documented in --help
  3. README.md: how to install, how to run, one worked example
  4. tests/ directory: at least three pytest tests; one test must cover an edge case you found by breaking the tool
  5. A Git history with at least five commits: each commit message a sentence; no "fix" or "wip" or "update"
  6. A 5-minute demo + a 5-minute Q&A at the capstone presentation block

Repository naming convention: fnd102-capstone-{your-name} (lowercase, hyphens, no spaces). Example: fnd102-capstone-jamie-smith.


What "automation" means here

A task counts as automation-worthy if it has these three properties:

  1. You do it more than once. Not a one-time chore. Something you repeat weekly, monthly, or every time a triggering condition occurs.
  2. The steps are precise. You can write them down as a recipe. A human could follow your recipe and get the right answer without judgment calls.
  3. It involves data that lives on your computer or on the public internet. No tasks that require physical action (no Raspberry-Pi robotics here; that is HW-101). No tasks that need a paid API or scraping a site that forbids it.

Tasks that DO fit:

  • Renaming photos from a trip into a consistent format using EXIF dates
  • Pulling sports stats from a public API and writing them into a CSV for spreadsheet analysis
  • Generating a weekly chore-rotation schedule for a household with N people
  • Backing up a directory to cloud storage with SHA-256 verification of every file
  • Scanning a directory of receipts and generating a monthly expense summary
  • Building a personal RSS-feed digest that emails you a weekly summary
  • Generating a grocery list from a meal plan stored as a JSON file
  • Renaming downloaded e-books to a consistent Author - Title.ext format

Tasks that do NOT fit:

  • Anything that needs a paid API (no Twitter, no GPT-4, no commercial APIs costing money)
  • Anything that needs JavaScript to render the page (Selenium / headless browser is out of scope)
  • Anything that violates a site's terms of service
  • "Build a web app"; that is a different course (and a different effort budget)
  • "Train a machine learning model"; out of scope; that is AI-101
  • A toy reimplementation of something sort or grep already does cleanly

Exemplar capstones (three full specs)

You may pick one of these verbatim, modify one of them for your situation, or invent your own. Most students do the third. These are concrete enough that a student can scope and ship one in the available time.

Exemplar 1: Photo Renamer

Real task: I have ~200 photos from each trip dumped into a folder with names like IMG_20240601_142337.JPG. I want them named 2024-06-01_paris_001.jpg, 2024-06-01_paris_002.jpg, etc.

Tool: photo-renamer.py SOURCE_DIR --trip-name "paris" [--dry-run]

Behavior:

  • Walks SOURCE_DIR for JPEG / HEIC / PNG files
  • Reads the EXIF "DateTimeOriginal" tag (use Pillow library, freely installable via pip)
  • Renames each file to {date}_{trip-name}_{seq:03d}.{ext}
  • --dry-run prints what it would do without renaming
  • Skips non-image files; warns on missing EXIF dates and falls back to file mtime

Tests:

  • Test 1 (happy path): given a directory of 3 fake JPEGs with known EXIF dates, the rename produces the expected filenames
  • Test 2 (no-EXIF fallback): given a JPEG with no EXIF tag, the rename uses the file's modification time
  • Test 3 (edge case): given a file that already has the target name, the rename is a no-op (not a duplicate-key error)

Why this is a fit: real recurring task, precise steps, files-only (no APIs).

Exemplar 2: Weekly Chore Scheduler

Real task: my household has 4 people and 6 weekly chores (dishes, trash, vacuum, bathrooms, kitchen, lawn). I want a fair rotation that does not repeat the same person on the same chore two weeks in a row.

Tool: chore-scheduler.py --config chores.json --week WEEK_NUMBER [--print|--csv]

Behavior:

  • Reads chores.json with the people list and chores list
  • Computes a rotation that gives each person ~1.5 chores per week (rounding up where N chores does not divide evenly into M people)
  • Avoids assigning a person their previous week's chore (use the deterministic seed WEEK_NUMBER so re-runs give the same answer)
  • --print shows a human-readable table; --csv emits a row per (week, person, chore)

Tests:

  • Test 1: with 4 people and 6 chores over 4 weeks, every person gets 6 chores total and no person repeats their previous chore
  • Test 2: the same WEEK_NUMBER always produces the same assignment (deterministic)
  • Test 3: a config with N people and N chores produces exactly one chore per person per week

Why this is a fit: the student actually has chores; the script answers a real weekly question.

Exemplar 3: Sports-Stats Scraper

Real task: I track my favorite NBA team's stats every week during the season. I currently copy-paste from a stats website into a spreadsheet, which takes 15 minutes weekly.

Tool: nba-stats.py --team-id TEAM_ID --season SEASON --out FILE.csv

Behavior:

  • Uses a free NBA stats API (e.g. https://www.balldontlie.io/; verify the terms-of-service before relying on it; or the official NBA stats endpoints at https://stats.nba.com/)
  • Fetches the team's most recent N games (default 10)
  • Writes one row per game: date, opponent, score, win/loss, top scorer, assists leader, rebounds leader
  • Appends to FILE.csv if it exists (does not duplicate rows; uses game ID as the key)

Tests:

  • Test 1: a mocked API response with 3 games produces a 3-row CSV with the expected columns
  • Test 2: re-running with the same data does not produce duplicates
  • Test 3: an empty API response (no games yet) produces a CSV with only the header row

Why this is a fit: the student actually wants this data; the manual workflow is concrete.


Two-tier grading rubric

Tier Weight What is graded
Code quality + craft 40% Functions are well-named and have docstrings; the code reads like prose; no dead code; argparse --help reads like documentation; exit codes are correct
Tests + docs 30% pytest tests cover the tool's documented behavior, including one regression test for a bug you found; README answers what / install / run in under 200 words
Reflective depth 30% The demo includes one paragraph on the bug you found and fixed, and one paragraph on what you would do differently next time

Reflective depth is weighted as heavily as testing because the academy is teaching practitioners. A capstone that ships clean code but cannot describe its own failure modes is half-finished.


Success criteria

Your capstone is graded on three things:

  1. It works. Running it from a fresh clone with your README's instructions produces the documented output.
  2. It is yours. The task is one you actually have. The instructor can tell when a student picked a textbook exercise off Real Python and rebadged it; the reflection paragraph in the demo always gives it away.
  3. It is shippable. A peer in the cohort can pull your repo, follow the README, and run your tool without asking you a question.

There is no minimum tool complexity. A 50-line, well-tested, well-documented photo-renamer earns full credit. A 500-line, undocumented, untested everything-app does not.


What the capstone does NOT require

  • No web framework (Flask, Django, FastAPI). Out of scope.
  • No database (SQLite, Postgres). Use JSON / CSV files for state.
  • No machine learning. Out of scope.
  • No GUI. CLI only.
  • No deployment. Ship to GitHub / GitLab; no server hosting required.
  • No custom CI. The graders run your tests with pytest from a fresh clone.

Timeline

When What
Week 13 Brainstorm 3-5 candidate tasks during week 13's reflection; bring them to office hours
Week 14, day 1-2 Pick one task; sketch the argparse interface on paper before any code
Week 14, day 2 (scope-check meeting with instructor) 10-minute conversation; instructor pushes back on scope. Trim if needed.
Week 14, days 3-5 Build the happy path; write the README as you go
Week 14, days 5-6 Write at least 3 pytest tests; one must catch a bug you found
Week 14, day 6 Polish: --help output, edge cases, commit history clean-up
Capstone presentation block 5-minute demo + 5-minute Q&A with the cohort

Submission

Push your capstone repository to GitHub or GitLab and email the URL to interested@virtuscyberacademy.org with subject FND-102 capstone, {your-name}. Include in the email:

  • The repository URL
  • A one-sentence description of the real task you automated
  • The one bug you found and fixed (a sentence; the full version is in the demo)

The course team replies within 7 days with the grade and brief feedback. Outstanding capstones (top decile per cohort) are invited to be added to the academy's public capstone showcase with the student's permission.


After the capstone

A finished FND-102 capstone is a portfolio piece. It demonstrates: Python fluency, CLI design sense, testing discipline, Git workflow, documentation, and the practitioner habit of automating real work. Students applying to internships or first jobs after the academy cite their capstone repository in cover letters and bring up the "one bug I found" story in interviews. The exercise of articulating the bug and the fix in plain English is, in many cases, the most directly career-relevant thing you do all course.


Capstone specification v0.1.