# Architecture Diagram

## System Overview

```
┌────────────────────────────────────────────────────────────────┐
│                     CLIENT APPLICATIONS                         │
│                                                                 │
│  ┌───────────────────┐         ┌───────────────────┐          │
│  │  Settlers Game    │         │   Chat Room App   │          │
│  │  ┌─────────────┐  │         │  ┌─────────────┐  │          │
│  │  │ Game UI     │  │         │  │ Chat UI     │  │          │
│  │  │ - Board     │  │         │  │ - Messages  │  │          │
│  │  │ - Actions   │  │         │  │ - Input     │  │          │
│  │  └─────────────┘  │         │  └─────────────┘  │          │
│  │                    │         │                    │          │
│  │  Uses:             │         │  Uses:             │          │
│  │  ┌──────────────────────────────────────────┐   │          │
│  │  │      REUSABLE COMPONENTS                 │   │          │
│  │  │  • MediaControl (Video/Audio UI)         │   │          │
│  │  │  • MediaAgent (WebRTC Signaling)         │   │          │
│  │  │  • PlayerList (Participant Display)      │   │          │
│  │  └──────────────────────────────────────────┘   │          │
│  └───────────────────┘         └───────────────────┘          │
└────────────────────────────────────────────────────────────────┘
                            │
                            │ WebSocket
                            ↓
┌────────────────────────────────────────────────────────────────┐
│                         SERVER LAYERS                           │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │             APPLICATION LAYER (App-Specific)             │  │
│  │                                                          │  │
│  │  Settlers Game              │    Chat App               │  │
│  │  ┌────────────────────┐     │    ┌───────────────────┐  │  │
│  │  │ GameSessionMeta    │     │    │ ChatSessionMeta   │  │  │
│  │  │ - color            │     │    │ - status          │  │  │
│  │  │ - player           │     │    │ - messageCount    │  │  │
│  │  │ - resources        │     │    │ - customStatus    │  │  │
│  │  └────────────────────┘     │    └───────────────────┘  │  │
│  │                             │                           │  │
│  │  ┌────────────────────┐     │    ┌───────────────────┐  │  │
│  │  │ GameRoomMeta       │     │    │ ChatRoomMeta      │  │  │
│  │  │ - players          │     │    │ - messages        │  │  │
│  │  │ - board setup      │     │    │ - topic           │  │  │
│  │  │ - game rules       │     │    │ - pinnedMessages  │  │  │
│  │  └────────────────────┘     │    └───────────────────┘  │  │
│  │                                                          │  │
│  │  Message Handlers:           │    Message Handlers:      │  │
│  │  • set color                 │    • send message         │  │
│  │  • place settlement          │    • set status           │  │
│  │  • trade resources            │    • pin message          │  │
│  └──────────────────────────────────────────────────────────┘  │
│                            │                                    │
│                            │ uses metadata                      │
│                            ↓                                    │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │         ADAPTER LAYER (Optional Compatibility)           │  │
│  │                                                          │  │
│  │  Proxy Handlers:                                        │  │
│  │  • session.color ─────→ session.metadata.color          │  │
│  │  • session.player ────→ session.metadata.player         │  │
│  │  • game.players ──────→ game.metadata.players           │  │
│  │                                                          │  │
│  │  Enables backward compatibility without code changes    │  │
│  └──────────────────────────────────────────────────────────┘  │
│                            │                                    │
│                            │ wraps                              │
│                            ↓                                    │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │        INFRASTRUCTURE LAYER (Reusable Framework)         │  │
│  │                                                          │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │                Session Management                  │  │  │
│  │  │  • BaseSession (id, name, ws, live, has_media)    │  │  │
│  │  │  • Session<TMeta> (+ metadata field)              │  │  │
│  │  │  • createBaseSession()                            │  │  │
│  │  │  • updateSessionActivity()                        │  │  │
│  │  │  • isSessionActive()                              │  │  │
│  │  │  • getSessionName()                               │  │  │
│  │  └────────────────────────────────────────────────────┘  │  │
│  │                                                          │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │                 Room Management                    │  │  │
│  │  │  • BaseRoom (id, name, sessions, state)           │  │  │
│  │  │  • Room<TMeta> (+ metadata field)                 │  │  │
│  │  │  • getParticipants()                              │  │  │
│  │  │  • getActiveSessions()                            │  │  │
│  │  │  • cleanupInactiveSessions()                      │  │  │
│  │  └────────────────────────────────────────────────────┘  │  │
│  │                                                          │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │              WebRTC Signaling                      │  │  │
│  │  │  • join() - Add peer to registry                  │  │  │
│  │  │  • part() - Remove peer from registry             │  │  │
│  │  │  • relayICECandidate() - Forward ICE              │  │  │
│  │  │  • relaySessionDescription() - Forward SDP        │  │  │
│  │  │  • PeerRegistry - Track peer connections          │  │  │
│  │  └────────────────────────────────────────────────────┘  │  │
│  │                                                          │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │             WebSocket Handling                     │  │  │
│  │  │  • Connection management                           │  │  │
│  │  │  • Automatic reconnection                          │  │  │
│  │  │  • Message routing                                 │  │  │
│  │  │  • Keep-alive pings                                │  │  │
│  │  └────────────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────┘
```

## Data Flow: Setting User Name

```
┌─────────────┐
│   CLIENT    │
└─────────────┘
      │
      │ 1. User types name "Alice"
      │
      ↓
  sendJsonMessage({
    type: "set",
    field: "name",
    value: "Alice"
  })
      │
      │ WebSocket
      ↓
┌─────────────────────────────────────────┐
│            SERVER                       │
│                                         │
│  Infrastructure Layer:                  │
│  ├─ Receive message                     │
│  ├─ Find session by WebSocket           │
│  └─ Route to handler                    │
│                                         │
│  Application Layer:                     │
│  ├─ session.name = "Alice"              │
│  └─ Broadcast to all sessions           │
│                                         │
│  Infrastructure Layer:                  │
│  └─ getParticipants(room.sessions)      │
│     └─ Returns: [                       │
│         { session_id, name: "Alice",    │
│           live: true, has_media: true } │
│       ]                                 │
└─────────────────────────────────────────┘
      │
      │ Broadcast update
      ↓
┌─────────────┐
│  ALL CLIENTS│
└─────────────┘
      │
      │ Receive participants update
      ↓
  PlayerList rerenders
  with "Alice" shown
```

## Data Flow: Joining Video Call

```
┌─────────────┐
│   CLIENT    │
└─────────────┘
      │
      │ 1. MediaAgent mounts
      │ 2. Gets user media (camera/mic)
      │
      ↓
  sendJsonMessage({
    type: "join",
    data: { has_media: true }
  })
      │
      │ WebSocket
      ↓
┌──────────────────────────────────────────┐
│           SERVER                         │
│                                          │
│  Infrastructure Layer (WebRTC):          │
│  ├─ join(peers, session, { has_media }) │
│  │                                       │
│  │  For each existing peer:              │
│  │  ├─ Send addPeer to existing peer    │
│  │  │   { peer_id: "Alice",             │
│  │  │     peer_name: "Alice",           │
│  │  │     has_media: true,              │
│  │  │     should_create_offer: false }  │
│  │  │                                   │
│  │  └─ Send addPeer to new peer         │
│  │      { peer_id: "Bob",               │
│  │        peer_name: "Bob",             │
│  │        has_media: true,              │
│  │        should_create_offer: true }   │
│  │                                       │
│  └─ Add to peer registry:                │
│      peers["Alice"] = {                  │
│        ws, has_media: true               │
│      }                                   │
│                                          │
│  └─ Send join_status:                    │
│      { type: "join_status",              │
│        status: "Joined" }                │
└──────────────────────────────────────────┘
      │
      │ Relay messages
      ↓
┌─────────────┐
│  ALL CLIENTS│
└─────────────┘
      │
      │ Each client:
      ├─ Creates RTCPeerConnection
      ├─ Adds local media tracks
      ├─ Creates offer/answer
      └─ Exchanges ICE candidates
      │
      ↓
  Peer-to-peer video/audio flows
```

## Data Flow: Game-Specific Action

```
┌─────────────┐
│  GAME CLIENT│
└─────────────┘
      │
      │ Player clicks "Blue" color
      │
      ↓
  sendJsonMessage({
    type: "set",
    field: "color",
    value: "blue"
  })
      │
      │ WebSocket
      ↓
┌───────────────────────────────────────────┐
│            SERVER                         │
│                                           │
│  Infrastructure Layer:                    │
│  ├─ Route message to app handler          │
│  └─ session object available              │
│                                           │
│  Adapter Layer (optional):                │
│  └─ Wraps session with proxy              │
│                                           │
│  Application Layer (Game):                │
│  ├─ setPlayerColor(game, session, "blue")│
│  │   ├─ Validate color available         │
│  │   ├─ session.color = "blue"           │  ← Direct access
│  │   │   (or session.metadata.color)     │  ← New arch
│  │   ├─ session.player = gamePlayer      │
│  │   └─ Update game.metadata.players     │
│  │                                        │
│  └─ Broadcast update:                     │
│      participants: [                      │
│        {                                  │
│          ...baseParticipant,              │  ← Infrastructure
│          color: "blue"                    │  ← App-specific
│        }                                  │
│      ]                                    │
└───────────────────────────────────────────┘
      │
      │ Broadcast
      ↓
┌─────────────┐
│  ALL CLIENTS│
└─────────────┘
      │
      │ Update UI
      ↓
  PlayerList shows
  "Alice" with blue color
```

## Metadata Access Patterns

### Without Adapter (New Code)

```typescript
// Explicit metadata access
const color = session.metadata?.color;
session.metadata = { ...session.metadata, color: 'blue' };

const players = room.metadata.players;
room.metadata.players['blue'] = newPlayer;
```

### With Adapter (Backward Compatible)

```typescript
// Same as before - adapter proxies to metadata
const color = session.color;
session.color = 'blue';

const players = room.players;
room.players['blue'] = newPlayer;
```

Both work! Adapter allows gradual migration.

## Reusability Layers

```
Application A (Settlers)    Application B (Chat)    Application C (Whiteboard)
        │                          │                        │
        ├── GameSessionMeta        ├── ChatSessionMeta      ├── WhiteboardSessionMeta
        │   - color                │   - status             │   - cursorColor
        │   - player               │   - messageCount       │   - selectedTool
        │                          │                        │
        └─────────────┬────────────┴────────────────────────┘
                      │
                      │ All apps extend base types
                      ↓
        ┌─────────────────────────────────┐
        │   INFRASTRUCTURE (Shared)       │
        │  • Session<TMeta>               │
        │  • Room<TMeta>                  │
        │  • MediaControl (WebRTC)        │
        │  • getParticipants()            │
        │  • Session management           │
        └─────────────────────────────────┘
                      ↑
            Single implementation,
            works for all apps!
```

## Summary

This architecture provides:

✅ **Clean separation** between infrastructure and application
✅ **Type-safe metadata** for app-specific data
✅ **Reusable components** that work across applications
✅ **Backward compatibility** via adapter layer
✅ **Clear data flows** from client to server to all clients
✅ **Proven patterns** ready for production use

Any new application can plug into the infrastructure and get:
- Multi-user rooms
- WebSocket connection management
- WebRTC video/audio signaling
- Participant tracking
- UI components (MediaControl)

All for free! Just define your metadata types and business logic.
