Level 2 / Project 05 - Text Report Generator¶
Home: README
Try in Browser: Run this exercise online — no installation needed!
Before You Start¶
Recall these prerequisites before diving in:
- Can you use zip() to pair two lists together?
- Can you group items from a list into a dictionary of lists?
Estimated time: 35 minutes
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| Concept | This project | — | Quiz | Flashcards | Diagram | Browser |
Focus¶
- build readable reports from records
Why this project exists¶
This project gives you level-appropriate practice in a realistic operations context. Goal: run the baseline, alter behavior, break one assumption, recover safely, and explain the fix.
Run (copy/paste)¶
Use <repo-root> as the folder containing this repository's README.md.
cd <repo-root>/projects/level-2/05-text-report-generator
python project.py data/sample_input.txt --group department --value salary
python project.py data/sample_input.txt --json
pytest -q
Expected terminal output¶
============================================================
Data Report
============================================================
Total records: 10
Breakdown by department: ...
9 passed
Expected artifacts¶
- Formatted text report on stdout
- Passing tests
- Updated
notes.md
Checkpoint: Baseline code runs and all tests pass. Commit your work before continuing.
Alter it (required) — Extension¶
- Add a
--sort-byflag to sort groups by total, mean, or count. - Add a "Bottom 5" section alongside the "Top 5" section.
- Add a
--outputflag to save the report to a file.
Break it (required) — Core¶
- Feed a CSV where the salary column has some non-numeric values (e.g. "N/A").
- Feed a CSV with mismatched column counts (some rows have more/fewer fields).
- Use a group field that does not exist in the header.
Fix it (required) — Core¶
- Ensure
extract_numerichandles "N/A" and blank values without crashing. - Handle rows with missing fields by padding with empty strings.
- Show "UNKNOWN" when a group field is missing from a record.
Checkpoint: All modifications done, tests still pass. Good time to review your changes.
Explain it (teach-back)¶
- How does
zip(headers, values)pair headers with values? - Why is
sorted(groups.keys())used instead of iteratinggroupsdirectly? - What does
dict.get(key, default)do differently fromdict[key]? - When would you choose text reports over JSON output?
Mastery check¶
You can move on when you can:
- explain how zip works with unequal-length lists,
- write a group_by function from memory,
- add a new statistic (e.g. median) to the report,
- format output with consistent column alignment.
Related Concepts¶
- Collections Explained
- Files and Paths
- Functions Explained
- How Imports Work
- Quiz: Collections Explained
Stuck? Ask AI¶
If you are stuck after trying for 20 minutes, use one of these prompts:
- "I am working on Text Report Generator. I got this error: [paste error]. Can you explain what this error means without giving me the fix?"
- "I am trying to group records by a field value. Can you show me how to build a dictionary of lists from a flat list, using a different example like grouping students by grade?"
- "Can you explain how
zip(headers, values)works when the lists have different lengths?"
| ← Prev | Home | Next → |
|---|---|---|