strat-gameplay-webapp/backend/app/config/league_configs.py
Cal Corum 0b6076d5b8 CLAUDE: Implement Phase 3B - X-Check league config tables
Complete X-Check resolution table system for defensive play outcomes.

Components:
- Defense range tables (20×5) for infield, outfield, catcher
- Error charts for LF/RF and CF (ratings 0-25)
- Placeholder error charts for P, C, 1B, 2B, 3B, SS (awaiting data)
- get_fielders_holding_runners() - Complete implementation
- get_error_chart_for_position() - Maps all 9 positions
- 6 X-Check placeholder advancement functions (g1-g3, f1-f3)

League Config Integration:
- Both SbaConfig and PdConfig include X-Check tables
- Shared common tables via league_configs.py
- Attributes: x_check_defense_tables, x_check_error_charts, x_check_holding_runners

Testing:
- 36 tests for X-Check tables (all passing)
- 9 tests for X-Check placeholders (all passing)
- Total: 45/45 tests passing

Documentation:
- Updated backend/CLAUDE.md with Phase 3B section
- Updated app/config/CLAUDE.md with X-Check tables documentation
- Updated app/core/CLAUDE.md with X-Check placeholder functions
- Updated tests/CLAUDE.md with new test counts (519 unit tests)
- Updated phase-3b-league-config-tables.md (marked complete)
- Updated NEXT_SESSION.md with Phase 3B completion

What's Pending:
- 6 infield error charts need actual data (P, C, 1B, 2B, 3B, SS)
- Phase 3C will implement full X-Check resolution logic

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 19:50:55 -05:00

149 lines
4.4 KiB
Python

"""
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 typing import Dict, List, Callable
from app.config.base_config import BaseGameConfig
from app.config.common_x_check_tables import (
INFIELD_DEFENSE_TABLE,
OUTFIELD_DEFENSE_TABLE,
CATCHER_DEFENSE_TABLE,
get_fielders_holding_runners,
get_error_chart_for_position,
)
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 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 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