🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
761 lines
30 KiB
Markdown
761 lines
30 KiB
Markdown
# Next Session Plan - Phase 3 Week 7 in Progress
|
|
|
|
**Current Status**: Phase 3 - Week 7 (~62% Complete)
|
|
**Last Commit**: `9cae63a` - "CLAUDE: Implement Week 7 Task 7 - WebSocket manual outcome handlers"
|
|
**Date**: 2025-10-30
|
|
**Remaining Work**: 38% (3 of 8 tasks remaining, Task 7 complete!)
|
|
|
|
---
|
|
|
|
## Quick Start for Next AI Agent
|
|
|
|
### 🎯 Where to Begin
|
|
1. Read this entire document first
|
|
2. Review `@.claude/implementation/WEEK_7_PLAN.md` for comprehensive task details
|
|
3. Start with **Task 4: Runner Advancement Logic** (next logical step)
|
|
4. Run tests after each change: `export PYTHONPATH=. && pytest tests/unit/config/ -v`
|
|
|
|
### 📍 Current Context
|
|
**Week 7 Tasks 1-3 and 7 are complete!**
|
|
- **Task 1**: Async decision workflow with asyncio Futures ✅
|
|
- **Task 2**: Defensive/offensive decision validators with 54 tests passing ✅
|
|
- **Task 3**: Result chart abstraction + PD auto mode with 21 tests passing ✅
|
|
- **Task 7**: WebSocket manual outcome handlers with 12 tests passing ✅
|
|
|
|
**Next up**: Implement runner advancement logic (Task 4)! This is the CRITICAL component that uses hit locations from Task 3 to determine where runners go based on outcome + game situation (Infield In/Back charts, tag-ups, force plays, etc.). This is where the advancement charts from the user images come into play.
|
|
|
|
**Note**: Task 7 completed out of order because Task 4 requires advancement chart images from user.
|
|
|
|
**IMPORTANT CONTEXT**: In this session, we clarified major architectural points:
|
|
- **Manual Mode (SBA + PD manual)**:
|
|
- Server rolls dice for fairness and auditing (NOT players!)
|
|
- Players read PHYSICAL cards based on server dice
|
|
- Players submit outcomes via WebSocket
|
|
- System validates and processes with server-rolled dice
|
|
- **PD Auto Mode**: System uses digitized ratings to auto-generate outcomes for faster/AI play. This is NEW functionality enabling AI vs AI games.
|
|
- **Decision Modifiers**: Do NOT change the base outcome (GROUNDBALL_C stays GROUNDBALL_C). They affect RUNNER ADVANCEMENT based on hit location and defensive positioning.
|
|
|
|
---
|
|
|
|
## What We Just Completed ✅
|
|
|
|
### 1. Validator Bug Fixes (Commit `c0051d2`)
|
|
- **File**: `app/core/validators.py`
|
|
- **Issue**: Validator checking wrong on_base_codes for "runner on third"
|
|
- **Fix**: Updated to use `state.is_runner_on_third()` helper method
|
|
- **Changes**:
|
|
- Fixed infield depth validation (corners_in/infield_in require runner on third)
|
|
- Updated DefensiveDecision Pydantic model: infield depths `['infield_in', 'normal', 'corners_in']`
|
|
- Updated DefensiveDecision Pydantic model: outfield depths `['in', 'normal']` (removed 'back')
|
|
- Removed 4 invalid double_play depth tests (depth doesn't exist)
|
|
- Added 4 proper corners_in/infield_in tests
|
|
- **Testing**: All 54 validator tests passing ✅
|
|
- **Impact**: Validators now correctly check game state using helper methods
|
|
|
|
### 2. Result Chart Abstraction & PD Auto Mode (Commit `9245b4e`) - Week 7 Task 3
|
|
- **Files**:
|
|
- `app/config/result_charts.py` (+400 lines)
|
|
- `app/models/game_models.py` (+55 lines)
|
|
- `tests/unit/config/test_result_charts.py` (+492 lines, NEW)
|
|
|
|
- **Core Implementation**:
|
|
- **ResultChart abstract base class**: Defines `get_outcome(roll, state, batter, pitcher) -> tuple[outcome, location]`
|
|
- **calculate_hit_location() helper**:
|
|
- 45% pull, 35% center, 20% opposite field distribution
|
|
- RHB pulls left (3B, SS, LF), LHB pulls right (1B, 2B, RF)
|
|
- Groundballs → infield positions (1B, 2B, SS, 3B, P, C)
|
|
- Flyouts → outfield positions (LF, CF, RF)
|
|
- **PlayOutcome.requires_hit_location()**: Returns True for groundballs and flyouts only
|
|
|
|
- **Manual Mode Support**:
|
|
- **ManualResultChart**: Passthrough class (raises NotImplementedError)
|
|
- Manual mode doesn't use result charts - players submit via WebSocket
|
|
- **ManualOutcomeSubmission model**: Validates PlayOutcome enum + hit location
|
|
- Validates outcome is valid PlayOutcome value
|
|
- Validates hit location in ['1B', '2B', 'SS', '3B', 'LF', 'CF', 'RF', 'P', 'C']
|
|
- Location is optional (only needed for certain outcomes)
|
|
|
|
- **PD Auto Mode Implementation**:
|
|
- **PdAutoResultChart**: Full auto-generation for PD games
|
|
- `_select_card()`: Coin flip (50/50) to choose batting or pitching card
|
|
- `_build_distribution()`: Creates cumulative distribution from rating percentages
|
|
- `_select_outcome()`: Rolls 1d100 to select outcome from distribution
|
|
- 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 (SINGLE_UNCAPPED, DOUBLE_UNCAPPED)
|
|
- Calculates hit location using handedness and pull rates
|
|
- Proper error handling when card data missing
|
|
|
|
- **Testing**: 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 over 1000 trials)
|
|
- Handedness matchup selection
|
|
- Cumulative distribution building
|
|
- Outcome selection from probabilities
|
|
- Hit location calculation for groundballs
|
|
- Error handling for missing cards
|
|
- Statistical distribution verification
|
|
- ManualOutcomeSubmission validation tests
|
|
|
|
- **Impact**:
|
|
- ✅ Foundation for both manual and auto play modes
|
|
- ✅ Hit locations ready for Task 4 runner advancement
|
|
- ✅ PD auto mode enables AI vs AI games
|
|
- ⏳ Integration with PlayResolver deferred (Phase 6)
|
|
- ⏳ Terminal client manual outcome command deferred (Phase 8)
|
|
|
|
### 3. WebSocket Manual Outcome Handlers (Current Session) - Week 7 Task 7
|
|
- **Files**:
|
|
- `app/websocket/handlers.py` (+240 lines - 2 new event handlers)
|
|
- `app/core/game_engine.py` (+147 lines - resolve_manual_play method)
|
|
- `app/models/game_models.py` (+1 line - pending_manual_roll field)
|
|
- `terminal_client/commands.py` (+128 lines - roll_manual_dice, submit_manual_outcome)
|
|
- `terminal_client/repl.py` (updated do_roll_dice, do_manual_outcome)
|
|
- `tests/unit/websocket/test_manual_outcome_handlers.py` (+432 lines, NEW)
|
|
|
|
- **Core Implementation**:
|
|
- **roll_dice WebSocket Handler**:
|
|
- Server rolls dice using dice_system.roll_ab()
|
|
- Stores ab_roll in state.pending_manual_roll
|
|
- Broadcasts dice results to all players in game room
|
|
- Events: `dice_rolled` (broadcast), `error` (validation failures)
|
|
|
|
- **submit_manual_outcome WebSocket Handler**:
|
|
- Validates ManualOutcomeSubmission model (outcome + optional location)
|
|
- Checks for pending_manual_roll (prevents submission without roll)
|
|
- Validates hit_location required for groundballs/flyouts
|
|
- Calls game_engine.resolve_manual_play() to process
|
|
- Events: `outcome_accepted`, `outcome_rejected`, `play_resolved`, `error`
|
|
|
|
- **GameEngine.resolve_manual_play()**:
|
|
- Accepts server-rolled ab_roll for audit trail
|
|
- Uses player-submitted outcome for resolution
|
|
- Validates hit_location when required
|
|
- Same orchestration as resolve_play() (save, update, advance inning)
|
|
- Tracks rolls for batch saving at inning boundaries
|
|
|
|
- **Terminal Client Commands**:
|
|
- `roll_dice` - Roll dice and display results
|
|
- `manual_outcome <outcome> [location]` - Submit manual outcome
|
|
- Both integrated into REPL for testing
|
|
|
|
- **Testing**: 12 comprehensive unit tests (all passing ✅)
|
|
- roll_dice tests (4):
|
|
- Successful roll and broadcast
|
|
- Missing game_id validation
|
|
- Invalid game_id format validation
|
|
- Game not found error handling
|
|
- submit_manual_outcome tests (8):
|
|
- Successful submission and play resolution
|
|
- Missing game_id validation
|
|
- Missing outcome validation
|
|
- Invalid outcome value validation
|
|
- Invalid hit_location validation
|
|
- Missing required hit_location validation
|
|
- No pending roll error handling
|
|
- Walk without location (valid case)
|
|
|
|
- **Key Architectural Decisions**:
|
|
- **Server rolls dice for fairness**: Clarified with user - server generates dice, stores for audit, players read cards
|
|
- **One-time roll usage**: pending_manual_roll cleared after submission to prevent reuse
|
|
- **Early validation**: Check for pending roll BEFORE emitting outcome_accepted
|
|
- **Comprehensive error handling**: Field-level error messages for clear user feedback
|
|
|
|
- **Impact**:
|
|
- ✅ Complete manual outcome workflow implemented
|
|
- ✅ WebSocket handlers ready for frontend integration
|
|
- ✅ Terminal client testing commands available
|
|
- ✅ Audit trail maintained with server-rolled dice
|
|
- ✅ Foundation for SBA and PD manual mode gameplay
|
|
|
|
---
|
|
|
|
## Key Architecture Decisions Made
|
|
|
|
### 1. **Manual vs Auto Mode Clarification**
|
|
**Decision**: Manual mode doesn't use result charts at all - humans submit outcomes directly
|
|
|
|
**Rationale**:
|
|
- SBA and PD manual games use physical cards that aren't digitized (SBA) or optional digitization (PD)
|
|
- Players roll dice, read their card, and tell system the outcome + location via WebSocket
|
|
- Result charts only used for PD auto mode where we need to generate outcomes
|
|
|
|
**Impact**:
|
|
- Simpler architecture - no "manual result chart" logic needed
|
|
- ManualResultChart exists only for interface completeness (raises NotImplementedError)
|
|
- WebSocket handlers will receive ManualOutcomeSubmission objects
|
|
- PdAutoResultChart is truly optional - only for auto mode
|
|
|
|
### 2. **Decision Modifiers Affect Advancement, Not Outcomes**
|
|
**Decision**: Defensive decisions don't change the PlayOutcome - they change runner advancement
|
|
|
|
**Rationale**:
|
|
- User provided advancement charts showing different runner movements for same outcome
|
|
- GROUNDBALL_C stays GROUNDBALL_C whether infield is "in", "back", or "normal"
|
|
- The HIT LOCATION + DEFENSIVE POSITIONING determine advancement (Infield In/Back charts)
|
|
- Example: GROUNDBALL_C to SS with "corners_in" = different advancement than "normal" depth
|
|
|
|
**Impact**:
|
|
- Task 3 (this session) focused on outcome selection + hit location calculation
|
|
- Task 4 (next) implements advancement logic using hit locations from Task 3
|
|
- SimplifiedResultChart in play_resolver.py remains untouched (no breaking changes)
|
|
- Original Week 7 plan overestimated decision modifier complexity
|
|
|
|
### 3. **Hit Location is Critical, Not Just Informational**
|
|
**Decision**: Track precise hit location (1B, 2B, SS, 3B, LF, CF, RF, P, C) for every groundball/flyout
|
|
|
|
**Rationale**:
|
|
- User's advancement charts show different rules for different fielders
|
|
- "Corners in" only affects plays hit to 1B, 3B, P, or C (not 2B/SS)
|
|
- Hit location determines which advancement chart row to use
|
|
- Tag-up logic for flyouts depends on location (deep fly vs shallow)
|
|
|
|
**Impact**:
|
|
- calculate_hit_location() must be accurate with proper pull rates
|
|
- ManualOutcomeSubmission requires location for groundballs/flyouts
|
|
- Task 4 will use location extensively in advancement logic
|
|
- Future: Could add fielder ratings affecting outcomes
|
|
|
|
### 4. **On-Base Code is Enumeration, Not Bit Field**
|
|
**Decision**: current_on_base_code is 0-7 enumeration, not bit-field addition
|
|
|
|
**Clarification** (from user):
|
|
- 0: empty
|
|
- 1: on first
|
|
- 2: on second
|
|
- 3: on third
|
|
- 4: first and second
|
|
- 5: first and third
|
|
- 6: second and third
|
|
- 7: bases loaded
|
|
|
|
**Impact**:
|
|
- Fixed validator bug checking wrong codes for "runner on third"
|
|
- Code should use helper methods (`is_runner_on_first()`) instead of hardcoding
|
|
- Documentation updated with correct enumeration values
|
|
|
|
---
|
|
|
|
## Blockers Encountered 🚧
|
|
|
|
### 1. **PYTHONPATH Required for Tests**
|
|
**Issue**: Tests fail with `ModuleNotFoundError: No module named 'app'` without PYTHONPATH set
|
|
|
|
**Workaround**: Run tests with `export PYTHONPATH=. && pytest ...`
|
|
|
|
**Status**: ⚠️ Need to investigate why PYTHONPATH isn't set automatically by pytest.ini
|
|
|
|
**TODO**: Add PYTHONPATH configuration to pytest.ini or add __init__.py files to fix imports
|
|
|
|
---
|
|
|
|
## Outstanding Questions ❓
|
|
|
|
### 1. **Legacy Bot Code Review Timing**
|
|
**Question**: When should we review `../paper-dynasty/discord-app/in_game/` for advancement logic?
|
|
|
|
**Context**: User mentioned legacy bot has dozens of advancement scenarios coded. We should NOT reuse the code (not optimized) but the LOGIC is valuable.
|
|
|
|
**Recommendation**: Review before starting Task 4 to understand all edge cases (TOOTBLAN, FARTSLAM, DECIDE mechanics from user's images).
|
|
|
|
### 2. **WebSocket Event Names for Manual Submissions**
|
|
**Question**: What events should manual mode use?
|
|
|
|
**Context**: Need events for:
|
|
- Rolling dice and presenting to players
|
|
- Players submitting ManualOutcomeSubmission
|
|
- Validating submission
|
|
- Broadcasting result
|
|
|
|
**Proposed Names**:
|
|
- `roll_dice` - Server rolls dice and broadcasts to players
|
|
- `submit_manual_outcome` - Player sends ManualOutcomeSubmission
|
|
- `outcome_accepted` - Server confirms valid outcome
|
|
- `outcome_rejected` - Server rejects invalid outcome (validation error)
|
|
|
|
**Recommendation**: Define in Task 6 (WebSocket Handlers).
|
|
|
|
### 3. **Terminal Client Testing Without Frontend**
|
|
**Question**: How to test manual outcome submission flow without WebSocket?
|
|
|
|
**Context**: Terminal client currently uses game engine directly. Manual mode flow goes through WebSocket.
|
|
|
|
**Options**:
|
|
- A) Add `manual_outcome` command that simulates WebSocket submission
|
|
- B) Skip terminal client manual mode testing until WebSocket handlers done
|
|
- C) Add test-only bypass in game engine for manual outcomes
|
|
|
|
**Recommendation**: Option A - add `manual_outcome` command in Task 8 (Terminal Client Enhancement).
|
|
|
|
---
|
|
|
|
## Tasks for Next Session
|
|
|
|
### Task 4: Runner Advancement Logic (6-8 hours) - **HIGH PRIORITY**
|
|
|
|
**Files**:
|
|
- `app/core/runner_advancement.py` (NEW)
|
|
- `app/core/play_resolver.py` (integrate)
|
|
- `tests/unit/core/test_runner_advancement.py` (NEW)
|
|
|
|
**Goal**: Implement complete runner advancement logic using hit locations and game situation
|
|
|
|
**Changes**:
|
|
|
|
1. **Create `RunnerAdvancement` class**:
|
|
- `advance_runners(outcome, hit_location, state, defensive_decision) -> dict`
|
|
- Returns movements: `{runner_id: {from_base: int, to_base: int, is_out: bool}}`
|
|
|
|
2. **Implement Infield Back advancement** (user's first image):
|
|
- Normal advancement for standard plays
|
|
- Special rules for GROUNDBALL_C based on base situation
|
|
|
|
3. **Implement Infield In advancement** (user's second image):
|
|
- Runner on 3rd scores on contact (GROUNDBALL_C)
|
|
- Lead runner advancement based on hit location
|
|
- TOOTBLAN mechanic (pick-off at third attempt)
|
|
- FARTSLAM mechanic (runner tries to score on grounder)
|
|
- DECIDE mechanic (lead runner can attempt advance)
|
|
|
|
4. **Implement tag-up logic for flyouts**:
|
|
- Shallow flies: no advancement
|
|
- Medium flies: R3 can tag
|
|
- Deep flies: R3 tags, R2 can advance
|
|
|
|
5. **Force play detection**:
|
|
- Runner must advance if forced
|
|
- Used in advancement calculations
|
|
|
|
**Files to Update**:
|
|
- `app/core/runner_advancement.py` - NEW file with RunnerAdvancement class
|
|
- `app/core/play_resolver.py` - Integration point (call RunnerAdvancement)
|
|
- `tests/unit/core/test_runner_advancement.py` - NEW, ~30 test cases
|
|
|
|
**Test Command**:
|
|
```bash
|
|
export PYTHONPATH=. && pytest tests/unit/core/test_runner_advancement.py -v
|
|
```
|
|
|
|
**Acceptance Criteria**:
|
|
- [ ] RunnerAdvancement.advance_runners() returns correct movements dict
|
|
- [ ] Infield Back chart implemented (all 9 base situations from user image)
|
|
- [ ] Infield In chart implemented (all variations from user image)
|
|
- [ ] TOOTBLAN mechanic implemented (d20 roll for pick-off attempt)
|
|
- [ ] FARTSLAM mechanic implemented (d20 roll for safe range)
|
|
- [ ] DECIDE mechanic implemented (offense chooses advancement)
|
|
- [ ] Tag-up logic for flyouts (R3 on deep fly, etc.)
|
|
- [ ] Force play detection works correctly
|
|
- [ ] Hit location affects advancement (1B/3B/P/C for corners_in)
|
|
- [ ] 30+ test cases covering all scenarios
|
|
- [ ] Integration with play_resolver works
|
|
|
|
**IMPORTANT**: Review `../paper-dynasty/discord-app/in_game/` before starting to understand all edge cases!
|
|
|
|
---
|
|
|
|
### Task 5: Double Play Mechanics (2-3 hours)
|
|
|
|
**Files**:
|
|
- `app/core/play_resolver.py` (enhance)
|
|
- `tests/unit/core/test_play_resolver.py` (add tests)
|
|
|
|
**Goal**: Implement double play resolution for GROUNDBALL_A outcomes
|
|
|
|
**Changes**:
|
|
1. Add `_resolve_double_play_attempt()` method
|
|
2. Calculate DP probability based on:
|
|
- Base probability: 45%
|
|
- Positioning modifiers (DP depth +20%, infield in -15%)
|
|
- Hit location modifiers (up middle +10%, corners -10%)
|
|
- Runner speed modifiers (fast -15%, slow +10%)
|
|
3. Return (outs_recorded, [runner_ids_out])
|
|
4. Integrate with `_resolve_outcome()` for GROUNDBALL_A
|
|
|
|
**Files to Update**:
|
|
- `app/core/play_resolver.py` - Add DP resolution
|
|
- `tests/unit/core/test_play_resolver.py` - Add ~10 DP tests
|
|
|
|
**Test Command**:
|
|
```bash
|
|
export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py::test_double_play -v
|
|
```
|
|
|
|
**Acceptance Criteria**:
|
|
- [ ] Base DP probability: 45%
|
|
- [ ] Positioning modifiers work correctly
|
|
- [ ] Hit location modifiers work correctly
|
|
- [ ] Runner speed considered (need player speed data)
|
|
- [ ] Returns correct outs_recorded
|
|
- [ ] Returns correct runner_ids_out list
|
|
- [ ] Terminal client shows "DP" in description
|
|
- [ ] 10+ test cases for various scenarios
|
|
|
|
---
|
|
|
|
### Task 6: PlayResolver Integration (3-4 hours)
|
|
|
|
**Files**:
|
|
- `app/core/play_resolver.py` (major refactor)
|
|
- `app/core/game_engine.py` (update calls)
|
|
|
|
**Goal**: Integrate result charts and runner advancement into play resolution
|
|
|
|
**Changes**:
|
|
1. Add `league_id` and `auto_mode` params to PlayResolver.__init__()
|
|
2. Create PdAutoResultChart for PD auto mode
|
|
3. Update resolve_play() to use result chart when in auto mode
|
|
4. Integrate RunnerAdvancement for all plays
|
|
5. Store hit_location in play results
|
|
6. Update all callers (game_engine, terminal_client)
|
|
|
|
**Files to Update**:
|
|
- `app/core/play_resolver.py` - Major refactor
|
|
- `app/core/game_engine.py` - Update resolve_play calls
|
|
- `tests/unit/core/test_play_resolver.py` - Update existing tests
|
|
- `terminal_client/commands.py` - Update for auto mode support
|
|
|
|
**Test Command**:
|
|
```bash
|
|
export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py -v
|
|
```
|
|
|
|
**Acceptance Criteria**:
|
|
- [ ] PlayResolver accepts league_id and auto_mode params
|
|
- [ ] PD auto mode uses PdAutoResultChart
|
|
- [ ] Manual mode bypasses result charts (expects ManualOutcomeSubmission)
|
|
- [ ] RunnerAdvancement called for all outcomes
|
|
- [ ] Hit location stored in play results
|
|
- [ ] All existing tests pass (no regressions)
|
|
- [ ] Terminal client works with both modes
|
|
|
|
---
|
|
|
|
### Task 7: WebSocket Handlers for Manual Submissions (3-4 hours)
|
|
|
|
**Files**:
|
|
- `app/websocket/handlers.py` (add handlers)
|
|
- `tests/unit/websocket/test_manual_outcome_handlers.py` (NEW)
|
|
|
|
**Goal**: Create WebSocket event handlers for manual outcome submission
|
|
|
|
**Changes**:
|
|
1. Add `roll_dice` event handler - Server rolls and broadcasts dice
|
|
2. Add `submit_manual_outcome` event handler - Validates ManualOutcomeSubmission
|
|
3. Validate outcome is valid PlayOutcome
|
|
4. Validate location provided when required
|
|
5. Call play_resolver with manual outcome
|
|
6. Broadcast result to game room
|
|
|
|
**Files to Update**:
|
|
- `app/websocket/handlers.py` - Add manual outcome handlers
|
|
- `app/websocket/events.py` - Define event names (if doesn't exist)
|
|
- `tests/unit/websocket/test_manual_outcome_handlers.py` - NEW, ~15 tests
|
|
|
|
**Test Command**:
|
|
```bash
|
|
export PYTHONPATH=. && pytest tests/unit/websocket/test_manual_outcome_handlers.py -v
|
|
```
|
|
|
|
**Acceptance Criteria**:
|
|
- [ ] `roll_dice` handler rolls dice and broadcasts to players
|
|
- [ ] `submit_manual_outcome` validates ManualOutcomeSubmission
|
|
- [ ] Validates outcome is valid PlayOutcome enum value
|
|
- [ ] Validates location provided for groundballs/flyouts
|
|
- [ ] Rejects invalid outcomes with clear error
|
|
- [ ] Calls play_resolver with manual outcome
|
|
- [ ] Broadcasts result to game room
|
|
- [ ] 15+ test cases for all scenarios
|
|
- [ ] Error handling with clear messages
|
|
|
|
---
|
|
|
|
### Task 8: Terminal Client Enhancement (2-3 hours)
|
|
|
|
**Files**:
|
|
- `terminal_client/commands.py` (add command)
|
|
- `terminal_client/help_text.py` (update docs)
|
|
- `terminal_client/completions.py` (add completions)
|
|
|
|
**Goal**: Add `manual_outcome` command for testing manual submission flow
|
|
|
|
**Changes**:
|
|
1. Add `manual_outcome <outcome> [location]` command
|
|
2. Validates outcome is valid PlayOutcome
|
|
3. Validates location if required
|
|
4. Simulates manual submission (bypasses WebSocket for testing)
|
|
5. Add TAB completion for outcome names
|
|
6. Update help text with examples
|
|
|
|
**Files to Update**:
|
|
- `terminal_client/commands.py` - Add manual_outcome command
|
|
- `terminal_client/help_text.py` - Update documentation
|
|
- `terminal_client/completions.py` - Add TAB completions
|
|
|
|
**Test Command**:
|
|
```bash
|
|
python -m terminal_client
|
|
> help manual_outcome
|
|
> new_game --league sba
|
|
> roll_dice
|
|
> manual_outcome groundball_c SS
|
|
> status
|
|
```
|
|
|
|
**Acceptance Criteria**:
|
|
- [ ] `manual_outcome` command accepts outcome + optional location
|
|
- [ ] Validates outcome is valid PlayOutcome
|
|
- [ ] Validates location if required (groundballs/flyouts)
|
|
- [ ] Simulates manual submission flow
|
|
- [ ] TAB completion for outcome names works
|
|
- [ ] Help text shows examples
|
|
- [ ] Manual testing passes
|
|
- [ ] Works alongside auto resolution mode
|
|
|
|
---
|
|
|
|
## Files to Review Before Starting
|
|
|
|
### For Task 4 (Runner Advancement):
|
|
1. `../paper-dynasty/discord-app/in_game/` - Legacy bot advancement logic (DO NOT copy code, study LOGIC)
|
|
2. User's advancement chart images (already provided - see session context)
|
|
3. `app/config/result_charts.py:203-278` - calculate_hit_location() for understanding locations
|
|
4. `app/models/game_models.py:247-450` - GameState model for base runner access
|
|
5. `app/core/play_resolver.py` - Current resolution logic to integrate with
|
|
|
|
### For Task 5 (Double Play):
|
|
1. `app/core/play_resolver.py` - SimplifiedResultChart.get_outcome() for integration point
|
|
2. `app/models/game_models.py` - GameState for runner access
|
|
3. `tests/unit/core/test_play_resolver.py` - Existing test patterns
|
|
|
|
### For Task 6 (Integration):
|
|
1. `app/core/play_resolver.py` - Entire file needs refactor
|
|
2. `app/core/game_engine.py:300-400` - resolve_play calls
|
|
3. `app/config/result_charts.py` - ResultChart interface
|
|
4. `tests/unit/core/test_play_resolver.py` - Update all tests
|
|
|
|
### For Task 7 (WebSocket):
|
|
1. `app/websocket/handlers.py` - Existing handler patterns
|
|
2. `app/websocket/connection_manager.py` - Broadcasting methods
|
|
3. `app/models/game_models.py:192-240` - ManualOutcomeSubmission model
|
|
|
|
---
|
|
|
|
## Verification Steps
|
|
|
|
After each task:
|
|
|
|
1. **Run unit tests**:
|
|
```bash
|
|
# After Task 4
|
|
export PYTHONPATH=. && pytest tests/unit/core/test_runner_advancement.py -v
|
|
|
|
# After Task 5
|
|
export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py -v
|
|
|
|
# After Task 6
|
|
export PYTHONPATH=. && pytest tests/unit/core/ -v
|
|
|
|
# After Task 7
|
|
export PYTHONPATH=. && pytest tests/unit/websocket/ -v
|
|
|
|
# After Task 8
|
|
python -m terminal_client # Manual testing
|
|
```
|
|
|
|
2. **Run all tests** (check for regressions):
|
|
```bash
|
|
export PYTHONPATH=. && pytest tests/unit/ -v
|
|
```
|
|
|
|
3. **Terminal client testing**:
|
|
```bash
|
|
python -m terminal_client
|
|
> new_game --league pd --auto
|
|
> defensive normal normal normal
|
|
> offensive normal
|
|
> resolve # Auto mode
|
|
|
|
> new_game --league sba
|
|
> roll_dice
|
|
> manual_outcome groundball_c SS # Manual mode
|
|
> status
|
|
```
|
|
|
|
4. **Commit after each task**:
|
|
```bash
|
|
git add [modified files]
|
|
git commit -m "CLAUDE: Implement Week 7 Task [N] - [Task Name]"
|
|
```
|
|
|
|
---
|
|
|
|
## Success Criteria
|
|
|
|
**Week 7** will be **100% complete** when:
|
|
|
|
- ✅ Task 1: Strategic Decision Integration (DONE)
|
|
- ✅ Task 2: Decision Validators (DONE - 54 tests passing)
|
|
- ✅ Task 3: Result Charts + PD Auto Mode (DONE - 21 tests passing)
|
|
- [ ] Task 4: Runner Advancement Logic (~30 tests passing) - **BLOCKED**: Awaiting advancement chart images from user
|
|
- [ ] Task 5: Double Play Mechanics (~10 tests passing)
|
|
- [ ] Task 6: PlayResolver Integration (all existing tests still pass)
|
|
- ✅ Task 7: WebSocket Manual Outcome Handlers (DONE - 12 tests passing)
|
|
- ✅ Task 8: Terminal Client Enhancement (DONE - manual commands working)
|
|
- [ ] All 130+ new tests passing (currently 87/130 done - 67%)
|
|
- ✅ Terminal client demonstrates both auto and manual modes
|
|
- ✅ Documentation updated
|
|
- ✅ Git commits for each task
|
|
|
|
**Week 8** will begin with:
|
|
- Substitution system (pinch hitters, defensive replacements)
|
|
- Pitching changes (bullpen management)
|
|
- Frontend game interface (mobile-first)
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
**Current Test Count**: ~489 tests passing
|
|
- Config tests: 79/79 ✅ (58 + 21 new from Task 3)
|
|
- Validators: 54/54 ✅
|
|
- WebSocket handlers: 12/12 ✅ (NEW from Task 7)
|
|
- Play resolver tests: 19/19 ✅
|
|
- Dice tests: 34/35 (1 pre-existing failure)
|
|
- Roll types tests: 27/27 ✅
|
|
- Player models: 32/32 ✅
|
|
- Game models: ~150+ ✅
|
|
- State manager: ~80+ ✅
|
|
|
|
**Target Test Count After Week 7**: ~550+ tests
|
|
**Current Progress**: 489/550 (89%)
|
|
|
|
**Last Test Run**: All passing except 1 pre-existing (2025-10-30)
|
|
**Branch**: `implement-phase-2`
|
|
**Python**: 3.13.3
|
|
**Virtual Env**: `backend/venv/`
|
|
**Database**: PostgreSQL @ 10.10.0.42:5432 (paperdynasty_dev)
|
|
|
|
**Key Imports for Week 7 Remaining Tasks**:
|
|
```python
|
|
from app.config import get_league_config, PlayOutcome
|
|
from app.config.result_charts import calculate_hit_location, PdAutoResultChart, ManualOutcomeSubmission
|
|
from app.core.dice import AbRoll
|
|
from app.core.validators import game_validator, ValidationError
|
|
from app.core.state_manager import state_manager
|
|
from app.core.ai_opponent import ai_opponent
|
|
from app.models.game_models import DefensiveDecision, OffensiveDecision, GameState, ManualOutcomeSubmission
|
|
```
|
|
|
|
**Recent Commit History** (Last 10):
|
|
```
|
|
9245b4e - CLAUDE: Implement Week 7 Task 3 - Result chart abstraction and PD auto mode (53 seconds ago)
|
|
c0051d2 - CLAUDE: Fix defensive decision validation for corners_in/infield_in depths (2 hours ago)
|
|
f07d8ca - CLAUDE: Update NEXT_SESSION.md - Task 2 complete (6 hours ago)
|
|
121a908 - CLAUDE: Implement Week 7 Task 2 - Decision Validators (6 hours ago)
|
|
0a21eda - CLAUDE: Update project plan for Week 7 continuation (11 hours ago)
|
|
95d8703 - CLAUDE: Implement Week 7 Task 1 - Strategic Decision Integration (15 hours ago)
|
|
d7caa75 - CLAUDE: Add manual outcome testing to terminal client and Phase 3 planning (16 hours ago)
|
|
6880b6d - CLAUDE: Complete Week 6 - granular PlayOutcome integration and metadata support (16 hours ago)
|
|
64aa800 - CLAUDE: Update implementation plans for next session (2 days ago)
|
|
5d5c13f - CLAUDE: Implement Week 6 league configuration and play outcome systems (2 days ago)
|
|
```
|
|
|
|
---
|
|
|
|
## Context for AI Agent Resume
|
|
|
|
**If the next agent needs to understand the bigger picture**:
|
|
- **Overall project**: See `@prd-web-scorecard-1.1.md` and `@CLAUDE.md`
|
|
- **Architecture**: See `@.claude/implementation/00-index.md`
|
|
- **Backend guide**: See `@backend/CLAUDE.md`
|
|
- **Current phase details**: See `@.claude/implementation/03-gameplay-features.md`
|
|
- **Week 7 detailed plan**: See `@.claude/implementation/WEEK_7_PLAN.md`
|
|
|
|
**Critical files for current work (Week 7 Tasks 4-8)**:
|
|
1. `app/core/runner_advancement.py` - CREATE for Task 4 (runner advancement logic)
|
|
2. `app/core/play_resolver.py` - UPDATE for Tasks 5-6 (DP mechanics + integration)
|
|
3. `app/websocket/handlers.py` - UPDATE for Task 7 (manual outcome handlers)
|
|
4. `terminal_client/commands.py` - UPDATE for Task 8 (manual outcome command)
|
|
5. `app/config/result_charts.py` - REFERENCE for hit location logic
|
|
6. `app/core/game_engine.py` - REFERENCE for integration points
|
|
7. `app/core/state_manager.py` - REFERENCE for decision workflow
|
|
8. `app/core/ai_opponent.py` - REFERENCE for AI decision generation
|
|
|
|
**What NOT to do**:
|
|
- ❌ Don't modify database schema without migration
|
|
- ❌ Don't use Python's datetime module (use Pendulum)
|
|
- ❌ Don't return Optional unless required (Raise or Return pattern)
|
|
- ❌ Don't disable type checking globally (use targeted # type: ignore)
|
|
- ❌ Don't skip validation - all decisions must be validated
|
|
- ❌ Don't implement full AI logic yet (Week 9 task)
|
|
- ❌ Don't commit without "CLAUDE: " prefix
|
|
- ❌ Don't forget `export PYTHONPATH=.` when running tests
|
|
- ❌ Don't try to change PlayOutcome with decision modifiers (affects advancement, not outcome)
|
|
|
|
**Patterns we're using**:
|
|
- ✅ Pydantic dataclasses for models
|
|
- ✅ Async/await for all database operations
|
|
- ✅ Frozen configs for immutability
|
|
- ✅ asyncio.Future for decision queue
|
|
- ✅ Validator pattern with clear error messages
|
|
- ✅ Result chart abstraction for league-specific resolution
|
|
- ✅ Manual vs auto mode separation (manual = WebSocket, auto = result charts)
|
|
- ✅ Hit location tracking for advancement logic
|
|
- ✅ TODO comments for future work (Week 9 AI, Week 8 substitutions)
|
|
|
|
**Manual Mode Flow**:
|
|
```python
|
|
# 1. Player requests action
|
|
> resolve
|
|
|
|
# 2. Server rolls dice
|
|
dice = dice_system.roll_ab(game_id)
|
|
|
|
# 3. Server broadcasts dice to players via WebSocket
|
|
emit('dice_rolled', {column_d6, row_2d6, chaos_d20})
|
|
|
|
# 4. Players read physical cards
|
|
[Human player looks at card]
|
|
|
|
# 5. Player submits outcome via WebSocket
|
|
emit('submit_manual_outcome', {
|
|
outcome: 'groundball_c',
|
|
hit_location: 'SS'
|
|
})
|
|
|
|
# 6. Server validates ManualOutcomeSubmission
|
|
submission = ManualOutcomeSubmission(**data)
|
|
|
|
# 7. Server resolves play with manual outcome
|
|
result = play_resolver.resolve_with_manual_outcome(submission, state)
|
|
|
|
# 8. Server broadcasts result
|
|
emit('play_resolved', result)
|
|
```
|
|
|
|
**Auto Mode Flow**:
|
|
```python
|
|
# 1. Player requests action
|
|
> resolve
|
|
|
|
# 2. Server generates outcome automatically
|
|
outcome, location = result_chart.get_outcome(roll, state, batter, pitcher)
|
|
|
|
# 3. Server resolves play with auto outcome
|
|
result = play_resolver.resolve_play(outcome, location, state)
|
|
|
|
# 4. Server broadcasts result
|
|
emit('play_resolved', result)
|
|
```
|
|
|
|
---
|
|
|
|
**Estimated Time for Next Session**: 16-22 hours (Tasks 4-8)
|
|
**Priority**: High (Task 4 is critical - all advancement logic)
|
|
**Blocking Other Work**: Yes (frontend needs WebSocket handlers from Task 7)
|
|
**Next Milestone After This**: Week 8 - Substitutions + Frontend UI
|