Ir al contenido

Pesos del Risk Advisor

/dashboard/riesgo/pesos analiza qué indicador estaba en rojo en los 14 días previos a cada lesión registrada de la org, y sugiere subir o bajar el peso de cada indicador para futuras versiones del score. La página es solo informativa hoy — el ajuste automático de pesos se aplicará en una iteración futura. Gated a pro / enterprise.

  • Problema: los pesos del Risk Advisor son el mismo set para todo el mundo (Williams 2017 + Drew/Finch 2016). Pero la morfología de lesiones varía por edad media, intensidad de competición y posición. Hay que poder calibrar por club.
  • Casos de uso: revisión trimestral del HoP para decidir si la sensibilidad del score es la correcta para su plantel.
  • Planes: solo pro y enterprise. esencial ve banner “ver planes” + link a /upgrade.
  • Ruta /dashboard/riesgo/pesos. Plan check en el render (profile.plan in {pro, enterprise}) — si no, banner y redirect a /upgrade.
  • Stat strip top — 3 KPIs: nº lesiones analizadas, nº snapshots pre-lesión cruzados, ventana de análisis (14 días).
  • Banner de muestra insuficiente — si hay < 10 lesiones registradas, banner amarillo “las sugerencias son orientativas”.
  • Tabla principal — fila por indicador (hoy 4: ACWR distancia, ACWR HSR, Hooper, dolor), columnas:
    • Frec. rojo pre-lesión — % de snapshots en los 14 días previos donde ese indicador estaba en rojo, con (redCount/totalCount).
    • Peso actual — el que aplica hoy en calcRisk().
    • Peso sugerido — heurística: redFreq > 60% → +25% (cap 0.35), redFreq < 20% → −25% (floor 0.02), sino sin cambio.
    • Acción — badge ”↑ Subir peso” / ”↓ Bajar peso” / “Sin cambio” / “Sin datos”.
  • Los pesos actuales viven hardcodeados en app/dashboard/riesgo/_components/risk-calculator.ts (función calcRisk). No hay UI hoy para aplicar los sugeridos — el workflow es: leer la página, abrir un issue en CÉNIT, revisar en PR el cambio del peso.
  • Los thresholds (que definen cuándo un indicador es rojo) sí son configurables por org en Settings → Riesgos.
  • “Sin datos” en un indicador: ningún snapshot en la ventana pre-lesión tenía valor para ese indicador. Suele pasar con Vmax% (gate <5 sesiones) o con orgs nuevas sin GPS aún.
  • ¿Por qué solo 4 indicadores? Los otros 6 del score (Vmax%, ACWR sprint, ACWR HMLD, lesiones 6m, no apto médico, fisio, ansiedad) son booleanos o muy correlacionados con los primeros — el análisis de calibración no aporta nuevo en esos hoy. Se puede ampliar después de una iteración.

Player surface: N/A. Staff-only y gated a pro/enterprise.

Por cada injury con injury_date no nulo de la org (max 500 recientes):

  1. Traer todos los risk_snapshots de ese player_id.
  2. Filtrar los snapshots con fecha en [injury_date - 14d, injury_date).
  3. Acumular redCount por indicador (level === ‘red’) y totalCount (level no nulo).
  4. redFreq = redCount / totalCount.
suggestWeight(current, redFreq):
if redFreq > 0.60: return min(current * 1.25, 0.35)
if redFreq < 0.20: return max(current * 0.75, 0.02)
return current

Cap superior 0.35 e inferior 0.02 para evitar pesos extremos incluso con muestras chicas.

  • injuries — filtradas por organization_id.
  • risk_snapshots — joined en memoria (Supabase no soporta correlated subqueries con in() eficientemente).
  • Risk Advisor principal — los pesos sugeridos refieren a calcRisk(). Un PR futuro habilitará una columna organizations.risk_weights JSONB para overrides por org.
  • No aplica los pesos sugeridos automáticamente — es solo observabilidad. Aplicar implica decisión humana hasta que haya validación A/B.
  • Muestra mínima recomendada 10 lesiones; debajo de eso el banner avisa que es orientativo.
  • Solo analiza 4 indicadores; el resto se evalúa cualitativamente.