strat-gameplay-webapp/frontend-sba/types/CLAUDE.md
Cal Corum cbdd8cf903 CLAUDE: Fix critical game engine issues and refactor CLAUDE.md docs
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>
2025-11-19 16:05:26 -06:00

2.8 KiB

Types Directory

TypeScript definitions matching backend Pydantic models. Type safety between frontend and backend.

File Overview

File Contents
game.ts GameState, PlayResult, decisions, outcomes
player.ts SbaPlayer, Lineup, LineupPlayerState
websocket.ts Socket event types (Client↔Server)
api.ts REST API request/response types
index.ts Re-exports all types

Critical Type Mappings

Backend → Frontend

Backend (Python) Frontend (TypeScript) Notes
GameState GameState game.ts:61
LineupPlayerState LineupPlayerState game.ts:44
DefensiveDecision DefensiveDecision game.ts:124
OffensiveDecision OffensiveDecision game.ts:136
PlayResult PlayResult game.ts:217
Lineup Lineup index.ts

Key Type Relationships

GameState
├── current_batter: LineupPlayerState     ← Minimal, for wire transfer
├── current_pitcher: LineupPlayerState
├── on_first/second/third: LineupPlayerState | null
└── pending_defensive_decision: DefensiveDecision | null

Lineup (from lineup_data event)
├── lineup_id: number                     ← Matches LineupPlayerState.lineup_id
├── position: string
├── is_active: boolean
└── player: SbaPlayer                     ← Full player data
    ├── id: number
    ├── name: string
    └── headshot: string

Why Two Player Types?

LineupPlayerState (in GameState):

  • Sent on every state update (~10-50 times per game)
  • Minimal: lineup_id, position, batting_order
  • ~50 bytes per player

Lineup (from lineup_data):

  • Sent once when joining game
  • Full data including nested player with name, headshot
  • ~500 bytes per player

Optimization: Send minimal data frequently, full data once.

Common Type Usage

Accessing Player Data

// GameState gives you LineupPlayerState
const batterState: LineupPlayerState = gameStore.currentBatter

// Need to lookup full Lineup for player details
const batterLineup: Lineup = gameStore.findPlayerInLineup(batterState.lineup_id)
const name: string = batterLineup.player.name

Decision Types

// Defensive (fielding team)
interface DefensiveDecision {
  infield_depth: 'infield_in' | 'normal' | 'corners_in'
  outfield_depth: 'normal' | 'shallow'
  hold_runners: number[]
}

// Offensive (batting team)
interface OffensiveDecision {
  action: 'swing_away' | 'steal' | 'hit_and_run' | 'sac_bunt' | 'squeeze_bunt'
  steal_attempts: number[]
}

Type Maintenance

When backend Pydantic models change:

  1. Update corresponding frontend type
  2. Check all components using that type
  3. Run npm run type-check to catch mismatches