From 4f2513ae8b51ef815266f40c0caf14f1bd1b42bb Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Sat, 7 Mar 2026 16:32:56 -0600 Subject: [PATCH] fix: use max() for pitcher OPS split weighting (#6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starters face both LHH and RHH, so the OPS aggregation formula should penalise the weaker platoon split (higher OPS allowed) rather than reward the stronger one. Changed min(ops_vl, ops_vr) → max(ops_vl, ops_vr) in both get_total_ops (line 621) and sort_starters (line 703) and replaced the TODO comment with an explanatory note. Co-Authored-By: Claude Sonnet 4.6 --- app/routers_v2/teams.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/routers_v2/teams.py b/app/routers_v2/teams.py index 91712a4..e4d4615 100644 --- a/app/routers_v2/teams.py +++ b/app/routers_v2/teams.py @@ -616,8 +616,9 @@ def sort_pitchers(pitching_card_query) -> DataFrame | None: return float("inf") ops_vl = vlval.obp + vlval.slg ops_vr = vrval.obp + vrval.slg - # TODO: should this be max?? - return (ops_vr + ops_vl + min(ops_vl, ops_vr)) / 3 + # Weight the weaker split (higher OPS allowed) so platoon weaknesses are penalized. + # Starters face both LHH and RHH, so vulnerability against either hand matters. + return (ops_vr + ops_vl + max(ops_vl, ops_vr)) / 3 pitcher_df["total_ops"] = pitcher_df.apply(get_total_ops, axis=1) return pitcher_df.sort_values(by="total_ops") @@ -698,7 +699,8 @@ async def get_team_sp( return float("inf") ops_vl = vlval.obp + vlval.slg ops_vr = vrval.obp + vrval.slg - return (ops_vr + ops_vl + min(ops_vl, ops_vr)) / 3 + # Weight the weaker split (higher OPS allowed) so platoon weaknesses are penalized. + return (ops_vr + ops_vl + max(ops_vl, ops_vr)) / 3 starter_df["total_ops"] = starter_df.apply(get_total_ops, axis=1) return starter_df.sort_values(by="total_ops")