paper-dynasty-card-creation/pd_cards/commands/scouting.py
Cal Corum 5b75a3d38f Implement CLI wrappers for live-series, retrosheet, scouting, upload
Migrated all major card creation workflows to pd-cards CLI:

live-series:
- update: Full FanGraphs/BBRef card generation with CLI options
- status: Show cardset status from database

retrosheet:
- process: Historical Retrosheet data processing
- arms: Generate outfield arm ratings from play-by-play
- validate: Check for position anomalies in cardsets
- defense: Fetch defensive stats from Baseball Reference

scouting:
- batters: Generate batting scouting reports
- pitchers: Generate pitching scouting reports
- all: Generate all reports at once

upload:
- s3: Upload card images to AWS S3
- check: Validate cards without uploading
- refresh: Re-generate and re-upload card images

Updated CLAUDE.md with comprehensive CLI documentation.
Legacy scripts remain available but CLI is now the primary interface.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 16:39:38 -06:00

216 lines
6.9 KiB
Python

"""
Scouting report generation commands.
Commands for generating scouting reports and ratings comparisons.
"""
import asyncio
from pathlib import Path
from typing import Optional, List
import typer
from rich.console import Console
app = typer.Typer(no_args_is_help=True)
console = Console()
@app.command()
def batters(
cardset_ids: Optional[List[int]] = typer.Option(None, "--cardset-id", "-c", help="Cardset ID(s) to include (can specify multiple)"),
output_dir: Path = typer.Option(Path("scouting"), "--output", "-o", help="Output directory"),
):
"""
Generate batting scouting reports.
Creates CSV files with batting ratings and comparisons.
Example:
pd-cards scouting batters --cardset-id 27 --cardset-id 29
"""
console.print()
console.print("=" * 70)
console.print("[bold]BATTING SCOUTING REPORT[/bold]")
console.print("=" * 70)
if cardset_ids:
console.print(f"Cardset IDs: {cardset_ids}")
else:
console.print("Cardset IDs: All")
console.print(f"Output: {output_dir}")
console.print()
try:
import sys
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
import scouting_batters as sb
import copy
async def run_scouting():
# Ensure output directory exists
output_dir.mkdir(parents=True, exist_ok=True)
console.print("Pulling scouting data...")
batting_dfs = await sb.get_scouting_dfs(cardset_ids or [])
console.print(f" Received {len(batting_dfs)} rows")
console.print("Generating basic scouting report...")
await sb.post_calc_basic(copy.deepcopy(batting_dfs))
console.print(f" [green]✓ Saved to {output_dir}/batting-basic.csv[/green]")
console.print("Generating ratings guide...")
await sb.post_calc_ratings(copy.deepcopy(batting_dfs))
console.print(f" [green]✓ Saved to {output_dir}/batting-ratings.csv[/green]")
console.print()
console.print("[green]✓ Batting scouting complete[/green]")
asyncio.run(run_scouting())
except ImportError as e:
console.print(f"[red]Error importing modules: {e}[/red]")
raise typer.Exit(1)
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
import traceback
traceback.print_exc()
raise typer.Exit(1)
@app.command()
def pitchers(
cardset_ids: Optional[List[int]] = typer.Option(None, "--cardset-id", "-c", help="Cardset ID(s) to include (can specify multiple)"),
output_dir: Path = typer.Option(Path("scouting"), "--output", "-o", help="Output directory"),
):
"""
Generate pitching scouting reports.
Creates CSV files with pitching ratings and comparisons.
Example:
pd-cards scouting pitchers --cardset-id 27 --cardset-id 29
"""
console.print()
console.print("=" * 70)
console.print("[bold]PITCHING SCOUTING REPORT[/bold]")
console.print("=" * 70)
if cardset_ids:
console.print(f"Cardset IDs: {cardset_ids}")
else:
console.print("Cardset IDs: All")
console.print(f"Output: {output_dir}")
console.print()
try:
import sys
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
import scouting_pitchers as sp
import copy
async def run_scouting():
# Ensure output directory exists
output_dir.mkdir(parents=True, exist_ok=True)
console.print("Pulling scouting data...")
pitching_dfs = await sp.get_scouting_dfs(cardset_ids or [])
console.print(f" Received {len(pitching_dfs)} rows")
console.print("Generating basic scouting report...")
await sp.post_calc_basic(copy.deepcopy(pitching_dfs))
console.print(f" [green]✓ Saved to {output_dir}/pitching-basic.csv[/green]")
console.print("Generating ratings guide...")
await sp.post_calc_ratings(copy.deepcopy(pitching_dfs))
console.print(f" [green]✓ Saved to {output_dir}/pitching-ratings.csv[/green]")
console.print()
console.print("[green]✓ Pitching scouting complete[/green]")
asyncio.run(run_scouting())
except ImportError as e:
console.print(f"[red]Error importing modules: {e}[/red]")
raise typer.Exit(1)
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
import traceback
traceback.print_exc()
raise typer.Exit(1)
@app.command()
def all(
cardset_ids: Optional[List[int]] = typer.Option(None, "--cardset-id", "-c", help="Cardset ID(s) to include"),
output_dir: Path = typer.Option(Path("scouting"), "--output", "-o", help="Output directory"),
):
"""
Generate all scouting reports (batters and pitchers).
Example:
pd-cards scouting all --cardset-id 27
"""
console.print()
console.print("=" * 70)
console.print("[bold]FULL SCOUTING REPORT[/bold]")
console.print("=" * 70)
console.print()
# Run batters
console.print("[bold]Phase 1: Batters[/bold]")
try:
import sys
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
import scouting_batters as sb
import scouting_pitchers as sp
import copy
async def run_all_scouting():
output_dir.mkdir(parents=True, exist_ok=True)
# Batters
console.print("Pulling batting data...")
batting_dfs = await sb.get_scouting_dfs(cardset_ids or [])
console.print(f" Received {len(batting_dfs)} batter rows")
await sb.post_calc_basic(copy.deepcopy(batting_dfs))
console.print(f" [green]✓ batting-basic.csv[/green]")
await sb.post_calc_ratings(copy.deepcopy(batting_dfs))
console.print(f" [green]✓ batting-ratings.csv[/green]")
console.print()
console.print("[bold]Phase 2: Pitchers[/bold]")
# Pitchers
console.print("Pulling pitching data...")
pitching_dfs = await sp.get_scouting_dfs(cardset_ids or [])
console.print(f" Received {len(pitching_dfs)} pitcher rows")
await sp.post_calc_basic(copy.deepcopy(pitching_dfs))
console.print(f" [green]✓ pitching-basic.csv[/green]")
await sp.post_calc_ratings(copy.deepcopy(pitching_dfs))
console.print(f" [green]✓ pitching-ratings.csv[/green]")
console.print()
console.print("=" * 70)
console.print("[bold green]✓ ALL SCOUTING REPORTS COMPLETE[/bold green]")
console.print("=" * 70)
asyncio.run(run_all_scouting())
except ImportError as e:
console.print(f"[red]Error importing modules: {e}[/red]")
raise typer.Exit(1)
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
import traceback
traceback.print_exc()
raise typer.Exit(1)