major-domo-v2/models/decision.py
Cal Corum 2409c27c1d CLAUDE: Add comprehensive scorecard submission system
Implements full Google Sheets scorecard submission with:
- Complete game data extraction (68 play fields, pitching decisions, box score)
- Transaction rollback support at 3 states (plays/game/complete)
- Duplicate game detection with confirmation dialog
- Permission-based submission (GMs only)
- Automated results posting to news channel
- Automatic standings recalculation
- Key plays display with WPA sorting

New Components:
- Play, Decision, Game models with full validation
- SheetsService for Google Sheets integration
- GameService, PlayService, DecisionService for data management
- ConfirmationView for user confirmations
- Discord helper utilities for channel operations

Services Enhanced:
- StandingsService: Added recalculate_standings() method
- CustomCommandsService: Fixed creator endpoint path
- Team/Player models: Added helper methods for display

Configuration:
- Added SHEETS_CREDENTIALS_PATH environment variable
- Added SBA_NETWORK_NEWS_CHANNEL and role constants
- Enabled pygsheets dependency

Documentation:
- Comprehensive README updates across all modules
- Added command, service, model, and view documentation
- Detailed workflow and error handling documentation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 00:21:32 -05:00

58 lines
2.0 KiB
Python

"""
Pitching Decision Model
Tracks wins, losses, saves, holds, and other pitching decisions for game results.
This model matches the database schema at /database/app/routers_v3/decisions.py.
"""
from pydantic import Field
from models.base import SBABaseModel
class Decision(SBABaseModel):
"""
Pitching decision model for game results.
Tracks wins, losses, saves, holds, and other pitching decisions.
"""
game_id: int = Field(..., description="Game ID")
season: int = Field(..., description="Season number")
week: int = Field(..., description="Week number")
game_num: int = Field(..., description="Game number in series")
pitcher_id: int = Field(..., description="Pitcher's player ID")
team_id: int = Field(..., description="Team ID")
# Decision flags
win: int = Field(0, description="Win (1 or 0)")
loss: int = Field(0, description="Loss (1 or 0)")
hold: int = Field(0, description="Hold (1 or 0)")
is_save: int = Field(0, description="Save (1 or 0)")
b_save: int = Field(0, description="Blown save (1 or 0)")
# Pitcher information
is_start: bool = Field(False, description="Was this a start?")
irunners: int = Field(0, description="Inherited runners")
irunners_scored: int = Field(0, description="Inherited runners scored")
rest_ip: float = Field(0.0, description="Rest innings pitched")
rest_required: int = Field(0, description="Rest required")
def __repr__(self):
"""String representation showing key decision info."""
decision_type = ""
if self.win == 1:
decision_type = "W"
elif self.loss == 1:
decision_type = "L"
elif self.is_save == 1:
decision_type = "SV"
elif self.hold == 1:
decision_type = "HLD"
elif self.b_save == 1:
decision_type = "BS"
return (
f"Decision(pitcher_id={self.pitcher_id}, "
f"game_id={self.game_id}, "
f"type={decision_type or 'NONE'})"
)