6.8 KiB
Historical Stats Domain Model
Objective
Definir la fuente real y el modelo de dominio minimo para construir una capa historica propia sobre los 2 servidores reales de Comunidad Hispana, sin implementar todavia la ingesta completa ni comprometer una base de datos productiva distinta de la base local ya usada en desarrollo.
Real Historical Sources
Los 2 servidores reales ya exponen historico publico en:
https://scoreboard.comunidadhll.es/gameshttps://scoreboard.comunidadhll.es:5443/games
Observaciones verificadas sobre ambas fuentes:
- ambas responden con una SPA publica titulada
Hell Let Loose Stats - la descripcion publica indica
Hell Let Loose Statistics and Game History - ambas cargan el mismo bundle frontend, por lo que la estructura funcional observable parece comun y cambia solo el dataset servido por cada dominio
- en el bundle publico aparecen referencias a conceptos como
games,players,kills,deaths,matchesyserver
Inferencia operativa:
- la fuente real no debe modelarse como una tabla HTML estable
- la primera opcion tecnica futura debe ser descubrir y consumir un endpoint estructurado del scoreboard si existe
- si no existe un endpoint publico reutilizable, la alternativa seria un parser controlado de HTML renderizado o del payload que hidrate la SPA
Scope Of Historical Analytics Phase 1
La primera capacidad historica util del proyecto sera:
- top kills de la ultima semana por servidor
Por tanto, la ingesta base debe capturar como minimo:
- servidor
- partida
- fecha/hora de partida
- duracion si esta disponible
- mapa
- modo
- jugador
- kills
- muertes si estan disponibles
Proposed Domain Entities
historical_servers
Proposito: representar cada servidor real de la comunidad como origen de historico.
Campos minimos:
server_idexternal_server_iddisplay_namescoreboard_base_urlis_active
Notas:
- esta entidad reutiliza la identidad ya establecida en
serverscuando la implementacion llegue a persistencia scoreboard_base_urlpermite mantener separado el origen historico por servidor sin hardcodear rutas dispersas
historical_matches
Proposito: representar una partida individual extraida del scoreboard.
Campos minimos:
match_idserver_idsource_match_refstarted_atended_atnullableduration_secondsnullablemap_idmode_idnullablesource_fingerprint
Notas:
source_match_refdebe conservar el identificador nativo del scoreboard si la fuente lo exponesource_fingerprintcubre el caso en que no exista un id perfecto y haya que deduplicar por combinacion de campos observables
historical_maps
Proposito: mantener identidad y nombre normalizado de mapa.
Campos minimos:
map_idmap_slugdisplay_nameraw_map_name
Notas:
- el pipeline debe conservar el valor crudo y tambien un nombre normalizado
- esto evita que los rankings historicos mezclen variantes tecnicas del mismo mapa
historical_modes
Proposito: normalizar el modo de partida si la fuente lo ofrece.
Campos minimos:
mode_idmode_slugdisplay_nameraw_mode_name
historical_players
Proposito: mantener una identidad de jugador lo bastante estable para consultas agregadas.
Campos minimos:
player_ididentity_kindcanonical_namelast_seen_namesource_player_refnullableidentity_fingerprint
Notas:
- si el scoreboard no da un id perfecto, la identidad inicial puede basarse en una huella controlada por servidor y nombre normalizado
- la identidad debe ser revisable porque el nombre visible puede cambiar
historical_player_participations
Proposito: representar que un jugador participo en una partida concreta.
Campos minimos:
participation_idmatch_idplayer_idteamnullablejoined_atnullableleft_atnullable
Notas:
- esta capa separa la presencia del jugador de sus metricas
- deja espacio para futuras metricas por equipo o duracion de participacion
historical_player_match_stats
Proposito: guardar las metricas observadas por jugador dentro de una partida.
Campos minimos:
participation_idkillsdeathsnullableassistsnullablescorenullablerank_in_matchnullablecaptured_at
Notas:
killses la metrica obligatoria de la primera fasedeathsse persiste solo si la fuente la ofrece de forma estable
Identity And Deduplication Strategy
Match identity
Orden preferido:
source_match_refdel scoreboard si existe y es estable- huella derivada de
server_id + started_at + map + mode + duration
Regla:
- no insertar una partida nueva si ya existe la misma referencia nativa o la misma huella derivada
Player identity
Orden preferido:
source_player_refdel scoreboard si existe- identidad derivada de
server_id + normalized_player_name
Riesgo:
- esto no resuelve por completo renombres o colisiones entre jugadores con el mismo nombre
Mitigacion inicial:
- conservar siempre
canonical_name,last_seen_namey la referencia nativa cuando exista - documentar que los rankings de fase 1 pueden tener precision limitada si el scoreboard no expone un id fuerte
Ingestion deduplication
Para poder reejecutar la ingesta sin duplicacion grave:
- upsert por
source_match_refosource_fingerprinten partidas - upsert por
source_player_refoidentity_fingerprinten jugadores - unicidad por
match_id + player_iden participaciones - unicidad por
participation_iden metricas de partida por jugador
Initial Query Shape
Consulta prioritaria:
- top kills de la ultima semana por servidor
Agrupacion minima necesaria:
- filtrar partidas del servidor cuya ventana temporal caiga dentro de los
ultimos 7 dias segun
started_atoended_at - sumar
killsporplayer_id - devolver nombre canonico del jugador, kills agregadas y rango
Definicion inicial de ventana:
- ventana rodante de 7 dias hacia atras desde el momento de consulta
- usar UTC en backend para evitar ambiguedades
Risks And Limits
- la estructura visible hoy es la de una SPA; el contrato interno del scoreboard puede cambiar sin aviso
- no se ha fijado todavia un endpoint JSON publico y estable del scoreboard
- si solo existe HTML cliente, el scraping sera mas fragil que una API
- la identidad de jugador puede ser imperfecta si la fuente no expone un id
- una misma partida podria aparecer con informacion parcial durante una captura
- la disponibilidad del scoreboard no debe bloquear el backend principal
Recommended Technical Direction For Following Tasks
- Descubrir primero el endpoint estructurado o payload interno usado por la SPA.
- Implementar un parser backend desacoplado por servidor de scoreboard.
- Persistir solo entidades y metricas necesarias para top kills semanal.
- Mantener la ingesta idempotente antes de abrir endpoints historicos nuevos.