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:
parent
88acd5308b
commit
a2f4d02b18
14
CLAUDE.md
14
CLAUDE.md
@ -98,15 +98,17 @@ pd-cards retrosheet defense 2005 --output "data-input/2005 Live Cardset/"
|
|||||||
|
|
||||||
### Scouting Reports
|
### 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
|
```bash
|
||||||
# Generate batting scouting reports
|
# Generate all scouting reports (ALWAYS run without cardset filter)
|
||||||
pd-cards scouting batters --cardset-id 27
|
pd-cards scouting all
|
||||||
|
|
||||||
# Generate pitching scouting reports
|
# Upload scouting reports to database server
|
||||||
pd-cards scouting pitchers --cardset-id 27
|
pd-cards scouting upload
|
||||||
|
|
||||||
# Generate all scouting reports
|
# Full workflow after any card changes:
|
||||||
pd-cards scouting all --cardset-id 27
|
pd-cards scouting all && pd-cards scouting upload
|
||||||
```
|
```
|
||||||
|
|
||||||
### S3 Upload
|
### S3 Upload
|
||||||
|
|||||||
@ -213,3 +213,104 @@ def all(
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise typer.Exit(1)
|
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)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user