Introduction
Baseball scouts do not just list batting lines. They turn numbers into a clear story about approach, consistency, and upside.
In this project, you will build a Python program that turns baseball 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 baseball stats into analysis language
- Load player data from CSV and generate multiple reports
Why this matters
This mirrors real front-office workflows: one reporting format that can be reused across many players.
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
baseball-scouting-report. - In Cursor, go to
File > Open Folderand openbaseball-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 = "Diego Alvarez"
team_name = "Greenville Hawks"
primary_stat_name = "Batting average"
primary_stat_value = 0.311
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 baseball 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: Diego Alvarez (Greenville Hawks)
Top stat: Batting average - 0.311
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, batting_avg, obp, slg):
report = (
f"=== Scouting Report ===\n"
f"Player: {player_name}\n"
f"Team: {team_name}\n"
f"Position: {position}\n"
f"AVG: {batting_avg}\n"
f"OBP: {obp}\n"
f"SLG: {slg}\n"
)
return report
print(build_report("Diego Alvarez", "Greenville Hawks", "SS", 0.311, 0.382, 0.512))
Expected output:
=== Scouting Report ===
Player: Diego Alvarez
Team: Greenville Hawks
Position: SS
AVG: 0.311
OBP: 0.382
SLG: 0.512
Milestone 2: Add strengths and growth areas
Now add decision logic (if/elif/else) so your code can describe what the stats mean.
Add this below Milestone 1 code:
def contact_label(batting_avg):
if batting_avg >= 0.300:
return "Strength: Excellent contact consistency."
if batting_avg >= 0.260:
return "Strength: Solid hit tool."
return "Growth Area: Improve quality of contact."
def discipline_label(obp):
if obp >= 0.370:
return "Strength: Advanced plate discipline."
if obp >= 0.330:
return "Strength: Serviceable on-base profile."
return "Growth Area: Improve swing decisions."
print(contact_label(0.311))
print(discipline_label(0.382))
Expected output:
Strength: Excellent contact consistency.
Strength: Advanced plate discipline.
Try different values to see how labels update.
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(
"Diego Alvarez",
"top-of-order contact bat with gap power",
"multi-hit games in 5 of the last 8 contests",
"Stays through the middle of the field with consistent timing.",
"Can improve damage on inside fastballs."
)
print(summary)
Expected output:
Diego Alvarez projects as a top-of-order contact bat with gap power. Stays through the middle of the field with consistent timing. Can improve damage on inside fastballs. Recent trend: multi-hit games in 5 of the last 8 contests.
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 lineup.
- 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,batting_avg,obp,slg,ops,trend_note
Diego Alvarez,Greenville Hawks,SS,0.311,0.382,0.512,0.894,multi-hit games in 5 of last 8 contests
Noah Bennett,Greenville Hawks,CF,0.287,0.356,0.471,0.827,extra-base hit in 4 of last 7 contests
Eli Ramos,Greenville Hawks,3B,0.263,0.338,0.446,0.784,walk rate improved over last 10 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"],
"batting_avg": float(row["batting_avg"]),
"obp": float(row["obp"]),
"slg": float(row["slg"]),
"ops": float(row["ops"]),
"trend_note": row["trend_note"]
})
print(players)
Click Run Python File again.
Expected output (shortened example):
[{'name': 'Diego Alvarez', 'team': 'Greenville Hawks', ...}, {'name': 'Noah Bennett', ...}, ...]
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 = contact_label(player["batting_avg"])
growth = discipline_label(player["obp"])
summary = build_summary(
player["name"],
"lineup bat who can control at-bats",
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["batting_avg"],
player["obp"],
player["slg"]
))
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 baseball scouting report generator from scratch.
Common Fixes
FileNotFoundError: confirm the path is exactlydata/players.csv.ValueError: check thatbatting_avg,obp, andslgare 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:
- 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 AVG, OBP, and SLG.
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 Batted-Ball Profile Section
Try this prompt:
You are my Python tutor and coding assistant.
Goal:
Add a "Batted-Ball Profile" section with line-drive and hard-hit 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