Fixed two critical bugs in Phase 3D X-Check implementation plus improved dice audit trail for better tracking. BUG #1: on_base_code Mapping Error (Sequential vs Bit Field) ============================================================ The implementation incorrectly treated on_base_code as a bit field when it is actually a sequential lookup mapping. WRONG (bit field): Code 3 (0b011) → R1 + R2 Code 4 (0b100) → R3 only CORRECT (sequential): Code 3 → R3 only Code 4 → R1 + R2 Fixed: - build_advancement_from_code() decoder (sequential mapping) - build_flyball_advancement_with_error() decoder (sequential mapping) - 13 test on_base_code values (3↔4 corrections) - Updated documentation to clarify NOT a bit field BUG #2: Table Data Not Matching Official Charts ================================================ 7 table entries in G1_ADVANCEMENT_TABLE and G2_ADVANCEMENT_TABLE did not match the official rulebook charts provided by user. Fixed table entries: - G1 Code 1, Infield In: Changed Result 3 → 2 - G1 Code 3, Normal: Changed Result 13 → 3 - G1 Code 3, Infield In: Changed Result 3 → 1 - G1 Code 4, Normal: Changed Result 3 → 13 - G1 Code 4, Infield In: Changed Result 4 → 2 - G2 Code 3, Infield In: Changed Result 3 → 1 - G2 Code 4, Normal: Changed Result 5 → 4 Also fixed 7 test expectations to match corrected tables. IMPROVEMENT: Better Dice Audit Trail ===================================== Updated _resolve_x_check() in PlayResolver to use proper dice_system.roll_fielding() instead of manual die rolling. Benefits: - All dice tracked in audit trail (roll_id, timestamp, position) - Automatic error_total calculation (no manual 3d6 addition) - Consistent with codebase patterns - Position recorded for historical analysis Testing: - All 59 X-Check advancement tests passing (100%) - All 9 PlayResolver tests passing (100%) - All table entries validated against official charts - Complete codebase scan: no bit field operations found Files modified: - backend/app/core/x_check_advancement_tables.py - backend/tests/unit/core/test_x_check_advancement_tables.py - backend/app/core/play_resolver.py - .claude/implementation/PHASE_3D_CRITICAL_FIX.md (documentation) - .claude/implementation/GROUNDBALL_CHART_REFERENCE.md (new) - .claude/implementation/XCHECK_TEST_VALIDATION.md (new) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6.3 KiB
6.3 KiB
Groundball Chart Reference - Official Source of Truth
Source: User-provided images from official rulebook charts Date Created: 2025-11-02 Purpose: Comprehensive reference for validating all groundball test expectations
GroundballResultType Reference (1-13)
1. BATTER_OUT_RUNNERS_HOLD
2. DOUBLE_PLAY_AT_SECOND - Batter out, runner on 1st out - double play! Other runners advance 1 base
3. BATTER_OUT_RUNNERS_ADVANCE
4. BATTER_SAFE_FORCE_OUT_AT_SECOND - Batter safe, runner on 1st forced out at 2nd. Other runners advance 1 base
5. HIT_TO_2B/SS - Batter out, runners advance 1 base. Hit anywhere else: batter out, runners hold
6. HIT_TO_1B/2B - Batter out, runners advance 1 base. Hit anywhere else: batter out, runners hold
7. BATTER_OUT_FORCED_ONLY - Batter out, runner holds (unless forced)
8. BATTER_OUT_FORCED_ONLY_ALT - Batter out, runner holds (unless forced)
9. LEAD_HOLDS_TRAIL_ADVANCES - Batter out, runner on 3rd holds, runner on 1st advances 1 base
10. DOUBLE_PLAY_HOME_TO_FIRST - Home to first double play, other runners advance
11. BATTER_SAFE_LEAD_OUT - Batter safe, lead runner is out, other runners advance 1 base
12. DECIDE - Hit to 1b/2b: batter is out, runners advance. Hit to 3b: batter is out, runners hold. Hit to ss/p/c: chance for DECIDE
13. CONDITIONAL_DOUBLE_PLAY - Hit to c/3b: double play at 3rd and 2nd base, batter safe. Otherwise: double play at 2nd and 1st base
G1 Chart (Groundball Type A - Fast Grounder)
Simplified View from Image #1
| Bases Occupied | Infield Normal | Infield In |
|---|---|---|
| Empty | 1 | N/A |
| 1st | 2 | 2 |
| 2nd | 12 | 12 |
| 3rd | 3 | 1 |
| 1st & 2nd | 13 | 2 |
| 1st & 3rd | 2 | 1 |
| 2nd & 3rd | 3 | 1 |
| Loaded | 2 | 10 |
Notes:
- Image #1 appears to show a simplified chart with one result per (base situation, defensive position)
- May represent GBA (Groundball A) specifically
- Need clarification: Are GBB and GBC different for G1, or is G1 always the same result?
G2 Chart (Groundball Type B - Medium Grounder)
Simplified View from Image #2
| Bases Occupied | Infield Normal | Infield In |
|---|---|---|
| Empty | 1 | N/A |
| 1st | 4 | 4 |
| 2nd | 12 | 12 |
| 3rd | 5 | 1 |
| 1st & 2nd | 4 | 4 |
| 1st & 3rd | 4 | 1 |
| 2nd & 3rd | 5 | 1 |
| Loaded | 4 | 11 |
G3 Chart (Groundball Type C - Slow Grounder)
Simplified View from Image #3
| Bases Occupied | Infield Normal | Infield In |
|---|---|---|
| Empty | 1 | N/A |
| 1st | 3 | 3 |
| 2nd | 12 | 3 |
| 3rd | 3 | DECIDE |
| 1st & 2nd | 3 | 3 |
| 1st & 3rd | 3 | 3 |
| 2nd & 3rd | 3 | DECIDE |
| Loaded | 3 | 11 |
Note: "DECIDE" in chart may map to Result 12 (DECIDE_OPPORTUNITY)
Detailed Infield Back Chart (Image #4)
This appears to be a more detailed breakdown showing GBA, GBB, GBC variations:
| Bases Occupied | GBA | GBB | GBC | Notes |
|---|---|---|---|---|
| Empty | 1 | 1 | 1 | Batter out, runners hold |
| 1st | 2 | 4 | 3 | GBA: DP. GBB: Batter safe, force out at 2nd. GBC: Batter out, advance |
| 2nd | 6 | 6 | 3 | GBA/B: Hit to right side conditional. GBC: Advance |
| 3rd | 5 | 5 | 3 | GBA/B: Hit to middle infield conditional. GBC: Advance |
| 1st & 2nd | 2 | 4 | 3 | GBA: DP. GBB: Batter safe, force. GBC: Advance |
| 1st & 3rd | 2 | 4 | 3 | Same as 1st only |
| 2nd & 3rd | 5 | 5 | 3 | GBA/B: Conditional middle IF. GBC: Advance |
| Loaded | 2 | 4 | 3 | GBA: DP. GBB: Batter safe, force. GBC: R3 holds, R1 advances |
Detailed Infield In Chart (Image #5)
| Bases Occupied | GBA | GBB | GBC | Notes |
|---|---|---|---|---|
| 3rd | 7 | 1 | 8 | Hit to 1b/2b: runners advance. Hit to 3b: hold. ss/p/c: DECIDE |
| 1st & 3rd | 7 | 9 | 8 | GBB: Lead holds, trail advances |
| 2nd & 3rd | 7 | 1 | 8 | Hit to c/3b: double play at 3rd and 2nd |
| Loaded | 10 | 11 | 11 | GBA: DP home to 1st. GBB/C: Batter safe, lead out |
Questions for Validation
-
Chart Relationship:
- Are Images #1, #2, #3 showing GBA results specifically?
- Or are they showing a simplified "most common" result?
- Do G1/G2/G3 have different results for GBA/GBB/GBC internally?
-
Mapping GBA/GBB/GBC to G1/G2/G3:
- Does G1 always use GBA column from detailed chart?
- Does G2 always use GBB column?
- Does G3 always use GBC column?
- Or is the relationship different?
-
Test Naming Convention:
- Current tests use outcome names: GROUNDBALL_A, GROUNDBALL_B, GROUNDBALL_C
- Do these map to: G1=GBA, G2=GBB, G3=GBC?
- Or to: G1/G2/G3 (which then have internal GBA/GBB/GBC logic)?
Current Understanding (To Be Validated)
Based on the code in runner_advancement.py, it appears:
- Tests use
PlayOutcome.GROUNDBALL_A/B/C - Code maps these to
gb_letter = 'A', 'B', or 'C' - Code has charts for "Infield Back" and "Infield In"
- Code selects result based on (gb_letter, base_situation, defensive_position)
Hypothesis:
- The detailed charts (Images #4 and #5) show the actual GBA/GBB/GBC breakdown
- The G1/G2/G3 simplified charts (Images #1, #2, #3) might be showing a different categorization
- OR they might be showing just one column from the detailed charts
Need clarification from user before proceeding with test fixes.
Next Steps
- ✅ Transcribe all charts (DONE)
- ⏳ Get user clarification on chart relationship
- ⏳ Map each current test to correct expected result
- ⏳ Fix all test expectations
- ⏳ Verify all 59 tests pass with correct expectations