feat: add current match killfeed overlay and player stats
This commit is contained in:
198
ai/tasks/done/TASK-154-current-match-killfeed-overlay-layout.md
Normal file
198
ai/tasks/done/TASK-154-current-match-killfeed-overlay-layout.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# TASK-154 - Current match killfeed overlay layout
|
||||
|
||||
Status: in-progress
|
||||
|
||||
## Goal
|
||||
|
||||
Redesign the current-match kill feed frontend so it behaves like a compact live killfeed overlay.
|
||||
|
||||
## Background
|
||||
|
||||
The current-match page already renders a kill feed using:
|
||||
|
||||
- `GET /api/current-match/kills?server=...`
|
||||
|
||||
The feed currently appears as a vertical list of large historical-style cards. This is not the desired UX.
|
||||
|
||||
## Desired UX
|
||||
|
||||
The kill feed should look like a compact live FPS-style overlay:
|
||||
|
||||
- A rectangular live panel.
|
||||
- Events rendered as compact rows/chips.
|
||||
- Each event should show:
|
||||
- killer name
|
||||
- weapon icon or weapon label fallback
|
||||
- victim name
|
||||
- Events should be arranged in three visual columns inside the panel.
|
||||
- New events should appear progressively.
|
||||
- Older events should move left and eventually disappear.
|
||||
- The feed should feel like a real-time combat screen, not a historical list.
|
||||
|
||||
The user explicitly wants:
|
||||
|
||||
- "una especie de pantalla en tiempo real"
|
||||
- "simplemente se muestre el texto, el que mata, el arma y alguien mata"
|
||||
- "iconos del arma que se utiliza"
|
||||
- "una pequeña pantalla rectangular"
|
||||
- "se irá poniendo de arriba abajo en tres columnas"
|
||||
- "se irá desplazando hacia la izquierda e irán desapareciendo las más antiguas"
|
||||
|
||||
## Scope
|
||||
|
||||
Replace the current large-card kill feed with a compact live overlay on the current-match page.
|
||||
|
||||
Allowed changes:
|
||||
|
||||
- `frontend/assets/js/partida-actual.js`
|
||||
- `frontend/partida-actual.html` if needed
|
||||
- `frontend/assets/css/historico.css` or the relevant CSS used by `partida-actual.html`
|
||||
- `frontend/assets/css/styles.css` only if the current-match page depends on it
|
||||
- `frontend/assets/img/weapons/*` if local weapon icons/placeholders are added
|
||||
- backend only if a small weapon normalization field is needed, but prefer frontend-side mapping first
|
||||
- focused tests or node validation
|
||||
|
||||
## Constraints - DO NOT BREAK
|
||||
|
||||
- Do not break `/api/current-match/kills`.
|
||||
- Do not expose raw AdminLog lines.
|
||||
- Do not fabricate kill events.
|
||||
- Do not show stale kills as live kills.
|
||||
- Do not break the current-match scoreboard/header.
|
||||
- Do not break historical match detail pages.
|
||||
- Do not query RCON directly from the frontend.
|
||||
- Do not depend on server #03.
|
||||
- Do not require external/CDN assets at runtime.
|
||||
- If weapon icons are added, they must be local/static assets or generated lightweight inline/SVG placeholders.
|
||||
- Keep the UI responsive.
|
||||
|
||||
## Files to inspect first
|
||||
|
||||
Read:
|
||||
|
||||
- `frontend/partida-actual.html`
|
||||
- `frontend/assets/js/partida-actual.js`
|
||||
- the CSS currently used by `frontend/partida-actual.html`
|
||||
- focused current-match kill feed tests or validation scripts if present
|
||||
|
||||
Inspect the current kill feed rendering, `event_id` handling, scope copy, and current polling behavior before changing code.
|
||||
|
||||
## Implementation requirements
|
||||
|
||||
### 1. Compact live panel
|
||||
|
||||
Replace the current large-card feed rendering with a compact live killfeed panel.
|
||||
|
||||
The panel must be visually rectangular and compact. It should look like a live combat overlay, not a list of historical cards.
|
||||
|
||||
### 2. Layout
|
||||
|
||||
- Use a three-column visual layout on desktop.
|
||||
- Events should fill vertically within a column, then continue through the next visual position.
|
||||
- Newer events should be visually prioritized.
|
||||
- Older events should shift left and disappear once the maximum number of visible events is exceeded.
|
||||
- On narrow/mobile widths, fall back to one or two columns without overflow.
|
||||
|
||||
### 3. Event content
|
||||
|
||||
Each kill event must show:
|
||||
|
||||
- killer name
|
||||
- weapon icon or weapon label
|
||||
- victim name
|
||||
- optional timestamp only if it does not make the UI noisy
|
||||
- teamkill indicator if `is_teamkill` is true
|
||||
|
||||
### 4. Weapon icons
|
||||
|
||||
Add a safe mapping for common weapons currently seen in AdminLog examples:
|
||||
|
||||
- `M1 GARAND`
|
||||
- `MP40`
|
||||
- `M1A1 THOMPSON`
|
||||
- `UNKNOWN`
|
||||
|
||||
Prefer local SVG/icon placeholders if real weapon assets are not available.
|
||||
|
||||
- Do not hotlink external images.
|
||||
- Unknown weapons must show a generic weapon icon/label fallback.
|
||||
- The icon mapping should be easy to extend later.
|
||||
|
||||
### 5. Motion and transition
|
||||
|
||||
- Use CSS transitions/animations only if they are subtle.
|
||||
- Avoid layout jumps.
|
||||
- Respect users with reduced motion if possible.
|
||||
- The feed should not flicker every poll.
|
||||
|
||||
### 6. Deduplication
|
||||
|
||||
- Preserve existing `event_id` deduplication.
|
||||
- Re-rendering must not duplicate rows.
|
||||
- Repeated polling must keep already visible events stable.
|
||||
|
||||
### 7. Maximum visible events
|
||||
|
||||
- Limit visible events to a reasonable number, for example 12 or 15.
|
||||
- Older events should be dropped from the visual panel.
|
||||
- Do not render an infinitely growing list.
|
||||
|
||||
### 8. Copy
|
||||
|
||||
Use these messages:
|
||||
|
||||
- If there are no events: "Todavía no se han detectado bajas en esta partida."
|
||||
- If scope is open match window: "Bajas detectadas en la partida actual."
|
||||
- If scope is `recent-admin-log-window`: "Cobertura parcial desde AdminLog reciente."
|
||||
- If stale/no current events: "Sin bajas recientes asociadas a la partida actual."
|
||||
|
||||
### 9. Accessibility
|
||||
|
||||
- Keep `aria-live` polite or equivalent.
|
||||
- Event text must remain readable even if icons fail.
|
||||
|
||||
## Validation
|
||||
|
||||
Run:
|
||||
|
||||
- `node --check frontend/assets/js/partida-actual.js`
|
||||
- any existing frontend validation if available
|
||||
|
||||
## Manual verification checklist
|
||||
|
||||
- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`.
|
||||
- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`.
|
||||
- Verify kill feed appears as a compact rectangular live overlay.
|
||||
- Verify events render as killer -> weapon/icon -> victim.
|
||||
- Verify it uses three columns on desktop.
|
||||
- Verify old events disappear instead of growing endlessly.
|
||||
- Verify repeated polling does not duplicate events.
|
||||
- Verify teamkills are visually distinguishable.
|
||||
- Verify unknown weapons use a clean fallback.
|
||||
- Verify no raw AdminLog line is shown.
|
||||
- Verify no external image URLs are required.
|
||||
|
||||
## Expected outcome
|
||||
|
||||
The current-match kill feed looks and behaves like a compact live FPS-style killfeed overlay with local/fallback weapon icon support.
|
||||
|
||||
## AI Platform lifecycle
|
||||
|
||||
After implementation and validation:
|
||||
|
||||
- Move this task according to the lifecycle defined in `AGENTS.md`.
|
||||
- Do not mark unrelated tasks as done automatically.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Replaced the historical-style kill cards with a capped 15-event rectangular overlay in `partida-actual`.
|
||||
- Kept `event_id` deduplication and avoided poll flicker by only re-rendering when the visible event-id set changes.
|
||||
- Rendered older visible events first so they occupy the left side of the three-column desktop panel while newer events remain visually prioritized on the right.
|
||||
- Added local text-glyph weapon placeholders for `M1 GARAND`, `MP40`, `M1A1 THOMPSON` and unknown/other weapons without external assets.
|
||||
- Validation run:
|
||||
- `node --check frontend/assets/js/partida-actual.js`
|
||||
- `scripts/run-historical-ui-regression-tests.ps1`
|
||||
- `git diff --check`
|
||||
- `git diff --name-only`
|
||||
- Scope review: changed product files are `frontend/assets/js/partida-actual.js` and `frontend/assets/css/historico.css`.
|
||||
- Manual/rendered Browser QA remains to be repeated when the Browser automation entry point is exposed; the local frontend and backend current-match endpoints were reachable during validation.
|
||||
245
ai/tasks/done/TASK-155-current-match-live-player-stats.md
Normal file
245
ai/tasks/done/TASK-155-current-match-live-player-stats.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# TASK-155 - Current match live player stats
|
||||
|
||||
Status: in-progress
|
||||
|
||||
## Goal
|
||||
|
||||
Investigate and implement live player/statistics rendering for the current-match page using the safest available data source.
|
||||
|
||||
## Background
|
||||
|
||||
The current-match page has an "Estadísticas en vivo" section, but it currently remains a placeholder:
|
||||
|
||||
> "Las estadísticas en vivo aparecerán cuando haya datos suficientes."
|
||||
|
||||
The user reports that players are not being shown.
|
||||
|
||||
Known context:
|
||||
|
||||
- `/api/current-match` exposes players and team player counts from RCON `getSession`, but those counts may be marked as `rcon-session-unverified`.
|
||||
- Public scoreboard can show player population even when RCON `getSession` reports 0.
|
||||
- AdminLog kill events already expose player names through normalized kill feed rows.
|
||||
- Historical materialization already derives player stats from AdminLog data for completed matches.
|
||||
- The current-match page should eventually show useful live player rows, but only if data is reliable enough.
|
||||
|
||||
## Scope
|
||||
|
||||
Investigate the available live player data sources and wire the current-match page to a safe current player statistics payload.
|
||||
|
||||
Allowed changes:
|
||||
|
||||
- `backend/app/routes.py`
|
||||
- `backend/app/payloads.py`
|
||||
- `backend/app/rcon_admin_log_storage.py`
|
||||
- backend read-model/helper files if needed
|
||||
- `frontend/assets/js/partida-actual.js`
|
||||
- `frontend/partida-actual.html`
|
||||
- `frontend/assets/css/historico.css` or relevant CSS
|
||||
- focused backend tests
|
||||
|
||||
## Constraints - DO NOT BREAK
|
||||
|
||||
- Do not fabricate player stats.
|
||||
- Do not show an empty/misleading table as if it were real data.
|
||||
- Do not show RCON `getSession` `playerCount=0` as reliable if quality is `rcon-session-unverified`.
|
||||
- Do not expose raw AdminLog lines.
|
||||
- Do not expose admin-only/sensitive data.
|
||||
- Do not break historical materialization.
|
||||
- Do not break historical match detail stats.
|
||||
- Do not query RCON directly from the frontend.
|
||||
- Do not depend on server #03.
|
||||
- Do not scrape the public scoreboard unless explicitly chosen and documented as a safe server-side fallback.
|
||||
- Keep current public scoreboard URLs trusted and without `/games`.
|
||||
|
||||
## Files to inspect first
|
||||
|
||||
Read:
|
||||
|
||||
- `frontend/partida-actual.html`
|
||||
- `frontend/assets/js/partida-actual.js`
|
||||
- `backend/app/routes.py`
|
||||
- `backend/app/payloads.py`
|
||||
- `backend/app/rcon_admin_log_storage.py`
|
||||
- focused tests and historical player stat materialization helpers related to current-match or AdminLog data
|
||||
|
||||
Inspect the existing RCON session payload, current kill feed freshness logic, open AdminLog match window support, and historical player stat aggregation before choosing a source.
|
||||
|
||||
## Required investigation before implementation
|
||||
|
||||
Perform RCA first and determine what live player data sources currently exist:
|
||||
|
||||
- RCON session payload
|
||||
- any RCON player-list command/wrapper already available in the codebase
|
||||
- AdminLog kill/death events
|
||||
- existing historical player stat materialization
|
||||
- current open AdminLog match window if available
|
||||
|
||||
Document the chosen source in the done task notes:
|
||||
|
||||
- what was available
|
||||
- what was not available
|
||||
- whether stats are complete, partial, or event-derived
|
||||
|
||||
## Implementation requirements
|
||||
|
||||
### 1. Backend endpoint
|
||||
|
||||
Add or extend a backend endpoint for current-match player stats.
|
||||
|
||||
Preferred route:
|
||||
|
||||
- `GET /api/current-match/players?server=...`
|
||||
|
||||
### 2. Supported servers
|
||||
|
||||
Support:
|
||||
|
||||
- `comunidad-hispana-01`
|
||||
- `comunidad-hispana-02`
|
||||
|
||||
### 3. Unknown server values
|
||||
|
||||
- Return a safe 400/404 style response.
|
||||
- Do not query arbitrary targets.
|
||||
|
||||
### 4. Data model
|
||||
|
||||
The endpoint should return:
|
||||
|
||||
- `server_slug`
|
||||
- `server_name`
|
||||
- `scope`
|
||||
- `confidence`
|
||||
- `source`
|
||||
- `captured_at` or `updated_at`
|
||||
- `items`: array of player rows
|
||||
|
||||
### 5. Player row fields
|
||||
|
||||
Include only fields that can be supported reliably:
|
||||
|
||||
- `player_name`
|
||||
- `team` if known
|
||||
- `kills` if known
|
||||
- `deaths` if known
|
||||
- `teamkills` if known
|
||||
- `deaths_by_teamkill` if known
|
||||
- `favorite_weapon` or `most_used_weapon` if known
|
||||
- `last_seen_at` if known
|
||||
- `confidence`/`source` if needed
|
||||
|
||||
### 6. AdminLog-derived data
|
||||
|
||||
If using AdminLog-derived data:
|
||||
|
||||
- Clearly mark scope/confidence as partial/event-derived.
|
||||
- Only include players observed in recent/current match event windows.
|
||||
- Do not imply this is the full server roster.
|
||||
- Use a freshness threshold consistent with kill feed freshness logic.
|
||||
- If no current/open event window exists, return empty items with a clear scope.
|
||||
|
||||
### 7. RCON player-list data
|
||||
|
||||
If a real RCON player-list command exists:
|
||||
|
||||
- Prefer it for live roster.
|
||||
- Combine it with AdminLog-derived kills/deaths only when safe.
|
||||
- Mark fields not supported by RCON as null.
|
||||
- Do not block the endpoint indefinitely on RCON timeouts.
|
||||
|
||||
### 8. Frontend rendering
|
||||
|
||||
Replace the static "Estadísticas en vivo" placeholder with dynamic rendering.
|
||||
|
||||
If items exist:
|
||||
|
||||
- Show a compact table or cards with player stats.
|
||||
- Sort by kills descending, then deaths ascending, then name.
|
||||
- Indicate if stats are partial.
|
||||
|
||||
If items are empty, show:
|
||||
|
||||
- "Todavía no hay estadísticas fiables de jugadores para esta partida."
|
||||
|
||||
If data is partial, show:
|
||||
|
||||
- "Estadísticas parciales derivadas de eventos recientes."
|
||||
|
||||
### 9. Frontend polling
|
||||
|
||||
- Poll player stats with the current-match page refresh cycle or a safe separate interval.
|
||||
- Avoid overlapping requests.
|
||||
- Do not flicker table rows on every poll.
|
||||
- Avoid duplicate player rows.
|
||||
|
||||
### 10. Tests
|
||||
|
||||
Add focused backend tests for:
|
||||
|
||||
- unsupported server rejection
|
||||
- empty current stats response
|
||||
- AdminLog-derived player aggregation if used
|
||||
- stale event filtering
|
||||
- no raw AdminLog exposure
|
||||
- stable sorting
|
||||
- partial confidence metadata
|
||||
|
||||
## Validation
|
||||
|
||||
Run:
|
||||
|
||||
- `python -m compileall backend/app`
|
||||
- focused backend tests if available
|
||||
- `node --check frontend/assets/js/partida-actual.js`
|
||||
|
||||
## Manual verification checklist
|
||||
|
||||
- Call `Invoke-RestMethod "http://localhost:8000/api/current-match/players?server=comunidad-hispana-01" | ConvertTo-Json -Depth 20`.
|
||||
- Call `Invoke-RestMethod "http://localhost:8000/api/current-match/players?server=comunidad-hispana-02" | ConvertTo-Json -Depth 20`.
|
||||
- Verify unsupported server values are rejected safely.
|
||||
- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`.
|
||||
- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`.
|
||||
- Verify the "Estadísticas en vivo" section no longer remains permanently empty when current reliable/partial player data exists.
|
||||
- Verify the UI clearly says when stats are partial or unavailable.
|
||||
- Verify no fake players are shown.
|
||||
- Verify no raw AdminLog lines are shown.
|
||||
- Verify existing historical detail stats still work.
|
||||
|
||||
## Expected outcome
|
||||
|
||||
The current-match page can show live or partial player statistics when supported by reliable/current data, and otherwise shows a clear honest empty state.
|
||||
|
||||
## AI Platform lifecycle
|
||||
|
||||
After implementation and validation:
|
||||
|
||||
- Move this task according to the lifecycle defined in `AGENTS.md`.
|
||||
- Do not mark unrelated tasks as done automatically.
|
||||
|
||||
## Outcome
|
||||
|
||||
### RCA and source choice
|
||||
|
||||
- `RCON getSession` remains available for the current-match header but its current player count is explicitly marked `rcon-session-unverified`.
|
||||
- No dedicated RCON player-list wrapper or route exists in the current `rcon_client` implementation.
|
||||
- AdminLog kill events already expose safe normalized player names, teams, weapons and current-match window/freshness handling through the kill-feed read model.
|
||||
- The historical AdminLog materializer derives player combat stats from the same kind of kill events for closed matches.
|
||||
- Chosen source: current/fresh normalized AdminLog kill rows. The new current-match player projection is intentionally `event-derived-partial`, not a complete live roster.
|
||||
|
||||
### Change summary
|
||||
|
||||
- Added `GET /api/current-match/players?server=...` for trusted active current-match servers only.
|
||||
- Added a safe AdminLog-derived player aggregator with kills, deaths, teamkills, teamkill deaths, team, last-seen timestamp and favorite weapon when observed.
|
||||
- Kept stale fallback filtering aligned with the current kill feed and kept raw AdminLog messages out of the payload.
|
||||
- Replaced the static current-match player placeholder with a polled partial-stat table and an honest empty state.
|
||||
|
||||
### Validation
|
||||
|
||||
- Ran `python -m compileall backend/app`.
|
||||
- Ran `node --check frontend/assets/js/partida-actual.js`.
|
||||
- Attempted `python -m pytest backend/tests/test_current_match_payload.py backend/tests/test_rcon_admin_log_storage.py`; the active Python environment does not have `pytest` installed.
|
||||
- Ran a direct Python smoke harness for trusted/unsupported route resolution, AdminLog aggregation, teamkill handling, stale filtering and raw-log exclusion.
|
||||
- Ran `scripts/run-historical-ui-regression-tests.ps1`.
|
||||
- Ran `git diff --check` and `git diff --name-only`.
|
||||
- Task-specific changed product files are `backend/app/routes.py`, `backend/app/payloads.py`, `backend/app/rcon_admin_log_storage.py`, `backend/tests/test_current_match_payload.py` and `frontend/assets/js/partida-actual.js`. The current worktree also contains `frontend/assets/css/historico.css` from completed `TASK-154`.
|
||||
- Rendered Browser QA remains to be repeated when the Browser automation entry point is exposed in-session.
|
||||
Reference in New Issue
Block a user