Add annual ranking snapshots for supported metrics

This commit is contained in:
devRaGonSa
2026-06-10 12:12:51 +02:00
parent 6a27f4c2b5
commit d5dee75166
7 changed files with 492 additions and 93 deletions

View File

@@ -0,0 +1,198 @@
---
id: TASK-217
title: Add annual ranking snapshots for supported metrics
status: done
type: backend
team: Backend Senior
supporting_teams:
- Frontend Senior
- Arquitecto de Base de Datos
- Arquitecto Python
roadmap_item: foundation
priority: high
---
# TASK-217 - Add annual ranking snapshots for supported metrics
## Goal
Permitir ranking anual para metricas adicionales usando un snapshot anual independiente por metrica, sin runtime publico pesado ni reutilizacion del snapshot top kills para otras metricas.
## Context
`TASK-211` dejo la lectura publica anual rapida y basada en `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`. `TASK-216` mantuvo annual limitado a `kills` porque no habia snapshot propio para otras metricas y corrigio el falso KPM: `kills_per_match` debe mostrarse como `Kills/partida`, no como kills por minuto.
Esta task amplia la generacion annual para metricas que ya se pueden calcular de forma segura desde los read models materializados durante un proceso interno/CLI. La lectura publica sigue leyendo solo snapshots anuales ya generados.
Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution.
## Steps
1. Revisar la lectura y generacion anual actual.
2. Confirmar que el esquema permite `metric_value` decimal para ratios.
3. Actualizar la normalizacion de metricas annual soportadas.
4. Generar snapshots independientes por metrica:
- `kills`
- `deaths`
- `teamkills`
- `matches_considered`
- `kd_ratio`
- `kills_per_match`
5. Mantener la lectura publica anual sobre tablas de snapshot, sin fallback runtime.
6. Actualizar frontend para permitir metricas annual soportadas y mostrar `kills_per_match` como `Kills/partida`.
7. Añadir tests de normalizacion, lectura publica y calculo/orden de `kd_ratio` y `kills_per_match`.
## Files to Read First
- `AGENTS.md`
- `ai/repo-context.md`
- `ai/architecture-index.md`
- `backend/app/rcon_annual_rankings.py`
- `backend/app/payloads.py`
- `frontend/assets/js/ranking.js`
## Expected Files to Modify
- `backend/app/rcon_annual_rankings.py`
- `backend/app/rcon_admin_log_materialization.py`
- `backend/app/postgres_rcon_storage.py`
- `backend/tests/test_annual_ranking_payload.py`
- `frontend/ranking.html`
- `frontend/assets/js/ranking.js`
- `ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md`
## Constraints
- Keep the change minimal.
- Preserve HLL Vietnam project identity.
- Do not introduce unnecessary frameworks or dependencies.
- No ejecutar `ai-platform run`.
- No hacer push.
- No tocar `frontend/assets/img/weapons/`.
- No tocar SVGs.
- No modificar imagenes fisicas.
- No tocar `ai/system-metrics.md`.
- No reactivar Elo/MMR.
- No reintroducir Comunidad Hispana #03.
- No implementar KPM real en esta task.
- No mostrar `kills_per_match` como KPM.
- No exponer metricas annual sin snapshot anual propio.
- No usar el snapshot top kills para representar otras metricas.
- La lectura publica annual debe leer solo `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`.
## Validation
Before completing the task ensure:
- `node --check frontend/assets/js/ranking.js`
- `python -m compileall backend\app\rcon_annual_rankings.py backend\app\payloads.py backend\tests\test_annual_ranking_payload.py`
- `python -m unittest backend.tests.test_annual_ranking_payload`
- Medicion directa de `build_global_ranking_payload` annual para metricas soportadas si el entorno local tiene datos.
- `git diff --name-only` matches the expected scope.
- No unrelated files were modified.
## Outcome
Archivos modificados por esta task:
- `backend/app/rcon_annual_rankings.py`
- `backend/app/rcon_admin_log_materialization.py`
- `backend/app/postgres_rcon_storage.py`
- `backend/tests/test_annual_ranking_payload.py`
- `frontend/ranking.html`
- `frontend/assets/js/ranking.js`
- `ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md`
Metricas anuales soportadas:
- `kills`
- `deaths`
- `teamkills`
- `matches_considered`
- `kd_ratio`
- `kills_per_match`
Cambios de backend:
- `_normalize_metric()` acepta solo las seis metricas anuales soportadas.
- La generacion anual calcula y ordena snapshots independientes por metrica real.
- `kd_ratio` se calcula como `kills / deaths` sobre agregados.
- `kills_per_match` se calcula como `kills / matches_considered` y sigue siendo `Kills/partida`, no KPM.
- La lectura publica anual no cambia de modelo: sigue usando `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`.
- No se introdujo fallback runtime ni lectura publica sobre `rcon_match_player_stats`.
- Se agregaron tests de normalizacion, rechazo de metrica no soportada, lectura publica sin inicializar storage y orden/calculo para `kd_ratio` y `kills_per_match`.
Cambios de esquema:
- Si hubo cambios de esquema.
- `rcon_annual_ranking_snapshots.metric` ahora permite:
- `kills`
- `deaths`
- `teamkills`
- `matches_considered`
- `kd_ratio`
- `kills_per_match`
- `rcon_annual_ranking_snapshot_items.metric_value` pasa de entero a valor decimal:
- SQLite: `REAL`
- PostgreSQL: `DOUBLE PRECISION`
- La inicializacion PostgreSQL incluye una migracion idempotente para ajustar `metric_value` y reemplazar el `CHECK` antiguo.
Cambios de frontend:
- Annual permite seleccionar las metricas soportadas.
- No se muestra KPM.
- `kills_per_match` se muestra como `Kills/partida`.
- Se renombraron identificadores internos heredados de KPM a KPP.
- Annual mantiene `2026` interno y no muestra input de año.
- Si falta un snapshot anual, la UI muestra `Snapshot anual no disponible para esta metrica.` sin fallback ni bloqueo.
Comandos de produccion para generar snapshots anuales 2026:
```bash
for server in all-servers comunidad-hispana-01 comunidad-hispana-02; do
for metric in kills deaths teamkills matches_considered kd_ratio kills_per_match; do
docker compose exec backend python -m app.rcon_annual_rankings generate \
--year 2026 \
--server-key "$server" \
--metric "$metric" \
--limit 30 \
--replace-existing
done
done
```
Validaciones ejecutadas:
- `node --check frontend/assets/js/ranking.js`
- `$env:PYTHONPATH='backend'; python -m compileall backend\app\rcon_annual_rankings.py backend\app\payloads.py backend\tests\test_annual_ranking_payload.py backend\app\postgres_rcon_storage.py backend\app\rcon_admin_log_materialization.py`
- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_annual_ranking_payload`
- Busqueda en `frontend/ranking.html` y `frontend/assets/js/ranking.js` para confirmar que no aparecen `KPM`, `Actualizar ranking`, `ranking-year`, `El ranking expone`, `Kills listo`, `listo en` ni `annualMetric`.
- Medicion directa con `build_global_ranking_payload(timeframe="annual", year=2026)` para las seis metricas soportadas.
Tiempos obtenidos en lectura directa local:
- `kills`: `1.66 ms`, `snapshot_status=ready`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=20`.
- `deaths`: `1.17 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`.
- `teamkills`: `1.10 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`.
- `matches_considered`: `1.09 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`.
- `kd_ratio`: `1.11 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`.
- `kills_per_match`: `1.10 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`.
Confirmacion de exclusiones:
- No se ejecuto `ai-platform run`.
- No se hizo push.
- No se hizo commit.
- No se tocaron assets de armas.
- No se tocaron SVGs.
- No se modificaron imagenes fisicas.
- No se toco `ai/system-metrics.md`.
- No se reactivo Elo/MMR.
- No se reintrodujo Comunidad Hispana #03.
- No se incluyeron cambios previos no relacionados.
## Change Budget
- Archivos modificados por la task: 7.
- El cambio supera el objetivo preferente de 5 archivos porque incluye schema SQLite/PostgreSQL, generador, test, frontend y documentacion de task.
- No se implemento KPM real; queda fuera de alcance hasta materializar tiempo jugado real por jugador.