Introduction
NBA scouts do not just list stats. They turn numbers into a clear story about a player's role, strengths, and next steps.
In this project, you will build a Python program that turns basketball 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 basketball stats into analysis language
- Load player data from CSV and generate multiple reports
Why this matters
This is exactly how real analytics workflows scale: one code template plus many rows of data.
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:
.pymeans Python code..csvmeans table-style data.
- Pick an easy location for your project folder:
- Mac:
Desktopin Finder - Windows:
Desktopin File Explorer - Chromebook:
My filesin the Files app
- Mac:
- Create a folder called
basketball-scouting-report. - In Cursor, go to
File > Open Folderand openbasketball-scouting-report. - 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 createplayers.csv
- click New Folder and create
- If you do not see file extensions on your computer, that is okay. Type the full names exactly, including
.pyand.csv.
Writing the code
Type this into scouting_report.py:
player_name = "Jalen Carter"
team_name = "Greenville Comets"
primary_stat_name = "Points per game"
primary_stat_value = 24.6
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 combining text and numbers into a readable 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: Jalen Carter (Greenville Comets)
Top stat: Points per game - 24.6
If your output matches, your project setup is working.
Part 2: Project Milestones
Milestone 1: Build a reusable report function
A function is a reusable recipe. Instead of rewriting print lines for every player, we write the recipe once and call it many times.
Add this below your existing code:
def build_report(player_name, team_name, position, ppg, apg, rpg):
report = (
f"=== Scouting Report ===\n"
f"Player: {player_name}\n"
f"Team: {team_name}\n"
f"Position: {position}\n"
f"PPG: {ppg}\n"
f"APG: {apg}\n"
f"RPG: {rpg}\n"
)
return report
print(build_report("Jalen Carter", "Greenville Comets", "SG", 24.6, 6.2, 5.1))
Expected output:
=== Scouting Report ===
Player: Jalen Carter
Team: Greenville Comets
Position: SG
PPG: 24.6
APG: 6.2
RPG: 5.1
Milestone 2: Add strengths and growth areas
Now we add decision logic with if, elif, and else.
This lets your program turn raw numbers into coaching language.
Add this below Milestone 1 code:
def scoring_label(ppg):
if ppg >= 25:
return "Strength: Elite scoring volume."
if ppg >= 18:
return "Strength: Reliable scoring pressure."
return "Growth Area: Increase scoring consistency."
def playmaking_label(apg):
if apg >= 7:
return "Strength: High-level playmaker."
if apg >= 4:
return "Strength: Solid secondary creator."
return "Growth Area: Improve passing reads."
print(scoring_label(24.6))
print(playmaking_label(6.2))
Expected output:
Strength: Reliable scoring pressure.
Strength: Solid secondary creator.
Try changing the numbers in print(scoring_label(...)) to see how labels change.
Milestone 3: Create a full scouting summary paragraph
Now build one polished paragraph that sounds like an analyst note.
Add this below your current code:
def build_summary(player_name, position, trend_note, strength_line, growth_line):
return (
f"{player_name} projects as a {position} who can impact both scoring and shot creation. "
f"{strength_line} {growth_line} "
f"Recent trend: {trend_note}."
)
summary = build_summary(
"Jalen Carter",
"two-way guard",
"scored 20+ in four of the last five games",
"Creates rim pressure and draws help defenders.",
"Can reduce live-ball turnovers against traps."
)
print(summary)
Expected output:
Jalen Carter projects as a two-way guard who can impact both scoring and shot creation. Creates rim pressure and draws help defenders. Can reduce live-ball turnovers against traps. Recent trend: scored 20+ in four of the last five games.
Milestone 4: Load player reports from CSV data
Now you will separate data from code by using data/players.csv.
This is how analysts scale from one player to many players.
- Open
data/players.csv. - Paste the data below.
- Save the file.
- Make sure the file name is exactly
players.csv(notplayers.csv.txt).
Paste this into data/players.csv:
name,team,position,ppg,apg,rpg,three_pt_pct,trend_note
Jalen Carter,Greenville Comets,SG,24.6,6.2,5.1,38.5,20+ points in 4 of last 5 games
Maya Brooks,Greenville Comets,PF,18.4,3.1,10.8,33.2,3 straight double-doubles
Noah Ellis,Greenville Comets,PG,15.9,8.4,4.3,36.1,assist rate up in last 6 games
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"],
"ppg": float(row["ppg"]),
"apg": float(row["apg"]),
"rpg": float(row["rpg"]),
"three_pt_pct": float(row["three_pt_pct"]),
"trend_note": row["trend_note"]
})
print(players)
Click Run Python File again.
Expected output (shortened example):
[{'name': 'Jalen Carter', 'team': 'Greenville Comets', ...}, {'name': 'Maya Brooks', ...}, ...]
If you see a list of dictionaries, your CSV load worked.
Milestone 5: Print final scouting cards for each player
Now connect everything:
- your report template
- your label rules
- your summary paragraph
- your CSV player list
Add this below Milestone 4:
def print_scouting_card(player):
strength = scoring_label(player["ppg"])
growth = playmaking_label(player["apg"])
summary = build_summary(
player["name"],
player["position"],
player["trend_note"],
strength,
growth
)
print("=" * 46)
print(f"SCOUTING CARD: {player['name']}")
print("=" * 46)
print(build_report(
player["name"],
player["team"],
player["position"],
player["ppg"],
player["apg"],
player["rpg"]
))
print(summary)
print("=" * 46)
for player in players:
print_scouting_card(player)
Expected result:
- You should see a scouting card for each player in your CSV.
- Each card should include profile lines plus a summary paragraph.
If you made it this far, you built an automated basketball scouting report generator from scratch.
Common Fixes
FileNotFoundError: confirm the path is exactlydata/players.csv.ValueError: check the CSV has only numbers inppg,apg, andrpg.- 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:
- Goal: what you want to build
- Context: file name + what code already exists
- Constraints: keep beginner-friendly, minimal changes
- 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 PPG, APG, and RPG in my scouting cards.
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 the smallest set of changes.
- Keep the code beginner-friendly.
Output format:
1) Short plan (3 bullets)
2) Exact code blocks to add/change
3) Exactly where to paste each block
4) Expected output example for one player
Bonus 2: Add a Shot Profile Section
Try this prompt:
You are my Python tutor and coding assistant.
Goal:
Add a "Shot Profile" section with 3PT% and FT% notes to each scouting card.
Context:
I am using data/players.csv in scouting_report.py.
Please include any CSV header changes I need.
Constraints:
- Keep the same project structure.
- Do not rewrite my whole file.
- Explain changes in simple language.
Output format:
1) Updated CSV header + sample rows
2) Code changes only
3) Where to paste changes
4) One quick test run to verify it works
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 also save to file.
- Use simple Python only.
- Keep code readable for beginners.
Output format:
1) Minimal code changes
2) Where each change goes
3) Expected contents of scouting_reports.txt (first 10 lines)
4) One troubleshooting tip if file is empty