Document teamkills ranking zero audit
This commit is contained in:
128
ai/tasks/done/TASK-251-investigate-teamkills-ranking-zeroes.md
Normal file
128
ai/tasks/done/TASK-251-investigate-teamkills-ranking-zeroes.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# TASK-251 - Investigate teamkills ranking zeroes
|
||||
|
||||
## Summary
|
||||
|
||||
This task audits why annual `teamkills` ranking data is missing or zeroed in practice.
|
||||
|
||||
No fix was implemented because the issue is upstream from the public ranking UI and needs a source decision first.
|
||||
|
||||
## Files Read First
|
||||
|
||||
- `backend/app/rcon_admin_log_parser.py`
|
||||
- `backend/app/rcon_admin_log_storage.py`
|
||||
- `backend/app/rcon_admin_log_materialization.py`
|
||||
- `backend/app/rcon_historical_player_stats.py`
|
||||
- `backend/app/rcon_annual_rankings.py`
|
||||
- `backend/app/routes.py`
|
||||
- `backend/tests/test_rcon_materialization_pipeline.py`
|
||||
|
||||
## Findings
|
||||
|
||||
### 1. Parser support exists
|
||||
|
||||
The parser already extracts:
|
||||
|
||||
- `killer_team`
|
||||
- `victim_team`
|
||||
|
||||
The materialization code already increments:
|
||||
|
||||
- `teamkills`
|
||||
- `deaths_by_teamkill`
|
||||
|
||||
when `killer_team == victim_team`.
|
||||
|
||||
Tests already cover this logic.
|
||||
|
||||
### 2. Local match facts contain no positive teamkills
|
||||
|
||||
Read-only local checks on `backend/data/hll_vietnam_dev.sqlite3` show:
|
||||
|
||||
- `rcon_admin_log_events` has many `kill` rows
|
||||
- `rcon_match_player_stats where teamkills > 0` returns zero rows
|
||||
- `rcon_annual_ranking_snapshot_items where teamkills > 0` returns zero rows
|
||||
|
||||
### 3. Local kill events contain no same-team kills
|
||||
|
||||
Read-only checks on parsed event payloads show:
|
||||
|
||||
- kill payloads include `killer_team` and `victim_team`
|
||||
- but the local dataset contains zero `kill` rows where both teams are equal
|
||||
|
||||
That means the materialized player facts never receive a positive `teamkills` increment in this dataset.
|
||||
|
||||
### 4. Player profile snapshots do contain teamkill totals
|
||||
|
||||
`rcon_player_profile_snapshots` contains positive values for:
|
||||
|
||||
- `teamkills_done`
|
||||
- `teamkills_received`
|
||||
|
||||
So the broader AdminLog/profile ecosystem does know about teamkills somewhere, but those totals are:
|
||||
|
||||
- lifetime-oriented
|
||||
- not tied to one exact closed match window
|
||||
- not directly usable for annual or per-match ranking backfills without a separate design
|
||||
|
||||
### 5. Annual public ranking payload currently returns empty for teamkills
|
||||
|
||||
Production and local checks both show:
|
||||
|
||||
- `/api/ranking?timeframe=annual&metric=teamkills&...` returns `items = []`
|
||||
|
||||
So the user-visible issue is not a frontend parse bug. It is a data-source gap for annual teamkill ranking inputs.
|
||||
|
||||
## Cause Probable
|
||||
|
||||
The annual ranking consumes `rcon_match_player_stats.teamkills`.
|
||||
|
||||
That field is derived from same-team `kill` events in the materialized AdminLog match stream.
|
||||
|
||||
In the audited dataset:
|
||||
|
||||
- same-team `kill` events are not present
|
||||
- therefore `rcon_match_player_stats.teamkills` stays at zero
|
||||
- therefore annual `teamkills` ranking has no rows
|
||||
|
||||
Meanwhile, profile snapshots expose lifetime teamkill totals, but they are not an annual closed-match ranking source.
|
||||
|
||||
## Decision
|
||||
|
||||
Do not patch the public ranking UI.
|
||||
|
||||
Do not inject lifetime `teamkills_done` into annual ranking, because that would mix incompatible time models.
|
||||
|
||||
Do not fabricate teamkills from unrelated signals.
|
||||
|
||||
## Follow-up Direction
|
||||
|
||||
The next correct task should choose one of these paths explicitly:
|
||||
|
||||
1. Confirm whether the real RCON/AdminLog kill stream should include same-team kills and why they are absent.
|
||||
2. If same-team kills are absent by product/API behavior, define a separate ranking source for teamkills.
|
||||
3. If an alternate raw source exists, backfill `rcon_match_player_stats.teamkills` from that source with tests.
|
||||
|
||||
## Validation
|
||||
|
||||
Read-only checks executed:
|
||||
|
||||
- local SQLite schema audit for:
|
||||
- `rcon_admin_log_events`
|
||||
- `rcon_match_player_stats`
|
||||
- `rcon_annual_ranking_snapshots`
|
||||
- `rcon_annual_ranking_snapshot_items`
|
||||
- local count of `event_type='kill'`
|
||||
- local count of `teamkills > 0` in materialized player stats
|
||||
- local count of same-team parsed kill events
|
||||
- local inspection of `parsed_payload_json` samples
|
||||
- local inspection of `rcon_player_profile_snapshots.teamkills_done/teamkills_received`
|
||||
- production endpoint checks for:
|
||||
- annual all-servers teamkills ranking
|
||||
- annual comunidad-hispana-01 teamkills ranking
|
||||
- annual comunidad-hispana-02 teamkills ranking
|
||||
|
||||
## Notes
|
||||
|
||||
- No backend code changed.
|
||||
- No frontend code changed for this audit.
|
||||
- No migrations or data writes were performed.
|
||||
Reference in New Issue
Block a user