Files
vim-sudoku/IMPLEMENTATION_PLAN.md
T
pastilhas 9292b83dd0 feat: prepare vim-sudoku for unified API implementation
- Archive previous implementation attempt (src -> src_failed)
- Create comprehensive IMPLEMENTATION_PLAN.md with phased approach
- Create IMPLEMENTATION.md to track implementation progress
- Update example app to match vim-maze patterns:
  - Simplify UI to desktop-only (no mobile support)
  - Add score metrics display (time, keystrokes, final score)
  - Update instructions for sudoku-specific keys (hjkl, i for edit)
  - Remove unnecessary mobile hooks

Phase 5 complete. Ready to begin Phase 10 (Setup & Core Types).
2025-10-22 18:08:33 +01:00

8.8 KiB

vim-sudoku Unified API Implementation Plan

Overview

Port vim-sudoku to the unified API architecture established by vim-maze, following the composable hook pattern with useGame() as the single entry point.

Goals

  1. Follow unified API architecture from UNIFIED_API.md
  2. Maintain vim-maze patterns and conventions
  3. Preserve all working functionality from src_old
  4. Support platform integration via optional platformHook parameter
  5. Enable code reuse across games (vim-maze, vim-sudoku, vim-snake)

Architecture

Core Composition

// Inside useGame:
const board = useBoard();
const gameStatusManager = useGameStatus();
const { cursor, keyManager } = useCursor(board, gameStatusManager);
const scoreManager = useScore({ board, gameStatusManager, keyManager });

// Returns unified GameManager interface

File Structure

src/
├── index.ts                    # Main package exports
├── types.ts                    # Re-exports all types from modules
├── useGame.ts                  # Main orchestrator hook
├── useGameStatus/
│   ├── index.ts                # Public exports
│   ├── types.ts                # GameStatus, GameStatusManager
│   └── useGameStatus.ts        # Game state management
├── useBoard/
│   ├── index.ts                # Public exports
│   ├── types.ts                # SudokuBoard, SudokuCell, Difficulty, BoardManager
│   ├── useBoard.ts             # Board management hook
│   ├── SudokuGenerator.ts      # Puzzle generation (from src_old/lib/Sudoku.ts)
│   └── SudokuRenderer.ts       # DOM rendering for sudoku grid
├── useCursor/
│   ├── index.ts                # Public exports
│   ├── types.ts                # CursorManager, CursorMode, VimMotionSystem, CellEditor
│   ├── useCursor.ts            # Main cursor/input hook
│   ├── useCellEditor.ts        # Cell editing logic (analog to useHero)
│   ├── useCursorRender.ts      # Cursor rendering on DOM (analog to useHeroRender)
│   ├── useVimMotions.ts        # Vim keybinding system
│   └── useGameKeys.ts          # Game-specific key handling
└── useScore/
    ├── index.ts                # Public exports
    ├── types.ts                # TimerManager, ScoreManager
    ├── useScore.ts             # Main scoring hook
    └── useTimer.ts             # Timer state management

Implementation Steps

Phase 5: Prepare Example App

  • Update example/src/App.tsx to match vim-maze structure
  • Update App to display score metrics (time, keystrokes, final score)
  • Update App to show game status messages
  • Update App instructions for sudoku-specific keys (i for edit)
  • Keep it simple - no mobile support for now

Phase 10: Setup & Core Types

  • Create clean src/ directory structure
  • Define all types in module-specific types.ts files
  • Create index.ts exports for each module
  • Set up main types.ts re-export file

Phase 20: useBoard Hook

  • Port SudokuGenerator from src_old/lib/Sudoku.ts
  • Port SudokuRenderer from src_old rendering logic
  • Implement useBoard hook with refs pattern
    • containerRef for DOM
    • boardRef for SudokuBoard (2D array of cells)
    • initialBoardRef for puzzle state
    • solutionRef for solved state
  • Methods: renderBoard, generateBoard, getCell, setCell, canEditCell, isComplete, isFullyValid

Phase 30: useGameStatus Hook

  • Implement GameStatus state machine
    • 'waiting' → 'started' → 'game-won' / 'game-over'
    • 'paused' state support
  • Methods: startGame, togglePause, quitGame, setGameStatus

Phase 40: useCursor Hook Composition

40.1 useCellEditor (analog to useHero)

  • Manage cursor position (row, col)
  • Handle cell editing operations
  • Validate edits against isGiven cells
  • Trigger validation on cell changes
  • Handle win condition detection

40.2 useVimMotions

  • Port vim motion system from vim-maze
  • Support: h/j/k/l, ^/$, g/G, . (repeat)
  • Support: i (insert), r (replace), x (delete)
  • Count prefix handling (e.g., 5j)
  • Mode transitions (normal ↔ edit)

40.3 useGameKeys

  • Keyboard event listener
  • Route keys through vim motion processor
  • Execute cursor movements
  • Execute cell editing commands
  • Track keystroke history
  • Handle game-specific keys (q, p, space)

40.4 useCursorRender (analog to useHeroRender)

  • Render cursor highlight on current cell
  • Show edit mode indicator
  • Flash animations (valid/invalid/locked)
  • Highlight conflict cells

40.5 useCursor Main Hook

  • Compose cellEditor, vimMotions, gameKeys, cursorRender
  • Return unified CursorManager interface
  • Split keyManager for useGame composition

Phase 50: useScore Hook

  • Port timer from src_old/useScore/hooks/useTimer.ts
  • Track keystrokes from keyManager.keyLog
  • Calculate efficiency metrics
  • Detect win/loss conditions based on completion
  • Compute final score on game-won

Phase 60: useGame Orchestrator

  • Compose all hooks (board, cursor, gameStatus, score)
  • Handle initial board generation
  • Coordinate rendering updates
  • Expose unified GameManager interface
  • Support optional platformHook parameter

Phase 70: Testing & Refinement

  • Test with example app
  • Verify all vim motions work
  • Verify edit mode (i/r/x) works
  • Verify validation and conflicts work
  • Verify win condition triggers
  • Test platform hook integration
  • Update UNIFIED_API.md with sudoku specifics

Key Design Decisions

1. Board Representation

Choice: Use 2D array of SudokuCell objects

type SudokuCell = {
  value: string;        // '1'-'9' or ''
  isGiven: boolean;     // true for puzzle clues
  hasConflict: boolean; // validation state
};
type SudokuBoard = SudokuCell[][];

Rationale: Easier to work with than 81-char string, matches vim-maze pattern of using structured data.

2. Cell Editing (analog to Hero Movement)

Choice: useCellEditor hook manages cell editing state

  • Similar to useHero managing hero position in maze
  • Handles validation before setting values
  • Triggers game status changes on completion

Rationale: Keeps editing logic separate from cursor movement, following vim-maze separation of concerns.

3. Edit Mode vs Insert Mode

Choice: Two modes - 'normal' and 'edit'

  • Normal mode: vim navigation + commands (i/r/x/d)
  • Edit mode: digit entry (1-9) + erase (x/Backspace)
  • i = insert (enter edit mode on empty cell)
  • r = replace (enter edit mode on filled cell)
  • Escape/Enter = exit edit mode

Rationale: Matches vim philosophy and src_old behavior.

4. Rendering Strategy

Choice: Keep rendering separate from state

  • SudokuRenderer handles DOM generation
  • useCursorRender handles cursor highlighting
  • useBoard calls renderer with board data

Rationale: Matches vim-maze pattern (MazeRenderer + useHeroRender).

5. Validation Approach

Choice: Validate on setCell, show conflicts visually

  • Real-time validation when setting digits
  • Flash animations for feedback
  • Highlight conflicting cells temporarily
  • Don't prevent invalid moves (optional strictMode)

Rationale: Provides immediate feedback without blocking player exploration.

Type Mappings (vim-maze → vim-sudoku)

vim-maze vim-sudoku Notes
MazeCell[][] SudokuBoard Board structure
Coord Coord Same (row, col)
useHero useCellEditor Cell editing vs movement
useHeroRender useCursorRender Visual feedback
MazeGenerator SudokuGenerator Puzzle generation
MazeRenderer SudokuRenderer Grid rendering
hero.moveTo cellEditor.setValue Action semantics
'entrance'/'exit'/'key' 'isGiven'/'value' Cell metadata

Differences from vim-maze

  1. No pathfinding: Simple grid bounds checking
  2. Edit mode: Need mode toggle for digit entry
  3. Validation: Real-time conflict detection
  4. Win condition: Complete + valid vs reach exit
  5. No animation: Cursor moves instantly (no multi-step)
  6. Board generation: On-demand vs one-time initialization

Success Criteria

  • All functionality from src_old preserved
  • Follows unified API architecture
  • Types match vim-maze patterns
  • Hook composition mirrors vim-maze
  • Example app works identically to src_old version
  • Platform hook integration works
  • Code is clean, documented, and maintainable
  • UNIFIED_API.md updated with vim-sudoku section

Notes

  • Keep game.css from src_old for styling
  • Port sudoku generation algorithm directly (working code)
  • Maintain existing vim keybindings (h/j/k/l, ^/$, g/G, ., i/r/x)
  • Preserve flash animations for visual feedback
  • Follow AGENTS.md conventions throughout