Introduction

Football scouts do not just read stat sheets. They turn numbers into clear stories about role, strengths, and what a player can improve next.

In this project, you will build a Python program that turns football stats into a clean scouting report.

What we're building

By the end of this project, you will:

  • Format report text with strings and f-strings
  • Use functions to generate reusable scouting templates
  • Turn football stats into analysis language
  • Load player data from CSV and generate multiple reports

Why this matters

This is how real analysis teams work: one report template, many players, consistent output.

Part 1: Quick Start

Set up your project in Cursor

For this project, you will create your files from scratch (no starter pack download).

Before you start: quick vocabulary

  • A folder is a container that holds files.
  • A file is one item inside a folder.
  • A file extension is the ending in the file name:
    • .py means Python code.
    • .csv means table-style data.
  1. Pick an easy location for your project folder:
    • Mac: Desktop in Finder
    • Windows: Desktop in File Explorer
    • Chromebook: My files in the Files app
  2. Create a folder called football-scouting-report.
  3. In Cursor, go to File > Open Folder and open football-scouting-report.
  4. In Cursor's left file explorer:
    • click New Folder and create data
    • click New File and create scouting_report.py
    • open data, click New File, and create players.csv
  5. If you do not see file extensions on your computer, that is okay. Type the full names exactly, including .py and .csv.

Writing the code

Type this into scouting_report.py:

player_name = "Aiden Brooks"
team_name = "Greenville Knights"
primary_stat_name = "Passing yards per game"
primary_stat_value = 278.4

print(f"Scouting Report: {player_name} ({team_name})")
print(f"Top stat: {primary_stat_name} - {primary_stat_value}")

This is your first quick win. You are already generating a readable football report line.

Running the code

Save the file (Cmd + S on Mac, Ctrl + S on Windows/Chromebook).

Run the file with Cursor's built-in Run Python File play button in the top-right.

If the play button is missing, install/enable the Python extension in Cursor and reopen scouting_report.py.

Expected output:

Scouting Report: Aiden Brooks (Greenville Knights)
Top stat: Passing yards per game - 278.4

If your output matches, your setup is working.

Part 2: Project Milestones

Milestone 1: Build a reusable report function

A function is a reusable recipe. Write it once, then use it for every player.

Add this below your existing code:

def build_report(player_name, team_name, position, pass_yds_pg, pass_td_pg, comp_pct):
    report = (
        f"=== Scouting Report ===\n"
        f"Player: {player_name}\n"
        f"Team: {team_name}\n"
        f"Position: {position}\n"
        f"Pass Yds/G: {pass_yds_pg}\n"
        f"Pass TD/G: {pass_td_pg}\n"
        f"Comp %: {comp_pct}\n"
    )
    return report

print(build_report("Aiden Brooks", "Greenville Knights", "QB", 278.4, 2.2, 67.8))

Expected output:

=== Scouting Report ===
Player: Aiden Brooks
Team: Greenville Knights
Position: QB
Pass Yds/G: 278.4
Pass TD/G: 2.2
Comp %: 67.8

Milestone 2: Add strengths and growth areas

Now add decision logic (if/elif/else) to convert numbers into coach-friendly language.

Add this below Milestone 1 code:

def passing_volume_label(pass_yds_pg):
    if pass_yds_pg >= 280:
        return "Strength: High passing volume."
    if pass_yds_pg >= 220:
        return "Strength: Reliable production through the air."
    return "Growth Area: Increase consistent yardage output."

def accuracy_label(comp_pct):
    if comp_pct >= 67:
        return "Strength: Efficient ball placement."
    if comp_pct >= 62:
        return "Strength: Solid short-area accuracy."
    return "Growth Area: Improve timing and accuracy under pressure."

print(passing_volume_label(278.4))
print(accuracy_label(67.8))

Expected output:

Strength: Reliable production through the air.
Strength: Efficient ball placement.

Try different numbers and watch the labels change.

Milestone 3: Create a full scouting summary paragraph

Now build one polished paragraph that sounds like a scouting note.

Add this below your current code:

def build_summary(player_name, role, trend_note, strength_line, growth_line):
    return (
        f"{player_name} projects as a {role}. "
        f"{strength_line} {growth_line} "
        f"Recent trend: {trend_note}."
    )

summary = build_summary(
    "Aiden Brooks",
    "rhythm passer with vertical upside",
    "9 passing touchdowns across the last 4 games",
    "Operates quickly and identifies leverage matchups.",
    "Can reduce risky throws late across the middle."
)

print(summary)

Expected output:

Aiden Brooks projects as a rhythm passer with vertical upside. Operates quickly and identifies leverage matchups. Can reduce risky throws late across the middle. Recent trend: 9 passing touchdowns across the last 4 games.

Milestone 4: Load player reports from CSV data

Now separate data from code with data/players.csv. This is how you scale from one player to a full position group.

  1. Open data/players.csv.
  2. Paste the data below.
  3. Save the file.
  4. Make sure the file name is exactly players.csv (not players.csv.txt).

Paste this into data/players.csv:

name,team,position,pass_yds_pg,pass_td_pg,comp_pct,rush_yds_pg,trend_note
Aiden Brooks,Greenville Knights,QB,278.4,2.2,67.8,24.1,9 passing touchdowns across the last 4 games
Liam Carter,Greenville Knights,QB,241.7,1.8,64.9,31.6,completion rate above 65 percent in 5 straight games
Mason Reed,Greenville Knights,QB,215.3,1.5,61.8,42.2,rushing usage increased in red zone packages

Now load that file in Python. Add this below your existing code:

import csv

players = []

with open("data/players.csv", "r") as file:
    reader = csv.DictReader(file)
    for row in reader:
        players.append({
            "name": row["name"],
            "team": row["team"],
            "position": row["position"],
            "pass_yds_pg": float(row["pass_yds_pg"]),
            "pass_td_pg": float(row["pass_td_pg"]),
            "comp_pct": float(row["comp_pct"]),
            "rush_yds_pg": float(row["rush_yds_pg"]),
            "trend_note": row["trend_note"]
        })

print(players)

Click Run Python File again.

Expected output (shortened example):

[{'name': 'Aiden Brooks', 'team': 'Greenville Knights', ...}, {'name': 'Liam Carter', ...}, ...]

If you see a list of dictionaries, your CSV load worked.

Milestone 5: Print final scouting cards for each player

Now combine:

  • your report template
  • your label rules
  • your summary paragraph
  • your CSV player list

Add this below Milestone 4:

def print_scouting_card(player):
    strength = passing_volume_label(player["pass_yds_pg"])
    growth = accuracy_label(player["comp_pct"])
    summary = build_summary(
        player["name"],
        "field general who can distribute across all levels",
        player["trend_note"],
        strength,
        growth
    )

    print("=" * 48)
    print(f"SCOUTING CARD: {player['name']}")
    print("=" * 48)
    print(build_report(
        player["name"],
        player["team"],
        player["position"],
        player["pass_yds_pg"],
        player["pass_td_pg"],
        player["comp_pct"]
    ))
    print(summary)
    print("=" * 48)

for player in players:
    print_scouting_card(player)

Expected result:

  • You should see one scouting card per player.
  • Each card should include report lines and a summary paragraph.

If you made it this far, you built a full football scouting report generator from scratch.

Common Fixes

  • FileNotFoundError: confirm the path is exactly data/players.csv.
  • ValueError: check that pass_yds_pg, pass_td_pg, and comp_pct are numeric in CSV.
  • No play button: install/enable Python extension in Cursor and reopen scouting_report.py.

Bonus Exercises: Push It Further with Your Agent

Use this short prompt structure for better AI help:

  1. Goal: what you want to build
  2. Context: file name + what code already exists
  3. Constraints: keep beginner-friendly, minimal changes
  4. Output format: ask for exact code + where to paste + expected output

Bonus 1: Add Letter Grades

Try this prompt:

You are my Python tutor and coding assistant.

Goal:
Add letter grades (A/B/C) for passing yards, touchdown rate, and completion percentage.

Context:
I am editing scouting_report.py.
I already have build_report(...), build_summary(...), and print_scouting_card(...).

Constraints:
- Keep my existing output working.
- Make minimal code changes.
- Keep code beginner-friendly.

Output format:
1) Short plan (3 bullets)
2) Exact code blocks to add/change
3) Where to paste each block
4) Expected output example for one player

Bonus 2: Add a Pocket Presence Section

Try this prompt:

You are my Python tutor and coding assistant.

Goal:
Add a "Pocket Presence" section with sack rate and pressure notes.

Context:
I am using data/players.csv in scouting_report.py.
Include any CSV header updates.

Constraints:
- Keep the same project structure.
- Do not rewrite the full file.
- Explain changes in simple language.

Output format:
1) Updated CSV header + sample row
2) Code changes only
3) Where to paste changes
4) One test run to verify output

Bonus 3: Export Reports to a File

Try this prompt:

You are my Python tutor and coding assistant.

Goal:
Write all scouting cards to scouting_reports.txt.

Context:
I already loop through players and print each card in scouting_report.py.

Constraints:
- Keep terminal output and save to file.
- Use simple Python only.

Output format:
1) Minimal code changes
2) Where each change goes
3) Expected first 8 lines of scouting_reports.txt
4) One troubleshooting tip if file is empty