use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; use sqlx::FromRow; // ============================================================================= // Core Entities (synced from league API) // ============================================================================= #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct Team { pub id: i64, pub abbrev: String, pub short_name: String, pub long_name: String, pub season: i64, pub manager1_name: Option, pub manager2_name: Option, pub gm_discord_id: Option, pub gm2_discord_id: Option, pub division_id: Option, pub division_name: Option, pub league_abbrev: Option, pub thumbnail: Option, pub color: Option, pub dice_color: Option, pub stadium: Option, pub salary_cap: Option, pub synced_at: Option, } #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct Player { pub id: i64, pub name: String, pub season: i64, pub team_id: Option, pub swar: Option, pub card_image: Option, pub card_image_alt: Option, pub headshot: Option, pub vanity_card: Option, pub pos_1: Option, pub pos_2: Option, pub pos_3: Option, pub pos_4: Option, pub pos_5: Option, pub pos_6: Option, pub pos_7: Option, pub pos_8: Option, pub hand: Option, pub injury_rating: Option, pub il_return: Option, pub demotion_week: Option, pub strat_code: Option, pub bbref_id: Option, pub sbaplayer_id: Option, pub last_game: Option, pub last_game2: Option, pub synced_at: Option, } impl Player { pub fn positions(&self) -> Vec<&str> { [ self.pos_1.as_deref(), self.pos_2.as_deref(), self.pos_3.as_deref(), self.pos_4.as_deref(), self.pos_5.as_deref(), self.pos_6.as_deref(), self.pos_7.as_deref(), self.pos_8.as_deref(), ] .into_iter() .flatten() .collect() } pub fn is_pitcher(&self) -> bool { self.positions() .iter() .any(|p| matches!(*p, "SP" | "RP" | "CP")) } pub fn is_batter(&self) -> bool { self.positions() .iter() .any(|p| matches!(*p, "C" | "1B" | "2B" | "3B" | "SS" | "LF" | "CF" | "RF" | "DH")) } } // ============================================================================= // Card Data (imported from Strat-o-Matic) // ============================================================================= #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct BatterCard { pub id: i64, pub player_id: i64, // vs Left-Handed Pitchers pub so_vlhp: f64, pub bb_vlhp: f64, pub hit_vlhp: f64, pub ob_vlhp: f64, pub tb_vlhp: f64, pub hr_vlhp: f64, pub dp_vlhp: f64, // vs Right-Handed Pitchers pub so_vrhp: f64, pub bb_vrhp: f64, pub hit_vrhp: f64, pub ob_vrhp: f64, pub tb_vrhp: f64, pub hr_vrhp: f64, pub dp_vrhp: f64, // Ballpark modifiers pub bphr_vlhp: f64, pub bphr_vrhp: f64, pub bp1b_vlhp: f64, pub bp1b_vrhp: f64, // Running game pub stealing: Option, pub steal_rating: Option, pub speed: Option, // Batting extras pub bunt: Option, pub hit_run: Option, // Fielding pub fielding: Option, // Catcher-specific pub catcher_arm: Option, pub catcher_pb: Option, pub catcher_t: Option, // Computed ratings pub rating_vl: Option, pub rating_vr: Option, pub rating_overall: Option, // Import metadata pub imported_at: Option, pub source: Option, } #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct PitcherCard { pub id: i64, pub player_id: i64, // vs Left-Handed Batters pub so_vlhb: f64, pub bb_vlhb: f64, pub hit_vlhb: f64, pub ob_vlhb: f64, pub tb_vlhb: f64, pub hr_vlhb: f64, pub dp_vlhb: f64, pub bphr_vlhb: f64, pub bp1b_vlhb: f64, // vs Right-Handed Batters pub so_vrhb: f64, pub bb_vrhb: f64, pub hit_vrhb: f64, pub ob_vrhb: f64, pub tb_vrhb: f64, pub hr_vrhb: f64, pub dp_vrhb: f64, pub bphr_vrhb: f64, pub bp1b_vrhb: f64, // Pitcher attributes pub hold_rating: Option, pub endurance_start: Option, pub endurance_relief: Option, pub endurance_close: Option, pub fielding_range: Option, pub fielding_error: Option, pub wild_pitch: Option, pub balk: Option, pub batting_rating: Option, // Computed ratings pub rating_vlhb: Option, pub rating_vrhb: Option, pub rating_overall: Option, // Import metadata pub imported_at: Option, pub source: Option, } // ============================================================================= // Transactions (synced from league API) // ============================================================================= #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct Transaction { pub id: i64, pub season: i64, pub week: i64, pub move_id: String, pub player_id: i64, pub from_team_id: i64, pub to_team_id: i64, pub cancelled: bool, pub frozen: bool, pub synced_at: Option, } // ============================================================================= // Roster (aggregate view, not a DB table) // ============================================================================= #[derive(Debug, Default, Serialize, Deserialize)] pub struct Roster { pub majors: Vec, pub minors: Vec, pub il: Vec, } // ============================================================================= // User Data (local only) // ============================================================================= #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct Lineup { pub id: i64, pub name: String, pub description: Option, pub lineup_type: String, pub batting_order: Option, // JSON string pub positions: Option, // JSON string pub starting_pitcher_id: Option, pub created_at: Option, pub updated_at: Option, } impl Lineup { pub fn batting_order_vec(&self) -> Vec { self.batting_order .as_deref() .and_then(|s| serde_json::from_str(s).ok()) .unwrap_or_default() } pub fn positions_map(&self) -> std::collections::HashMap { self.positions .as_deref() .and_then(|s| serde_json::from_str(s).ok()) .unwrap_or_default() } pub fn set_batting_order(&mut self, order: &[i64]) { self.batting_order = serde_json::to_string(order).ok(); } pub fn set_positions(&mut self, positions: &std::collections::HashMap) { self.positions = serde_json::to_string(positions).ok(); } } #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct MatchupCache { pub id: i64, pub batter_id: i64, pub pitcher_id: i64, pub rating: f64, pub tier: Option, pub details: Option, // JSON string pub computed_at: Option, pub weights_hash: Option, } #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct StandardizedScoreCache { pub id: i64, pub batter_card_id: Option, pub pitcher_card_id: Option, pub split: String, pub total_score: f64, pub stat_scores: String, // JSON string pub computed_at: Option, pub weights_hash: Option, pub league_stats_hash: Option, } #[derive(Debug, FromRow, Serialize, Deserialize)] pub struct SyncStatus { pub id: i64, pub entity_type: String, pub last_sync: Option, pub last_sync_count: Option, pub last_error: Option, }