strat-gameplay-webapp/backend/app/models/CLAUDE.md
Cal Corum 88a5207c2c CLAUDE: Refactor backend CLAUDE.md files for conciseness
Major reduction in CLAUDE.md file sizes to follow concise documentation standard:

| File | Before | After | Reduction |
|------|--------|-------|-----------|
| backend/CLAUDE.md | 2,467 | 123 | 95% |
| models/CLAUDE.md | 1,586 | 102 | 94% |
| websocket/CLAUDE.md | 2,094 | 119 | 94% |
| config/CLAUDE.md | 1,017 | 126 | 88% |
| database/CLAUDE.md | 946 | 130 | 86% |
| api/CLAUDE.md | 906 | 140 | 85% |

Total: 9,016 -> 740 lines (92% reduction)

All files now under 150 lines with:
- Essential patterns and usage
- Cross-references to related docs
- Quick-start examples
- Updated timestamps

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:10:08 -06:00

3.1 KiB

Models - Data Models for Game Engine

Purpose

Data models split into two systems:

  • Pydantic: In-memory game state, API contracts, WebSocket serialization
  • SQLAlchemy: Database persistence, relationships, audit trail

Directory Structure

models/
├── __init__.py        # Central exports - import from here
├── game_models.py     # Pydantic in-memory state (GameState, decisions)
├── player_models.py   # Polymorphic players (BasePlayer → SbaPlayer, PdPlayer)
├── db_models.py       # SQLAlchemy ORM (Game, Play, Lineup)
└── roster_models.py   # Roster link models

Key Models

GameState (game_models.py)

Core in-memory state for active games.

Critical Fields:

  • Identity: game_id, league_id
  • Teams: home_team_id, away_team_id, *_is_ai
  • Game state: inning, half, outs, *_score
  • Runners: on_first, on_second, on_third (LineupPlayerState)
  • Current: current_batter, current_pitcher, current_catcher
  • Decisions: pending_defensive_decision, pending_offensive_decision

Helper Methods: 20+ including get_batting_team_id(), add_runner(), is_game_over()

LineupPlayerState

Lightweight player reference in lineup.

  • lineup_id, card_id, position, batting_order, is_active
  • position_rating (Optional - PD league only)

TeamLineupState

Team's active lineup with helpers: get_batting_order(), get_pitcher(), get_batter()

Decision Models

  • DefensiveDecision: alignment, infield_depth, outfield_depth, hold_runners
  • OffensiveDecision: action, steal_attempts, hit_and_run, bunt_attempt

Player Models (player_models.py)

Polymorphic architecture for league-agnostic game engine.

BasePlayer (ABC)
├── SbaPlayer - Simple (id, name, image, positions)
└── PdPlayer - Complex (scouting data, ratings)

Factory: Player.from_api_data(config, data)

Database Models (db_models.py)

Model Purpose
Game Game container with status, scores, AI flags
Play At-bat record with 25+ stat fields
Lineup Player assignments and substitutions
GameSession WebSocket state tracking
RosterLink Eligible cards/players (polymorphic)

Common Patterns

Import from Package

from app.models import GameState, Game, SbaPlayer  # ✅
from app.models.game_models import GameState       # ❌

Data Resolution

GameState uses minimal LineupPlayerState refs. Get full player data from StateManager:

lineup_state = state_manager.get_lineup(game_id, team_id)
player = lineup_state.get_player_by_lineup_id(lineup_id)

Pydantic Validation

All models use field validators for data integrity:

@field_validator('position')
@classmethod
def validate_position(cls, v):
    if v not in VALID_POSITIONS:
        raise ValueError(...)
    return v

References

  • Game Recovery: See app/core/state_manager.py for state rebuild
  • Database Schema: See app/database/CLAUDE.md for table details
  • Type Checking: See backend/.claude/type-checking-guide.md

Tests: tests/unit/models/ | Updated: 2025-01-19