Critical fixes in game_engine.py: - Fix silent error swallowing in _batch_save_inning_rolls (re-raise) - Add per-game asyncio.Lock for race condition prevention - Add _cleanup_game_resources() for memory leak prevention - All 739 tests passing Documentation refactoring: - Created CODE_REVIEW_GAME_ENGINE.md documenting 24 identified issues - Trimmed backend/app/core/CLAUDE.md from 1371 to 143 lines - Trimmed frontend-sba/CLAUDE.md from 696 to 110 lines - Created focused subdirectory CLAUDE.md files: - frontend-sba/components/CLAUDE.md (105 lines) - frontend-sba/composables/CLAUDE.md (79 lines) - frontend-sba/store/CLAUDE.md (116 lines) - frontend-sba/types/CLAUDE.md (95 lines) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2.8 KiB
2.8 KiB
Store Directory
Pinia stores for centralized state management. All stores use Composition API syntax.
Available Stores
game.ts - Active Game State
Purpose: Central state for real-time gameplay, synchronized via WebSocket.
Key State:
gameState: GameState | null // Full game state from backend
homeLineup: Lineup[] // Cached home team roster
awayLineup: Lineup[] // Cached away team roster
playHistory: PlayResult[] // Play-by-play history
currentDecisionPrompt: DecisionPrompt | null
pendingRoll: RollData | null // Manual mode dice roll
Critical Getters:
// Team determination (mirrors backend logic)
battingTeamId // away if top, home if bottom
fieldingTeamId // home if top, away if bottom
// Current players (LineupPlayerState)
currentBatter
currentPitcher
currentCatcher
// Decision state
needsDefensiveDecision
needsOffensiveDecision
canRollDice
canSubmitOutcome
Player Lookup Method:
// Critical: Joins LineupPlayerState with full Lineup data
findPlayerInLineup(lineupId: number): Lineup | undefined
auth.ts - Authentication
Purpose: Discord OAuth state and JWT token management.
Key State: user, token, isAuthenticated, isTokenValid
ui.ts - UI State
Purpose: Toasts, modals, loading states.
Key Methods: showSuccess(), showError(), showWarning(), showInfo()
Data Resolution Pattern
Game state contains minimal LineupPlayerState:
interface LineupPlayerState {
lineup_id: number // Key for lookup
card_id: number
position: string
// NO player name, headshot, etc.
}
Store caches full Lineup with nested player:
interface Lineup {
lineup_id: number
player: {
id: number
name: string
headshot: string
}
}
Resolution:
const batterState = gameStore.currentBatter // LineupPlayerState
const batterLineup = gameStore.findPlayerInLineup( // Full Lineup
batterState.lineup_id
)
const name = batterLineup?.player.name // "Mike Trout"
Store Patterns
Nuxt 4 Import Requirement
// ALWAYS explicitly import stores
import { useGameStore } from '~/store/game'
const gameStore = useGameStore()
// NEVER rely on auto-imports (breaks in Nuxt 4)
Readonly State
All state refs are exposed as readonly() to prevent direct mutation:
return {
gameState: readonly(gameState), // Can't do gameStore.gameState.value = x
setGameState, // Use action instead
}
Team Determination Logic
// Same logic as backend state_manager.py
const battingTeamId = computed(() => {
return gameState.value.half === 'top'
? gameState.value.away_team_id // Top: away bats
: gameState.value.home_team_id // Bottom: home bats
})