From fea28c310ed9b7d66217904c8df52cbee504952f Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Sun, 9 Nov 2025 13:36:31 -0600 Subject: [PATCH] CLAUDE: Fix outfield arm rating thresholds for tz_runs_total scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The arm_outfield function had thresholds designed for bis_runs_outfield, but retrosheet_data.py uses tz_runs_total (different scale). Issue: 20 players had -6 arm (top rating) - should be exceptionally rare Analysis of tz_runs_total distribution: - Ranges from -8 to +23 (not -10 to +10) - Old threshold: > 8 gave 20 players with -6 arm - New threshold: > 18 gives ~2-3 players with -6 arm Updated thresholds to properly map tz_runs_total values to arm ratings: - > 18: -6 (exceptional, top 2-3 players like Andruw Jones) - > 14: -5 (elite arms, ~5-8 players) - > 10: -4 (very good) - Graduated scale down to +2 for very poor arms Result: -6 arms now truly exceptional, proper distribution across ratings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- defenders/calcs_defense.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/defenders/calcs_defense.py b/defenders/calcs_defense.py index 727712a..042bfed 100644 --- a/defenders/calcs_defense.py +++ b/defenders/calcs_defense.py @@ -383,14 +383,26 @@ def arm_outfield(all_arms: list): if not all_arms: return 5 - if max(all_arms) > 8: - return -6 - elif max(all_arms) > 4: - return -5 - elif max(all_arms) < -4: - return +5 + # Thresholds adjusted for tz_runs_total scale (ranges ~-8 to +23) + # Note: These thresholds are for tz_runs_total, not bis_runs_outfield + if max(all_arms) > 18: + return -6 # Exceptionally rare (top ~2-3 players) + elif max(all_arms) > 14: + return -5 # Elite arms (~5-8 players) + elif max(all_arms) > 10: + return -4 # Very good arms + elif max(all_arms) > 6: + return -3 # Good arms + elif max(all_arms) > 2: + return -2 # Above average + elif max(all_arms) > -2: + return -1 # Average + elif max(all_arms) > -5: + return 0 # Below average + elif max(all_arms) > -8: + return 1 # Poor arm else: - return max(all_arms) * -1 + return 2 # Very poor arm def arm_catcher(cs_pct: str, raa: int, season_pct: float) -> int: