Comprehensive documentation for real-time gameplay workflow: **New Documentation**: 1. WEBSOCKET_PROTOCOL_SPEC.md (49KB) - Complete catalog of all 15 backend WebSocket event handlers - Complete catalog of all frontend event listeners - Game workflow sequences (connection → game start → play resolution) - Critical issues identified and resolution status - Event payload specifications with examples - Timing and performance expectations 2. DECISION_REQUIRED_IMPLEMENTATION.md (11KB) - Issue #1 detailed analysis and resolution - Backend implementation of decision_required event - Frontend integration approach - Before/After workflow comparison - Test validation results 3. GAMEPLAY_SESSION_HANDOFF.md (10KB) - Session work summary and accomplishments - Live testing results and observations - Known issues and next steps - Quick start guide for next session - Technical architecture notes **Why**: - Provides single source of truth for WebSocket protocol - Documents complete event flow for frontend/backend alignment - Captures implementation decisions and rationale - Enables faster onboarding for new developers - Creates reference for debugging WebSocket issues **Impact**: - Reduces protocol confusion between frontend and backend - Accelerates future WebSocket feature development - Provides clear integration patterns for new events 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
339 lines
9.9 KiB
Markdown
339 lines
9.9 KiB
Markdown
# Gameplay Loop Implementation - Session Handoff
|
|
|
|
**Date**: 2025-01-21
|
|
**Session Focus**: Connecting frontend gameplay UI to backend WebSocket handlers
|
|
**Status**: 🟡 In Progress - Defensive decisions working, testing offensive workflow next
|
|
|
|
---
|
|
|
|
## 🎯 Session Goals
|
|
|
|
Implement the core gameplay loop: dice rolling → outcome submission → play resolution
|
|
|
|
**Target Workflow**:
|
|
1. User submits defensive setup (infield/outfield positioning)
|
|
2. User submits offensive decision (batting action)
|
|
3. User rolls dice
|
|
4. User submits manual outcome (from physical card)
|
|
5. Backend resolves play and broadcasts result
|
|
6. Game state updates, play appears in feed
|
|
|
|
---
|
|
|
|
## ✅ What We Accomplished
|
|
|
|
### 1. **Connected Gameplay Loop Components**
|
|
- Fixed `submitManualOutcome()` signature in `useGameActions.ts`
|
|
- Added `play_resolved` WebSocket event handler
|
|
- Fixed game page to call outcome submission correctly
|
|
- Added missing TypeScript imports
|
|
|
|
### 2. **Fixed Decision Panel Visibility Issues**
|
|
|
|
**Root Cause**: Frontend was checking for `decision_phase: "defense"` but backend uses `"awaiting_defensive"`
|
|
|
|
**Files Modified**:
|
|
- `frontend-sba/store/game.ts` - Added checks for both naming conventions:
|
|
```typescript
|
|
needsDefensiveDecision: checks 'defense' OR 'awaiting_defensive'
|
|
needsOffensiveDecision: checks 'offensive_approach' OR 'awaiting_offensive'
|
|
```
|
|
|
|
### 3. **Fixed Game Start Issues**
|
|
|
|
**Problem**: Games were stuck in `decision_phase: "idle"` after lineups submitted
|
|
|
|
**Root Causes Fixed**:
|
|
1. Missing `game_engine` import in `backend/app/api/routes/games.py`
|
|
2. `start_game()` wasn't setting `decision_phase` after preparing first play
|
|
|
|
**Files Modified**:
|
|
- `backend/app/api/routes/games.py`:
|
|
```python
|
|
from app.core.game_engine import game_engine # Added import
|
|
```
|
|
|
|
- `backend/app/core/game_engine.py`:
|
|
```python
|
|
# In start_game() after _prepare_next_play():
|
|
state.decision_phase = "awaiting_defensive" # Added this line
|
|
```
|
|
|
|
### 4. **Fixed State Updates After Decision Submission**
|
|
|
|
**Problem**: After submitting defensive decision, UI stayed on defensive panel instead of advancing to offensive
|
|
|
|
**Solution**: Frontend now requests updated game state after decision submissions
|
|
|
|
**File Modified**:
|
|
- `frontend-sba/composables/useWebSocket.ts`:
|
|
```typescript
|
|
socketInstance.on('defensive_decision_submitted', (data) => {
|
|
// Request updated game state to get new decision_phase
|
|
socketInstance.emit('request_game_state', { game_id: gameStore.gameId })
|
|
})
|
|
```
|
|
|
|
### 5. **Added Debug Logging**
|
|
- Added console logging in game page to debug panel visibility
|
|
- Logs show `decision_phase`, `needsDefensiveDecision`, `needsOffensiveDecision`, etc.
|
|
|
|
---
|
|
|
|
## 📁 Files Modified (Need Committing)
|
|
|
|
### Backend Changes
|
|
```
|
|
backend/app/api/routes/games.py
|
|
backend/app/core/game_engine.py
|
|
```
|
|
|
|
### Frontend Changes
|
|
```
|
|
frontend-sba/store/game.ts
|
|
frontend-sba/composables/useGameActions.ts
|
|
frontend-sba/composables/useWebSocket.ts
|
|
frontend-sba/pages/games/[id].vue
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ What's Working Now
|
|
|
|
### ✓ Game Creation Flow
|
|
- Create game → submit lineups → game auto-starts
|
|
- Game enters `"awaiting_defensive"` phase immediately
|
|
- Frontend shows **Defensive Setup** panel
|
|
|
|
### ✓ Defensive Decision Submission
|
|
- User can select infield/outfield positioning
|
|
- Clicking "Submit" sends decision to backend
|
|
- Backend receives and processes decision
|
|
- Emits `defensive_decision_submitted` event
|
|
- Frontend requests updated game state
|
|
|
|
### ✓ WebSocket Communication
|
|
- Connection established successfully
|
|
- Events flowing backend → frontend
|
|
- `dice_rolled`, `outcome_accepted`, `play_resolved` handlers implemented
|
|
|
|
### ✓ Backend Game Engine
|
|
- All 15 WebSocket handlers implemented (Phase 3E-Final)
|
|
- Manual outcome workflow complete
|
|
- Play resolution working
|
|
- Database persistence functional
|
|
|
|
---
|
|
|
|
## 🔄 Current State
|
|
|
|
### What User Just Did
|
|
1. ✅ Created new game (ID: `0411d0ce-f41f-46eb-b0ac-23bae818d6ad`)
|
|
2. ✅ Saw defensive setup panel appear
|
|
3. ✅ Submitted defensive decision
|
|
4. ⚠️ Still seeing "Your Defensive Turn" indicator
|
|
|
|
### What Should Happen Next
|
|
After latest fix (requesting game state after submission), user should:
|
|
1. Refresh game page
|
|
2. Submit defensive decision again
|
|
3. Should see **Offensive Approach** panel appear
|
|
4. Select batting action → Submit
|
|
5. Should see **Gameplay Panel** with **Roll Dice** button
|
|
|
|
---
|
|
|
|
## 🧪 Testing Checklist
|
|
|
|
### ✅ Tested & Working
|
|
- [x] Game creation
|
|
- [x] Lineup submission
|
|
- [x] Game auto-start
|
|
- [x] Defensive panel appears
|
|
- [x] Defensive decision sends to backend
|
|
|
|
### ⏳ Next to Test
|
|
- [ ] Defensive submission → Offensive panel transition
|
|
- [ ] Offensive decision submission
|
|
- [ ] Offensive → Resolution phase (dice rolling)
|
|
- [ ] Dice roll button click
|
|
- [ ] Dice results display
|
|
- [ ] Manual outcome entry
|
|
- [ ] Outcome submission
|
|
- [ ] Play resolution display
|
|
- [ ] Play-by-play feed update
|
|
- [ ] Game state updates (score, outs, runners)
|
|
- [ ] Second at-bat (loop continues)
|
|
|
|
---
|
|
|
|
## 🔧 Technical Details
|
|
|
|
### Backend Decision Phase Values
|
|
```python
|
|
"idle" # Initial state (before start)
|
|
"awaiting_defensive" # Waiting for defensive setup
|
|
"awaiting_offensive" # Waiting for offensive approach
|
|
"resolution" # Ready for dice rolling
|
|
```
|
|
|
|
### WebSocket Event Flow
|
|
|
|
**Decision Submission**:
|
|
```
|
|
Frontend: submit_defensive_decision →
|
|
Backend: process → emit defensive_decision_submitted →
|
|
Frontend: request_game_state →
|
|
Backend: game_state (with decision_phase: "awaiting_offensive") →
|
|
Frontend: Show offensive panel
|
|
```
|
|
|
|
**Dice Rolling & Outcome**:
|
|
```
|
|
Frontend: roll_dice →
|
|
Backend: roll dice → emit dice_rolled →
|
|
Frontend: Show dice results →
|
|
User: Read card, select outcome →
|
|
Frontend: submit_manual_outcome →
|
|
Backend: validate & resolve → emit play_resolved →
|
|
Frontend: Display result, update state
|
|
```
|
|
|
|
### Key Store Properties
|
|
```typescript
|
|
// Game Store (frontend-sba/store/game.ts)
|
|
needsDefensiveDecision // Shows defensive panel
|
|
needsOffensiveDecision // Shows offensive panel
|
|
canRollDice // Enables dice roll button
|
|
canSubmitOutcome // Enables outcome submission
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Known Issues & Workarounds
|
|
|
|
### Issue 1: Frontend Compilation Warnings
|
|
**Symptom**: "Element is missing end tag" errors in console
|
|
**Impact**: None - server still runs fine
|
|
**Status**: Cosmetic, doesn't affect functionality
|
|
|
|
### Issue 2: Old Games Stuck in "idle"
|
|
**Symptom**: Games created before our fixes still show "Waiting for strategic decisions"
|
|
**Workaround**: Create fresh games - old games won't auto-advance
|
|
**Fix**: Old games need manual state update or recreation
|
|
|
|
---
|
|
|
|
## 🚀 Quick Start for Next Session
|
|
|
|
### 1. Check Server Status
|
|
```bash
|
|
# Backend should be running on port 8000
|
|
# Frontend should be running on port 3001
|
|
```
|
|
|
|
### 2. Test Defensive → Offensive Transition
|
|
1. Go to current game: `http://localhost:3001/games/0411d0ce-f41f-46eb-b0ac-23bae818d6ad`
|
|
2. Submit defensive decision
|
|
3. **Should** see offensive panel appear now (after latest fix)
|
|
|
|
### 3. If Offensive Panel Appears - Continue Testing!
|
|
- Submit offensive decision
|
|
- Click "Roll Dice"
|
|
- Check dice results display
|
|
- Submit outcome
|
|
- Verify play resolution
|
|
|
|
### 4. If Still Stuck - Create Fresh Game
|
|
```
|
|
http://localhost:3001/games/create
|
|
```
|
|
New games will have all fixes applied.
|
|
|
|
---
|
|
|
|
## 📝 Pending Commits
|
|
|
|
### Gameplay Loop Connection (Already Committed)
|
|
```bash
|
|
git log --oneline -1
|
|
# 58b5deb CLAUDE: Connect gameplay loop - dice rolling and play resolution
|
|
```
|
|
|
|
### Decision Panel Fixes (Need Committing)
|
|
```bash
|
|
# Backend changes
|
|
backend/app/api/routes/games.py # Added game_engine import
|
|
backend/app/core/game_engine.py # Set decision_phase in start_game
|
|
|
|
# Frontend changes
|
|
frontend-sba/store/game.ts # Check both decision_phase naming conventions
|
|
frontend-sba/composables/useWebSocket.ts # Request state after decision submissions
|
|
frontend-sba/pages/games/[id].vue # Added debug logging
|
|
```
|
|
|
|
---
|
|
|
|
## 🎓 Lessons Learned
|
|
|
|
### 1. Backend/Frontend Contract Mismatches
|
|
**Issue**: Backend used "awaiting_defensive" but frontend checked for "defense"
|
|
**Solution**: Frontend now checks both variants for robustness
|
|
|
|
### 2. State Synchronization
|
|
**Issue**: Backend updated state but didn't broadcast changes
|
|
**Solution**: Frontend explicitly requests updated state after key events
|
|
|
|
### 3. Game Initialization
|
|
**Issue**: `start_game()` prepared play but didn't set decision_phase
|
|
**Solution**: Explicitly set initial decision_phase after prepare
|
|
|
|
### 4. Import Issues Can Fail Silently
|
|
**Issue**: Missing `game_engine` import caused silent failure with try/catch
|
|
**Solution**: Always verify imports are present and check logs for errors
|
|
|
|
---
|
|
|
|
## 📞 If You Get Stuck
|
|
|
|
### Check These First
|
|
1. **Backend logs**: `BashOutput` with filter for game ID or event names
|
|
2. **Browser console**: Look for `[Game Page] Panel visibility check:` log
|
|
3. **WebSocket events**: Check if events are being received
|
|
4. **Game state**: Look at `decision_phase` value in console log
|
|
|
|
### Common Fixes
|
|
- **Panels not showing**: Check `decision_phase` value, create fresh game
|
|
- **Events not working**: Check WebSocket connection status
|
|
- **State not updating**: Look for `game_state` or `game_state_update` events
|
|
|
|
---
|
|
|
|
## 🎯 Success Criteria
|
|
|
|
**Session Complete When**:
|
|
- [x] Defensive panel appears ✅
|
|
- [ ] Offensive panel appears after defensive submission
|
|
- [ ] Dice can be rolled
|
|
- [ ] Outcome can be submitted
|
|
- [ ] Play resolves and appears in feed
|
|
- [ ] Second at-bat starts automatically
|
|
- [ ] All changes committed
|
|
|
|
**Current Progress**: ~60% complete
|
|
|
|
---
|
|
|
|
## 📚 References
|
|
|
|
- **Backend Handlers**: `backend/app/websocket/handlers.py` (15 handlers, all implemented)
|
|
- **Game Engine**: `backend/app/core/game_engine.py` (Phase 3E-Final complete)
|
|
- **Frontend Components**: `frontend-sba/components/Gameplay/` (all built, partially connected)
|
|
- **Main Session Context**: `CLAUDE.md` in project root
|
|
|
|
---
|
|
|
|
**Next Session Goal**: Complete offensive decision → dice rolling → outcome submission flow
|
|
|
|
Good luck! 🚀
|