Spaces:
Sleeping
Sleeping
File size: 5,334 Bytes
6424951 92a832f 6424951 92a832f 6424951 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | """Pydantic models for player and game data."""
from typing import Any, ClassVar
from pydantic import BaseModel, Field, field_validator
from src.config import DIFFICULTY_PRESETS
class PlayerStats(BaseModel):
"""Model representing a player's career statistics."""
full_name: str = Field(..., min_length=1, max_length=100)
ast: int = Field(..., ge=0, description="Career assists")
blk: int = Field(..., ge=0, description="Career blocks")
dreb: int = Field(..., ge=0, description="Career defensive rebounds")
fg3a: int = Field(..., ge=0, description="Career 3-point attempts")
fg3m: int = Field(..., ge=0, description="Career 3-pointers made")
fg3_pct: float = Field(..., ge=0.0, le=1.0, description="3-point percentage")
fga: int = Field(..., ge=0, description="Career field goal attempts")
fgm: int = Field(..., ge=0, description="Career field goals made")
fg_pct: float = Field(..., ge=0.0, le=1.0, description="Field goal percentage")
fta: int = Field(..., ge=0, description="Career free throw attempts")
ftm: int = Field(..., ge=0, description="Career free throws made")
ft_pct: float = Field(..., ge=0.0, le=1.0, description="Free throw percentage")
gp: int = Field(..., ge=0, description="Games played")
gs: int = Field(..., ge=0, description="Games started")
min: int = Field(..., ge=0, description="Career minutes")
oreb: int = Field(..., ge=0, description="Career offensive rebounds")
pf: int = Field(..., ge=0, description="Career personal fouls")
pts: int = Field(..., ge=0, description="Career points")
reb: int = Field(..., ge=0, description="Career rebounds")
stl: int = Field(..., ge=0, description="Career steals")
tov: int = Field(..., ge=0, description="Career turnovers")
first_name: str = Field(..., max_length=50)
last_name: str = Field(..., max_length=50)
full_name_lower: str = Field(..., max_length=100)
first_name_lower: str = Field(..., max_length=50)
last_name_lower: str = Field(..., max_length=50)
is_active: bool = Field(default=False)
@classmethod
def from_db_row(cls, row: tuple[Any, ...]) -> "PlayerStats":
"""Create PlayerStats from a database row tuple.
Args:
row: Database row tuple in PLAYER_COLUMNS order
Returns:
PlayerStats instance
"""
return cls(
full_name=row[0],
ast=row[1],
blk=row[2],
dreb=row[3],
fg3a=row[4],
fg3m=row[5],
fg3_pct=row[6] or 0.0,
fga=row[7],
fgm=row[8],
fg_pct=row[9] or 0.0,
fta=row[10],
ftm=row[11],
ft_pct=row[12] or 0.0,
gp=row[13],
gs=row[14],
min=row[15],
oreb=row[16],
pf=row[17],
pts=row[18],
reb=row[19],
stl=row[20],
tov=row[21],
first_name=row[22],
last_name=row[23],
full_name_lower=row[24],
first_name_lower=row[25],
last_name_lower=row[26],
is_active=bool(row[27]) if row[27] is not None else False,
)
class DifficultySettings(BaseModel):
"""Model for game difficulty settings."""
VALID_PRESETS: ClassVar[set[str]] = set(DIFFICULTY_PRESETS.keys())
name: str = Field(..., min_length=1)
pts_threshold: int = Field(..., ge=0, description="Minimum career points")
reb_threshold: int = Field(..., ge=0, description="Minimum career rebounds")
ast_threshold: int = Field(..., ge=0, description="Minimum career assists")
stl_threshold: int = Field(..., ge=0, description="Minimum career steals")
@field_validator("name")
@classmethod
def validate_preset_name(cls, v: str) -> str:
"""Validate that preset name is recognized."""
if v not in cls.VALID_PRESETS:
raise ValueError(
f"Unknown difficulty preset: {v}. "
f"Valid options: {', '.join(sorted(cls.VALID_PRESETS))}"
)
return v
@classmethod
def from_preset(cls, preset_name: str) -> "DifficultySettings":
"""Create DifficultySettings from a named preset.
Args:
preset_name: Name of difficulty preset (e.g., "Regular", "Dream Team")
Returns:
DifficultySettings instance
Raises:
ValueError: If preset_name is not valid
"""
if preset_name not in DIFFICULTY_PRESETS:
raise ValueError(
f"Unknown difficulty preset: {preset_name}. "
f"Valid options: {', '.join(sorted(DIFFICULTY_PRESETS.keys()))}"
)
pts, reb, ast, stl = DIFFICULTY_PRESETS[preset_name]
return cls(
name=preset_name,
pts_threshold=pts,
reb_threshold=reb,
ast_threshold=ast,
stl_threshold=stl,
)
def as_tuple(self) -> tuple[int, int, int, int]:
"""Return thresholds as tuple for backward compatibility.
Returns:
Tuple of (pts, reb, ast, stl) thresholds
"""
return (
self.pts_threshold,
self.reb_threshold,
self.ast_threshold,
self.stl_threshold,
)
|