/** * Game State and Play Result Types * * TypeScript definitions matching backend Pydantic models exactly. * These types ensure type safety between frontend and backend. * * Backend Reference: app/models/game_models.py */ /** * Game status enumeration */ export type GameStatus = 'pending' | 'active' | 'paused' | 'completed' | 'abandoned' /** * Inning half */ export type InningHalf = 'top' | 'bottom' /** * Game mode */ export type GameMode = 'live' | 'async' | 'vs_ai' /** * Game visibility */ export type GameVisibility = 'public' | 'private' /** * League identifier */ export type LeagueId = 'sba' | 'pd' /** * Decision phase in the play workflow */ export type DecisionPhase = 'defense' | 'stolen_base' | 'offensive_approach' | 'resolution' | 'complete' /** * Lineup player state - represents a player in the game * Backend: LineupPlayerState */ export interface LineupPlayerState { lineup_id: number card_id: number position: string batting_order: number | null is_active: boolean position_rating?: { range: number error: number innings: number } | null } /** * Core game state - complete representation of active game * Backend: GameState */ export interface GameState { // Identity game_id: string league_id: LeagueId // Teams home_team_id: number away_team_id: number home_team_is_ai: boolean away_team_is_ai: boolean // Resolution mode auto_mode: boolean // Game state status: GameStatus inning: number half: InningHalf outs: number balls: number strikes: number home_score: number away_score: number // Runners (direct references) on_first: LineupPlayerState | null on_second: LineupPlayerState | null on_third: LineupPlayerState | null // Current players current_batter: LineupPlayerState current_pitcher: LineupPlayerState | null current_catcher: LineupPlayerState | null current_on_base_code: number // Batting order tracking away_team_batter_idx: number // 0-8 home_team_batter_idx: number // 0-8 // Decision tracking pending_decision: DecisionPhase | null decision_phase: DecisionPhase decisions_this_play: Record pending_defensive_decision: DefensiveDecision | null pending_offensive_decision: OffensiveDecision | null // Manual mode pending_manual_roll: RollData | null // Play history play_count: number last_play_result: string | null // Timestamps created_at: string started_at: string | null completed_at: string | null } /** * Defensive strategic decision * Backend: DefensiveDecision */ export interface DefensiveDecision { infield_depth: 'in' | 'normal' | 'back' | 'double_play' | 'corners_in' outfield_depth: 'in' | 'normal' | 'back' hold_runners: number[] // Bases to hold (e.g., [1, 3]) } /** * Offensive strategic decision * Backend: OffensiveDecision * * Session 2 Update (2025-01-14): Replaced approach/hit_and_run/bunt_attempt with action field. */ export interface OffensiveDecision { action: 'swing_away' | 'steal' | 'check_jump' | 'hit_and_run' | 'sac_bunt' | 'squeeze_bunt' steal_attempts: number[] // Bases to steal (2, 3, or 4) - only used when action="steal" } /** * Dice roll data from server * Backend: AbRoll (simplified for frontend) */ export interface RollData { roll_id: string d6_one: number d6_two_a: number d6_two_b: number d6_two_total: number chaos_d20: number resolution_d20: number check_wild_pitch: boolean check_passed_ball: boolean timestamp: string } /** * Play outcome enumeration (subset of backend PlayOutcome) */ export type PlayOutcome = // Standard outs | 'STRIKEOUT' | 'GROUNDOUT' | 'FLYOUT' | 'LINEOUT' | 'POPOUT' | 'DOUBLE_PLAY' // Walks and hits by pitch | 'WALK' | 'INTENTIONAL_WALK' | 'HIT_BY_PITCH' // Hits (capped - specific bases) | 'SINGLE_1' | 'SINGLE_2' | 'DOUBLE_2' | 'DOUBLE_3' | 'TRIPLE' | 'HOMERUN' // Uncapped hits (require advancement decisions) | 'SINGLE_UNCAPPED' | 'DOUBLE_UNCAPPED' // Interrupt plays (baserunning events) | 'STOLEN_BASE' | 'CAUGHT_STEALING' | 'WILD_PITCH' | 'PASSED_BALL' | 'BALK' | 'PICK_OFF' // Errors | 'ERROR' // Ballpark power (PD specific) | 'BP_HOMERUN' | 'BP_FLYOUT' | 'BP_SINGLE' | 'BP_LINEOUT' /** * Runner advancement during a play */ export interface RunnerAdvancement { from: number // 0=batter, 1-3=bases to: number // 1-4=bases (4=home/scored) out?: boolean // Runner was out during advancement } /** * Play resolution result from server * Backend: PlayResult */ export interface PlayResult { // Play identification play_number: number outcome: PlayOutcome // Play description description: string hit_type?: string // Results outs_recorded: number runs_scored: number // Runner advancement runners_advanced: RunnerAdvancement[] batter_result: number | null // Where batter ended up (1-4, null=out) // Updated state snapshot new_state: Partial // Categorization helpers is_hit: boolean is_out: boolean is_walk: boolean is_strikeout: boolean // Roll reference (if manual mode) roll_id?: string // X-Check details (if defensive play) x_check_details?: XCheckResult } /** * X-Check resolution audit trail */ export interface XCheckResult { check_position: string defense_range: number error_rating: number d20_roll: number error_3d6: number base_result: string error_result: string final_outcome: PlayOutcome held_runners: string[] } /** * Decision prompt from server * Backend: DecisionPrompt (WebSocket event) */ export interface DecisionPrompt { phase: DecisionPhase role: 'home' | 'away' timeout_seconds: number options?: string[] message?: string } /** * Manual outcome submission to server * Backend: ManualOutcomeSubmission */ export interface ManualOutcomeSubmission { outcome: PlayOutcome hit_location?: string // Required for groundballs/flyballs } /** * Game list item for active/completed games */ export interface GameListItem { game_id: string league_id: LeagueId home_team_id: number away_team_id: number status: GameStatus current_inning: number current_half: InningHalf home_score: number away_score: number started_at: string | null completed_at: string | null } /** * Game creation request */ export interface CreateGameRequest { league_id: LeagueId home_team_id: number away_team_id: number game_mode: GameMode visibility: GameVisibility } /** * Game creation response */ export interface CreateGameResponse { game_id: string status: GameStatus created_at: string }