/** * 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 * * Standardized naming (2025-01-21): Uses backend convention 'awaiting_*' * for clarity about what action is pending. */ export type DecisionPhase = 'awaiting_defensive' | 'awaiting_stolen_base' | 'awaiting_offensive' | '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 // Team display info (from game_metadata, stored at creation time) home_team_name?: string | null // Full name: "Chicago Cyclones" home_team_abbrev?: string | null // Abbreviation: "CHC" home_team_color?: string | null // Hex color without #: "ff5349" home_team_thumbnail?: string | null // Team logo URL away_team_name?: string | null away_team_abbrev?: string | null away_team_color?: string | null away_team_thumbnail?: string | null // Creator (for demo/testing - creator can control home team) creator_discord_id: string | null // 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: 'infield_in' | 'normal' | 'corners_in' outfield_depth: 'normal' | 'shallow' 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 (matches backend PlayOutcome enum values) * Note: These are the STRING VALUES, not enum names */ export type PlayOutcome = // Standard outs | 'strikeout' | 'groundball_a' | 'groundball_b' | 'groundball_c' | 'flyout_a' | 'flyout_b' | 'flyout_bq' | 'flyout_c' | 'lineout' | 'popout' // Walks and hits by pitch | 'walk' | 'intentional_walk' | 'hbp' // Hits (capped - specific bases) | 'single_1' | 'single_2' | 'single_uncapped' | 'double_2' | 'double_3' | 'double_uncapped' | 'triple' | 'homerun' // Interrupt plays (baserunning events) | 'stolen_base' | 'caught_stealing' | 'wild_pitch' | 'passed_ball' | 'balk' | 'pick_off' // Errors | 'error' | 'x_check' // 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) lineup_id: number // Player's lineup ID for name lookup is_out?: boolean // Runner was out during advancement (renamed from 'out') } /** * Play resolution result from server * Backend: PlayResult */ export interface PlayResult { // Play identification play_number: number inning?: number // Inning when play occurred half?: InningHalf // 'top' or 'bottom' outcome: PlayOutcome // Play description description: string hit_type?: string // Results outs_recorded: number runs_scored: number // Player identification for display batter_lineup_id?: number // Batter's lineup ID for name lookup // 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 * Note: Field names match backend GameListItem response */ export interface GameListItem { game_id: string league_id: LeagueId home_team_id: number away_team_id: number status: GameStatus // Enriched team info from backend home_team_name?: string away_team_name?: string home_team_abbrev?: string away_team_abbrev?: string home_score: number away_score: number inning?: number half?: InningHalf // External schedule reference (for linking to SBA/PD schedule systems) schedule_game_id?: number } /** * 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 }