- Fix TypeError in check_steal_opportunity by properly mocking catcher defense - Correct tag_from_third test calculation to account for all adjustment conditions - Fix pitcher replacement test by setting appropriate allowed runners threshold - Add comprehensive test coverage for AI service business logic - Implement VS Code testing panel configuration with pytest integration - Create pytest.ini for consistent test execution and warning management - Add test isolation guidelines and factory pattern implementation - Establish 102 passing tests with zero failures 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
72 lines
1.8 KiB
Python
72 lines
1.8 KiB
Python
"""
|
|
AI Response models for decision-making output.
|
|
|
|
These models represent the output of AI decision-making processes,
|
|
migrated from Discord app managerai_responses.py.
|
|
"""
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class AiResponse(BaseModel):
|
|
"""Base class for AI decision responses."""
|
|
|
|
ai_note: str = ""
|
|
|
|
|
|
class RunResponse(AiResponse):
|
|
"""Response for running decisions."""
|
|
|
|
min_safe: int | None = None
|
|
|
|
|
|
class JumpResponse(RunResponse):
|
|
"""Response for steal attempt decisions."""
|
|
|
|
must_auto_jump: bool = False
|
|
run_if_auto_jump: bool = False
|
|
|
|
|
|
class TagResponse(RunResponse):
|
|
"""Response for tag-up decisions."""
|
|
|
|
pass
|
|
|
|
|
|
class UncappedRunResponse(RunResponse):
|
|
"""Response for uncapped advance decisions."""
|
|
|
|
send_trail: bool = False
|
|
trail_min_safe: int = 10
|
|
trail_min_safe_delta: int = 0
|
|
|
|
|
|
class ThrowResponse(AiResponse):
|
|
"""Response for throw target decisions."""
|
|
|
|
cutoff: bool = False # Stops on True
|
|
at_lead_runner: bool = True
|
|
at_trail_runner: bool = False # Stops on False
|
|
trail_max_safe: int = 10
|
|
trail_max_safe_delta: int = -6
|
|
|
|
|
|
class DefenseResponse(AiResponse):
|
|
"""Response for defensive alignment decisions."""
|
|
|
|
hold_first: bool = False
|
|
hold_second: bool = False
|
|
hold_third: bool = False
|
|
outfield_in: bool = False
|
|
infield_in: bool = False
|
|
corners_in: bool = False
|
|
|
|
def defender_in(self, position: str) -> bool:
|
|
"""Check if a defender should play in based on position."""
|
|
if self.infield_in and position in ['C', '1B', '2B', '3B', 'SS', 'P']:
|
|
return True
|
|
elif self.corners_in and position in ['C', '1B', '3B', 'P']:
|
|
return True
|
|
elif self.outfield_in and position in ['LF', 'CF', 'RF']:
|
|
return True
|
|
return False |