From e54abdcbd26741c715f26ce0dae70cf0b564509f Mon Sep 17 00:00:00 2001 From: root Date: Sun, 8 Mar 2026 04:30:44 +0000 Subject: [PATCH] docs: add superlatives system design Co-Authored-By: Claude Opus 4.6 --- docs/plans/2026-03-08-superlatives-design.md | 120 +++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/plans/2026-03-08-superlatives-design.md diff --git a/docs/plans/2026-03-08-superlatives-design.md b/docs/plans/2026-03-08-superlatives-design.md new file mode 100644 index 0000000..c147ed5 --- /dev/null +++ b/docs/plans/2026-03-08-superlatives-design.md @@ -0,0 +1,120 @@ +# Superlatives System Design + +## Overview + +A slide-out panel on the left edge of the screen showing NPC superlatives — who holds the extreme values across relationship categories. Available in both camera and follow modes. Clicking an NPC name enters follow mode for that NPC. + +## Data Model + +### SuperlativeEntry +```typescript +interface SuperlativeEntry { + entityId: EntityId; + name: string; + value: number; // the relevant score +} +``` + +### SuperlativesData +```typescript +interface SuperlativesData { + mostLoved: SuperlativeEntry | null; + mostPopular: SuperlativeEntry | null; + mostReviled: SuperlativeEntry | null; + mostAnnoying: SuperlativeEntry | null; + shyest: SuperlativeEntry | null; + mostOutgoing: SuperlativeEntry | null; + biggestHeartbreaker: SuperlativeEntry | null; + mostDevoted: SuperlativeEntry | null; + loneliest: SuperlativeEntry | null; + mostPolarizing: SuperlativeEntry | null; + socialButterfly: SuperlativeEntry | null; +} +``` + +### Category Definitions + +| Category | Metric | Value Shown | +|----------|--------|-------------| +| Most Loved | Highest single incoming relationship value | That relationship value | +| Most Popular | Highest average incoming relationship value | The average | +| Most Reviled | Lowest single incoming relationship value | That relationship value | +| Most Annoying | Lowest average incoming relationship value | The average | +| Shyest | Fewest active relationships | Count | +| Most Outgoing | Most active relationships | Count | +| Biggest Heartbreaker | Most former partner bonds | Count | +| Most Devoted | Highest mutual relationship average (both directions) | Average of both | +| Loneliest | Most memory-status relationships (lost connections) | Count | +| Most Polarizing | Highest variance in incoming relationship values | Standard deviation | +| Social Butterfly | Most partners + close friends combined | Count | + +Minimum thresholds apply to avoid trivial winners (e.g., "most popular" requires at least 2 incoming relationships). + +## Server Computation + +A `computeSuperlatives()` function iterates all NPCs with relationship components in a single pass, accumulating per-NPC incoming values, counts, and bond stats. Then reduces per category to find the winner. + +Requires access to: all Relationships components, BondRegistry, entity names. + +## Socket Protocol + +### Events +- **Client -> Server:** `superlatives-subscribe` — panel opened, no payload +- **Client -> Server:** `superlatives-unsubscribe` — panel closed, no payload +- **Server -> Client:** `superlatives-update` — SuperlativesData payload + +### Server Lifecycle +- Tracks `Set` of subscribed clients +- On subscribe: compute immediately and emit to that client, add to set +- On unsubscribe / disconnect: remove from set +- `setInterval(10000)` runs only while set is non-empty (starts on first subscriber, clears when last unsubscribes) +- When interval fires: compute once, broadcast to all subscribers + +## Client UI + +### Collapsed State (Tab) +- Fixed to left edge, vertically centered +- Small tab showing "S" in Press Start 2P font +- Right side has double-border frame matching existing panels, left side flush with screen edge +- Subtle hover effect (slight rightward shift or color change) +- Click to expand + +### Expanded State +- Slides out from left edge using `translateX` animation (matching NpcInfoPanel pattern) +- ~260px wide, EarthBound double-border styling +- Header: "SUPERLATIVES" centered +- Categories listed showing: label in dim text, NPC name as clickable link + value in parentheses +- Null entries show dash or are hidden +- Scrollable if content overflows +- Click tab or close area to collapse + +### Category Display Order (paired opposites) +1. Most Loved / Most Reviled (extremes) +2. Most Popular / Most Annoying (averages) +3. Most Outgoing / Shyest (counts) +4. Social Butterfly / Loneliest (connections) +5. Most Devoted / Most Polarizing (relationship quality) +6. Biggest Heartbreaker (bonds) + +### Interaction +- Clicking NPC name: enters follow mode for that entity, panel auto-collapses +- Panel emits DOM custom event `superlative-follow` with entityId +- GameScene listens and triggers follow mode logic +- Subscribe on expand, unsubscribe on collapse + +## Integration + +### GameScene +- `SuperlativesPanel` instantiated in constructor alongside existing panels +- Tab visible in both camera and follow modes +- GameScene manages socket subscribe/unsubscribe triggered by panel open/close callbacks +- On `superlatives-update` event, passes data to `superlativesPanel.update(data)` + +### New Files +- `client/src/ui/SuperlativesPanel.ts` — panel UI component +- `server/src/systems/superlativesComputer.ts` — computation logic +- `shared/src/types.ts` — SuperlativeEntry and SuperlativesData types added + +### Modified Files +- `server/src/main.ts` — socket event handlers for subscribe/unsubscribe +- `client/src/scenes/GameScene.ts` — panel instantiation, socket integration, follow mode trigger