Files
BreakEscape/MODULE_ARCHITECTURE.md

35 KiB

Lockpicking Minigame - Module Architecture Diagram# Module Architecture Reference

Current Monolithic Architecture## Current Module Structure


┌─────────────────────────────────────────────────────────────────┐**File**: `js/minigames/lockpicking/lock-renderer.js`

│         LockpickingMinigamePhaser (4670 lines)                  │**Lines**: ~700

│                                                                  │**Dependencies**: Phaser Scene (passed via parent)

│  ┌────────────────────────────────────────────────────────┐   │**Status**: Ready for production

│  │ Constructor                                            │   │

│  │  - Lock configuration                                 │   │```

│  │  - Game state initialization                          │   │LockRenderer

│  │  - Settings (difficulty, mode, etc.)                  │   │├── Constructor(parentScene)

│  └────────────────────────────────────────────────────────┘   ││   ├── this.parent = parentScene

│                                                                  ││   ├── this.scene = parentScene.scene

│  ┌────────────────────────────────────────────────────────┐   ││   └── Property initialization

│  │ Configuration Management                               │   ││

│  │  - saveLockConfiguration()                             │   │├── Lock Visual Components

│  │  - loadLockConfiguration()                             │   ││   ├── createLockBackground()

│  │  - clearLockConfiguration()                            │   ││   ├── createShearLine()

│  └────────────────────────────────────────────────────────┘   ││   ├── createPins()

│                                                                  ││   │   ├── Pin container creation

│  ┌────────────────────────────────────────────────────────┐   ││   │   ├── Spring, driver pin, key pin graphics

│  │ Graphics Rendering                                     │   ││   │   ├── Highlight overlays

│  │  - createLockBackground()                              │   ││   │   ├── Channel rectangles

│  │  - createTensionWrench()                               │   ││   │   ├── Interactive event zones

│  │  - createHookPick()                                    │   ││   │   └── Labels

│  └────────────────────────────────────────────────────────┘   ││   └── createLockableItemDisplay()

│                                                                  ││

│  ┌────────────────────────────────────────────────────────┐   │├── Tool Components

│  │ Pin System (900+ lines)                                │   ││   ├── createTensionWrench()

│  │  - createPins()                                        │   ││   │   ├── Wrench graphics

│  │  - updatePinVisuals()                                  │   ││   │   ├── Interactive handlers

│  │  - liftPin()                                           │   ││   │   └── Color state (active/inactive)

│  │  - applyGravity()                                      │   ││   └── createHookPick()

│  │  - checkAllPinsCorrect()                               │   ││       ├── Hook graphics (diagonal + vertical segments)

│  └────────────────────────────────────────────────────────┘   ││       ├── Positioning calculation

│                                                                  ││       └── Configuration storage

│  ┌────────────────────────────────────────────────────────┐   ││

│  │ Key System (1200+ lines)                               │   │├── Pin Rendering

│  │  - createKey()                                         │   ││   ├── updatePinVisuals(pin)

│  │  - drawKeyBladeAsSolidShape()                           │   ││   │   ├── Key pin redraw

│  │  - startKeyInsertion()                                 │   ││   │   ├── Driver pin redraw

│  │  - checkKeyCorrectness()                               │   ││   │   └── Spring compression animation

│  └────────────────────────────────────────────────────────┘   ││   └── handlePinClick(pin)

│                                                                  ││       ├── Visual feedback

│  ┌────────────────────────────────────────────────────────┐   ││       ├── Label hiding

│  │ Key Selection UI (300+ lines)                          │   ││       └── Tension check

│  │  - createKeySelectionUI()                              │   ││

│  │  - selectKey()                                         │   │├── Tool Handling

│  └────────────────────────────────────────────────────────┘   ││   ├── handleTensionWrenchClick()

│                                                                  ││   │   ├── Tension state toggle

│  ┌────────────────────────────────────────────────────────┐   ││   │   ├── Visual feedback (color change)

│  │ Input & Interaction                                    │   ││   │   ├── Sound effects

│  │  - setupInputHandlers()                                │   ││   │   ├── Pin reset logic

│  │  - update()                                            │   ││   │   └── Lock state update

│  │  - checkHookCollisions()                               │   ││   └── [Many event handlers delegated]

│  └────────────────────────────────────────────────────────┘   ││

│                                                                  │└── Utility Methods

│  ┌────────────────────────────────────────────────────────┐   │    ├── hideLabels()

│  │ Completion & Success                                  │   │    └── hideLockpickingTools()

│  │  - lockPickingSuccess()                                │   │```

│  │  - complete()                                          │   │

│  │  - cleanup()                                           │   │### 🔄 NEXT: Lock Configuration Module

│  └────────────────────────────────────────────────────────┘   │**File**: `js/minigames/lockpicking/lock-configuration-store.js`

│                                                                  │**Lines**: ~100

│  ┌────────────────────────────────────────────────────────┐   │**Dependencies**: None (uses window globals)

│  │ UI & Utilities                                         │   │**Priority**: HIGH (no dependencies)

│  │  - init()                                              │   │**Status**: Ready for extraction

│  │  - updateFeedback()                                    │   │

│  │  - shuffleArray()                                      │   │```

│  │  - [15+ helper methods]                                │   │LockConfigurationStore

│  └────────────────────────────────────────────────────────┘   │├── saveLockConfiguration()

│                                                                  ││   ├── Extract pin heights from this.pins[]

└─────────────────────────────────────────────────────────────────┘│   ├── Save to window.lockConfigurations

```│   └── Save to localStorage (persistence)

│

## Proposed Modular Architecture├── loadLockConfiguration()

│   ├── Check window.lockConfigurations

```│   ├── Fallback to localStorage

                    ┌─────────────────────────────┐│   └── Return pin heights array

                    │ LockpickingMinigamePhaser   ││

                    │   (Main Orchestrator)       │├── clearLockConfiguration()

                    │   ~1500 lines               ││   ├── Clear single lock config

                    └────────────┬────────────────┘│   └── Update localStorage

                                 ││

                ┌────────────────┼────────────────┐├── clearAllLockConfigurations()

                │                │                ││   ├── Clear window storage

         ┌──────▼─────┐   ┌──────▼─────┐   ┌──────▼────────┐│   ├── Clear localStorage

         │   Setup    │   │  Graphics  │   │  Interaction  ││   └── Log confirmation

         │  Phase     │   │   Phase    │   │    Phase      ││

         └─────┬──────┘   └─────┬──────┘   └───────┬───────┘├── getLockPinConfiguration()

               │                │                   ││   ├── Return pin heights

          ┌────▼────┐      ┌────▼────┐      ┌──────▼──────┐│   └── Return pin lengths (keyPin, driverPin)

          │   UI    │      │ Graphics │     │   Input     ││

          │Elements │      │          │     │  Handlers   │└── resetPinsToOriginalPositions()

          └─────────┘      │ • Lock   │     │             │    ├── Set all currentHeight to 0

                           │ • Tools  │     └──────────────┘    ├── Restore original positions

                           │ • Pins   │    └── Clear override heights

                           └────┬─────┘```

                                │

                    ┌───────────┼───────────┐### 🔜 FUTURE: Key System Module

                    │           │           │**File**: `js/minigames/lockpicking/key-system.js`

              ┌─────▼──┐  ┌─────▼──┐  ┌────▼────┐**Lines**: ~200

              │   Pin  │  │   Key  │  │   Key   │**Dependencies**: Lock Configuration Module

              │ System │  │Rendering│  │Selection│**Priority**: MEDIUM

              │        │  │         │  │   UI    │**Status**: Design ready

              └─────────┘  └────┬────┘  └────────┘

                                │```

                        ┌───────▼──────┐KeySystem

                        │ Key Data     │├── generateKeyDataFromPins()

                        │ Generator    ││   ├── Calculate cut depths from pin heights

                        │              ││   └── Create key blade profile

                        └──────────────┘│

                                │├── generateRandomKey(pinCount)

                        ┌───────▼──────┐│   ├── Random cuts array

                        │   Lock       ││   └── Return key data object

                        │Configuration││

                        │   Storage    │├── createKeyFromPinSizes(pinSizes)

                        └──────────────┘│   ├── Convert pin sizes to key

```│   └── Return key object

│

## Module Dependency Relationship├── createKeysFromInventory(keys, correctKeyId)

│   ├── Filter valid keys

```│   ├── Shuffle order

Lock Configuration  (Level 0 - Foundation)│   └── Return selection UI

    ││

    └─── Key Data Generator (Level 1 - Pure calculation)├── createKeysForChallenge(correctKeyId)

            ││   ├── Generate 3 random keys

            ├─── Pin System (Level 2 - State & Physics)│   ├── Make first one correct

            │     ││   ├── Shuffle

            │     └─── Lock Graphics (Level 2 - Rendering)│   └── Return for selection

            ││

            └─── Key Rendering (Level 3 - Key visuals)└── startWithKeySelection(inventoryKeys, correctKeyId)

                  │    ├── Initialize key selection mode

                  └─── Key Selection UI (Level 4 - UI/UX)    └── Show UI

Input Handlers (Orthogonal - Level 3)

├─ Pin System### 🔜 FUTURE: Pin Physics Module

├─ Key Rendering**File**: `js/minigames/lockpicking/pin-physics.js`

└─ Hook Collision Detection**Lines**: ~600

Dependencies: Lock Renderer, Lock Configuration

UI Elements (Level 4 - Initialization)Priority: HIGH (core mechanic)

└─ All graphics, input, and data modules**Status**: Design ready

Completion Handler (Level 5 - End state)```

├─ Pin SystemPinPhysics

├─ Key Rendering├── Pin Lifting

└─ All other modules│   ├── liftPin()

│   │   ├── Height calculation

## Phase-by-Phase Extraction Timeline│   │   ├── Binding detection

│   │   └── Overpicking check

```│   └── liftCollidedPin(pin)

┌─────────────────────────────────────────────────────────────────┐│

│ PHASE 1: FOUNDATION (Safest)                                    │├── Physics Simulation

│ ─────────────────────────────────────────────────────────────── ││   ├── applyGravity()

│ • Lock Configuration (100 LOC)                                  ││   │   ├── Downward force

│   └─ 6 methods: save/load/clear operations                      ││   │   ├── Spring restoration

├─────────────────────────────────────────────────────────────────┤│   │   └── Collision handling

│ PHASE 2: GRAPHICS (Low Risk)                                    ││   └── checkHookCollisions(pinIndex)

│ ─────────────────────────────────────────────────────────────── ││

│ • Lock Graphics (200 LOC)                                       │├── Pin State Management

│   └─ 3 methods: render lock, wrench, hook                       ││   ├── checkAllPinsCorrect()

├─────────────────────────────────────────────────────────────────┤│   │   ├── Verify all set

│ PHASE 3: DATA (Low Risk)                                        ││   │   └── Check shear line alignment

│ ─────────────────────────────────────────────────────────────── ││   ├── checkPinSet(pin)

│ • Key Data Generator (400 LOC)                                  ││   │   ├── Tolerance checking

│   └─ 8 methods: key calculations                                ││   │   └── Binding verification

├─────────────────────────────────────────────────────────────────┤│   └── shouldPinBind(pin)

│ PHASE 4: PIN SYSTEM (Medium Risk) ← MAJOR MILESTONE             ││

│ ─────────────────────────────────────────────────────────────── │├── Pin Highlighting

│ • Pin System (900 LOC)                                          ││   ├── updatePinHighlighting(pin)

│   └─ 10 methods: pins, physics, checking                        ││   ├── updateBindingPins()

├─────────────────────────────────────────────────────────────────┤│   └── updateHookPosition(pinIndex)

│ PHASE 5: KEY RENDERING (Medium-High Risk) ← MAJOR MILESTONE    ││

│ ─────────────────────────────────────────────────────────────── │└── Hook Interaction

│ • Key Rendering (1200 LOC)                                      │    ├── returnHookToStart()

│   └─ 10 methods: key visuals, insertion, animation              │    └── updateHookPosition(pinIndex)

├─────────────────────────────────────────────────────────────────┤```

│ PHASE 6: UI & CONTROLS (High Risk)                             │

│ ─────────────────────────────────────────────────────────────── │### 🔜 FUTURE: Lockpicking Mechanics Module

│ • Key Selection UI (300 LOC)                                    │**File**: `js/minigames/lockpicking/lockpicking-mechanics.js`

│ • Input Handlers (200 LOC)                                      │**Lines**: ~800

│ • Completion Handler (150 LOC)                                  │**Dependencies**: All other modules

│ • UI Elements (400 LOC)                                         │**Priority**: MEDIUM (orchestrator)

│ • Mode Switching (150 LOC)                                      │**Status**: Design ready

│ • Utilities (300 LOC)                                           │

└─────────────────────────────────────────────────────────────────┘```

```LockpickingMechanics

├── Game Loop

## Code Quality Metrics│   ├── init()

│   ├── create()

### Before Refactoring│   └── update()

```│

File: lockpicking-game-phaser.js├── Input Handling

Lines of Code:     4670│   ├── setupInputHandlers()

Methods:           50+│   │   ├── Mouse down

Average Method:    93 lines│   │   ├── Mouse move

Complexity:        Very High (single 4670-line class)│   │   ├── Mouse up

Testability:       Low│   │   └── Touch events

Maintainability:   Low│   └── Event processing

Reusability:       Low│

```├── Success/Failure

│   ├── lockPickingSuccess()

### After Refactoring (Target)│   │   ├── Animation

```│   │   ├── Sound effects

Module               LOC    Methods  Avg Method  Complexity│   │   ├── Pin rotation

─────────────────────────────────────────────────────────────│   │   └── Completion

Main Class          1500   15       100         Medium│   └── Handle failures

Lock Configuration   100   6        17          Low│

Lock Graphics       200    3        67          Low-Medium├── Game State

Key Data Gen.       400    8        50          Medium│   ├── resetAllPins()

Pin System          900    10       90          Medium-High│   ├── updateBindingPins()

Key Rendering       1200   10       120         Medium-High│   └── State validation

Key Selection UI    300    7        43          Medium│

Input Handlers      200    5        40          Medium├── Feedback/UI

Completion          150    3        50          Low│   ├── updateFeedback(message)

UI Elements         400    6        67          Medium│   ├── flashWrenchRed()

Mode Switching      150    4        37          Low│   └── Visual indicators

Utilities           300    8        37          Low│

─────────────────────────────────────────────────────────────└── Mode Switching

TOTAL              6400    85       75          Moderate    ├── switchToPickMode()

    ├── switchToKeyMode()

Improvements:    └── Mode synchronization

✓ 85 methods distributed across 12 modules```

✓ Average method size reduced from 93 → 75 lines

✓ Each module has single responsibility### 🔜 FUTURE: Key Mode System (Optional)

✓ Cyclomatic complexity per module reduced**File**: `js/minigames/lockpicking/key-mode-system.js`

✓ Unit testability increased ~60%**Lines**: ~400

✓ Code reusability increased ~40%**Dependencies**: All others

```**Priority**: LOW (optional feature)

**Status**: Design ready

## Data Flow Architecture


User Input                Browser├── Key Insertion

    │                       ││   ├── createKey()

    ├──────────┬────────────┤│   ├── startKeyInsertion()

             Input Handlers│   └── updateKeyPosition(progress)

                   ││

                   ├─────────────────────┬────────────────┐├── Key Rendering

                   │                     │                ││   ├── drawKeyWithRenderTexture()

              Pin Lifting         Key Insertion    Mode Switching│   ├── drawKeyBladeAsSolidShape()

                   │                     │                ││   └── createKeyVisual()

                   └─────────┬───────────┴────────────┬───┘│

                             │                        │├── Key Selection UI

                          Pin System          Key Rendering│   ├── createKeySelectionUI()

                             │                        ││   ├── selectKey(index)

                             └────────────┬───────────┘│   └── showKeySelection()

                                          ││

                        Collision Detection & Physics├── Collision Detection

                                          ││   ├── createKeyBladeCollision()

                        ┌─────────────────┴──────────────┐│   ├── getKeySurfaceHeightAtPosition()

                        │                                ││   └── findVerticalIntersection()

                    Feedback                       State Update│

                        │                                │├── Success Animation

                    UI Feedback               Lock Configuration│   ├── startKeyRotationAnimationWithChamberHoles()

                        │                                ││   ├── snapPinsToExactPositions()

                    Render                       Storage (Memory/localStorage)│   └── checkKeyCorrectness()

                        │                                ││

                    Display                          Persist└── Utility

```    ├── hideLockpickingTools()

    └── showWrongKeyFeedback()

## Integration Points```



### Main Class → Modules## Data Flow Diagram



```javascript```

class LockpickingMinigamePhaser extends MinigameScene {User Interaction

          ↓

    // Initialize each modulePhaser Input Events

    constructor(container, params) {      ↓

        super(container, params);┌─────────────────────────────────────┐

        this.lockConfig = new LockConfiguration(this);│ LockpickingMinigamePhaser           │ (Orchestrator)

        this.graphics = new LockGraphics(this.scene, this);│ (Main Game Logic)                   │

        this.keyDataGen = new KeyDataGenerator(this);└─────────────────────────────────────┘

        this.pinSystem = new PinSystem(this.scene, this);      ↓

        this.keyRendering = new KeyRendering(this.scene, this);┌─────────────────────────────────────┐

        this.keyUI = new KeySelectionUI(this.scene, this);│ LockRenderer              ← Rendering

        this.inputHandler = new InputHandlers(this.scene, this);│ LockConfigurationStore   ← Persistence

        this.uiElements = new UIElements(this.gameContainer, this);│ KeySystem                ← Key logic

        this.modeSwitch = new ModeSwitching(this);│ PinPhysics              ← Physics

        this.completion = new CompletionHandler(this);│ LockpickingMechanics    ← Game rules

    }│ KeyModeSystem (opt)     ← Key mode

    └─────────────────────────────────────┘

    // Orchestrate modules      ↓

    init() {Phaser Scene (Graphics, Physics, Input)

        this.uiElements.init();      ↓

        this.setupPhaserGame(); // Still in main classCanvas / WebGL

    }      ↓

    Visual Output

    setupPhaserGame() {```

        // Create Phaser scene, then call module methods

        this.graphics.createLockBackground();## Dependency Graph

        this.pinSystem.createPins();

        // ... etc```

    }LockConfiguration

}├── (No dependencies)

```└── Used by: KeySystem, PinPhysics



## Testing Strategy by ModuleKeySystem

├── Depends on: LockConfiguration

```└── Used by: LockpickingMechanics, KeyModeSystem

┌──────────────────────────────────────────────────────────────┐

│ Unit Tests (Isolated)                                        │LockRenderer

├──────────────────────────────────────────────────────────────┤├── Depends on: Phaser Scene

│ • Key Data Generator      → Pure functions, easily testable  │└── Used by: LockpickingMinigamePhaser

│ • Lock Configuration      → Persistence logic                │

│ • Utilities               → Helper functions                 │PinPhysics

├──────────────────────────────────────────────────────────────┤├── Depends on: LockConfiguration, LockRenderer

│ Integration Tests                                            │└── Used by: LockpickingMechanics

├──────────────────────────────────────────────────────────────┤

│ • Pin System + Graphics   → Visual rendering + physics       │LockpickingMechanics

│ • Key Rendering + Pins    → Key insertion mechanics          │├── Depends on: All above modules

│ • Input + Pin System      → Interaction flow                 │└── Used by: LockpickingMinigamePhaser

├──────────────────────────────────────────────────────────────┤

│ E2E Tests (Manual)                                           │KeyModeSystem

├──────────────────────────────────────────────────────────────┤├── Depends on: KeySystem, LockRenderer, PinPhysics

│ • Lock picking flow       → Full game cycle                  │└── Used by: LockpickingMechanics (optional)

│ • Key insertion flow      → Alternative game path            │

│ • Mode switching          → Feature interaction              │LockpickingMinigamePhaser (Main Class)

└──────────────────────────────────────────────────────────────┘├── Initializes all modules

```├── Handles Phaser lifecycle

└── Orchestrates interaction

## Rollback Strategy```



At any point during refactoring, if something breaks:## Extraction Order Rationale



```bash1. **Lock Rendering** ✅ (DONE)

# Option 1: Revert last extraction   - No internal dependencies

git revert HEAD   - Isolates graphics code

   - Safe to extract first

# Option 2: Reset to before extraction

git reset --hard <commit-before-extraction>2. **Lock Configuration** → NEXT

   - No internal dependencies

# Option 3: Start fresh extraction with different methods   - Required by multiple modules

git checkout -- js/minigames/lockpicking/lockpicking-game-phaser.js   - Very low risk

python3 scripts/extract_lockpicking_methods.py --methods "subset" ...

```3. **Key System**

   - Depends on: Config

## Migration Checklist   - Used by: Mechanics, Key Mode

   - Medium complexity

Phase 1 (Lock Configuration):4. Pin Physics

☐ Extract lock-configuration.js - Depends on: Config, Rendering

☐ Update imports in main class - Core game mechanic

☐ Test game loads - Most complex

☐ Test lock state persists

☐ Commit changes5. Lockpicking Mechanics

 - Depends on: All above

Phase 2 (Graphics): - Final orchestrator

☐ Extract lock-graphics.js - Ties everything together

☐ Create LockGraphics helper class

☐ Update method calls in main6. Key Mode System

☐ Test graphics render - Optional feature

☐ Commit changes - Depends on all above

 - Extract last (or skip)

Phase 3 (Key Data):

☐ Extract key-data-generator.js## Backward Compatibility Strategy

☐ Update imports

☐ Test key generationAll extracted modules maintain backward compatibility:

☐ Commit changes


Phase 4 (Pin System):// Old code (still works)

 Extract pin-system.jsthis.wrenchText.setVisible(false);

 Create PinSystem helper class Delegates to

 Update all pin method callsthis.lockRenderer.wrenchText.setVisible(false);

 Test pin interactions

 Commit changes// New code (encouraged)

this.lockRenderer.wrenchText.setVisible(false);

Phase 5 (Key Rendering):```

☐ Extract key-rendering.js

☐ Create KeyRendering helper classGetters/Setters in main class proxy to renderer, ensuring no breaking changes.

☐ Update all key method calls

☐ Test key insertion## Testing Strategy by Module

☐ Commit changes

### LockRenderer ✅

Phase 6+ (UI & Controls):- Visual regression testing

☐ Extract remaining modules- Event handler verification

☐ Test full feature set- Graphics rendering validation

☐ Final testing

☐ Final commit### LockConfiguration (Next)

```- Save/load functionality

- localStorage persistence

---- Default handling



**Total Refactoring Effort:** ~1-2 weeks of development### KeySystem

**Risk Level:** Medium (high reward, manageable risk with incremental approach)- Key generation

**Testing Required:** High (full feature verification after each phase)- Key validation

- Inventory integration

### PinPhysics
- Pin movement calculation
- Gravity simulation
- Collision detection

### LockpickingMechanics
- Input handling
- Game loop
- Success/failure states

### KeyModeSystem
- Key insertion animation
- Key selection UI
- Mode switching

---

## File Locations

js/minigames/lockpicking/ ├── lockpicking-game-phaser.js (Main orchestrator) ├── lock-renderer.js ( Rendering) ├── lock-configuration-store.js (→ Next) ├── key-system.js (→ Future) ├── pin-physics.js (→ Future) ├── lockpicking-mechanics.js (→ Future) ├── key-mode-system.js (→ Future) ├── index.js (Export all modules) └── [existing test files]