Files
comunidadhll/docs/monthly-mvp-v2-scoring-design.md
devRaGonSa 0da8338ba8 Fix
2026-06-05 16:57:25 +02:00

244 lines
7.0 KiB
Markdown

# Monthly MVP V2 Scoring Design
## Validation Date
- 2026-03-24
## Objective
Definir una formula V2 precisa, explicable e implementable para el MVP mensual
usando la base V1 ya aprobada y solo las senales avanzadas V2 que hoy tienen
soporte real en la repo.
## Evidence Base
This proposal is based on:
- `docs/monthly-mvp-ranking-scoring-design.md`
- `docs/monthly-player-ranking-data-audit.md`
- `docs/player-event-pipeline-v2-design.md`
- `backend/app/monthly_mvp.py`
- `backend/app/player_event_aggregates.py`
- `backend/app/historical_snapshots.py`
- `backend/app/payloads.py`
## Design Position
V2 should not replace the V1 logic with a radically different opaque model.
The correct direction is:
- keep V1 as the stable baseline
- preserve the same monthly UTC window and closed-match policy
- add a small set of advanced event-derived signals with limited weight
- avoid weapon-type or kill-type complexity until the source is richer
## Meaning Of MVP In V2
V2 still means "best monthly player", not "best fragger only".
Compared with V1, V2 should reward:
- sustained offensive output
- team contribution
- efficiency over the month
- cleaner player-vs-player control in repeated encounters
- better discipline through a stricter teamkill penalty
## Signals Included In V2
V2 keeps these V1 signals:
- total kills
- total support
- KPM recomputed from monthly totals
- KDA recomputed from monthly totals
- participation based on monthly time played
- monthly teamkills as penalty input
V2 adds these advanced signals:
- `most_killed`
- `death_by`
- net duel summaries
These signals are used only as modest scoring components, not as the core of
the ranking.
## Signals Explicitly Excluded From V2 Formula
Do not score these yet:
- weapon-type weighting
- kill-category weighting
- weapon variety bonus
- `death_by_weapons`
- combat, offense and defense
- win/loss context
Reason:
- the current CRCON-derived V2 layer is partial and summary-based
- weapon and type semantics are not robust enough for a serious weighted score
- adding too many low-confidence knobs would make V2 harder to defend than V1
Weapon kills remain useful for product readouts and future analysis, but not as
a weighted scoring factor in this phase.
## Eligibility Rules
Player eligibility for V2 should remain identical to V1:
- at least `6` closed matches in the selected month and scope
- at least `21600` seconds (`6` hours) played in the selected month and scope
- non-null monthly totals for kills, deaths, support and time
Additional publication gate for the ranking itself:
- publish V2 only when the selected month and scope have matching player-event
coverage for that same `month_key`
This avoids ranking a month with V1 totals but missing V2 event coverage.
## Derived Advanced Metrics
For each eligible player-month, derive:
- `most_killed_count`
- kills against the player most often killed by this player in the month
- `death_by_count`
- deaths suffered from the player that killed this player most often in the
month
- `rivalry_edge_raw = max(0, most_killed_count - death_by_count)`
- `duel_control_raw`
- sum of positive `net_duel_value` across the player's top `3` duel pairs in
the selected month and scope
Then normalize:
- `rivalry_edge_score = 100 * ln(1 + rivalry_edge_raw) / ln(1 + max_rivalry_edge_raw_eligible)`
- `duel_control_score = 100 * ln(1 + duel_control_raw) / ln(1 + max_duel_control_raw_eligible)`
## Small-Sample Treatment
Advanced event signals should be damped on low-volume months.
Use:
- `advanced_confidence = min(1, total_kills / 35)`
Effect:
- under `35` kills, advanced components contribute only partially
- at `35+` kills, the full advanced weight is available
This keeps V2 from overreacting to tiny rivalry samples.
## Normalized Core Component Scores
V2 keeps the same V1 normalization style on a `0..100` scale:
- `kills_score = 100 * ln(1 + total_kills) / ln(1 + max_total_kills_eligible)`
- `support_score = 100 * ln(1 + total_support) / ln(1 + max_total_support_eligible)`
- `kpm_score = 100 * ln(1 + kpm) / ln(1 + max_kpm_eligible)`
- `kda_score = 100 * ln(1 + kda) / ln(1 + max_kda_eligible)`
- `participation_score = 100 * min(1, total_time_seconds / 28800)`
## V2 Teamkill Penalty
V2 should be slightly stricter than V1 on discipline.
Use:
- `teamkill_penalty_v2 = min(8, total_teamkills * 0.75)`
Effect:
- `1` teamkill subtracts `0.75`
- `4` teamkills subtract `3`
- penalty caps at `8`
## V2 Scoring Formula
Recommended V2 monthly MVP score:
`mvp_v2_score = 0.30 * kills_score + 0.18 * support_score + 0.18 * kpm_score + 0.12 * kda_score + 0.10 * participation_score + advanced_confidence * (0.07 * rivalry_edge_score + 0.05 * duel_control_score) - teamkill_penalty_v2`
Weight rationale:
- `30%` kills keeps offense as the main visible driver
- `18%` support preserves MVP rather than pure frag logic
- `18%` KPM rewards productive time
- `12%` KDA rewards cleaner performance without dominating the table
- `10%` participation keeps monthly presence relevant
- `7%` rivalry edge rewards players who repeatedly finish ahead in their
strongest recurring encounter
- `5%` duel control adds a second advanced signal but keeps it clearly bounded
## Why Weapon Kills Are Not Weighted Yet
The repository can already expose kills by weapon, but the current source layer:
- is summary-based, not a full raw kill feed
- does not yet prove a stable weapon taxonomy for competitive weighting
- would invite fragile distinctions such as tank vs infantry vs artillery too
early
Decision:
- do not weight kills by weapon in V2
- do not assign bonus or penalty by weapon type
- keep weapon-kill outputs as audit and UI-facing data only
## Tie-Break Rules
If two players have the same `mvp_v2_score`, resolve ties in this order:
1. higher `advanced_confidence`
2. higher `participation_score`
3. higher `kills_score`
4. higher `rivalry_edge_score`
5. lower `total_teamkills`
6. alphabetical `display_name`
7. stable player key as final deterministic fallback
## Coexistence With V1
V1 and V2 should coexist explicitly:
- `V1` remains the stable default ranking
- `V2` is a separate ranking version with its own `ranking_version`
- both versions should use the same month and scope selectors
- V2 should never overwrite or reinterpret the V1 payload contract
## Implementation Guidance For Next Task
The backend task should compute V2 from:
- the same monthly player totals already used by V1
- direct player-event monthly aggregates derived from the raw ledger
Required per-player V2 outputs:
- `mvp_v2_score`
- `advanced_confidence`
- `rivalry_edge_raw`
- `duel_control_raw`
- `component_scores`
- `teamkill_penalty_v2`
Recommended `ranking_version`:
- `v2`
## Final Recommendation
The correct V2 for the current repository is an incremental evolution of V1:
- keep the same explainable weighted-score structure
- add only `most_killed` / `death_by` / duel-derived pressure signals
- make discipline stricter
- refuse weapon-type weighting until the signal quality improves
This yields a V2 that is materially richer than V1 without becoming speculative.