feat: analyst insights batch 2 — 20 new individual player rules#245
Conversation
Add 20 new analyst insight rules for individual players (I1–I20): vision share, ward clears, objective/structure damage, CS, hero pool depth, first-death/early-death/pre-objective death rates, gold efficiency, and comfort overreliance. Includes EN/ES strings for all rules. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1f2a5ef7d0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const playerEventMatches = eventMatchIds.filter((mid) => | ||
| heroKills.some((k) => k.matchId === mid && (k.killedPlayerId === playerId || k.killerPlayerId === playerId)), | ||
| ); |
There was a problem hiding this comment.
Use played matches for first-death denominator
When a roster player played an event-stream match but had no hero kill or death in that match, this filters the match out of the denominator because it keys participation off heroKills involvement instead of the player's MatchPlayer row. That inflates fdPct for low-death/assist-only games; for example, 2 first deaths across 10 played matches can be reported as 40% if the player only had kills/deaths in 5 of them, incorrectly triggering this insight.
Useful? React with 👍 / 👎.
| const winRates = Object.entries(heroStats) | ||
| .map(([slug, v]) => { | ||
| const s = v as Record<string, unknown>; | ||
| const wins = (s?.wins as number) ?? 0; | ||
| const matches = (s?.matches as number) ?? 0; | ||
| return { slug, wr: matches > 0 ? wins / matches : 0 }; |
There was a problem hiding this comment.
Read hero slugs from snapshot heroData
Player snapshots store heroStats as an array of stat objects with the slug under heroData.slug (the sync code builds that shape), so Object.entries(heroStats) yields array indexes like "0", "1", etc. instead of hero slugs. In the comfort-overreliance rule, winRates.includes(topHero[0]) therefore never recognizes that the most-played hero is already top-3 by win rate, causing false overreliance insights whenever a player repeats a strong hero in at least 60% of recent games.
Useful? React with 👍 / 👎.
Implementa 20 nuevas reglas de análisis individual para jugadores (Batch 2).
Nuevas reglas
Riesgo y muertes (event stream)
Visión individual
Objetivos y estructuras (usa totalDamageDealtToObjectives/Structures)
Eficiencia y recursos
Farm y economía (por rol)
Hero pool y draft
Todas las reglas con texto EN/ES. Solo para equipos propios (no rival). Umbrales por rol donde aplica (support excluido de CS/objective damage).