Major Refactor: Outcome-First Architecture - PlayResolver now accepts league_id and auto_mode in constructor - Added core resolve_outcome() method - all resolution logic in one place - Added resolve_manual_play() wrapper for manual submissions (primary) - Added resolve_auto_play() wrapper for PD auto mode (rare) - Removed SimplifiedResultChart (obsolete with new architecture) - Removed play_resolver singleton RunnerAdvancement Integration: - All groundball outcomes (GROUNDBALL_A/B/C) now use RunnerAdvancement - Proper DP probability calculation with positioning modifiers - Hit location tracked for all relevant outcomes - 13 result types fully integrated from advancement charts Game State Updates: - Added auto_mode field to GameState (stored per-game) - Updated state_manager.create_game() to accept auto_mode parameter - GameEngine now uses state.auto_mode to create appropriate resolver League Configuration: - Added supports_auto_mode() to BaseGameConfig - SbaConfig: returns False (no digitized cards) - PdConfig: returns True (has digitized ratings) - PlayResolver validates auto mode support and raises error for SBA Play Results: - Added hit_location field to PlayResult - Groundballs include location from RunnerAdvancement - Flyouts track hit_location for tag-up logic (future) - Other outcomes have hit_location=None Testing: - Completely rewrote test_play_resolver.py for new architecture - 9 new tests covering initialization, strikeouts, walks, groundballs, home runs - All 9 tests passing - All 180 core tests still passing (1 pre-existing failure unrelated) Terminal Client: - No changes needed - defaults to manual mode (auto_mode=False) - Perfect for human testing of manual submissions This completes Week 7 Task 6 - the final task of Week 7! Week 7 is now 100% complete with all 8 tasks done. 🎯 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""
|
|
Base configuration class for league-specific game rules.
|
|
|
|
Provides abstract interface that all league configs must implement.
|
|
|
|
Author: Claude
|
|
Date: 2025-10-28
|
|
"""
|
|
from abc import ABC, abstractmethod
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class BaseGameConfig(BaseModel, ABC):
|
|
"""
|
|
Abstract base configuration for all leagues.
|
|
|
|
Defines common game rules and requires league-specific implementations
|
|
to provide result chart names, API endpoints, and feature flags.
|
|
"""
|
|
|
|
league_id: str = Field(..., description="League identifier ('sba' or 'pd')")
|
|
version: str = Field(default="1.0.0", description="Config version for compatibility")
|
|
|
|
# Basic baseball rules (same across leagues)
|
|
innings: int = Field(default=9, description="Standard innings per game")
|
|
outs_per_inning: int = Field(default=3, description="Outs required per half-inning")
|
|
strikes_for_out: int = Field(default=3, description="Strikes for strikeout") # TODO: remove - unneeded
|
|
balls_for_walk: int = Field(default=4, description="Balls for walk") # TODO: remove - unneeded
|
|
|
|
@abstractmethod
|
|
def get_result_chart_name(self) -> str:
|
|
"""
|
|
Get name of result chart to use for this league.
|
|
|
|
Returns:
|
|
Chart name identifier (e.g., 'sba_standard_v1')
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def supports_manual_result_selection(self) -> bool: # TODO: consider refactor: manually selecting results is default behavior with PD allowing auto-results as an option
|
|
"""
|
|
Whether players manually select results after dice roll.
|
|
|
|
Returns:
|
|
True if players pick from chart, False if auto-resolved
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def supports_auto_mode(self) -> bool:
|
|
"""
|
|
Whether this league supports auto-resolution of outcomes.
|
|
|
|
Auto mode uses digitized player ratings to automatically generate
|
|
outcomes without human input. This is only available for leagues
|
|
with fully digitized card data.
|
|
|
|
Returns:
|
|
True if auto mode is supported, False otherwise
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_api_base_url(self) -> str:
|
|
"""
|
|
Get base URL for league's external API.
|
|
|
|
Returns:
|
|
Base URL for roster/player data API
|
|
"""
|
|
pass
|
|
|
|
class Config:
|
|
"""Pydantic configuration."""
|
|
frozen = True # Immutable config - prevents accidental modification
|