Commit Graph

13 Commits

Author SHA1 Message Date
Cal Corum
02e816a57f CLAUDE: Phase 3E-Main - Position Ratings Integration for X-Check Resolution
Complete integration of position ratings system enabling X-Check defensive plays
to use actual player ratings from PD API with intelligent fallbacks for SBA.

**Live API Testing Verified**: 
- Endpoint: GET https://pd.manticorum.com/api/v2/cardpositions?player_id=8807
- Response: 200 OK, 7 positions retrieved successfully
- Cache performance: 16,601x faster (API: 0.214s, Cache: 0.000s)
- Data quality: Real defensive ratings (range 1-5, error 0-88)

**Architecture Overview**:
- League-aware: PD league fetches ratings from API, SBA uses defaults
- StateManager integration: Defenders retrieved from lineup cache
- Self-contained GameState: All data needed for X-Check in memory
- Graceful degradation: Falls back to league averages if ratings unavailable

**Files Created**:

1. app/services/pd_api_client.py (NEW)
   - PdApiClient class for PD API integration
   - Endpoint: GET /api/v2/cardpositions?player_id={id}&position={pos}
   - Async HTTP client using httpx (already in requirements.txt)
   - Optional position filtering: get_position_ratings(8807, ['SS', '2B'])
   - Returns List[PositionRating] for all positions player can play
   - Handles both list and dict response formats
   - Comprehensive error handling with logging

2. app/services/position_rating_service.py (NEW)
   - PositionRatingService with in-memory caching
   - get_ratings_for_card(card_id, league_id) - All positions
   - get_rating_for_position(card_id, position, league_id) - Specific position
   - Cache performance: >16,000x faster on hits
   - Singleton pattern: position_rating_service instance
   - TODO Phase 3E-Final: Upgrade to Redis

3. app/services/__init__.py (NEW)
   - Package exports for clean imports

4. test_pd_api_live.py (NEW)
   - Live API integration test script
   - Tests with real PD player 8807 (7 positions)
   - Verifies caching, filtering, GameState integration
   - Run: `python test_pd_api_live.py`

5. test_pd_api_mock.py (NEW)
   - Mock integration test for CI/CD
   - Demonstrates flow without API dependency

6. tests/integration/test_position_ratings_api.py (NEW)
   - Pytest integration test suite
   - Real API tests with player 8807
   - Cache verification, SBA skip logic
   - Full end-to-end GameState flow

**Files Modified**:

1. app/models/game_models.py
   - LineupPlayerState: Added position_rating field (Optional[PositionRating])
   - GameState: Added get_defender_for_position(position, state_manager)
   - Uses StateManager's lineup cache to find active defender by position
   - Iterates through lineup.players to match position + is_active

2. app/config/league_configs.py
   - SbaConfig: Added supports_position_ratings() → False
   - PdConfig: Added supports_position_ratings() → True
   - Enables league-specific behavior without hardcoded conditionals

3. app/core/play_resolver.py
   - __init__: Added state_manager parameter for X-Check defender lookup
   - _resolve_x_check(): Replaced placeholder defender ratings with actual lookup
   - Uses league config to check if ratings supported
   - Fetches defender via state.get_defender_for_position()
   - Falls back to defaults (range=3, error=15) if ratings unavailable
   - Detailed logging for debugging rating lookups

4. app/core/game_engine.py
   - Added _load_position_ratings_for_lineup() method
   - Loads all position ratings at game start for PD league
   - Skips loading for SBA (league config check)
   - start_game(): Calls rating loader for both teams before marking active
   - PlayResolver instantiation: Now passes state_manager parameter
   - Logs: "Loaded X/9 position ratings for team Y"

**X-Check Resolution Flow**:
1. League check: config.supports_position_ratings()?
2. Get defender: state.get_defender_for_position(pos, state_manager)
3. If PD + defender.position_rating exists: Use actual range/error
4. Else if defender found: Use defaults (range=3, error=15)
5. Else: Log warning, use defaults

**Position Rating Loading (Game Start)**:
1. Check if league supports ratings (PD only)
2. Get lineup from StateManager cache
3. For each player:
   - Fetch rating from position_rating_service (with caching)
   - Set player.position_rating field
4. Cache API responses (16,000x faster on subsequent access)
5. Log success: "Loaded X/9 position ratings for team Y"

**Live Test Results (Player 8807)**:
```
Position   Range    Error    Innings
CF         3        2        372
2B         3        8        212
SS         4        12       159
RF         2        2        74
LF         3        2        62
1B         4        0        46
3B         3        65       34
```

**Testing**:
-  Live API: Player 8807 → 7 positions retrieved successfully
-  Caching: 16,601x performance improvement
-  League config: SBA=False, PD=True
-  GameState integration: Defender lookup working
-  Existing tests: 27/28 config tests passing (1 pre-existing URL failure)
-  Syntax validation: All files compile successfully

**Benefits**:
-  X-Check now uses real defensive ratings in PD league
-  SBA league continues working with manual entry (uses defaults)
-  No breaking changes to existing functionality
-  Graceful degradation if API unavailable
-  In-memory caching reduces API calls by >99%
-  League-agnostic design via config system
-  Production-ready with live API verification

**Phase 3E Status**: Main complete (85% → 90%)
**Next**: Phase 3E-Final (WebSocket events, Redis upgrade, full defensive lineup)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:00:37 -06:00
Cal Corum
d560844704 CLAUDE: Phase 3E-Prep - Refactor GameState to use full LineupPlayerState objects
**Architectural Improvement**: Unified player references in GameState

**Changed**: Make all player references consistent
- BEFORE: current_batter/pitcher/catcher were IDs (int)
- AFTER: current_batter/pitcher/catcher are full LineupPlayerState objects
- Matches pattern of on_first/on_second/on_third (already objects)

**Benefits**:
1. Consistent API - all player references use same type
2. Self-contained GameState - everything needed for resolution
3. No lookups needed - direct access to player data
4. Sets foundation for Phase 3E-Main (adding position ratings)

**Files Modified**:
- app/models/game_models.py: Changed current_batter/pitcher/catcher to objects
- app/core/game_engine.py: Updated _prepare_next_play() to populate full objects
- app/core/state_manager.py: Create placeholder batter on game creation
- tests/unit/models/test_game_models.py: Updated all 27 GameState tests

**Database Operations**:
- No schema changes needed
- Play table still stores IDs (for referential integrity)
- IDs extracted from objects when saving: state.current_batter.lineup_id

**Testing**:
- All 27 GameState tests passing
- No regressions in existing functionality
- Type checking passes

**Next**: Phase 3E-Main - Add PositionRating dataclass and load ratings at game start

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:11:40 -06:00
Cal Corum
a1f42a93b8 CLAUDE: Implement Phase 3A - X-Check data models and enums
Add foundational data structures for X-Check play resolution system:

Models Added:
- PositionRating: Defensive ratings (range 1-5, error 0-88) for X-Check resolution
- XCheckResult: Dataclass tracking complete X-Check resolution flow with dice rolls,
  conversions (SPD test, G2#/G3#→SI2), error results, and final outcomes
- BasePlayer.active_position_rating: Optional field for current defensive position

Enums Extended:
- PlayOutcome.X_CHECK: New outcome type requiring special resolution
- PlayOutcome.is_x_check(): Helper method for type checking

Documentation Enhanced:
- Play.check_pos: Documented as X-Check position identifier
- Play.hit_type: Documented with examples (single_2_plus_error_1, etc.)

Utilities Added:
- app/core/cache.py: Redis cache key helpers for player positions and game state

Implementation Planning:
- Complete 6-phase implementation plan (3A-3F) documented in .claude/implementation/
- Phase 3A complete with all acceptance criteria met
- Zero breaking changes, all existing tests passing

Next: Phase 3B will add defense tables, error charts, and advancement logic

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 15:32:09 -05:00
Cal Corum
a696473d0a CLAUDE: Integrate flyball advancement with RunnerAdvancement system
Major Phase 2 refactoring to consolidate runner advancement logic:

**Flyball System Enhancement**:
- Add FLYOUT_BQ variant (medium-shallow depth)
- 4 flyball types with clear semantics: A (deep), B (medium), BQ (medium-shallow), C (shallow)
- Updated helper methods to include FLYOUT_BQ

**RunnerAdvancement Integration**:
- Extend runner_advancement.py to handle both groundballs AND flyballs
- advance_runners() routes to _advance_runners_groundball() or _advance_runners_flyball()
- Comprehensive flyball logic with proper DECIDE mechanics per flyball type
- No-op movements recorded for state recovery consistency

**PlayResolver Refactoring**:
- Consolidate all 4 flyball outcomes to delegate to RunnerAdvancement (DRY)
- Eliminate duplicate flyball resolution code
- Rename helpers for clarity: _advance_on_single_1/_advance_on_single_2 (was _advance_on_single)
- Fix single/double advancement logic for different hit types

**State Recovery Fix**:
- Fix state_manager.py game recovery to build LineupPlayerState objects properly
- Use get_lineup_player() helper to construct from lineup data
- Correctly track runners in on_first/on_second/on_third fields (matches Phase 2 model)

**Database Support**:
- Add runner tracking fields to play data for accurate recovery
- Include batter_id, on_first_id, on_second_id, on_third_id, and *_final fields

**Type Safety Improvements**:
- Fix lineup_id access throughout runner_advancement.py (was accessing on_first directly, now on_first.lineup_id)
- Make current_batter_lineup_id non-optional (always set by _prepare_next_play)
- Add type: ignore for known SQLAlchemy false positives

**Documentation**:
- Update CLAUDE.md with comprehensive flyball documentation
- Add flyball types table, usage examples, and test coverage notes
- Document differences between groundball and flyball mechanics

**Testing**:
- Add test_flyball_advancement.py with 21 flyball tests
- Coverage: all 4 types, DECIDE scenarios, no-op movements, edge cases

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 17:04:23 -05:00
Cal Corum
76e24ab22b CLAUDE: Refactor ManualOutcomeSubmission to use PlayOutcome enum + comprehensive documentation
## Refactoring
- Changed `ManualOutcomeSubmission.outcome` from `str` to `PlayOutcome` enum type
- Removed custom validator (Pydantic handles enum validation automatically)
- Added direct import of PlayOutcome (no circular dependency due to TYPE_CHECKING guard)
- Updated tests to use enum values while maintaining backward compatibility

Benefits:
- Better type safety with IDE autocomplete
- Cleaner code (removed 15 lines of validator boilerplate)
- Backward compatible (Pydantic auto-converts strings to enum)
- Access to helper methods (is_hit(), is_out(), etc.)

Files modified:
- app/models/game_models.py: Enum type + import
- tests/unit/config/test_result_charts.py: Updated 7 tests + added compatibility test

## Documentation
Created comprehensive CLAUDE.md files for all backend/app/ subdirectories to help future AI agents quickly understand and work with the code.

Added 8,799 lines of documentation covering:
- api/ (906 lines): FastAPI routes, health checks, auth patterns
- config/ (906 lines): League configs, PlayOutcome enum, result charts
- core/ (1,288 lines): GameEngine, StateManager, PlayResolver, dice system
- data/ (937 lines): API clients (planned), caching layer
- database/ (945 lines): Async sessions, operations, recovery
- models/ (1,270 lines): Pydantic/SQLAlchemy models, polymorphic patterns
- utils/ (959 lines): Logging, JWT auth, security
- websocket/ (1,588 lines): Socket.io handlers, real-time events
- tests/ (475 lines): Testing patterns and structure

Each CLAUDE.md includes:
- Purpose & architecture overview
- Key components with detailed explanations
- Patterns & conventions
- Integration points
- Common tasks (step-by-step guides)
- Troubleshooting with solutions
- Working code examples
- Testing guidance

Total changes: +9,294 lines / -24 lines
Tests: All passing (62/62 model tests, 7/7 ManualOutcomeSubmission tests)
2025-10-31 16:03:54 -05:00
Cal Corum
e2f1d6079f CLAUDE: Implement Week 7 Task 6 - PlayResolver Integration with RunnerAdvancement
Major Refactor: Outcome-First Architecture
- PlayResolver now accepts league_id and auto_mode in constructor
- Added core resolve_outcome() method - all resolution logic in one place
- Added resolve_manual_play() wrapper for manual submissions (primary)
- Added resolve_auto_play() wrapper for PD auto mode (rare)
- Removed SimplifiedResultChart (obsolete with new architecture)
- Removed play_resolver singleton

RunnerAdvancement Integration:
- All groundball outcomes (GROUNDBALL_A/B/C) now use RunnerAdvancement
- Proper DP probability calculation with positioning modifiers
- Hit location tracked for all relevant outcomes
- 13 result types fully integrated from advancement charts

Game State Updates:
- Added auto_mode field to GameState (stored per-game)
- Updated state_manager.create_game() to accept auto_mode parameter
- GameEngine now uses state.auto_mode to create appropriate resolver

League Configuration:
- Added supports_auto_mode() to BaseGameConfig
- SbaConfig: returns False (no digitized cards)
- PdConfig: returns True (has digitized ratings)
- PlayResolver validates auto mode support and raises error for SBA

Play Results:
- Added hit_location field to PlayResult
- Groundballs include location from RunnerAdvancement
- Flyouts track hit_location for tag-up logic (future)
- Other outcomes have hit_location=None

Testing:
- Completely rewrote test_play_resolver.py for new architecture
- 9 new tests covering initialization, strikeouts, walks, groundballs, home runs
- All 9 tests passing
- All 180 core tests still passing (1 pre-existing failure unrelated)

Terminal Client:
- No changes needed - defaults to manual mode (auto_mode=False)
- Perfect for human testing of manual submissions

This completes Week 7 Task 6 - the final task of Week 7!
Week 7 is now 100% complete with all 8 tasks done.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 08:20:52 -05:00
Cal Corum
9cae63ac43 CLAUDE: Implement Week 7 Task 7 - WebSocket manual outcome handlers
Complete manual outcome workflow for SBA and PD manual mode gameplay:

**WebSocket Event Handlers** (app/websocket/handlers.py):
- roll_dice: Server rolls dice, stores in state, broadcasts to players
- submit_manual_outcome: Validates and processes player submissions
- Events: dice_rolled, outcome_accepted, outcome_rejected, play_resolved

**Game Engine Integration** (app/core/game_engine.py):
- resolve_manual_play(): Processes manual outcomes with server dice
- Uses ab_roll for audit trail, player outcome for resolution
- Same orchestration as resolve_play() (save, update, advance inning)

**Data Model** (app/models/game_models.py):
- pending_manual_roll: Stores server dice between roll and submission

**Terminal Client** (terminal_client/):
- roll_dice command: Roll dice and display results
- manual_outcome command: Submit outcomes from physical cards
- Both integrated into REPL for testing

**Tests** (tests/unit/websocket/test_manual_outcome_handlers.py):
- 12 comprehensive tests covering all validation paths
- All tests passing (roll_dice: 4, submit_manual_outcome: 8)

**Key Decisions**:
- Server rolls dice for fairness (not players!)
- One-time roll usage (cleared after submission)
- Early validation (check pending roll before accepting)
- Field-level error messages for clear feedback

**Impact**:
- Complete manual mode workflow ready
- Frontend WebSocket integration supported
- Terminal testing commands available
- Audit trail with server-rolled dice maintained

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 22:51:31 -05:00
Cal Corum
9245b4e008 CLAUDE: Implement Week 7 Task 3 - Result chart abstraction and PD auto mode
Core Implementation:
- Added ResultChart abstract base class with get_outcome() method
- Implemented calculate_hit_location() helper for hit distribution
  - 45% pull, 35% center, 20% opposite field
  - RHB pulls left, LHB pulls right
  - Groundballs → infield positions, flyouts → outfield positions
- Added PlayOutcome.requires_hit_location() helper method
  - Returns True for groundballs and flyouts only

Manual Mode Support:
- Added ManualResultChart (passthrough for interface completeness)
- Manual mode doesn't use result charts - players submit directly
- Added ManualOutcomeSubmission model for WebSocket submissions
  - Validates PlayOutcome enum values
  - Validates hit location positions (1B, 2B, SS, 3B, LF, CF, RF, P, C)

PD Auto Mode Implementation:
- Implemented PdAutoResultChart for automated outcome generation
  - Coin flip (50/50) to choose batting or pitching card
  - Gets rating for correct handedness matchup
  - Builds cumulative distribution from rating percentages
  - Rolls 1d100 to select outcome
  - Calculates hit location using handedness and pull rates
- Maps rating fields to PlayOutcome enum:
  - Common: homerun, triple, doubles, singles, walks, strikeouts
  - Batting-specific: lineouts, popouts, flyout variants, groundout variants
  - Pitching-specific: uncapped singles/doubles, flyouts by location
- Proper error handling when card data missing

Testing:
- Created 21 comprehensive unit tests (all passing)
- Helper function tests (calculate_hit_location)
- PlayOutcome helper tests (requires_hit_location)
- ManualResultChart tests (NotImplementedError)
- PdAutoResultChart tests:
  - Coin flip distribution (~50/50)
  - Handedness matchup selection
  - Cumulative distribution building
  - Outcome selection from probabilities
  - Hit location calculation
  - Error handling for missing cards
  - Statistical distribution verification (1000 trials)
- ManualOutcomeSubmission validation tests
  - Valid/invalid outcomes
  - Valid/invalid hit locations
  - Optional location handling

Deferred to Future Tasks:
- PlayResolver integration (Phase 6 - Week 7 Task 3B)
- Terminal client manual outcome command (Phase 8)
- WebSocket handlers for manual submissions (Week 7 Task 6)
- Runner advancement logic using hit locations (Week 7 Task 4)

Files Modified:
- app/config/result_charts.py: Added base class, auto mode, and helpers
- app/models/game_models.py: Added ManualOutcomeSubmission model
- tests/unit/config/test_result_charts.py: 21 comprehensive tests

All tests passing, no regressions.
2025-10-30 12:42:41 -05:00
Cal Corum
c0051d2a65 CLAUDE: Fix defensive decision validation for corners_in/infield_in depths
- Updated validators.py to use is_runner_on_third() helper method instead of hardcoded on_base_code values
- Fixed DefensiveDecision Pydantic model: infield depths now ['infield_in', 'normal', 'corners_in']
- Fixed DefensiveDecision Pydantic model: outfield depths now ['in', 'normal'] (removed 'back')
- Removed invalid double_play depth tests (depth doesn't exist)
- Added proper tests for corners_in and infield_in validation (requires runner on third)
- All 54 validator tests now passing

Changes maintain consistency between Pydantic validation and GameValidator logic.
2025-10-30 10:25:01 -05:00
Cal Corum
95d8703f56 CLAUDE: Implement Week 7 Task 1 - Strategic Decision Integration
Enhanced game engine with async decision workflow and AI opponent integration:

GameState Model Enhancements:
- Added pending_defensive_decision and pending_offensive_decision fields
- Added decision_phase tracking (idle, awaiting_defensive, awaiting_offensive, resolving, completed)
- Added decision_deadline field for timeout handling
- Added is_batting_team_ai() and is_fielding_team_ai() helper methods
- Added validator for decision_phase

StateManager Enhancements:
- Added _pending_decisions dict for asyncio.Future-based decision queue
- Added set_pending_decision() to create decision futures
- Added await_decision() to wait for decision submission
- Added submit_decision() to resolve pending futures
- Added cancel_pending_decision() for cleanup

GameEngine Enhancements:
- Added await_defensive_decision() with AI/human branching and timeout
- Added await_offensive_decision() with AI/human branching and timeout
- Enhanced submit_defensive_decision() to resolve pending futures
- Enhanced submit_offensive_decision() to resolve pending futures
- Added DECISION_TIMEOUT constant (30 seconds)

AI Opponent (Stub):
- Created ai_opponent.py with stub implementations
- generate_defensive_decision() returns default "normal" positioning
- generate_offensive_decision() returns default "normal" approach
- TODO markers for Week 9 full AI logic implementation

Integration:
- Backward compatible with existing terminal client workflow
- New async methods ready for WebSocket integration (Week 7 Task 4)
- AI teams get instant decisions, human teams wait with timeout
- Default decisions applied on timeout (no game blocking)

Testing:
- Config tests: 58/58 passing 
- Terminal client: Working perfectly 
- Existing workflows: Fully compatible 

Week 7 Task 1: Complete
Next: Task 2 - Decision Validators

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 21:38:11 -05:00
Cal Corum
1c32787195 CLAUDE: Refactor game models and modularize terminal client
This commit includes cleanup from model refactoring and terminal client
modularization for better code organization and maintainability.

## Game Models Refactor

**Removed RunnerState class:**
- Eliminated separate RunnerState model (was redundant)
- Replaced runners: List[RunnerState] with direct base references:
  - on_first: Optional[LineupPlayerState]
  - on_second: Optional[LineupPlayerState]
  - on_third: Optional[LineupPlayerState]
- Updated helper methods:
  - get_runner_at_base() now returns LineupPlayerState directly
  - get_all_runners() returns List[Tuple[int, LineupPlayerState]]
  - is_runner_on_X() simplified to direct None checks

**Benefits:**
- Matches database structure (plays table has on_first_id, etc.)
- Simpler state management (direct references vs list management)
- Better type safety (LineupPlayerState vs generic runner)
- Easier to work with in game engine logic

**Updated files:**
- app/models/game_models.py - Removed RunnerState, updated GameState
- app/core/play_resolver.py - Use get_all_runners() instead of state.runners
- app/core/validators.py - Updated runner access patterns
- tests/unit/models/test_game_models.py - Updated test assertions
- tests/unit/core/test_play_resolver.py - Updated test data
- tests/unit/core/test_validators.py - Updated test data

## Terminal Client Refactor

**Modularization (DRY principle):**
Created separate modules for better code organization:

1. **terminal_client/commands.py** (10,243 bytes)
   - Shared command functions for game operations
   - Used by both CLI (main.py) and REPL (repl.py)
   - Functions: submit_defensive_decision, submit_offensive_decision,
     resolve_play, quick_play_sequence
   - Single source of truth for command logic

2. **terminal_client/arg_parser.py** (7,280 bytes)
   - Centralized argument parsing and validation
   - Handles defensive/offensive decision arguments
   - Validates formats (alignment, depths, hold runners, steal attempts)

3. **terminal_client/completions.py** (10,357 bytes)
   - TAB completion support for REPL mode
   - Command completions, option completions, dynamic completions
   - Game ID completions, defensive/offensive option suggestions

4. **terminal_client/help_text.py** (10,839 bytes)
   - Centralized help text and command documentation
   - Detailed command descriptions
   - Usage examples for all commands

**Updated main modules:**
- terminal_client/main.py - Simplified by using shared commands module
- terminal_client/repl.py - Cleaner with shared functions and completions

**Benefits:**
- DRY: Behavior consistent between CLI and REPL modes
- Maintainability: Changes in one place affect both interfaces
- Testability: Can test commands module independently
- Organization: Clear separation of concerns

## Documentation

**New files:**
- app/models/visual_model_relationships.md
  - Visual documentation of model relationships
  - Helps understand data flow between models
- terminal_client/update_docs/ (6 phase documentation files)
  - Phased documentation for terminal client evolution
  - Historical context for implementation decisions

## Tests

**New test files:**
- tests/unit/terminal_client/__init__.py
- tests/unit/terminal_client/test_arg_parser.py
- tests/unit/terminal_client/test_commands.py
- tests/unit/terminal_client/test_completions.py
- tests/unit/terminal_client/test_help_text.py

**Updated tests:**
- Integration tests updated for new runner model
- Unit tests updated for model changes
- All tests passing with new structure

## Summary

-  Simplified game state model (removed RunnerState)
-  Better alignment with database structure
-  Modularized terminal client (DRY principle)
-  Shared command logic between CLI and REPL
-  Comprehensive test coverage
-  Improved documentation

Total changes: 26 files modified/created

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 14:16:38 -05:00
Cal Corum
13e924a87c CLAUDE: Refactor GameEngine to forward-looking play tracking pattern
Replaced awkward "lookback" pattern with clean "prepare → execute → save"
orchestration that captures state snapshots BEFORE each play.

Key improvements:
- Added per-team batter indices (away_team_batter_idx, home_team_batter_idx)
- Added play snapshot fields (current_batter/pitcher/catcher_lineup_id)
- Added on_base_code bit field for efficient base situation queries
- Created _prepare_next_play() method for snapshot preparation
- Refactored start_game() with hard lineup validation requirement
- Refactored resolve_play() with explicit 6-step orchestration
- Updated _save_play_to_db() to use snapshots (no DB lookbacks)
- Enhanced state recovery to rebuild from last play (single query)
- Added defensive lineup position validator

Benefits:
- No special cases for first play
- Single source of truth in GameState
- Saves 18+ database queries per game
- Fast state recovery without replay
- Complete runner tracking (before/after positions)
- Explicit orchestration (easy to debug)

Testing:
- Added 3 new test functions (lineup validation, snapshot tracking, batting order)
- All 5 test suites passing (100%)
- Type checking cleaned up with targeted suppressions for SQLAlchemy

Documentation:
- Added comprehensive "Type Checking & Common False Positives" section to CLAUDE.md
- Created type-checking-guide.md and type-checking-summary.md
- Added mypy.ini configuration for SQLAlchemy/Pydantic

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:18:15 -05:00
Cal Corum
a287784328 CLAUDE: Complete Week 4 - State Management & Persistence
Implemented hybrid state management system with in-memory game states and async
PostgreSQL persistence. This provides the foundation for fast gameplay (<500ms
response) with complete state recovery capabilities.

## Components Implemented

### Production Code (3 files, 1,150 lines)
- app/models/game_models.py (492 lines)
  - Pydantic GameState with 20+ helper methods
  - RunnerState, LineupPlayerState, TeamLineupState
  - DefensiveDecision and OffensiveDecision models
  - Full Pydantic v2 validation with field validators

- app/core/state_manager.py (296 lines)
  - In-memory state management with O(1) lookups
  - State recovery from database
  - Idle game eviction mechanism
  - Statistics tracking

- app/database/operations.py (362 lines)
  - Async PostgreSQL operations
  - Game, lineup, and play persistence
  - Complete state loading for recovery
  - GameSession WebSocket state tracking

### Tests (4 files, 1,963 lines, 115 tests)
- tests/unit/models/test_game_models.py (60 tests, ALL PASSING)
- tests/unit/core/test_state_manager.py (26 tests, ALL PASSING)
- tests/integration/database/test_operations.py (21 tests)
- tests/integration/test_state_persistence.py (8 tests)
- pytest.ini (async test configuration)

### Documentation (6 files)
- backend/CLAUDE.md (updated with Week 4 patterns)
- .claude/implementation/02-week4-state-management.md (marked complete)
- .claude/status-2025-10-22-0113.md (planning session summary)
- .claude/status-2025-10-22-1147.md (implementation session summary)
- .claude/implementation/player-data-catalog.md (player data reference)
- Week 5 & 6 plans created

## Key Features

- Hybrid state: in-memory (fast) + PostgreSQL (persistent)
- O(1) state access via dictionary lookups
- Async database writes (non-blocking)
- Complete state recovery from database
- Pydantic validation on all models
- Helper methods for common game operations
- Idle game eviction with configurable timeout
- 86 unit tests passing (100%)

## Performance

- State access: O(1) via UUID lookup
- Memory per game: ~1KB (just state)
- Target response time: <500ms 
- Database writes: <100ms (async) 

## Testing

- Unit tests: 86/86 passing (100%)
- Integration tests: 29 written
- Test configuration: pytest.ini created
- Fixed Pydantic v2 config deprecation
- Fixed pytest-asyncio configuration

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 12:01:03 -05:00