95 lines
3.3 KiB
Python
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
|