Files
comunidadhll/ai/tasks/done/TASK-168-add-annual-ranking-snapshot-generator.md
2026-06-08 14:24:21 +02:00

104 lines
4.6 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: TASK-168
title: Add annual ranking snapshot generator
status: done
type: backend
team: Arquitecto de Base de Datos
supporting_teams:
- Backend Senior
- Arquitecto Python
roadmap_item: foundation
priority: medium
---
# TASK-168 - Add annual ranking snapshot generator
## Goal
Implementar un generador backend para snapshots anuales top 20 de jugadores sobre datos RCON materializados.
## Context
TASK-166 definió el diseño de persistencia, y TASK-167 ya añadió las tablas:
- `rcon_annual_ranking_snapshots`
- `rcon_annual_ranking_snapshot_items`
Ahora se necesita el generador que rellene esas tablas desde
`rcon_materialized_matches` y `rcon_match_player_stats` con `source_basis = admin-log-match-ended`.
Debe mantenerse separado de frontend y sin introducir una API pública todavía.
## Files to Read First
- `AGENTS.md`
- `ai/repo-context.md`
- `ai/architecture-index.md`
- `docs/annual-ranking-snapshot-schema-plan.md`
- `backend/app/rcon_admin_log_materialization.py`
- `backend/app/rcon_historical_leaderboards.py`
- `backend/app/rcon_historical_player_stats.py`
- `backend/app/postgres_rcon_storage.py`
- `backend/app/sqlite_to_postgres_migration.py`
## Expected Files to Modify
- `backend/app/rcon_annual_rankings.py` (crear)
- `backend/app/rcon_admin_log_materialization.py` (si hace falta reutilizar inicialización o alcance)
- `backend/app/postgres_rcon_storage.py` (solo si detecta ajustes de soporte SQLite/Postgres)
- `backend/app/sqlite_to_postgres_migration.py` (solo si detecta ajustes migratorios necesarios)
## Steps
1. Seguir los archivos de `Files to Read First` y respetar el contrato de datos existente.
2. Implementar `generate_annual_ranking_snapshot` con:
- `year`, `server_key`, `metric`, `limit`, `replace_existing`.
- Soporte inicial para `metric='kills'`.
3. Agregar una ruta CLI opcional (`python -m app.rcon_annual_rankings generate --year ...`).
4. Reusar conexión SQLite/Postgres con `connect_sqlite_readonly`/`connect_postgres_compat` y placeholders `?`.
5. Validar la función con datos existentes y con BD vacía sin crash.
6. Preparar la Outcome con validación, comportamiento con vacío y limitaciones.
## Constraints
- No crear API pública en esta task.
- Mantener el cambio pequeño y verificable.
- No tocar frontend ni archivos `frontend/assets/js/partida-actual.js`.
- No tocar `frontend/assets/img/clans/bxb.png`.
- No reactivar Elo/MMR.
- No reintroducir Comunidad Hispana #03.
- No ampliar workers históricos salvo que sea imprescindible y justificable.
- No incluir métricas adicionales a `kills` salvo que no amplíe el alcance de forma razonable y segura.
## Validation
- `python -m compileall backend/app`
- `scripts/run-integration-tests.ps1` cuando aplique.
- Validación local con SQLite:
- inicializar storage,
- ejecutar generador con un año de prueba (si hay datos),
- verificar que se inserta el snapshot y hasta `limit` items.
- Verificar comportamiento sin datos: debe terminar sin excepción y crear snapshot vacío o sin items cuando corresponda.
- `git diff --name-only` y confirmar que no se tocó frontend.
## Outcome
- Archivos modificados:
- `backend/app/rcon_annual_rankings.py` (nuevo)
- Función/comando generado:
- `generate_annual_ranking_snapshot(year: int, server_key: str | None = None, metric: str = "kills", limit: int = 20, replace_existing: bool = True, db_path: Path | None = None) -> dict[str, object]`.
- CLI opcional: `python -m app.rcon_annual_rankings generate --year <year> [--server-key <server>] [--metric kills] [--limit <n>] [--replace-existing]`.
- Validaciones ejecutadas y resultados:
- `python -m compileall backend/app` (sin errores).
- `scripts/run-integration-tests.ps1` (pasado).
- `initialize_rcon_materialized_storage()` + `generate_annual_ranking_snapshot(year=2026, metric='kills', limit=10)` con datos existentes: snapshot creado (`source_matches_count` > 0), `items <= 10`.
- `generate_annual_ranking_snapshot(year=1990, metric='kills', limit=20)` con ventana sin datos: snapshot creado y `items: []` sin excepción.
- `replace_existing=False` devuelve `skipped_regeneration: True` y reutiliza snapshot existente.
- CLI manual ejecutada: `python -m app.rcon_annual_rankings generate --year 1990 --metric kills --limit 3`.
- Limitaciones conocidas:
- Soporte inicial exclusivamente para `metric='kills'`.
- No se implementó API pública ni refresco programado.
- No se modificón workers históricos.
- No se tocó frontend ni archivos preexistentes `frontend/assets/js/partida-actual.js` y `frontend/assets/img/clans/bxb.png`.
- Siguiente task recomendada: API pública de ranking anual snapshot.