Skip to content

feat(archives): players-over-time chart (replaces player engagement)#448

Merged
elfensky merged 5 commits into
developfrom
feature/players-over-time
Jun 28, 2026
Merged

feat(archives): players-over-time chart (replaces player engagement)#448
elfensky merged 5 commits into
developfrom
feature/players-over-time

Conversation

@elfensky

Copy link
Copy Markdown
Owner

Replaces the per-event Player Engagement scatter with a per-war player-count line over time, with war events mapped onto it — as discussed.

Behavior (hooks into the existing faction toggle)

  • Global → total-players line (brand primary) + dots for every event
  • A faction → that faction's line (faction-colored) + only its events' dots
  • Event dots sit on the line at each event's start day; hover → type · region · faction · outcome
  • No legend (the faction toggle labels the line — also sidesteps the legend/axis-label overlap bug that kicked this off)
  • Telemetry seasons only — hides for historical wars with no bucketed player data

Implementation

  • getCampaign: additive playerTimeseries field (per-bucket player counts from h1_statistic via a new groupStatisticByBucket, mirroring groupStatusByBucket); [] for pre-telemetry seasons. Verified additive — no existing consumer changes.
  • buildPlayerLine.mjs: pure, unit-tested builder (line points + event dots, faction-driven).
  • PlayersOverTimeChart.jsx (+ …Loader), wired into ArchivesClient's faction section.
  • Removed: PlayerEngagementChart.jsx, PlayerEngagementChartLoader.jsx, buildEngagementSeries.mjs (+ test).

Verification

✅ lint (0 err) · typecheck · test:unit (1514) · build — node 24.
DevTools, live (Chrome MCP), all confirmed:

  • global = yellow primary line, no legend, no axis-label overlap
  • Bugs toggle → line recolors #e8822a, dots filter 25→1, faction-colored
  • pre-telemetry season 120 → chart + section correctly hidden

⚠️ Notes for review

🤖 Generated with Claude Code

elfensky and others added 5 commits June 27, 2026 00:34
…catter)

Replace the per-event Player Engagement scatter with a per-war player-count
line that hooks into the existing /archives faction toggle:
- global → total-players line (brand primary) + dots for every event
- a faction → that faction's line (faction-colored) + only its events' dots
Event dots sit on the line at each event's start day with a
type · region · faction · outcome tooltip. No legend (the toggle labels it).

- getCampaign: additive `playerTimeseries` field (per-bucket players from
  h1_statistic via new groupStatisticByBucket); [] for pre-telemetry seasons.
- buildPlayerLine.mjs: pure, unit-tested line+dots builder.
- PlayersOverTimeChart.jsx (+ Loader), wired into ArchivesClient's faction
  section; removed PlayerEngagementChart + buildEngagementSeries (+ scatter).
- Hides for historical seasons with no player timeseries.

Verified: lint, typecheck, test:unit (1514), build; DevTools across all toggle
states + hide-when-empty on a telemetry-less season.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The x-axis plotted the integer day, so multiple intra-day buckets collapsed
onto one column and the line drew vertical stacks instead of a real time
series. Use continuous (fractional) day-into-war anchored to war_start, and
switch the line from monotone to linear so sharp changes read as honest cliffs
rather than smoothed curves.

- buildPlayerLine: `warStart` param; fractional `dayInto` x for points + dots
- PlayersOverTimeChart: declares `warStart`, line type="linear"
- ArchivesClient: passes `warStart={data?.war_start}`
- tests: fractional-x dot, intra-day-distinct-x regression, warStart anchor

Verified: lint, typecheck, test:unit (1516), build; DevTools on S157 — x is
strictly increasing, no vertical collapse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Show a tick for every day (D0…D<last>) instead of the ~5 auto-thinned ticks,
and anchor the axis 0-based to war_start so the day labels match Conquest
Progress for side-by-side reading. The line stays time-proportional (continuous
fractional x); only the tick set and base changed.

- buildPlayerLine: 0-based dayInto (drop the +1)
- PlayersOverTimeChart: explicit ticks=[0..lastDay], domain=[0, lastDay]
- tests updated to the 0-based convention

Verified: lint, typecheck, test:unit (1516), build; DevTools S157 shows D0…D40.
Two fixes for the players-over-time chart and its comparability with
Conquest Progress (FactionHealthChart):

1. Tooltip was stuck on one event regardless of cursor. It read the dots
   Scatter (a separate data array from the line), whose payload doesn't follow
   the active index. Rewrote it to read the LINE series + active `label` —
   showing "Day N · M players" at the hovered point, with the event details
   appended when an event sits on that day.

2. Conquest Progress used a category x-axis (one slot per snapshot, not
   time-proportional, duplicate day labels). Gave it the same continuous,
   0-based, time-proportional day axis as players-over-time, and a SHARED
   day-domain (warDayMax, passed to both) so the two charts line up day-for-day.

- FactionHealthChart: fractional 0-based day, type=number XAxis, all-day ticks,
  warStart + domainMax props; ChartTooltip rounds the day.
- PlayersOverTimeChart: PlayerTooltip reads line+label+event; domainMax prop.
- ArchivesClient: computes warDayMax, passes warStart+domainMax to both charts.
- Tests: FactionHealthChart intra-day fractional-day regression.

Verified: lint, typecheck, test:unit, build; DevTools — both axes D0-based,
time-proportional, shared [0,44] domain; tooltip reads the hovered line point.
…cursor

The players-over-time tooltip froze past the first few days. The <Scatter> held
its OWN short data array (~25-78 dots) inside a ComposedChart whose single
activeTooltipIndex sweeps the ~600-point line; past the scatter's indices
recharts clamped the index and froze the tooltip. Conquest Progress never broke
because all its series share one data array.

Render events as <ReferenceDot> markers (non-data decorators) instead of a
Scatter, so the Line is the SOLE tooltip data source — like Conquest. The
tooltip now reports the player count (+ event) at every hovered day.

Root cause + fix from a four-way debate (Opus/Sonnet/Codex/Gemini): unanimous
on the cause, 3/4 on ReferenceDots over Gemini's unified-data merge.

Verified: lint, typecheck, test:unit, build; DevTools differential sweep —
Players now tracks D6/186 → D28/168 → D34/166, identical behaviour to Conquest.
@elfensky elfensky merged commit 8668322 into develop Jun 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant