docs: add superlatives system design
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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<Socket>` 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
|
||||
Reference in New Issue
Block a user