paper-dynasty-card-creation/batters/stat_prep.py
2024-12-22 15:46:52 -06:00

95 lines
3.3 KiB
Python

import pandas as pd
import pydantic
from pydantic import root_validator, validator
from typing import Literal, Optional
from pydantic import model_validator
from pydantic import computed_field
from pydantic_core import PydanticCustomError
class DataMismatchError(Exception):
pass
class BattingCardModel(pydantic.BaseModel):
player_id: Optional[int] = None
variant: int = 0
steal_low: int = 3
steal_high: int = 20
steal_auto: bool = False
steal_jump: float = 0
bunting: str = 'C'
hit_and_run: str = 'C'
running: int = 10
offense_col: int = None
hand: Literal['R', 'L', 'S'] = 'R'
class CardPositionModel(pydantic.BaseModel):
player_id: int
variant: int = 0
position: Literal['P', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF', 'DH']
innings: int = 1
range: int = 5
error: int = 0
arm: Optional[int] = None
pb: Optional[int] = None
overthrow: Optional[int] = None
@model_validator(mode='after')
def position_validator(self):
if self.position in ['C', 'LF', 'CF', 'RF'] and self.arm is None:
raise ValueError(f'player_id: {self.player_id} - {self.position} must have an arm rating')
if self.position == 'C' and (self.pb is None or self.overthrow is None):
raise ValueError(f'player_id: {self.player_id} - Catchers must have a pb and overthrow rating')
return self
class BattingCardRatingsModel(pydantic.BaseModel):
battingcard_id: int
vs_hand: Literal['R', 'L', 'vR', 'vL']
homerun: float = 0.0
bp_homerun: float = 0.0
triple: float = 0.0
double_three: float = 0.0
double_two: float = 0.0
double_pull: float = 0.0
single_two: float = 0.0
single_one: float = 0.0
single_center: float = 0.0
bp_single: float = 0.0
hbp: float = 0.0
walk: float = 0.0
strikeout: float = 0.0
lineout: float = 0.0
popout: float = 0.0
flyout_a: float = 0.0
flyout_bq: float = 0.0
flyout_lf_b: float = 0.0
flyout_rf_b: float = 0.0
groundout_a: float = 0.0
groundout_b: float = 0.0
groundout_c: float = 0.0
avg: float = 0.0
obp: float = 0.0
slg: float = 0.0
pull_rate: float = 0.0
center_rate: float = 0.0
slap_rate: float = 0.0
@model_validator(mode='after')
def avg(self):
self.avg = (self.homerun + self.bp_homerun / 2 + self.triple + self.double_three + self.double_two + self.double_pull + self.single_two + self.single_one + self.single_center + self.bp_single / 2) / 108
self.obp = ((self.hbp + self.walk) / 108) + self.avg
self.slg = (self.homerun * 4 + self.bp_homerun * 2 + self.triple * 3 + self.double_three * 2 + self.double_two * 2 + self.double_pull * 2 + self.single_two + self.single_one + self.single_center + self.bp_single / 2) / 108
total_chances = (self.homerun + self.bp_homerun + self.triple + self.double_three + self.double_two + self.double_pull + self.single_two + self.single_one + self.single_center + self.bp_single + self.hbp + self.walk + self.strikeout + self.lineout + self.popout + self.flyout_a + self.flyout_bq + self.flyout_lf_b + self.flyout_rf_b + self.groundout_a + self.groundout_b + self.groundout_c)
if total_chances != 108:
raise ValueError(f'BC {self.battingcard_id} has {total_chances} chances listed; must be 108')
return self