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

19 KiB

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)