major-domo-v2/models/roster.py
2025-09-24 09:32:04 -05:00

148 lines
5.4 KiB
Python

"""
Roster models for SBA team roster management
Represents team rosters and roster-related data.
"""
from typing import Optional, List, Dict, Any
from pydantic import Field
from models.base import SBABaseModel
from models.player import Player
class RosterPlayer(SBABaseModel):
"""Represents a player on a team roster."""
player_id: int = Field(..., description="Player ID from database")
player_name: str = Field(..., description="Player name")
position: str = Field(..., description="Primary position")
wara: float = Field(..., description="Player WARA value")
status: str = Field(default="active", description="Player status (active, il, minor)")
# Optional player details
injury_status: Optional[str] = Field(None, description="Injury status if applicable")
contract_info: Optional[Dict[str, Any]] = Field(None, description="Contract information")
@property
def is_active(self) -> bool:
"""Check if player is on active roster."""
return self.status == "active"
@property
def is_injured(self) -> bool:
"""Check if player is on injured list."""
return self.status == "il"
@property
def is_minor_league(self) -> bool:
"""Check if player is in minor leagues."""
return self.status == "minor"
@property
def status_emoji(self) -> str:
"""Emoji representation of player status."""
status_emojis = {
"active": "",
"il": "🏥",
"minor": "🏗️",
"suspended": ""
}
return status_emojis.get(self.status, "")
class TeamRoster(SBABaseModel):
"""Represents a complete team roster for a specific week."""
team_id: int = Field(..., description="Team ID from database")
team_abbrev: str = Field(..., description="Team abbreviation")
season: int = Field(..., description="Season number")
week: int = Field(..., description="Week number")
# Roster sections
active_players: List[RosterPlayer] = Field(default_factory=list, description="Active roster players")
il_players: List[RosterPlayer] = Field(default_factory=list, description="Injured list players")
minor_league_players: List[RosterPlayer] = Field(default_factory=list, description="Minor league players")
# Roster statistics
total_wara: float = Field(default=0.0, description="Total active roster WARA")
salary_total: Optional[float] = Field(None, description="Total salary if applicable")
@property
def all_players(self) -> List[RosterPlayer]:
"""All players on the roster regardless of status."""
return self.active_players + self.il_players + self.minor_league_players
@property
def total_players(self) -> int:
"""Total number of players on roster."""
return len(self.all_players)
@property
def active_count(self) -> int:
"""Number of active players."""
return len(self.active_players)
@property
def il_count(self) -> int:
"""Number of players on IL."""
return len(self.il_players)
@property
def minor_league_count(self) -> int:
"""Number of minor league players."""
return len(self.minor_league_players)
def get_players_by_position(self, position: str) -> List[RosterPlayer]:
"""Get all active players at a specific position."""
return [p for p in self.active_players if p.position == position]
def find_player(self, player_name: str) -> Optional[RosterPlayer]:
"""Find a player by name on the roster."""
for player in self.all_players:
if player.player_name.lower() == player_name.lower():
return player
return None
@classmethod
def from_api_data(cls, data: dict) -> 'TeamRoster':
"""
Create TeamRoster instance from API data.
Expected format from API:
{
'team_id': 123,
'team_abbrev': 'NYY',
'season': 12,
'week': 5,
'active': {'players': [...], 'WARa': 45.2},
'il': {'players': [...], 'WARa': 2.1},
'minor': {'players': [...], 'WARa': 12.5}
}
"""
roster_data = data.copy()
# Convert player sections
for section, status in [('active', 'active'), ('il', 'il'), ('minor', 'minor')]:
if section in data and isinstance(data[section], dict):
players_data = data[section].get('players', [])
players = []
for player_data in players_data:
player = RosterPlayer(
player_id=player_data.get('id', 0),
player_name=player_data.get('name', ''),
position=player_data.get('pos_1', 'UNKNOWN'),
wara=player_data.get('wara', 0.0),
status=status
)
players.append(player)
roster_data[f'{section}_players'] = players
# Remove original section
if section in roster_data:
del roster_data[section]
# Handle WARA totals
if 'active' in data and isinstance(data['active'], dict):
roster_data['total_wara'] = data['active'].get('WARa', 0.0)
return super().from_api_data(roster_data)