243 lines
12 KiB
Markdown
243 lines
12 KiB
Markdown
# Technical Decisions
|
|
|
|
## Decision 001: frontend simple HTML/CSS/JS
|
|
|
|
Se adopta una base estatica con HTML, CSS y JavaScript puro para priorizar simplicidad, velocidad de arranque y compatibilidad total al abrir el frontend directamente en navegador.
|
|
|
|
## Decision 002: backend previsto en Python
|
|
|
|
La estructura del repositorio reserva desde el inicio una carpeta de backend porque la implementacion futura se realizara en Python.
|
|
|
|
## Decision 003: estructura preparada para orquestacion por agentes
|
|
|
|
Se incluye una carpeta `ai/` y un documento `AGENTS.md` para facilitar una futura organizacion del trabajo por roles, tareas y orquestacion.
|
|
|
|
## Decision 004: branding militar Vietnam
|
|
|
|
La direccion visual inicial se alinea con una estetica sobria, tactica y militar inspirada en el contexto Vietnam para mantener coherencia tematica desde la primera iteracion.
|
|
|
|
## Decision 005: AI Development Platform integrada de forma adaptada
|
|
|
|
Se integra una capa de orquestacion por tasks inspirada en la plantilla de AI Development Platform, pero adaptada al contexto real de HLL Vietnam y sin arrastrar supuestos genericos de otros stacks. La plataforma se usa como soporte operativo del repositorio, no como funcionalidad del producto.
|
|
|
|
## Decision 006: contrato API pequeno antes de integraciones reales
|
|
|
|
Antes de implementar endpoints de comunidad o integraciones externas, se fija un contrato JSON minimo entre frontend y backend para evitar que la landing y el backend evolucionen con supuestos incompatibles.
|
|
|
|
La unica ruta implementada hoy es `GET /health`. Las rutas `/api/community`, `/api/trailer`, `/api/discord` y `/api/servers` quedan definidas como contrato previsto o placeholder en `docs/frontend-backend-contract.md`, manteniendo el backend en Python y sin introducir todavia Discord real, servidores reales ni base de datos.
|
|
|
|
## Decision 007: estrategia por fases para Discord y servidores
|
|
|
|
Los datos de Discord y de servidores de juego se incorporaran por fases para evitar dependencias prematuras de credenciales, APIs externas o consultas de red todavia no validadas.
|
|
|
|
La fase inicial debe usar datos manuales o placeholder controlados por el backend para mantener estable el contrato del frontend. Una fase intermedia podra anadir una integracion limitada con fuentes publicas o consultas tecnicas de bajo riesgo. Solo una fase posterior evaluara integraciones mas reales, siempre que queden claras las restricciones de seguridad, disponibilidad, latencia y mantenimiento.
|
|
|
|
La estrategia detallada de bloques de datos, fuentes posibles, riesgos y orden recomendado de implementacion queda documentada en `docs/discord-and-server-data-plan.md`.
|
|
|
|
## Decision 008: consumo frontend progresivo con fallback estatico
|
|
|
|
El frontend no debe depender de datos dinamicos para renderizar la landing base mientras el proyecto siga en fase fundacional.
|
|
|
|
Cuando se incorporen endpoints del backend, el consumo debe hacerse con `fetch` y JavaScript simple, priorizando bloques independientes y manteniendo contenido estatico o placeholders visuales si falla una llamada. `GET /health` queda reservado para comprobaciones tecnicas y no debe bloquear el render principal.
|
|
|
|
La estrategia detallada de prioridades de endpoints, estados de carga, errores y orden de migracion queda en `docs/frontend-data-consumption-plan.md`.
|
|
|
|
## Decision 009: servidores actuales de HLL como referencia provisional
|
|
|
|
Mientras no existan datos reales o representativos de HLL Vietnam, la web puede
|
|
mostrar un bloque provisional con servidores actuales de Hell Let Loose siempre
|
|
que quede claramente etiquetado como referencia temporal.
|
|
|
|
La primera version de ese bloque debe salir de un payload controlado del backend
|
|
Python, no de una integracion directa desde frontend ni de scraping prematuro.
|
|
Esto permite fijar campos utiles, preservar el tono del producto y evitar que la
|
|
landing dependa de una fuente externa aun no validada.
|
|
|
|
La estrategia de campos, riesgos, fases y sustitucion futura queda documentada
|
|
en `docs/current-hll-servers-source-plan.md`.
|
|
|
|
## Decision 010: ingesta por snapshots y adaptadores desacoplados
|
|
|
|
La evolucion desde payloads placeholder hacia datos mas realistas debe hacerse
|
|
con una arquitectura de snapshots de servidor, no conectando el frontend a una
|
|
fuente externa ni acoplando el backend a una integracion unica desde el inicio.
|
|
|
|
La unidad tecnica base sera un snapshot con `captured_at` y campos normalizados
|
|
como estado, jugadores, capacidad y mapa actual cuando exista. La lectura de
|
|
fuente, la normalizacion y la produccion del snapshot deben quedar separadas
|
|
para poder sustituir mocks por una fuente publica o consulta tecnica posterior
|
|
sin romper el contrato interno.
|
|
|
|
La estrategia detallada de fuentes, riesgos, fases y limites queda documentada
|
|
en `docs/current-hll-data-ingestion-plan.md`.
|
|
|
|
## Decision 011: modelo de almacenamiento logico antes de fijar tecnologia
|
|
|
|
Antes de introducir una base de datos concreta, el proyecto debe fijar un
|
|
modelo logico minimo para identidad de servidores y snapshots historicos.
|
|
|
|
La base inicial se apoya en entidades genericas como `game_sources`, `servers`
|
|
y `server_snapshots`. Las metricas iniciales deben derivarse primero de esos
|
|
snapshots en vez de materializar agregados prematuros. Esto mantiene el diseno
|
|
reutilizable para HLL actual y para futuras fuentes mas cercanas a HLL Vietnam.
|
|
|
|
El modelo base y las preguntas abiertas quedan documentados en
|
|
`docs/stats-database-schema-foundation.md`.
|
|
|
|
## Decision 012: historico de partidas desde CRCON scoreboard JSON
|
|
|
|
El historico reutilizable para estadisticas por partida y por jugador debe
|
|
salir de la capa JSON publica expuesta por los scoreboards CRCON de la
|
|
comunidad, no de A2S ni del HTML renderizado de `/games`.
|
|
|
|
La discovery tecnica confirma que ambos scoreboards sirven una SPA cuya fuente
|
|
real de datos usa `baseURL: "/api"` y endpoints como
|
|
`/get_scoreboard_maps` y `/get_map_scoreboard`. Esa capa permite obtener listas
|
|
de partidas, detalle por `map_id` y metricas por jugador suficientes para una
|
|
futura agregacion semanal por servidor.
|
|
|
|
A2S se mantiene como fuente de estado actual de servidores. El historico de
|
|
partidas y rankings debe construirse en una linea separada basada en CRCON. La
|
|
discovery detallada queda en `docs/historical-crcon-source-discovery.md`.
|
|
|
|
## Decision 013: persistencia historica local separada del flujo live
|
|
|
|
El backend mantiene el estado live de servidores y el historico CRCON en el
|
|
mismo SQLite local de desarrollo para no introducir infraestructura prematura,
|
|
pero ambas lineas quedan separadas por tablas y contratos distintos.
|
|
|
|
El flujo live sigue usando `server_snapshots` via A2S. El flujo historico usa
|
|
tablas `historical_*` para:
|
|
|
|
- servidores historicos configurados
|
|
- partidas
|
|
- mapas
|
|
- jugadores
|
|
- estadisticas por jugador y partida
|
|
- ejecuciones de ingesta
|
|
|
|
Las claves estables son:
|
|
|
|
- servidor: `historical_servers.slug`
|
|
- partida: `(historical_server_id, external_match_id)`
|
|
- jugador: `stable_player_key`
|
|
- estadistica por partida: `(historical_match_id, historical_player_id)`
|
|
|
|
Esto permite bootstrap, refresco incremental e idempotencia sin mezclar
|
|
semanticas de estado actual con historico persistido. El modelo detallado queda
|
|
en `docs/historical-domain-model.md`.
|
|
|
|
## Decision 014: despliegue normal simplificado sin servidor #03
|
|
|
|
El despliegue operativo normal vuelve a quedar reducido a `backend` +
|
|
`frontend`. Los servicios `historical-runner` y `rcon-historical-worker` se
|
|
mantienen disponibles solo para uso avanzado y explicito mediante el perfil
|
|
Compose `advanced`.
|
|
|
|
Comunidad Hispana #03 deja de formar parte de los targets RCON por defecto
|
|
porque ya no es una fuente operativa vigente. El codigo historico, los datos
|
|
persistidos, las migraciones y las piezas Elo/MMR no se eliminan; quedan
|
|
pausadas operativamente para esta fase y pueden reintroducirse mediante una
|
|
task futura si se valida de nuevo la fuente y el coste de mantenimiento.
|
|
|
|
## Decision 015: historico RCON-first con fallback publico
|
|
|
|
La politica por defecto para historico vuelve a ser RCON-first:
|
|
`HLL_BACKEND_HISTORICAL_DATA_SOURCE=rcon`. El scoreboard publico de CRCON se
|
|
mantiene como fallback controlado cuando RCON falla, no tiene cobertura util o
|
|
no soporta todavia una operacion competitiva concreta.
|
|
|
|
La arquitectura historica RCON-first se compone de captura de sesiones RCON,
|
|
ingesta de AdminLog, parser de eventos, almacenamiento de eventos/snapshots y
|
|
materializacion de partidas y estadisticas por jugador. Los snapshots de perfil
|
|
procedentes de `MESSAGE` enriquecen lecturas de jugador, pero no sustituyen los
|
|
hechos de partida derivados de eventos RCON.
|
|
|
|
Comandos operativos manuales:
|
|
|
|
```powershell
|
|
docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440
|
|
docker compose exec backend python -m app.rcon_historical_worker capture
|
|
```
|
|
|
|
Esta decision no reactiva Elo/MMR dentro del arranque normal del backend. Las
|
|
piezas Elo/MMR, migraciones, datos persistidos y modulos historicos se
|
|
conservan, pero su operativa compleja sigue pausada y desacoplada salvo task
|
|
explicita.
|
|
|
|
## Decision 016: catalogo confiable de scoreboards publicos activos
|
|
|
|
Los origenes publicos de scoreboard que el backend puede exponer o validar se
|
|
centralizan en un catalogo explicito de servidores activos. En esta fase solo
|
|
son confiables `comunidad-hispana-01`, con origen
|
|
`https://scoreboard.comunidadhll.es`, y `comunidad-hispana-02`, con origen
|
|
`https://scoreboard.comunidadhll.es:5443`.
|
|
|
|
`comunidad-hispana-03` no forma parte de ese catalogo ni de los seeds por
|
|
defecto nuevos. Los datos historicos ya persistidos no se eliminan, pero las
|
|
URLs publicas de partidas solo se aceptan si el `raw_payload_ref` usa HTTP(S),
|
|
apunta al origen confiable del servidor activo y mantiene una ruta `/games/`.
|
|
|
|
## Decision 017: PostgreSQL phase 1 for RCON historical persistence
|
|
|
|
La primera migracion de persistencia a PostgreSQL cubre el camino que sufria
|
|
contencion SQLite entre `backend`, `historical-runner` y
|
|
`rcon-historical-worker`:
|
|
|
|
- captura prospectiva RCON, muestras y ventanas competitivas
|
|
- eventos AdminLog deduplicados y snapshots de perfil derivados
|
|
- partidas RCON materializadas y estadisticas por jugador
|
|
- candidatos confiables de URL de scoreboard que puedan poblarse para
|
|
correlacion de detalle
|
|
|
|
Docker Compose configura `HLL_BACKEND_DATABASE_URL` y usa PostgreSQL como
|
|
backend autoritativo para esas tablas. La ejecucion local sin esa variable sigue
|
|
usando SQLite como fallback temporal para preservar comandos y tests locales.
|
|
|
|
Quedan SQLite-backed en esta fase porque no forman parte del lock-prone writer
|
|
path migrado y siguen cubriendo fallback publico o caches locales:
|
|
|
|
- snapshots live y cache de `/api/servers`
|
|
- tablas `historical_*` de scoreboard publico, rankings y correlacion legacy
|
|
- snapshots historicos precalculados, ledger player-event y Elo/MMR pausado
|
|
|
|
La correlacion de URL publica en detalle usa primero candidatos PostgreSQL
|
|
confiables cuando existan y puede seguir leyendo filas `historical_*`
|
|
persistidas en SQLite durante la transicion. El diagnostico operativo se expone
|
|
con `python -m app.storage_diagnostics`.
|
|
|
|
## Decision 018: PostgreSQL phase 2 for displayed historical data
|
|
|
|
PostgreSQL pasa a ser la fuente de lectura para los datos historicos visibles:
|
|
|
|
- fallback publico `historical_*` de partidas, detalle y rankings
|
|
- snapshots historicos precalculados que consume `historico.html`
|
|
- cache live de servidores que consume `/api/servers`
|
|
- ledger player-event usado para reconstruir snapshots visibles
|
|
- tablas RCON de AdminLog, perfiles, ventanas, partidas materializadas,
|
|
estadisticas y candidatos seguros ya migradas en phase 1
|
|
|
|
La migracion se ejecuta de forma idempotente con:
|
|
|
|
```powershell
|
|
cd backend
|
|
python -m app.sqlite_to_postgres_migration
|
|
python -m app.storage_diagnostics
|
|
```
|
|
|
|
El comando conserva IDs y `external_match_id` del scoreboard publico, claves
|
|
`match_key` materializadas y URLs seguras existentes. Copia SQLite y los JSON
|
|
historicos de `backend/data/snapshots` como fuentes legacy; no los vuelve a
|
|
usar como read model visible cuando `HLL_BACKEND_DATABASE_URL` esta definido.
|
|
Las filas legacy de `comunidad-hispana-03` se omiten en el read model visible
|
|
de esta migracion para no reactivar ese target.
|
|
|
|
Permanecen fuera de phase 2:
|
|
|
|
- checkpoints y runs operativos del import publico que no aparecen en frontend
|
|
- Elo/MMR pausado y oculto en la UI actual
|
|
|
|
`app.storage_diagnostics` muestra conteos PostgreSQL, ultimas partidas
|
|
materializadas, ultimos `match_end`, dominios restantes y un resumen de paridad
|
|
para verificar la migracion antes de retirar fuentes legacy.
|