""" Common X-Check resolution tables shared across SBA and PD leagues. Tables include: - Defense range tables (20x5) for each position type - Error charts mapping 3d6 rolls to error types - Holding runner responsibility chart Author: Claude Date: 2025-11-01 """ # ============================================================================ # DEFENSE RANGE TABLES (1d20 × Defense Range 1-5) # ============================================================================ # Row index = d20 roll - 1 (0-indexed) # Column index = defense range - 1 (0-indexed) # Values = base result code (G1, SI2, F2, etc.) INFIELD_DEFENSE_TABLE: list[list[str]] = [ # Range: 1 2 3 4 5 # Best Good Avg Poor Worst ["G3#", "SI1", "SI2", "SI2", "SI2"], # d20 = 1 ["G2#", "SI1", "SI2", "SI2", "SI2"], # d20 = 2 ["G2#", "G3#", "SI1", "SI2", "SI2"], # d20 = 3 ["G2#", "G3#", "SI1", "SI2", "SI2"], # d20 = 4 ["G1", "G3#", "G3#", "SI1", "SI2"], # d20 = 5 ["G1", "G2#", "G3#", "SI1", "SI2"], # d20 = 6 ["G1", "G2", "G3#", "G3#", "SI1"], # d20 = 7 ["G1", "G2", "G3#", "G3#", "SI1"], # d20 = 8 ["G1", "G2", "G3", "G3#", "G3#"], # d20 = 9 ["G1", "G1", "G2", "G3#", "G3#"], # d20 = 10 ["G1", "G1", "G2", "G3", "G3#"], # d20 = 11 ["G1", "G1", "G2", "G3", "G3#"], # d20 = 12 ["G1", "G1", "G2", "G3", "G3"], # d20 = 13 ["G1", "G1", "G2", "G2", "G3"], # d20 = 14 ["G1", "G1", "G1", "G2", "G3"], # d20 = 15 ["G1", "G1", "G1", "G2", "G3"], # d20 = 16 ["G1", "G1", "G1", "G1", "G3"], # d20 = 17 ["G1", "G1", "G1", "G1", "G2"], # d20 = 18 ["G1", "G1", "G1", "G1", "G2"], # d20 = 19 ["G1", "G1", "G1", "G1", "G1"], # d20 = 20 ] OUTFIELD_DEFENSE_TABLE: list[list[str]] = [ # Range: 1 2 3 4 5 # Best Good Avg Poor Worst ["TR3", "DO3", "DO3", "DO3", "DO3"], # d20 = 1 ["DO3", "DO3", "DO3", "DO3", "DO3"], # d20 = 2 ["DO2", "DO3", "DO3", "DO3", "DO3"], # d20 = 3 ["DO2", "DO2", "DO3", "DO3", "DO3"], # d20 = 4 ["SI2", "DO2", "DO2", "DO3", "DO3"], # d20 = 5 ["SI2", "SI2", "DO2", "DO2", "DO3"], # d20 = 6 ["F1", "SI2", "SI2", "DO2", "DO2"], # d20 = 7 ["F1", "F1", "SI2", "SI2", "DO2"], # d20 = 8 ["F1", "F1", "F1", "SI2", "SI2"], # d20 = 9 ["F1", "F1", "F1", "SI2", "SI2"], # d20 = 10 ["F1", "F1", "F1", "F1", "SI2"], # d20 = 11 ["F1", "F1", "F1", "F1", "SI2"], # d20 = 12 ["F1", "F1", "F1", "F1", "F1"], # d20 = 13 ["F2", "F1", "F1", "F1", "F1"], # d20 = 14 ["F2", "F2", "F1", "F1", "F1"], # d20 = 15 ["F2", "F2", "F2", "F1", "F1"], # d20 = 16 ["F2", "F2", "F2", "F2", "F1"], # d20 = 17 ["F3", "F2", "F2", "F2", "F2"], # d20 = 18 ["F3", "F3", "F2", "F2", "F2"], # d20 = 19 ["F3", "F3", "F3", "F2", "F2"], # d20 = 20 ] CATCHER_DEFENSE_TABLE: list[list[str]] = [ # Range: 1 2 3 4 5 # Best Good Avg Poor Worst ["G3", "SI1", "SI1", "SI1", "SI1"], # d20 = 1 ["G2", "G3", "SI1", "SI1", "SI1"], # d20 = 2 ["G2", "G3", "SI1", "SI1", "SI1"], # d20 = 3 ["G1", "G2", "G3", "SI1", "SI1"], # d20 = 4 ["G1", "G2", "G3", "SI1", "SI1"], # d20 = 5 ["G1", "G1", "G2", "G3", "SI1"], # d20 = 6 ["G1", "G1", "G2", "G3", "SI1"], # d20 = 7 ["G1", "G1", "G1", "G2", "G3"], # d20 = 8 ["G1", "G1", "G1", "G2", "G3"], # d20 = 9 ["SPD", "G1", "G1", "G1", "G2"], # d20 = 10 ["SPD", "SPD", "G1", "G1", "G1"], # d20 = 11 ["SPD", "SPD", "SPD", "G1", "G1"], # d20 = 12 ["FO", "SPD", "SPD", "SPD", "G1"], # d20 = 13 ["FO", "FO", "SPD", "SPD", "SPD"], # d20 = 14 ["FO", "FO", "FO", "SPD", "SPD"], # d20 = 15 ["PO", "FO", "FO", "FO", "SPD"], # d20 = 16 ["PO", "PO", "FO", "FO", "FO"], # d20 = 17 ["PO", "PO", "PO", "FO", "FO"], # d20 = 18 ["PO", "PO", "PO", "PO", "FO"], # d20 = 19 ["PO", "PO", "PO", "PO", "PO"], # d20 = 20 ] # ============================================================================ # ERROR CHARTS (3d6 totals by Error Rating and Position Type) # ============================================================================ # Structure: {error_rating: {'RP': [rolls], 'E1': [rolls], 'E2': [rolls], 'E3': [rolls]}} # If 3d6 sum is in the list for that error rating, apply that error type # Otherwise, error_result = 'NO' (no error) # Corner Outfield (LF, RF) Error Chart LF_RF_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [3], "E2": [], "E3": [17]}, 2: {"RP": [5], "E1": [3, 18], "E2": [], "E3": [16]}, 3: {"RP": [5], "E1": [3, 18], "E2": [], "E3": [15]}, 4: {"RP": [5], "E1": [4], "E2": [3, 15], "E3": [18]}, 5: {"RP": [5], "E1": [4], "E2": [14], "E3": [18]}, 6: {"RP": [5], "E1": [3, 4], "E2": [14, 17], "E3": [18]}, 7: {"RP": [5], "E1": [16], "E2": [6, 15], "E3": [18]}, 8: {"RP": [5], "E1": [16], "E2": [6, 15, 17], "E3": [3, 18]}, 9: {"RP": [5], "E1": [16], "E2": [11], "E3": [3, 18]}, 10: {"RP": [5], "E1": [4, 16], "E2": [14, 15, 17], "E3": [3, 18]}, 11: {"RP": [5], "E1": [4, 16], "E2": [13, 15], "E3": [3, 18]}, 12: {"RP": [5], "E1": [4, 16], "E2": [13, 14], "E3": [3, 18]}, 13: {"RP": [5], "E1": [6], "E2": [4, 12, 15], "E3": [17]}, 14: {"RP": [5], "E1": [3, 6], "E2": [12, 14], "E3": [17]}, 15: {"RP": [5], "E1": [3, 6, 18], "E2": [4, 12, 14], "E3": [17]}, 16: {"RP": [5], "E1": [4, 6], "E2": [12, 13], "E3": [17]}, 17: {"RP": [5], "E1": [4, 6], "E2": [9, 12], "E3": [17]}, 18: {"RP": [5], "E1": [3, 4, 6], "E2": [11, 12, 18], "E3": [17]}, 19: {"RP": [5], "E1": [7], "E2": [3, 10, 11], "E3": [17, 18]}, 20: {"RP": [5], "E1": [3, 7], "E2": [11, 13, 16], "E3": [17, 18]}, 21: {"RP": [5], "E1": [3, 7], "E2": [11, 12, 15], "E3": [17, 18]}, 22: {"RP": [5], "E1": [3, 6, 16], "E2": [9, 12, 14], "E3": [17, 18]}, 23: {"RP": [5], "E1": [4, 7], "E2": [11, 12, 14], "E3": [17, 18]}, 24: {"RP": [5], "E1": [4, 6, 16], "E2": [8, 11, 13], "E3": [3, 17, 18]}, 25: {"RP": [5], "E1": [4, 6, 16], "E2": [11, 12, 13], "E3": [3, 17, 18]}, } # Center Field Error Chart CF_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [3], "E2": [], "E3": [17]}, 2: {"RP": [5], "E1": [3, 18], "E2": [], "E3": [16]}, 3: {"RP": [5], "E1": [3, 18], "E2": [], "E3": [15]}, 4: {"RP": [5], "E1": [4], "E2": [3, 15], "E3": [18]}, 5: {"RP": [5], "E1": [4], "E2": [14], "E3": [18]}, 6: {"RP": [5], "E1": [3, 4], "E2": [14, 17], "E3": [18]}, 7: {"RP": [5], "E1": [16], "E2": [6, 15], "E3": [18]}, 8: {"RP": [5], "E1": [16], "E2": [6, 15, 17], "E3": [3, 18]}, 9: {"RP": [5], "E1": [16], "E2": [11], "E3": [3, 18]}, 10: {"RP": [5], "E1": [4, 16], "E2": [14, 15, 17], "E3": [3, 18]}, 11: {"RP": [5], "E1": [4, 16], "E2": [13, 15], "E3": [3, 18]}, 12: {"RP": [5], "E1": [4, 16], "E2": [13, 14], "E3": [3, 18]}, 13: {"RP": [5], "E1": [6], "E2": [4, 12, 15], "E3": [17]}, 14: {"RP": [5], "E1": [3, 6], "E2": [12, 14], "E3": [17]}, 15: {"RP": [5], "E1": [3, 6, 18], "E2": [4, 12, 14], "E3": [17]}, 16: {"RP": [5], "E1": [4, 6], "E2": [12, 13], "E3": [17]}, 17: {"RP": [5], "E1": [4, 6], "E2": [9, 12], "E3": [17]}, 18: {"RP": [5], "E1": [3, 4, 6], "E2": [11, 12, 18], "E3": [17]}, 19: {"RP": [5], "E1": [7], "E2": [3, 10, 11], "E3": [17, 18]}, 20: {"RP": [5], "E1": [3, 7], "E2": [11, 13, 16], "E3": [17, 18]}, 21: {"RP": [5], "E1": [3, 7], "E2": [11, 12, 15], "E3": [17, 18]}, 22: {"RP": [5], "E1": [3, 6, 16], "E2": [9, 12, 14], "E3": [17, 18]}, 23: {"RP": [5], "E1": [4, 7], "E2": [11, 12, 14], "E3": [17, 18]}, 24: {"RP": [5], "E1": [4, 6, 16], "E2": [8, 11, 13], "E3": [3, 17, 18]}, 25: {"RP": [5], "E1": [4, 6, 16], "E2": [11, 12, 13], "E3": [3, 17, 18]}, } # Infield Error Charts # Note: Infield charts do not use E3 (unlike outfield charts) # Structure: same as OF but E3 is always empty # Catcher Error Chart CATCHER_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [17], "E2": [], "E3": []}, 2: {"RP": [5], "E1": [3, 17, 18], "E2": [], "E3": []}, 3: {"RP": [5], "E1": [3, 16, 10], "E2": [], "E3": []}, 4: {"RP": [5], "E1": [16, 17], "E2": [18], "E3": []}, 5: {"RP": [5], "E1": [4, 16, 17], "E2": [18], "E3": []}, 6: {"RP": [5], "E1": [14], "E2": [18], "E3": []}, 7: {"RP": [5], "E1": [3, 15, 16], "E2": [18], "E3": []}, 8: {"RP": [5], "E1": [6, 15], "E2": [18], "E3": []}, 9: {"RP": [5], "E1": [3, 13], "E2": [18], "E3": []}, 10: {"RP": [5], "E1": [12], "E2": [18], "E3": []}, 11: {"RP": [5], "E1": [3, 11], "E2": [18], "E3": []}, 12: {"RP": [5], "E1": [6, 15, 16, 17], "E2": [3, 18], "E3": []}, 13: {"RP": [5], "E1": [4, 6, 15, 16, 17], "E2": [3, 18], "E3": []}, 14: {"RP": [5], "E1": [12, 16, 17], "E2": [3, 18], "E3": []}, 15: {"RP": [5], "E1": [11, 15], "E2": [3, 18], "E3": []}, 16: {"RP": [5], "E1": [7, 14, 16, 17], "E2": [3, 18], "E3": []}, } # First Base Error Chart FIRST_BASE_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [17, 18], "E2": [], "E3": []}, 2: {"RP": [5], "E1": [3, 16, 18], "E2": [], "E3": []}, 3: {"RP": [5], "E1": [3, 15], "E2": [18], "E3": []}, 4: {"RP": [5], "E1": [14], "E2": [18], "E3": []}, 5: {"RP": [5], "E1": [14, 17], "E2": [18], "E3": []}, 6: {"RP": [5], "E1": [3, 13], "E2": [18], "E3": []}, 7: {"RP": [5], "E1": [3, 9], "E2": [18], "E3": []}, 8: {"RP": [5], "E1": [6, 15, 16, 17], "E2": [3, 18], "E3": []}, 9: {"RP": [5], "E1": [7, 14, 17], "E2": [3, 18], "E3": []}, 10: {"RP": [5], "E1": [11, 15], "E2": [3, 18], "E3": []}, 11: {"RP": [5], "E1": [6, 8, 15], "E2": [3, 18], "E3": []}, 12: {"RP": [5], "E1": [6, 9, 15], "E2": [3, 18], "E3": []}, 13: {"RP": [5], "E1": [11, 13], "E2": [17], "E3": []}, 14: {"RP": [5], "E1": [3, 9, 12], "E2": [17], "E3": []}, 15: {"RP": [5], "E1": [7, 12, 14], "E2": [17], "E3": []}, 16: {"RP": [5], "E1": [3, 11, 12, 16], "E2": [17], "E3": []}, 17: {"RP": [5], "E1": [3, 6, 11, 12], "E2": [17], "E3": []}, 18: {"RP": [5], "E1": [11, 12, 14], "E2": [17], "E3": []}, 19: {"RP": [5], "E1": [10, 11, 15, 16], "E2": [17, 18], "E3": []}, 20: {"RP": [5], "E1": [6, 10, 11, 15], "E2": [17, 18], "E3": []}, 21: {"RP": [5], "E1": [3, 9, 10, 12], "E2": [17, 18], "E3": []}, 22: {"RP": [5], "E1": [7, 11, 12, 14], "E2": [17, 18], "E3": []}, 23: {"RP": [5], "E1": [10, 11, 12, 16], "E2": [17, 18], "E3": []}, 24: {"RP": [5], "E1": [11, 12, 13, 14], "E2": [3, 17, 18], "E3": []}, 25: {"RP": [5], "E1": [9, 11, 12, 14], "E2": [3, 17, 18], "E3": []}, 26: {"RP": [5], "E1": [9, 12, 13, 14, 15], "E2": [3, 17, 18], "E3": []}, 27: {"RP": [5], "E1": [7, 8, 11, 13, 14], "E2": [3, 17, 18], "E3": []}, 28: {"RP": [5], "E1": [7, 11, 12, 13, 14], "E2": [3, 17, 18], "E3": []}, 29: {"RP": [5], "E1": [9, 10, 11, 12, 17], "E2": [16], "E3": []}, 30: {"RP": [5], "E1": [10, 11, 12, 13, 15, 18], "E2": [16], "E3": []}, } # Second Base Error Chart SECOND_BASE_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [18], "E2": [], "E3": []}, 2: {"RP": [5], "E1": [3, 18], "E2": [], "E3": []}, 3: {"RP": [5], "E1": [3, 17], "E2": [], "E3": []}, 4: {"RP": [5], "E1": [3, 17], "E2": [18], "E3": []}, 5: {"RP": [5], "E1": [16], "E2": [18], "E3": []}, 6: {"RP": [5], "E1": [3, 16], "E2": [18], "E3": []}, 8: {"RP": [5], "E1": [16, 17], "E2": [18], "E3": []}, 10: {"RP": [5], "E1": [4, 16, 17], "E2": [18], "E3": []}, 11: {"RP": [5], "E1": [15, 17], "E2": [18], "E3": []}, 12: {"RP": [5], "E1": [15, 17], "E2": [3, 18], "E3": []}, 13: {"RP": [5], "E1": [14], "E2": [3, 18], "E3": []}, 14: {"RP": [5], "E1": [15, 16], "E2": [3, 18], "E3": []}, 15: {"RP": [5], "E1": [14, 17], "E2": [3, 18], "E3": []}, 16: {"RP": [5], "E1": [15, 16, 17], "E2": [3, 18], "E3": []}, 17: {"RP": [5], "E1": [6, 15], "E2": [3, 18], "E3": []}, 18: {"RP": [5], "E1": [13], "E2": [3, 18], "E3": []}, 19: {"RP": [5], "E1": [6, 15, 17], "E2": [3, 18], "E3": []}, 20: {"RP": [5], "E1": [3, 13, 18], "E2": [17], "E3": []}, 21: {"RP": [5], "E1": [4, 13], "E2": [17], "E3": []}, 22: {"RP": [5], "E1": [12, 18], "E2": [17], "E3": []}, 23: {"RP": [5], "E1": [11], "E2": [17], "E3": []}, 24: {"RP": [5], "E1": [11, 18], "E2": [17], "E3": []}, 25: {"RP": [5], "E1": [3, 11, 18], "E2": [17], "E3": []}, 26: {"RP": [5], "E1": [13, 15], "E2": [17], "E3": []}, 27: {"RP": [5], "E1": [13, 15, 18], "E2": [17], "E3": []}, 28: {"RP": [5], "E1": [3, 13, 15], "E2": [17, 18], "E3": []}, 29: {"RP": [5], "E1": [3, 11, 16], "E2": [17, 18], "E3": []}, 30: {"RP": [5], "E1": [12, 15], "E2": [17, 18], "E3": []}, 32: {"RP": [5], "E1": [11, 15], "E2": [17, 18], "E3": []}, 34: {"RP": [5], "E1": [12, 14], "E2": [17, 18], "E3": []}, 37: {"RP": [5], "E1": [11, 15, 18], "E2": [3, 17, 18], "E3": []}, 39: {"RP": [5], "E1": [12, 13], "E2": [3, 17, 18], "E3": []}, 41: {"RP": [5], "E1": [11, 13], "E2": [3, 17, 18], "E3": []}, 44: {"RP": [5], "E1": [9, 12, 18], "E2": [16], "E3": []}, 47: {"RP": [5], "E1": [7, 12, 14], "E2": [16], "E3": []}, 50: {"RP": [5], "E1": [11, 13, 15, 18], "E2": [16], "E3": []}, 53: {"RP": [5], "E1": [11, 12, 15], "E2": [16, 18], "E3": []}, 56: {"RP": [5], "E1": [6, 12, 13, 15], "E2": [16, 18], "E3": []}, 59: {"RP": [5], "E1": [6, 11, 13, 15], "E2": [3, 16, 18], "E3": []}, 62: {"RP": [5], "E1": [6, 11, 12, 15], "E2": [3, 16, 18], "E3": []}, 65: {"RP": [5], "E1": [7, 12, 13, 14], "E2": [3, 16, 18], "E3": []}, 68: {"RP": [5], "E1": [10, 11, 12], "E2": [16, 17], "E3": []}, 71: {"RP": [5], "E1": [11, 12, 13, 15], "E2": [16, 17], "E3": []}, } # Third Base Error Chart THIRD_BASE_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [3], "E2": [18], "E3": []}, 2: {"RP": [5], "E1": [3, 4], "E2": [18], "E3": []}, 3: {"RP": [5], "E1": [3, 4], "E2": [17], "E3": []}, 4: {"RP": [5], "E1": [3, 16], "E2": [17], "E3": []}, 5: {"RP": [5], "E1": [15], "E2": [17], "E3": []}, 6: {"RP": [5], "E1": [4, 15], "E2": [17], "E3": []}, 8: {"RP": [5], "E1": [3, 15, 16], "E2": [17, 18], "E3": []}, 10: {"RP": [5], "E1": [13], "E2": [3, 17, 18], "E3": []}, 11: {"RP": [5], "E1": [6, 15, 17], "E2": [16], "E3": []}, 12: {"RP": [5], "E1": [12], "E2": [16], "E3": []}, 13: {"RP": [5], "E1": [11], "E2": [16, 18], "E3": []}, 14: {"RP": [5], "E1": [3, 4, 14, 15], "E2": [16, 18], "E3": []}, 15: {"RP": [5], "E1": [13, 15], "E2": [3, 16, 18], "E3": []}, 16: {"RP": [5], "E1": [4, 7, 14], "E2": [3, 16, 18], "E3": []}, 17: {"RP": [5], "E1": [12, 15], "E2": [16, 17], "E3": []}, 18: {"RP": [5], "E1": [3, 11, 15], "E2": [16, 17], "E3": []}, 19: {"RP": [5], "E1": [7, 14, 16, 17], "E2": [15], "E3": []}, 20: {"RP": [5], "E1": [11, 14], "E2": [15], "E3": []}, 21: {"RP": [5], "E1": [6, 11, 16], "E2": [15, 18], "E3": []}, 22: {"RP": [5], "E1": [12, 14, 16], "E2": [15, 18], "E3": []}, 23: {"RP": [5], "E1": [11, 13], "E2": [3, 15, 18], "E3": []}, 24: {"RP": [5], "E1": [9, 12], "E2": [3, 15, 18], "E3": []}, 25: {"RP": [5], "E1": [6, 8, 13], "E2": [15, 17], "E3": []}, 26: {"RP": [5], "E1": [10, 11], "E2": [15, 17], "E3": []}, 27: {"RP": [5], "E1": [9, 12, 16], "E2": [15, 17, 18], "E3": []}, 28: {"RP": [5], "E1": [11, 13, 15], "E2": [14], "E3": []}, 29: {"RP": [5], "E1": [9, 12, 15], "E2": [14], "E3": []}, 30: {"RP": [5], "E1": [6, 8, 13, 15], "E2": [14, 18], "E3": []}, 31: {"RP": [5], "E1": [10, 11, 15], "E2": [14, 18], "E3": []}, 32: {"RP": [5], "E1": [11, 13, 14, 17], "E2": [15, 16, 18], "E3": []}, 33: {"RP": [5], "E1": [8, 11, 13], "E2": [15, 16, 18], "E3": []}, 34: {"RP": [5], "E1": [6, 9, 12, 15], "E2": [14, 17], "E3": []}, 35: {"RP": [5], "E1": [11, 12, 13], "E2": [14, 17], "E3": []}, 37: {"RP": [5], "E1": [9, 11, 12], "E2": [15, 16, 17], "E3": []}, 39: {"RP": [5], "E1": [7, 9, 12, 14, 18], "E2": [6, 15], "E3": []}, 41: {"RP": [5], "E1": [10, 11, 12, 16], "E2": [13], "E3": []}, 44: {"RP": [5], "E1": [4, 11, 12, 13, 14], "E2": [6, 15, 17], "E3": []}, 47: {"RP": [5], "E1": [8, 9, 11, 12], "E2": [13, 17], "E3": []}, 50: {"RP": [5], "E1": [9, 10, 11, 12], "E2": [14, 15, 18], "E3": []}, 53: {"RP": [5], "E1": [6, 8, 9, 10, 11], "E2": [13, 16], "E3": []}, 56: {"RP": [5], "E1": [8, 9, 10, 15, 14, 17], "E2": [3, 11, 18], "E3": []}, 59: {"RP": [5], "E1": [4, 7, 9, 10, 11, 12], "E2": [13, 15], "E3": []}, 62: {"RP": [5], "E1": [7, 8, 9, 10, 11, 14], "E2": [12, 16, 18], "E3": []}, 65: {"RP": [5], "E1": [7, 8, 9, 10, 12, 13], "E2": [11, 16, 18], "E3": []}, } # Shortstop Error Chart SHORTSTOP_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 1: {"RP": [5], "E1": [18], "E2": [], "E3": []}, 2: {"RP": [5], "E1": [3, 18], "E2": [], "E3": []}, 3: {"RP": [5], "E1": [17], "E2": [], "E3": []}, 4: {"RP": [5], "E1": [17], "E2": [18], "E3": []}, 5: {"RP": [5], "E1": [3, 17], "E2": [18], "E3": []}, 6: {"RP": [5], "E1": [16], "E2": [18], "E3": []}, 7: {"RP": [5], "E1": [3, 16], "E2": [18], "E3": []}, 8: {"RP": [5], "E1": [16, 17], "E2": [18], "E3": []}, 10: {"RP": [5], "E1": [6, 17], "E2": [3, 18], "E3": []}, 12: {"RP": [5], "E1": [15], "E2": [3, 18], "E3": []}, 14: {"RP": [5], "E1": [4, 15], "E2": [17], "E3": []}, 16: {"RP": [5], "E1": [14], "E2": [17], "E3": []}, 17: {"RP": [5], "E1": [15, 16], "E2": [17], "E3": []}, 18: {"RP": [5], "E1": [15, 16, 18], "E2": [17], "E3": []}, 19: {"RP": [5], "E1": [4, 14], "E2": [17], "E3": []}, 20: {"RP": [5], "E1": [4, 15, 16], "E2": [17], "E3": []}, 21: {"RP": [5], "E1": [6, 15], "E2": [17], "E3": []}, 22: {"RP": [5], "E1": [6, 15], "E2": [17, 18], "E3": []}, 23: {"RP": [5], "E1": [3, 13], "E2": [17, 18], "E3": []}, 24: {"RP": [5], "E1": [4, 6, 15], "E2": [17, 18], "E3": []}, 25: {"RP": [5], "E1": [4, 13], "E2": [17, 18], "E3": []}, 26: {"RP": [5], "E1": [12], "E2": [17, 18], "E3": []}, 27: {"RP": [5], "E1": [3, 12], "E2": [17, 18], "E3": []}, 28: {"RP": [5], "E1": [6, 15, 16], "E2": [3, 17, 18], "E3": []}, 29: {"RP": [5], "E1": [11], "E2": [3, 17, 18], "E3": []}, 30: {"RP": [5], "E1": [4, 12], "E2": [3, 17, 18], "E3": []}, 31: {"RP": [5], "E1": [4, 6, 15, 16], "E2": [3, 17, 18], "E3": []}, 32: {"RP": [5], "E1": [13, 15], "E2": [3, 17, 18], "E3": []}, 33: {"RP": [5], "E1": [13, 15], "E2": [16], "E3": []}, 34: {"RP": [5], "E1": [13, 15, 18], "E2": [16], "E3": []}, 36: {"RP": [5], "E1": [13, 15, 17], "E2": [16], "E3": []}, 38: {"RP": [5], "E1": [13, 14], "E2": [16], "E3": []}, 40: {"RP": [5], "E1": [11, 15], "E2": [16, 18], "E3": []}, 42: {"RP": [5], "E1": [12, 14], "E2": [16, 18], "E3": []}, 44: {"RP": [5], "E1": [8, 13], "E2": [16, 18], "E3": []}, 48: {"RP": [5], "E1": [6, 12, 15], "E2": [3, 18, 18], "E3": []}, 52: {"RP": [5], "E1": [11, 13, 18], "E2": [16, 17], "E3": []}, 56: {"RP": [5], "E1": [11, 12, 18], "E2": [16, 17], "E3": []}, 60: {"RP": [5], "E1": [7, 11, 14], "E2": [15], "E3": []}, 64: {"RP": [5], "E1": [6, 9, 12], "E2": [15, 18], "E3": []}, 68: {"RP": [5], "E1": [9, 12, 14], "E2": [15, 18], "E3": []}, 72: {"RP": [5], "E1": [6, 11, 13, 15], "E2": [4, 16, 17], "E3": []}, 76: {"RP": [5], "E1": [9, 12, 13], "E2": [15, 17], "E3": []}, 80: {"RP": [5], "E1": [4, 11, 12, 13], "E2": [15, 17], "E3": []}, 84: {"RP": [5], "E1": [10, 11, 12], "E2": [3, 15, 17], "E3": []}, 88: {"RP": [5], "E1": [9, 11, 12, 16], "E2": [14], "E3": []}, } # Pitcher Error Chart PITCHER_ERROR_CHART: dict[int, dict[str, list[int]]] = { 0: {"RP": [5], "E1": [], "E2": [], "E3": []}, 4: {"RP": [5], "E1": [14], "E2": [18], "E3": []}, 6: {"RP": [5], "E1": [3, 13], "E2": [18], "E3": []}, 7: {"RP": [5], "E1": [3, 12], "E2": [18], "E3": []}, 8: {"RP": [5], "E1": [6, 15, 16, 17], "E2": [3, 18], "E3": []}, 10: {"RP": [5], "E1": [11, 15], "E2": [3, 18], "E3": []}, 11: {"RP": [5], "E1": [12, 15, 16], "E2": [3, 18], "E3": []}, 12: {"RP": [5], "E1": [6, 12, 15], "E2": [3, 18], "E3": []}, 13: {"RP": [5], "E1": [11, 13], "E2": [17], "E3": []}, 14: {"RP": [5], "E1": [7, 13, 14], "E2": [17], "E3": []}, 15: {"RP": [5], "E1": [4, 11, 12], "E2": [17], "E3": []}, 16: {"RP": [5], "E1": [4, 9, 12, 16], "E2": [17], "E3": []}, 17: {"RP": [5], "E1": [3, 6, 11, 12], "E2": [17], "E3": []}, 18: {"RP": [5], "E1": [11, 12, 14], "E2": [17], "E3": []}, 19: {"RP": [5], "E1": [6, 9, 12, 15], "E2": [17, 18], "E3": []}, 20: {"RP": [5], "E1": [6, 10, 11, 15], "E2": [17, 18], "E3": []}, 21: {"RP": [5], "E1": [7, 11, 13, 14], "E2": [17, 18], "E3": []}, 22: {"RP": [5], "E1": [8, 12, 13, 14], "E2": [17, 18], "E3": []}, 23: {"RP": [5], "E1": [10, 11, 12, 16], "E2": [17, 18], "E3": []}, 24: {"RP": [5], "E1": [10, 11, 12, 15], "E2": [17, 18], "E3": []}, 26: {"RP": [5], "E1": [9, 12, 13, 14, 15], "E2": [3, 17, 18], "E3": []}, 27: {"RP": [5], "E1": [10, 11, 12, 13], "E2": [3, 17, 18], "E3": []}, 28: {"RP": [5], "E1": [9, 10, 11, 12], "E2": [3, 17, 18], "E3": []}, 30: {"RP": [5], "E1": [3, 10, 11, 12, 13, 15], "E2": [16], "E3": []}, 31: {"RP": [5], "E1": [10, 11, 12, 13, 14], "E2": [16], "E3": []}, 33: {"RP": [5], "E1": [3, 8, 10, 11, 12, 13], "E2": [16], "E3": []}, 34: {"RP": [5], "E1": [9, 10, 11, 12, 13], "E2": [16, 18], "E3": []}, 35: {"RP": [5], "E1": [9, 10, 11, 12, 14, 15], "E2": [16, 18], "E3": []}, 36: {"RP": [5], "E1": [3, 4, 6, 7, 9, 10, 11, 12], "E2": [16, 18], "E3": []}, 38: {"RP": [5], "E1": [6, 8, 10, 11, 12, 13, 15], "E2": [16, 18], "E3": []}, 39: {"RP": [5], "E1": [6, 7, 8, 9, 10, 12, 13], "E2": [3, 16, 18], "E3": []}, 40: {"RP": [5], "E1": [4, 6, 9, 10, 11, 12, 13, 15], "E2": [3, 16, 18], "E3": []}, 42: {"RP": [5], "E1": [7, 9, 10, 11, 12, 13, 14], "E2": [3, 16, 18], "E3": []}, 43: {"RP": [5], "E1": [6, 7, 8, 9, 10, 12, 13, 14], "E2": [3, 16, 18], "E3": []}, 44: {"RP": [5], "E1": [3, 7, 8, 9, 10, 11, 12, 13], "E2": [16, 17], "E3": []}, 46: {"RP": [5], "E1": [6, 8, 9, 10, 11, 12, 13, 15], "E2": [16, 17, 18], "E3": []}, 47: {"RP": [5], "E1": [7, 8, 9, 10, 11, 12, 13, 15], "E2": [16, 17, 18], "E3": []}, 48: {"RP": [5], "E1": [7, 8, 9, 10, 11, 12, 13, 14], "E2": [16, 17, 18], "E3": []}, 50: {"RP": [5], "E1": [7, 8, 9, 10, 11, 12, 13, 14], "E2": [15, 17], "E3": []}, 51: {"RP": [5], "E1": [7, 8, 9, 10, 11, 12, 13, 14], "E2": [15, 16], "E3": []}, } # ============================================================================ # HOLDING RUNNER RESPONSIBILITY CHART # ============================================================================ def get_fielders_holding_runners( runner_bases: list[int], batter_handedness: str ) -> list[str]: """ Determine which fielders are responsible for holding runners. Used to determine if G2#/G3# results should convert to SI2. Args: runner_bases: List of bases with runners (e.g., [1, 3] for R1 and R3) batter_handedness: 'L' or 'R' Returns: List of position codes responsible for holds (e.g., ['1B', 'SS']) """ if not runner_bases: return [] holding_positions = [] mif_vs_batter = "2B" if batter_handedness.lower() == "r" else "SS" if 1 in runner_bases: holding_positions.append("1B") holding_positions.append(mif_vs_batter) if 2 in runner_bases and mif_vs_batter not in holding_positions: holding_positions.append(mif_vs_batter) if 3 in runner_bases: holding_positions.append("3B") return holding_positions # ============================================================================ # ERROR CHART LOOKUP HELPER # ============================================================================ def get_error_chart_for_position(position: str) -> dict[int, dict[str, list[int]]]: """ Get error chart for a specific position. Args: position: Position code (P, C, 1B, 2B, 3B, SS, LF, CF, RF) Returns: Error chart dict Raises: ValueError: If position not recognized """ charts = { "P": PITCHER_ERROR_CHART, "C": CATCHER_ERROR_CHART, "1B": FIRST_BASE_ERROR_CHART, "2B": SECOND_BASE_ERROR_CHART, "3B": THIRD_BASE_ERROR_CHART, "SS": SHORTSTOP_ERROR_CHART, "LF": LF_RF_ERROR_CHART, "RF": LF_RF_ERROR_CHART, "CF": CF_ERROR_CHART, } if position not in charts: raise ValueError(f"Unknown position: {position}") return charts[position]