""" League-specific configuration implementations. Provides concrete configs for SBA and PD leagues with their unique rules, API endpoints, and feature flags. Author: Claude Date: 2025-10-28 """ import logging from collections.abc import Callable from app.config.base_config import BaseGameConfig from app.config.common_x_check_tables import ( CATCHER_DEFENSE_TABLE, INFIELD_DEFENSE_TABLE, OUTFIELD_DEFENSE_TABLE, get_error_chart_for_position, get_fielders_holding_runners, ) logger = logging.getLogger(f"{__name__}.LeagueConfigs") class SbaConfig(BaseGameConfig): """ SBA League configuration. Features: - Manual result selection after dice roll - Simple player data model - Standard baseball rules """ league_id: str = "sba" # SBA-specific features player_selection_mode: str = "manual" # Players manually select from chart # X-Check defense tables (shared common tables) x_check_defense_tables: dict[str, list[list[str]]] = { "infield": INFIELD_DEFENSE_TABLE, "outfield": OUTFIELD_DEFENSE_TABLE, "catcher": CATCHER_DEFENSE_TABLE, } # X-Check error chart lookup function x_check_error_charts: Callable[[str], dict[int, dict[str, list[int]]]] = ( get_error_chart_for_position ) # Holding runners function x_check_holding_runners: Callable[[list[int], str], list[str]] = ( get_fielders_holding_runners ) def get_result_chart_name(self) -> str: """Use SBA standard result chart.""" return "sba_standard_v1" def supports_manual_result_selection(self) -> bool: """SBA players manually pick results from chart.""" return True def supports_auto_mode(self) -> bool: """SBA does not support auto mode - cards are not digitized.""" return False def supports_position_ratings(self) -> bool: """ Check if this league supports position ratings for X-Check resolution. Returns: False for SBA (uses manual entry only) Phase 3E-Main: SBA players manually enter defensive ratings """ return False def get_api_base_url(self) -> str: """SBA API base URL.""" return "https://api.sba.manticorum.com" class PdConfig(BaseGameConfig): """ Paper Dynasty League configuration. Features: - Flexible result selection (manual or auto via scouting) - Complex scouting data model - Cardset validation - Advanced analytics """ league_id: str = "pd" # PD-specific features player_selection_mode: str = "flexible" # Manual or auto via scouting model use_scouting_model: bool = True # Use detailed ratings for auto-resolution cardset_validation: bool = True # Validate cards against approved cardsets # Advanced features detailed_analytics: bool = True # Track advanced stats (WPA, RE24, etc.) wpa_calculation: bool = True # Calculate win probability added # X-Check defense tables (shared common tables) x_check_defense_tables: dict[str, list[list[str]]] = { "infield": INFIELD_DEFENSE_TABLE, "outfield": OUTFIELD_DEFENSE_TABLE, "catcher": CATCHER_DEFENSE_TABLE, } # X-Check error chart lookup function x_check_error_charts: Callable[[str], dict[int, dict[str, list[int]]]] = ( get_error_chart_for_position ) # Holding runners function x_check_holding_runners: Callable[[list[int], str], list[str]] = ( get_fielders_holding_runners ) def get_result_chart_name(self) -> str: """Use PD standard result chart.""" return "pd_standard_v1" def supports_manual_result_selection(self) -> bool: """PD supports manual selection (though auto is also available).""" return True def supports_auto_mode(self) -> bool: """PD supports auto mode via digitized scouting data.""" return True def supports_position_ratings(self) -> bool: """ Check if this league supports position ratings for X-Check resolution. Returns: True for PD (has position ratings API) Phase 3E-Main: PD fetches ratings from API with Redis caching """ return True def get_api_base_url(self) -> str: """PD API base URL.""" return "https://pd.manticorum.com/api/" # ==================== Config Registry ==================== LEAGUE_CONFIGS: dict[str, BaseGameConfig] = {"sba": SbaConfig(), "pd": PdConfig()} def get_league_config(league_id: str) -> BaseGameConfig: """ Get configuration for specified league. Args: league_id: League identifier ('sba' or 'pd') Returns: League-specific config instance Raises: ValueError: If league_id is not recognized """ config = LEAGUE_CONFIGS.get(league_id) if not config: logger.error(f"Unknown league ID: {league_id}") raise ValueError( f"Unknown league: {league_id}. Valid leagues: {list(LEAGUE_CONFIGS.keys())}" ) logger.debug(f"Retrieved config for league: {league_id}") return config