Files
crypto_clash/docs/data-structure-diagram.md
2025-11-14 20:44:58 +01:00

258 lines
19 KiB
Markdown

# Game Contract Data Structure Diagram
## Overview
This diagram illustrates how the Game contract manages multiple concurrent games using mappings and arrays.
## Data Structure Visualization
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ GAME CONTRACT STATE │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. playerToActiveGame (mapping: address => uint) │
│ Maps each player address to their active game ID │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Player Address → Game ID │
│ ┌──────────────────┐ ┌───────┐ │
│ │ 0xABC...123 │ ──────→ │ 1 │ │
│ └──────────────────┘ └───────┘ │
│ │
│ ┌──────────────────┐ ┌───────┐ │
│ │ 0xDEF...456 │ ──────→ │ 1 │ (same game) │
│ └──────────────────┘ └───────┘ │
│ │
│ ┌──────────────────┐ ┌───────┐ │
│ │ 0xGHI...789 │ ──────→ │ 2 │ │
│ └──────────────────┘ └───────┘ │
│ │
│ ┌──────────────────┐ ┌───────┐ │
│ │ 0xJKL...012 │ ──────→ │ 0 │ (no active game) │
│ └──────────────────┘ └───────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 2. games (mapping: uint => GameState) │
│ Maps game ID to the complete game state │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Game ID Game State │
│ ┌───────┐ ┌────────────────────────────────────┐ │
│ │ 1 │ ───────────→ │ GameState { │ │
│ └───────┘ │ gameId: 1 │ │
│ │ isActive: true │ │
│ │ playerA: { │ │
│ │ addr: 0xABC...123 │ │
│ │ bet: 0.01 ETH │ │
│ │ encrMove: 0x4f2a... │ │
│ │ move: Rock │ │
│ │ } │ │
│ │ playerB: { │ │
│ │ addr: 0xDEF...456 │ │
│ │ bet: 0.01 ETH │ │
│ │ encrMove: 0x8b3c... │ │
│ │ move: Paper │ │
│ │ } │ │
│ │ outcome: PlayerB │ │
│ │ firstReveal: 1699876543 │ │
│ │ initialBet: 0.01 ETH │ │
│ │ } │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌───────┐ ┌────────────────────────────────────┐ │
│ │ 2 │ ───────────→ │ GameState { │ │
│ └───────┘ │ gameId: 2 │ │
│ │ isActive: true │ │
│ │ playerA: { addr: 0xGHI...789 } │ │
│ │ playerB: { addr: 0x000...000 } │ │
│ │ outcome: None │ │
│ │ ... │ │
│ │ } │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3. gameIds (array: uint[]) │
│ Tracks all game IDs for enumeration │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Index: 0 1 2 3 4 │
│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │
│ Value: │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ 5 │ ... │
│ └───┘ └───┘ └───┘ └───┘ └───┘ │
│ │
│ Used to iterate over all games (active and inactive) │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 4. pastGames (array: GameState[]) │
│ Stores completed games for historical reference │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Index: 0 1 │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ GameState { │ │ GameState { │ │
│ │ gameId: 1 │ │ gameId: 3 │ │
│ │ isActive: false │ │ isActive: false │ │
│ │ playerA: ... │ │ playerA: ... │ │
│ │ playerB: ... │ │ playerB: ... │ │
│ │ outcome: PlayerB │ │ outcome: Draw │ │
│ │ } │ │ } │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ Grows as games are completed via getOutcome() │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 5. nextGameId (uint counter) │
│ Auto-incrementing counter for unique game IDs │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Current Value: 6 ──→ Next game created will have ID = 6 │
│ │
│ Increments with each new game: createNewGame() │
└─────────────────────────────────────────────────────────────────────────────┘
```
## Flow Diagram: Player Lifecycle
```
┌──────────────────────────────────────────────────────────────────────────┐
│ PLAYER GAME LIFECYCLE │
└──────────────────────────────────────────────────────────────────────────┘
Player: 0xABC...123
│ register(0)
┌─────────────────────────────────────┐
│ 1. Check playerToActiveGame │
│ 0xABC...123 → 0 (not in game) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 2. findOrCreateGame() │
│ - Search for open game │
│ - Or create new game ID: 1 │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 3. Update mappings │
│ playerToActiveGame[0xABC] = 1 │
│ games[1].playerA = 0xABC...123 │
│ games[1].isActive = true │
│ gameIds.push(1) │
└─────────────────────────────────────┘
│ play(encrMove) → reveal(clearMove)
┌─────────────────────────────────────┐
│ 4. Game progresses │
│ Both players commit & reveal │
└─────────────────────────────────────┘
│ getOutcome()
┌─────────────────────────────────────┐
│ 5. Game completion │
│ - Calculate winner │
│ - pastGames.push(games[1]) │
│ - playerToActiveGame[0xABC] = 0 │
│ - playerToActiveGame[0xDEF] = 0 │
│ - games[1].isActive = false │
│ - Pay winners │
└─────────────────────────────────────┘
Player can register for new game
```
## Relationship Diagram
```
┌───────────────────────────────┐
│ Player Addresses │
│ (External participants) │
└──────────────┬────────────────┘
playerToActiveGame
│ (mapping)
┌───────────────────────────────┐
│ Game IDs │
│ (1, 2, 3, 4, 5...) │
└──────────────┬────────────────┘
┌──────────────┴────────────────┐
│ │
games (mapping) gameIds (array)
│ │
↓ ↓
┌─────────────────────┐ ┌────────────────┐
│ GameState Objects │ │ For iteration │
│ - Player data │ │ over all games│
│ - Moves │ └────────────────┘
│ - Outcomes │
│ - isActive flag │
└──────────┬──────────┘
When game completes (isActive = false)
┌──────────────────────┐
│ pastGames array │
│ (Historical record) │
└──────────────────────┘
```
## Key Relationships
1. **playerToActiveGame → games**:
- A player's address maps to a game ID
- That game ID is used to access the full game state in `games` mapping
2. **gameIds array**:
- Maintains list of all game IDs ever created
- Enables iteration over games (e.g., `getActiveGameIds()`)
- Never removes entries, only marks games inactive
3. **pastGames array**:
- Snapshot of completed games
- Grows with each completed game
- Provides historical game data
4. **nextGameId counter**:
- Ensures unique game IDs
- Increments with each new game
- Never resets, preventing ID collisions
## Data Flow Example: Two Players Join Game
```
Step 1: Player A registers
playerToActiveGame[PlayerA] = 0 → 1
games[1] = { playerA: PlayerA, playerB: null, isActive: true }
gameIds = [1]
Step 2: Player B joins same game
playerToActiveGame[PlayerB] = 0 → 1
games[1] = { playerA: PlayerA, playerB: PlayerB, isActive: true }
gameIds = [1] (unchanged)
Step 3: Game completes
pastGames.push(games[1]) → pastGames[0] = games[1]
playerToActiveGame[PlayerA] = 1 → 0
playerToActiveGame[PlayerB] = 1 → 0
games[1].isActive = true → false
gameIds = [1] (unchanged, but game is inactive)
```