| --- |
| title: Scouting · Racing Santander |
| emoji: ⚽ |
| colorFrom: blue |
| colorTo: indigo |
| sdk: docker |
| app_port: 7860 |
| pinned: true |
| --- |
| |
| # Scouting · Racing Santander |
|
|
| FastAPI + DuckDB scouting dashboard. Reuses the visual design of the static |
| HTML report but loads data from a Hugging Face Dataset and recomputes scoring |
| on the server. |
|
|
| ## Required Space secrets |
|
|
| Set these in **Settings → Repository secrets** of the Space: |
|
|
| | Secret | Required | Purpose | |
| |---|---|---| |
| | `APP_PASSWORD` | yes | Shared password for the login gate | |
| | `SESSION_SECRET` | yes | Random string used to sign auth cookies | |
| | `DATASET_REPO_ID` | yes | HF dataset repo id, e.g. `racing-tools/scouting-data` | |
| | `HF_TOKEN` | yes if dataset is private | Read-scope token for the dataset repo | |
| | `DATA_MAX_AGE_HOURS` | no | Cache TTL before re-pulling the dataset (default 24) | |
|
|
| ## Local development |
|
|
| ```bash |
| cd scouting |
| # 1. produce parquets locally (one-time / on refresh) |
| python ingest_azure.py |
| python build_player_season.py |
| python enrich_attrs.py |
| python enrich_tm.py --skip-extra --limit 100 |
| |
| # 2. point app to the local data dir and run |
| export DATA_DIR=$(pwd)/data/clean |
| cd app && uvicorn main:app --reload --port 7860 |
| ``` |
|
|
| Open http://localhost:7860/ — no `APP_PASSWORD` set means dev-mode (any |
| password is accepted on the login form, or skip if env unset). |
|
|
| ## Refreshing data without a Docker rebuild |
|
|
| ```bash |
| HF_TOKEN=hf_xxx python scripts/push_to_hf_dataset.py |
| ``` |
|
|
| Then restart the Space (Settings → Factory rebuild) — the next boot pulls the |
| new parquets via `huggingface_hub.snapshot_download`. |
|
|
| ## Architecture |
|
|
| - `app/main.py` — FastAPI app, mounts static, registers routes |
| - `app/data.py` — DuckDB on parquet, registers `base` view joining player_season + tm_enrichment |
| - `app/scoring.py` — wraps `scouting_score.py` for in-memory scoring with custom weights |
| - `app/auth.py` — signed-cookie shared-password gate |
| - `app/routes/` — meta / score / player / best11 endpoints |
| - `app/static/` — extracted HTML, CSS, JS from `generate_report.py` with `fetch()` calls |
|
|
| ## API quick reference |
|
|
| - `GET /api/meta` — seasons, leagues, positions, blocks |
| - `POST /api/score` — filtered + scored player-season rows |
| - `GET /api/player/{playerId}?season=24-25` — full detail |
| - `POST /api/best11` — top-1 per pitch slot |
| - `POST /api/login` — set auth cookie |
| - `GET /api/auth-status` — whether the current session is authenticated |
| - `GET /healthz` — bypasses auth, returns row counts |
|
|