Fix SLG formula drift in extracted rating models
The extracted batting and pitching models used malformed SLG equations that double-counted and omitted outcomes, skewing slash lines. Align formulas with canonical weighting and add regression tests to prevent recurrence. Co-Authored-By: Claude GPT-5.3-Codex <noreply@anthropic.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
39c652e55c
commit
2bf3a6cee7
@ -269,8 +269,9 @@ class BattingCardRatingsModel(pydantic.BaseModel):
|
||||
self.avg = mround(self.total_hits() / 108, prec=5, base=0.00001)
|
||||
self.obp = mround((self.total_hits() + self.hbp + self.walk) / 108, prec=5, base=0.00001)
|
||||
self.slg = mround((
|
||||
self.homerun * 4 + self.triple * 3 + self.single_center + self.single_two + self.single_two +
|
||||
(self.double_two + self.double_three + self.double_two + self.bp_homerun) * 2 + self.bp_single / 2) / 108, prec=5, base=0.00001)
|
||||
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, prec=5, base=0.00001)
|
||||
|
||||
def custom_to_dict(self):
|
||||
self.calculate_rate_stats()
|
||||
|
||||
@ -89,8 +89,9 @@ class PitchingCardRatingsModel(pydantic.BaseModel):
|
||||
self.avg = mround(self.total_hits() / 108, prec=5, base=0.00001)
|
||||
self.obp = mround((self.total_hits() + self.hbp + self.walk) / 108, prec=5, base=0.00001)
|
||||
self.slg = mround((
|
||||
self.homerun * 4 + self.triple * 3 + self.single_center + self.single_two + self.single_two +
|
||||
(self.double_two + self.double_three + self.double_two + self.bp_homerun) * 2 + self.bp_single / 2) / 108, prec=5, base=0.00001)
|
||||
self.homerun * 4 + self.bp_homerun * 2 + self.triple * 3 + self.double_three * 2 +
|
||||
self.double_two * 2 + self.double_cf * 2 + self.single_two + self.single_one +
|
||||
self.single_center + self.bp_single / 2) / 108, prec=5, base=0.00001)
|
||||
|
||||
def custom_to_dict(self):
|
||||
self.calculate_rate_stats()
|
||||
|
||||
90
tests/test_rate_stats_formulas.py
Normal file
90
tests/test_rate_stats_formulas.py
Normal file
@ -0,0 +1,90 @@
|
||||
from batters.models import BattingCardRatingsModel
|
||||
from pitchers.models import PitchingCardRatingsModel
|
||||
from creation_helpers import mround
|
||||
|
||||
|
||||
def test_batting_model_slg_formula_matches_canonical_weights():
|
||||
ratings = BattingCardRatingsModel(
|
||||
battingcard_id=1,
|
||||
bat_hand='R',
|
||||
vs_hand='R',
|
||||
hard_rate=0.3,
|
||||
med_rate=0.3,
|
||||
soft_rate=0.3,
|
||||
pull_rate=0.3,
|
||||
center_rate=0.3,
|
||||
slap_rate=0.3,
|
||||
homerun=1,
|
||||
bp_homerun=2,
|
||||
triple=3,
|
||||
double_three=4,
|
||||
double_two=5,
|
||||
double_pull=6,
|
||||
single_two=7,
|
||||
single_one=8,
|
||||
single_center=9,
|
||||
bp_single=10,
|
||||
)
|
||||
|
||||
ratings.calculate_rate_stats()
|
||||
|
||||
expected = mround(
|
||||
(
|
||||
ratings.homerun * 4
|
||||
+ ratings.bp_homerun * 2
|
||||
+ ratings.triple * 3
|
||||
+ ratings.double_three * 2
|
||||
+ ratings.double_two * 2
|
||||
+ ratings.double_pull * 2
|
||||
+ ratings.single_two
|
||||
+ ratings.single_one
|
||||
+ ratings.single_center
|
||||
+ ratings.bp_single / 2
|
||||
) / 108,
|
||||
prec=5,
|
||||
base=0.00001,
|
||||
)
|
||||
|
||||
assert ratings.slg == expected
|
||||
|
||||
|
||||
def test_pitching_model_slg_formula_matches_canonical_weights():
|
||||
ratings = PitchingCardRatingsModel(
|
||||
pitchingcard_id=1,
|
||||
pit_hand='R',
|
||||
vs_hand='R',
|
||||
hard_rate=0.3,
|
||||
med_rate=0.3,
|
||||
soft_rate=0.3,
|
||||
homerun=1,
|
||||
bp_homerun=2,
|
||||
triple=3,
|
||||
double_three=4,
|
||||
double_two=5,
|
||||
double_cf=6,
|
||||
single_two=7,
|
||||
single_one=8,
|
||||
single_center=9,
|
||||
bp_single=10,
|
||||
)
|
||||
|
||||
ratings.calculate_rate_stats()
|
||||
|
||||
expected = mround(
|
||||
(
|
||||
ratings.homerun * 4
|
||||
+ ratings.bp_homerun * 2
|
||||
+ ratings.triple * 3
|
||||
+ ratings.double_three * 2
|
||||
+ ratings.double_two * 2
|
||||
+ ratings.double_cf * 2
|
||||
+ ratings.single_two
|
||||
+ ratings.single_one
|
||||
+ ratings.single_center
|
||||
+ ratings.bp_single / 2
|
||||
) / 108,
|
||||
prec=5,
|
||||
base=0.00001,
|
||||
)
|
||||
|
||||
assert ratings.slg == expected
|
||||
Loading…
Reference in New Issue
Block a user