Add scouting upload CLI command

- Add `pd-cards scouting upload` command to upload scouting CSVs to database server via SCP
- Update CLAUDE.md with critical warning: scouting must always run for ALL cardsets
- Document full workflow: `pd-cards scouting all && pd-cards scouting upload`

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2026-01-12 14:17:14 -06:00
parent 88acd5308b
commit a2f4d02b18
2 changed files with 109 additions and 6 deletions

View File

@ -98,15 +98,17 @@ pd-cards retrosheet defense 2005 --output "data-input/2005 Live Cardset/"
### Scouting Reports
**CRITICAL**: Scouting reports must ALWAYS be generated for ALL cardsets (no --cardset-id filter). The scouting database is a unified view across all players, and filtering to a single cardset will overwrite the full reports with partial data.
```bash
# Generate batting scouting reports
pd-cards scouting batters --cardset-id 27
# Generate all scouting reports (ALWAYS run without cardset filter)
pd-cards scouting all
# Generate pitching scouting reports
pd-cards scouting pitchers --cardset-id 27
# Upload scouting reports to database server
pd-cards scouting upload
# Generate all scouting reports
pd-cards scouting all --cardset-id 27
# Full workflow after any card changes:
pd-cards scouting all && pd-cards scouting upload
```
### S3 Upload

View File

@ -213,3 +213,104 @@ def all(
import traceback
traceback.print_exc()
raise typer.Exit(1)
@app.command()
def upload(
input_dir: Path = typer.Option(Path("scouting"), "--input", "-i", help="Input directory with scouting CSVs"),
remote_host: str = typer.Option("sba-db", "--host", "-h", help="Remote host to upload to"),
remote_dir: str = typer.Option("/home/cal/container-data/pd-database/storage", "--remote-dir", "-r", help="Remote directory path"),
dry_run: bool = typer.Option(False, "--dry-run", "-n", help="Show what would be uploaded without uploading"),
):
"""
Upload scouting reports to remote server via SCP.
Uploads the generated CSV files to the Paper Dynasty database server.
Example:
pd-cards scouting upload
pd-cards scouting upload --dry-run
pd-cards scouting upload --host sba-db --remote-dir /path/to/storage
"""
import subprocess
console.print()
console.print("=" * 70)
console.print("[bold]SCOUTING REPORT UPLOAD[/bold]")
console.print("=" * 70)
console.print()
FILES_TO_UPLOAD = [
'batting-basic.csv',
'batting-ratings.csv',
'pitching-basic.csv',
'pitching-ratings.csv'
]
# Verify files exist
console.print("[bold]Verifying files...[/bold]")
missing_files = []
for filename in FILES_TO_UPLOAD:
filepath = input_dir / filename
if not filepath.exists():
missing_files.append(str(filepath))
else:
console.print(f" [green]✓[/green] {filepath}")
if missing_files:
console.print()
console.print(f"[red]Missing files:[/red]")
for f in missing_files:
console.print(f" [red]✗[/red] {f}")
console.print()
console.print("[yellow]Run 'pd-cards scouting all' first to generate reports.[/yellow]")
raise typer.Exit(1)
console.print()
console.print(f"[bold]Upload destination:[/bold] {remote_host}:{remote_dir}")
console.print()
if dry_run:
console.print("[yellow]DRY RUN - No files will be uploaded[/yellow]")
console.print()
for filename in FILES_TO_UPLOAD:
console.print(f" Would upload: {input_dir / filename}")
console.print()
console.print("=" * 70)
console.print("[bold yellow]✓ DRY RUN COMPLETE[/bold yellow]")
console.print("=" * 70)
return
# Upload files via SCP
console.print("[bold]Uploading files...[/bold]")
try:
local_files = [str(input_dir / f) for f in FILES_TO_UPLOAD]
scp_command = [
'scp',
*local_files,
f"{remote_host}:{remote_dir}/"
]
result = subprocess.run(
scp_command,
check=True,
capture_output=True,
text=True
)
for filename in FILES_TO_UPLOAD:
console.print(f" [green]✓[/green] {filename}")
console.print()
console.print("=" * 70)
console.print("[bold green]✓ SCOUTING UPLOAD COMPLETE[/bold green]")
console.print("=" * 70)
except subprocess.CalledProcessError as e:
console.print(f"[red]Upload failed: {e}[/red]")
if e.stderr:
console.print(f"[red]{e.stderr}[/red]")
raise typer.Exit(1)
except FileNotFoundError:
console.print("[red]Error: 'scp' command not found. Ensure SSH is installed.[/red]")
raise typer.Exit(1)