Spaces:
Running
Running
Commit ·
77bf160
1
Parent(s): ffe78f2
Fix arranque en HF: import de goalkicks opcional (feature WIP no commiteada) + re-aplicar p=2 y plegables
Browse filesEl deploy fallaba (ModuleNotFoundError: routes_goalkicks) porque app.py importaba la
feature de goalkicks (en desarrollo local, sin commitear). Ahora el import es opcional.
Se re-aplican similitud p=2 y los plegables de perfil/similares.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
src/racing_reports/team_vars.py
CHANGED
|
@@ -289,8 +289,8 @@ def similar_teams(league: str, season: str, team: str, variables: list[str],
|
|
| 289 |
dist = dist[~is_self.values]
|
| 290 |
order = dist.sort_values().head(top).index
|
| 291 |
# Similitud 0-100% calibrada: d̄ = distancia promedio entre TODOS los pares del pool
|
| 292 |
-
# (referencia del 50%). sim = 100·2^(-d/d̄)
|
| 293 |
-
# 100% en d=0;
|
| 294 |
from scipy.spatial.distance import pdist
|
| 295 |
Z = zmat.to_numpy()
|
| 296 |
if len(Z) > 1500: # cota para pools enormes (scope "todas")
|
|
@@ -299,7 +299,7 @@ def similar_teams(league: str, season: str, team: str, variables: list[str],
|
|
| 299 |
dbar = float(pdist(Z).mean()) if len(Z) > 1 else 0.0
|
| 300 |
|
| 301 |
def _sim(d):
|
| 302 |
-
return round(100.0 * (2.0 ** (-float(d) / dbar)), 1) if dbar > 1e-9 else (100.0 if d < 1e-9 else 0.0)
|
| 303 |
|
| 304 |
teams = [{
|
| 305 |
"equipo": str(pool.loc[i, "equipo"]),
|
|
|
|
| 289 |
dist = dist[~is_self.values]
|
| 290 |
order = dist.sort_values().head(top).index
|
| 291 |
# Similitud 0-100% calibrada: d̄ = distancia promedio entre TODOS los pares del pool
|
| 292 |
+
# (referencia del 50%). sim = 100·2^(-(d/d̄)²) (p=2: aplana cerca de 0, cae fuerte lejos).
|
| 293 |
+
# 100% en d=0; 95.8% en 0.25·d̄; 84.1% en 0.5·d̄; 50% en d̄; 6.25% en 2·d̄.
|
| 294 |
from scipy.spatial.distance import pdist
|
| 295 |
Z = zmat.to_numpy()
|
| 296 |
if len(Z) > 1500: # cota para pools enormes (scope "todas")
|
|
|
|
| 299 |
dbar = float(pdist(Z).mean()) if len(Z) > 1 else 0.0
|
| 300 |
|
| 301 |
def _sim(d):
|
| 302 |
+
return round(100.0 * (2.0 ** (-(float(d) / dbar) ** 2)), 1) if dbar > 1e-9 else (100.0 if d < 1e-9 else 0.0)
|
| 303 |
|
| 304 |
teams = [{
|
| 305 |
"equipo": str(pool.loc[i, "equipo"]),
|
src/racing_reports/web/app.py
CHANGED
|
@@ -22,7 +22,10 @@ from racing_reports.api.routes_meta import router as api_meta_router
|
|
| 22 |
from racing_reports.api.routes_reports import router as api_reports_router
|
| 23 |
from racing_reports.api.routes_team_vars import router as api_team_vars_router
|
| 24 |
from racing_reports.api.routes_ejes import router as api_ejes_router
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
| 26 |
from racing_reports.api.routes_lowblock import router as api_lowblock_router
|
| 27 |
from racing_reports.config import DEFAULT_SETTINGS
|
| 28 |
from racing_reports.datastore import DataStore
|
|
@@ -51,7 +54,8 @@ app.include_router(api_reports_router)
|
|
| 51 |
app.include_router(api_jobs_router)
|
| 52 |
app.include_router(api_team_vars_router)
|
| 53 |
app.include_router(api_ejes_router)
|
| 54 |
-
|
|
|
|
| 55 |
app.include_router(api_lowblock_router)
|
| 56 |
|
| 57 |
# Estado en memoria (single container en HF Space). Re-export para retrocompat.
|
|
|
|
| 22 |
from racing_reports.api.routes_reports import router as api_reports_router
|
| 23 |
from racing_reports.api.routes_team_vars import router as api_team_vars_router
|
| 24 |
from racing_reports.api.routes_ejes import router as api_ejes_router
|
| 25 |
+
try: # feature en desarrollo (archivos pueden no estar en el deploy)
|
| 26 |
+
from racing_reports.api.routes_goalkicks import router as api_goalkicks_router
|
| 27 |
+
except Exception: # noqa: BLE001
|
| 28 |
+
api_goalkicks_router = None
|
| 29 |
from racing_reports.api.routes_lowblock import router as api_lowblock_router
|
| 30 |
from racing_reports.config import DEFAULT_SETTINGS
|
| 31 |
from racing_reports.datastore import DataStore
|
|
|
|
| 54 |
app.include_router(api_jobs_router)
|
| 55 |
app.include_router(api_team_vars_router)
|
| 56 |
app.include_router(api_ejes_router)
|
| 57 |
+
if api_goalkicks_router is not None:
|
| 58 |
+
app.include_router(api_goalkicks_router)
|
| 59 |
app.include_router(api_lowblock_router)
|
| 60 |
|
| 61 |
# Estado en memoria (single container en HF Space). Re-export para retrocompat.
|
src/racing_reports/web/templates/home.html
CHANGED
|
@@ -441,9 +441,12 @@
|
|
| 441 |
<p class="text-xs text-red-300 mt-2" x-show="tvpError" x-text="tvpError"></p>
|
| 442 |
|
| 443 |
<!-- gráfico de z-scores (barras centradas en 0, banda ±1 sombreada) -->
|
| 444 |
-
<div x-show="tvpResult && tvpResult.items && tvpResult.items.length" class="mt-5">
|
| 445 |
-
<div class="text-sm font-medium mb-1
|
|
|
|
|
|
|
| 446 |
<span class="text-xs text-gray-400" x-text="'('+tvpResult?.competencia+' · '+tvpResult?.temporada+') · vs '+tvpResult?.scope+' · '+tvpResult?.pool_size+' equipos'"></span></div>
|
|
|
|
| 447 |
<div class="space-y-1.5">
|
| 448 |
<template x-for="it in (tvpResult?.items || [])" :key="it.variable">
|
| 449 |
<div class="flex items-center gap-2 text-xs">
|
|
@@ -489,6 +492,7 @@
|
|
| 489 |
<img :src="tvpResult?.radar_b64 ? 'data:image/png;base64,'+tvpResult.radar_b64 : ''" alt="Radar" class="rounded-lg max-w-md w-full"/>
|
| 490 |
</div>
|
| 491 |
<p x-show="tvpResult && tvpResult.items && tvpResult.items.length && !tvpResult.radar_b64" class="text-xs text-gray-500 mt-2">El radar necesita al menos 3 variables.</p>
|
|
|
|
| 492 |
</div>
|
| 493 |
</section>
|
| 494 |
|
|
@@ -530,9 +534,11 @@
|
|
| 530 |
</div>
|
| 531 |
<p class="text-xs text-gray-500 mt-1" x-show="tvsPool.length">Con pool armado, "Buscar en" queda ignorado: los similares se buscan en esas ligas-temporadas.</p>
|
| 532 |
<p class="text-xs text-red-300 mt-2" x-show="tvsError" x-text="tvsError"></p>
|
| 533 |
-
<div x-show="tvsResult && tvsResult.teams" class="mt-3">
|
| 534 |
-
<div class="text-xs text-gray-400 mb-1
|
| 535 |
-
|
|
|
|
|
|
|
| 536 |
<thead><tr class="text-gray-400 text-left"><th class="py-1">#</th><th>Equipo</th><th>Liga</th><th>Temp.</th><th class="text-right">Similitud</th></tr></thead>
|
| 537 |
<tbody>
|
| 538 |
<template x-for="(t, i) in (tvsResult?.teams || [])" :key="t.competencia+t.temporada+t.equipo">
|
|
|
|
| 441 |
<p class="text-xs text-red-300 mt-2" x-show="tvpError" x-text="tvpError"></p>
|
| 442 |
|
| 443 |
<!-- gráfico de z-scores (barras centradas en 0, banda ±1 sombreada) -->
|
| 444 |
+
<div x-show="tvpResult && tvpResult.items && tvpResult.items.length" class="mt-5" x-data="{ pOpen: true }">
|
| 445 |
+
<div class="text-sm font-medium mb-1 cursor-pointer select-none flex items-center gap-2" @click="pOpen=!pOpen">
|
| 446 |
+
<span class="text-xs transition-transform" :class="pOpen ? 'rotate-90' : ''">▶</span>
|
| 447 |
+
<span x-text="tvpResult?.equipo"></span>
|
| 448 |
<span class="text-xs text-gray-400" x-text="'('+tvpResult?.competencia+' · '+tvpResult?.temporada+') · vs '+tvpResult?.scope+' · '+tvpResult?.pool_size+' equipos'"></span></div>
|
| 449 |
+
<div x-show="pOpen">
|
| 450 |
<div class="space-y-1.5">
|
| 451 |
<template x-for="it in (tvpResult?.items || [])" :key="it.variable">
|
| 452 |
<div class="flex items-center gap-2 text-xs">
|
|
|
|
| 492 |
<img :src="tvpResult?.radar_b64 ? 'data:image/png;base64,'+tvpResult.radar_b64 : ''" alt="Radar" class="rounded-lg max-w-md w-full"/>
|
| 493 |
</div>
|
| 494 |
<p x-show="tvpResult && tvpResult.items && tvpResult.items.length && !tvpResult.radar_b64" class="text-xs text-gray-500 mt-2">El radar necesita al menos 3 variables.</p>
|
| 495 |
+
</div>
|
| 496 |
</div>
|
| 497 |
</section>
|
| 498 |
|
|
|
|
| 534 |
</div>
|
| 535 |
<p class="text-xs text-gray-500 mt-1" x-show="tvsPool.length">Con pool armado, "Buscar en" queda ignorado: los similares se buscan en esas ligas-temporadas.</p>
|
| 536 |
<p class="text-xs text-red-300 mt-2" x-show="tvsError" x-text="tvsError"></p>
|
| 537 |
+
<div x-show="tvsResult && tvsResult.teams" class="mt-3" x-data="{ sOpen: true }">
|
| 538 |
+
<div class="text-xs text-gray-400 mb-1 cursor-pointer select-none flex items-center gap-2" @click="sOpen=!sOpen">
|
| 539 |
+
<span class="transition-transform" :class="sOpen ? 'rotate-90' : ''">▶</span>
|
| 540 |
+
Más parecidos a <span class="text-gray-200" x-text="tvsResult?.equipo"></span> · vs <span x-text="tvsResult?.scope"></span> (<span x-text="tvsResult?.pool_size"></span> equipos)</div>
|
| 541 |
+
<table class="w-full text-xs" x-show="sOpen">
|
| 542 |
<thead><tr class="text-gray-400 text-left"><th class="py-1">#</th><th>Equipo</th><th>Liga</th><th>Temp.</th><th class="text-right">Similitud</th></tr></thead>
|
| 543 |
<tbody>
|
| 544 |
<template x-for="(t, i) in (tvsResult?.teams || [])" :key="t.competencia+t.temporada+t.equipo">
|