Commit Graph

13 Commits

Author SHA1 Message Date
Thomas Hallock
2a3af973f7 feat(arcade): migrate matching pairs - phases 1-4 and 7 complete
Phases completed:
- Phase 1: Pre-migration audit (arcade version is canonical)
- Phase 2: Create modular game definition with registry
- Phase 3: Move and update validator to modular location
- Phase 4: Consolidate and move SDK-compatible types
- Phase 7: Move utility functions (cardGeneration, matchValidation, gameScoring)

Changes:
- Created /src/arcade-games/matching/ with game definition
- Registered matching game in game registry
- Added type inference for MatchingGameConfig
- Moved validator with updated imports to use local types
- Created SDK-compatible MatchingConfig, MatchingState, MatchingMove types
- Moved utils with updated import paths

Remaining:
- Phase 5: Create unified Provider
- Phase 6: Consolidate and move components
- Phase 8: Update routes and clean up legacy files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 00:38:08 -05:00
Thomas Hallock
39485826fc docs: add matching pairs battle migration plan
Create comprehensive migration plan for Matching Pairs Battle game.
Documents dual-location complexity, 8-phase migration approach, and
key differences from Memory Quiz migration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 22:33:39 -05:00
Thomas Hallock
7e2df106e6 docs: add memory-quiz migration plan documentation
Add detailed migration plan document for the Memory Quiz game migration
to the modular game system. This serves as a reference for future game
migrations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 22:31:35 -05:00
Thomas Hallock
99eee69f28 docs: update playbook with memory-quiz completion
Mark memory-quiz migration as completed in the Game Migration Playbook.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 22:31:35 -05:00
Thomas Hallock
704f34f83e docs(arcade): document Phase 3 completion in ARCHITECTURAL_IMPROVEMENTS.md
**Updates**:
- Added Phase 3 section with implementation details
- Updated "Before vs After" comparison: 12 files → 3 files (75% reduction)
- Updated Executive Summary: Grade A (up from B- originally, A- after Phase 2)
- Updated Conclusion with all three phases completed
- Updated Quick Reference with Phase 3 type inference steps
- Renamed "Future Work" to include optional Phase 4

**Key Metrics**:
- Files to update: 12 → 3 (75% reduction)
- Lines of boilerplate: ~60 → ~20 (67% reduction)
- All critical architectural issues resolved

**Status**: Production-ready modular game system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 21:40:39 -05:00
Thomas Hallock
784793ba24 fix(arcade): prevent server-side loading of React components
Issue: game-config-helpers.ts was importing game-registry.ts which loads
game definitions including React components. This caused server startup to
fail with MODULE_NOT_FOUND for GameModeContext.

Solution: Lazy-load game registry only in browser environment.
On server, getGame() returns undefined and validation falls back to
switch statement for legacy games.

Changes:
- game-config-helpers.ts: Add conditional getGame() that checks typeof window
- Only requires game-registry in browser environment
- Server uses switch statement fallback for validation
- Browser uses game.validateConfig() when available

This maintains the architectural improvement (games own validation)
while keeping server-side code working.

Test: Dev server starts successfully, no MODULE_NOT_FOUND errors
2025-10-15 21:27:59 -05:00
Thomas Hallock
e135d92abb refactor(db): remove database schema coupling for game names
BREAKING CHANGE: Database schemas now accept any string for game names

This implements Critical Fix #1 from AUDIT_2_ARCHITECTURE_QUALITY.md

Changes:
- Remove hardcoded enums from all database schemas
- arcade-rooms.ts: gameName now accepts any string
- arcade-sessions.ts: currentGame now accepts any string
- room-game-configs.ts: gameName now accepts any string

Runtime Validation:
- Add isValidGameName() helper to validate against registry
- Add assertValidGameName() helper for fail-fast validation
- Update settings API to use runtime validation instead of hardcoded array

Benefits:
 No schema migration needed when adding new games
 No TypeScript compilation errors for new games
 Single source of truth: validator registry
 "Just register and go" - no database changes required

Migration Impact:
- Existing data is compatible (strings remain strings)
- No data migration needed
- TypeScript will now allow any string, but runtime validation enforces correctness

This eliminates the most critical architectural issue identified in the audit.
Future games can be added by:
1. Register validator in validators.ts
2. Register game in game-registry.ts
That's it! No database schema changes needed.
2025-10-15 21:17:00 -05:00
Thomas Hallock
5b91b71078 docs: add architecture quality audit #2
Comprehensive audit of modular game system after implementing Math Sprint.

Key Findings:
- Grade: B- (down from B+ after implementation testing)
- SDK design is solid (useArcadeSession, Provider pattern)
- Unified validator registry works well
- BUT: Significant boilerplate and coupling issues

Critical Issues Identified:
1. 🚨 Database Schema Coupling - Must update schema for each game
2. ⚠️ game-config-helpers.ts - Switch statements for defaults/validation
3. ⚠️ game-configs.ts - 5 places to update per game
4. 📊 High Boilerplate Ratio - 12 files touched per game, ~44 lines boilerplate

Files That Required Updates for Math Sprint:
- 3 database schemas (arcade-rooms, arcade-sessions, room-game-configs)
- 1 API endpoint (settings/route.ts)
- 2 config files (game-configs.ts, game-config-helpers.ts)
- 2 registry files (validators.ts, game-registry.ts)
- 8 game implementation files (types, validator, provider, components, etc.)

Recommendations:
- Critical: Fix database schema to accept any string, validate at runtime
- Infer config types from game definitions (single source of truth)
- Move config validation to game definitions (eliminate switch statements)

Developer Experience:
- Time to add a game: 3-5 hours (including boilerplate)
- Pain point: Database schema updates require migration
- Pain point: Easy to forget one of the 12 files

See audit for detailed analysis and architectural recommendations.
2025-10-15 21:12:18 -05:00
Thomas Hallock
6f6cb14650 docs(arcade): update docs for unified validator registry
## Documentation Updates

### src/arcade-games/README.md
- **Step 7**: Expanded to explain both registration steps
  - 7a: Register validator in validators.ts (server-side)
  - 7b: Register game in game-registry.ts (client-side)
- Added explanation of why both steps are needed
- Added verification warnings that appear during registration
- Clarified the difference between isomorphic and client-only code

### docs/AUDIT_MODULAR_GAME_SYSTEM.md
- **Status**: Updated from "CRITICAL ISSUES" to "ISSUE RESOLVED"
- **Executive Summary**: Marked system as Production Ready
- **Issue #1**: Marked as RESOLVED with implementation details
- **Issue #2**: Marked as RESOLVED (validators now accessible)
- **Issue #5**: Marked as RESOLVED (GameName auto-derived)
- **Compliance Table**: Updated grade from D to B+
- **Action Items**: Marked critical items 1-3 as completed

## Summary

Documentation now accurately reflects the unified validator registry
implementation, providing clear guidance for developers adding new games.

Related: 9459f37b (implementation commit)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 20:41:06 -05:00
Thomas Hallock
bda5bc6c0e fix: prevent database imports from being bundled into client code
**Problem:**
- player-ownership.ts imported drizzle-orm and @/db at top level
- When RoomMemoryPairsProvider imported client-safe utilities, Webpack bundled ALL imports including database code
- This caused hydration error: "The 'original' argument must be of type Function"
- Node.js util.promisify was being called in browser context

**Solution:**
1. Created player-ownership.client.ts with ONLY client-safe utilities
   - No database imports
   - Safe to import from 'use client' components
   - Contains: buildPlayerOwnershipFromRoomData(), buildPlayerMetadata(), helper functions

2. Updated player-ownership.ts to re-export client utilities and add server-only functions
   - Re-exports everything from .client.ts
   - Adds buildPlayerOwnershipMap() (async, database-backed)
   - Safe to import from server components/API routes

3. Updated RoomMemoryPairsProvider to import from .client.ts

**Result:**
- No more hydration errors on /arcade/room
- Client bundle doesn't include database code
- Server code can still use both client and server utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-10 11:40:46 -05:00
Thomas Hallock
8175c43533 feat: implement room-wide multi-user game state synchronization
Enable real-time game state sync across all users in a room playing
at /arcade/room. Previously only synced across one user's tabs, now
syncs across all room members.

Server changes (socket-server.ts):
- Accept optional roomId in join-arcade-session event
- Join socket to both arcade:userId and game:roomId rooms
- Broadcast move-accepted to both rooms when processing moves
- Log game room joins for debugging

Client changes:
- useArcadeSocket: Accept roomId parameter in joinSession()
- useArcadeSession: Accept roomId in options, pass to joinSession()
- ArcadeMemoryPairsContext: Get roomId from useRoomData() and wire up

How it works:
- User A joins game room → joins arcade:userA + game:room123
- User B joins game room → joins arcade:userB + game:room123
- User A makes move → broadcasts to both rooms
- User A's tabs receive on arcade:userA (reconcile optimistic update)
- User B's tabs receive on game:room123 (sync with server state)
- Optimistic update system handles both cases automatically

Architecture:
- Reuses existing optimistic update reconciliation
- Minimal changes (5 edits across 4 files)
- Backward compatible (roomId is optional)
- Solo play unaffected

See docs/MULTIPLAYER_SYNC_ARCHITECTURE.md for full details.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 11:16:27 -05:00
Thomas Hallock
f005fbbb77 feat: implement modal room enforcement (one room per user)
Implement hybrid database + application-level enforcement to ensure users
can only be in one room at a time, with graceful auto-leave behavior and
clear error messaging.

## Changes

### Database Layer
- Add unique index on `room_members.user_id` to enforce one room per user
- Migration includes cleanup of any existing duplicate memberships
- Constraint provides safety net if application logic fails

### Application Layer
- Auto-leave logic: when joining a room, automatically remove user from
  all other rooms first
- Return `AutoLeaveResult` with metadata about rooms that were left
- Idempotent rejoining: rejoining the same room just updates status

### API Layer
- Join route returns auto-leave information in response
- Catches and handles constraint violations with 409 Conflict
- User-friendly error messages when conflicts occur

### Frontend
- Room list and detail pages handle ROOM_MEMBERSHIP_CONFLICT errors
- Show alerts when user needs to leave current room
- Refresh room list after conflicts to show current state

### Testing
- 7 integration tests for modal room behavior
- Tests cover: first join, auto-leave, rejoining, multi-user scenarios,
  constraint enforcement, and metadata accuracy
- Updated existing unit tests for new return signature

## Technical Details

- `addRoomMember()` now returns `{ member, autoLeaveResult? }`
- Auto-leave happens before new room join, preventing race conditions
- Database unique constraint as ultimate safety net
- Socket events remain status-only (joining goes through API)

## Testing
-  All modal room tests pass (7/7)
-  All room API e2e tests pass (12/12)
-  Format and lint checks pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 08:41:39 -05:00
Thomas Hallock
a9175a050c feat: add arcade room system database schema and managers (Phase 1)
Implement foundational infrastructure for multi-room arcade system:

Database:
- Add arcade_rooms table for room metadata and lifecycle
- Add room_members table for membership tracking
- Add nullable roomId field to arcade_sessions for room association
- Create migration 0003_naive_reptil.sql

Managers:
- Implement room-manager.ts with full CRUD operations
- Implement room-membership.ts for member management
- Add room-code.ts utility for unique room code generation
- Include TTL-based room cleanup functionality

Documentation:
- Add arcade-rooms-technical-plan.md with complete system design
- Add arcade-rooms-implementation-tasks.md with 62-task breakdown

This establishes the foundation for public multiplayer rooms with:
- URL-addressable rooms with unique codes
- Guest user support
- Configurable TTL for automatic cleanup
- Room creator moderation controls

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 15:11:24 -05:00