65f5b66b05
- src/export/warehouse.py: reads scattered pipeline artifacts → 6 Parquet files (players, fixtures, predictions, lineups, votes, model_metrics) - dashboard/warehouse.py: read-only cached Parquet loader - .streamlit/config.toml: dark theme base, server config - dashboard/viz/template.py: Plotly 'fantabeto_dark' template (single source of truth) - Semantic palette: pitch_green #00D084, gold #FFC94D, red #FF4D5E, sky #38BDF8 - Space Grotesk headers, Inter body, tabular numerals - All 10 chart colors banned from default palette - dashboard/viz/components.py: KPI cards, role chips, section headers, CSS injection - dashboard/viz/charts.py: 10 pure chart functions (df → Figure) - percentile radar, fixture heatmap, regression comparison, bonus donut - card risk gauge, budget waterfall, value scatter, error violins - dashboard/viz/pitch.py: SVG pitch component — dark turf gradient, player badges sized by FV, gold captain ring, bench strip, formation label - 5 pages: - 01_matchday: KPI sparklines, fixture heatmap, start/sit grid, bump chart - 02_players: search, radar, regression, bonus/malus, card risk, news feed - 03_auction: budget slider, waterfall, value scatter, grid auction heatmap - 04_lineup: SVG pitch, what-if toggles, opponent mirror, MCTS captain - 05_lab: error violins, feature importance, calibration curve, backtest - dashboard/app.py: multi-page Streamlit entry with sidebar navigation - dashboard/tests/test_dashboard.py: 18 unit tests (warehouse, template, charts, pitch) - DASHBOARD.md: full architecture docs, design system reference - 49 total tests passing (31 existing + 18 dashboard)
138 lines
5.4 KiB
Markdown
138 lines
5.4 KiB
Markdown
# Fantabeto Dashboard
|
||
|
||
**Project Al-Cihred** — Production-grade Streamlit dashboard for the 2026/27 Fantacalcio season.
|
||
|
||
```bash
|
||
streamlit run dashboard/app.py
|
||
```
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
```
|
||
data/warehouse/ ← Versioned Parquet (read by dashboard)
|
||
players.parquet 505 rows — roster + 25/26 stats + per-90 metrics
|
||
fixtures.parquet 10 rows — matchday 1 home/away + formations
|
||
predictions.parquet 505 rows — FV projections with std + starter prob
|
||
lineups.parquet 466 rows — probable lineups with starter %
|
||
votes.parquet 12,049 rows — historical per-matchday votes (25/26)
|
||
model_metrics.parquet 1 row — RMSE, R², sample count
|
||
|
||
dashboard/
|
||
app.py ← Entry point: multi-page routing via sidebar
|
||
warehouse.py ← Read-only Parquet loader (@st.cache_data)
|
||
viz/
|
||
template.py ← Plotly template "fantabeto_dark" + color palette
|
||
charts.py ← Pure functions: df → Figure (heatmap, radar, etc.)
|
||
pitch.py ← SVG pitch component with player badges
|
||
components.py ← KPI cards, role chips, section headers, CSS
|
||
pages/
|
||
01_matchday.py ← Control Room: KPIs, fixture heatmap, start/sit
|
||
02_players.py ← Intelligence: radar, regression, card risk, news
|
||
03_auction.py ← War Room: waterfall, value scatter, grid heatmap
|
||
04_lineup.py ← Optimizer: SVG pitch, what-if toggles, opponent
|
||
05_lab.py ← Model Lab: error violins, calibration, backtest
|
||
tests/
|
||
test_dashboard.py 18 unit tests (warehouse, template, charts, pitch)
|
||
|
||
src/export/warehouse.py ← Exporter: reads pipeline artifacts → Parquet
|
||
.streamlit/config.toml ← Dark theme base, server config
|
||
```
|
||
|
||
---
|
||
|
||
## Design System — Stadium Night
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Background | `#0B0F17` |
|
||
| Card bg | `#111827` at 70% opacity, 14px radius, blur 8px |
|
||
| Border | `#1F2937` |
|
||
| Pitch Green | `#00D084` — positive, bonus |
|
||
| Gold | `#FFC94D` — captain, highlight |
|
||
| Red | `#FF4D5E` — malus, risk |
|
||
| Sky | `#38BDF8` — neutral data |
|
||
| Violet | `#A78BFA` — uncertainty |
|
||
| Type | Space Grotesk (headers), Inter (body), tabular numerals |
|
||
| Charts | All use `fantabeto_dark` template. No default Plotly palette anywhere. |
|
||
|
||
---
|
||
|
||
## Pages
|
||
|
||
### 1. Matchday Control Room
|
||
- **KPI row**: projected points, players at risk (P(start) < 70%), matchday count, FV trend sparkline
|
||
- **Fixture difficulty heatmap**: teams × gameweeks, colored by opponent xGA/FV strength
|
||
- **Start/Sit grid**: top 20 players with role chips, H/A indicator, projected FV ± std, risk status (🟢 START / 🟡 DOUBT / 🔴 RISK)
|
||
- **Bump chart**: projected rank trajectory across first 10 GWs
|
||
|
||
### 2. Player Intelligence
|
||
- **Search**: autocomplete on all 505 players, filtered by role/team
|
||
- **Player header**: FV avg, games played, GW1 start %, role chip, FVM, QI
|
||
- **Percentile radar**: 7 metrics normalized vs role average (goals, assists, xG, prog passes, tackles, interceptions, SoT%)
|
||
- **Goals vs Expected**: bar chart with divergence annotation
|
||
- **Bonus/malus donut**: goal bonus + assist bonus − card malus breakdown
|
||
- **Card risk gauge**: yellow/red card per-game risk indicators
|
||
- **News feed**: placeholder for RAG pipeline output (injuries, suspensions, tactical shifts)
|
||
- **Historical votes**: last 10 matchday votes table
|
||
|
||
### 3. Auction War Room
|
||
- **Budget controls**: sliders for budget (300–700 cr) and role quotas
|
||
- **KPI row**: players drafted, total spent, projected FV, avg price per player
|
||
- **Budget waterfall**: Sankey-style allocation per role (GK/DEF/MID/FWD)
|
||
- **Value scatter**: FV avg vs QI, bubble size = games played, top steals labeled, cost-per-FV isolines
|
||
- **Grid auction heatmap**: top players × bid multipliers, colored by value surplus
|
||
- **Recommended squad**: per-role player list with max bid, FV, and games played
|
||
|
||
### 4. Lineup Optimizer
|
||
- **What-if controls**: force IN/OUT a player, select formation (4-4-2, 4-3-3, 3-5-2, etc.)
|
||
- **KPI row**: expected points (with captain), captain name, avg start %, win probability
|
||
- **SVG pitch**: dark turf gradient, player badges sized by FV, gold captain ring, risk markers, bench strip, formation label
|
||
- **Player list**: role-chipped players with FV and risk flags
|
||
- **Opponent mirror**: per-duel edge arrows (🟢 advantage / 🔴 disadvantage / ⚪ neutral)
|
||
|
||
### 5. Model Lab
|
||
- **KPI row**: RMSE, R², training samples, feature count
|
||
- **Error violins**: prediction error distribution by role
|
||
- **Feature importance**: Pearson correlation with FV avg
|
||
- **Calibration curve**: predicted vs observed uncertainty
|
||
- **Backtest**: league average FV across 38 matchdays
|
||
- **Architecture notes**: model overview, key insights, limitations
|
||
|
||
---
|
||
|
||
## Running
|
||
|
||
```bash
|
||
# First time: export warehouse
|
||
python -m src.export.warehouse
|
||
|
||
# Install (if not already)
|
||
pip install streamlit
|
||
|
||
# Launch dashboard
|
||
streamlit run dashboard/app.py
|
||
|
||
# Run tests
|
||
python -m pytest dashboard/tests/ -v
|
||
```
|
||
|
||
## Data Refresh
|
||
|
||
The warehouse reads pre-computed Parquet files. To refresh after running the pipeline:
|
||
|
||
```bash
|
||
python -m src.export.warehouse
|
||
```
|
||
|
||
Then reload the dashboard — `@st.cache_data(ttl=3600)` will pick up new files after 1 hour or on manual cache clear.
|
||
|
||
## Dependencies
|
||
|
||
Added to `requirements.txt`:
|
||
- `streamlit>=1.35`
|
||
|
||
Already present:
|
||
- `plotly>=5.18`, `pandas>=2.1`, `numpy>=1.26`, `openpyxl>=3.1`
|