""" Test script to simulate a complete at-bat Tests the full GameEngine flow: 1. Create game in state manager 2. Start game 3. Submit defensive decision 4. Submit offensive decision 5. Resolve play 6. Check results Author: Claude Date: 2025-10-24 """ import asyncio import sys from pathlib import Path # Add backend to path sys.path.insert(0, str(Path(__file__).parent.parent)) from uuid import uuid4 from app.core.state_manager import state_manager from app.core.game_engine import game_engine from app.database.operations import DatabaseOperations from app.models.game_models import DefensiveDecision, OffensiveDecision async def test_single_at_bat(): """Test a single at-bat flow""" print("=" * 60) print("TESTING SINGLE AT-BAT FLOW") print("=" * 60) # Create game game_id = uuid4() print(f"\n1. Creating game {game_id}...") # Create in database first db_ops = DatabaseOperations() await db_ops.create_game( game_id=game_id, league_id="sba", home_team_id=1, away_team_id=2, game_mode="friendly", visibility="public" ) # Create dummy lineups for testing # Away team lineup positions = ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF"] for i in range(1, 10): await db_ops.add_sba_lineup_player( game_id=game_id, team_id=2, # Away team player_id=100 + i, # Dummy player IDs position=positions[i-1], batting_order=i ) # Home team lineup for i in range(1, 10): await db_ops.add_sba_lineup_player( game_id=game_id, team_id=1, # Home team player_id=200 + i, # Dummy player IDs position=positions[i-1], batting_order=i ) # Then create in state manager state = await state_manager.create_game( game_id=game_id, league_id="sba", home_team_id=1, away_team_id=2 ) print(f" ✅ Game created with lineups - Status: {state.status}") # Start game print("\n2. Starting game...") state = await game_engine.start_game(game_id) print(f" ✅ Game started") print(f" Inning: {state.inning} {state.half}") print(f" Outs: {state.outs}") print(f" Status: {state.status}") # Defensive decision print("\n3. Submitting defensive decision...") def_decision = DefensiveDecision( alignment="normal", infield_depth="normal", outfield_depth="normal" ) state = await game_engine.submit_defensive_decision(game_id, def_decision) print(f" ✅ Defensive decision submitted") print(f" Pending: {state.pending_decision}") # Offensive decision print("\n4. Submitting offensive decision...") off_decision = OffensiveDecision( approach="normal" ) state = await game_engine.submit_offensive_decision(game_id, off_decision) print(f" ✅ Offensive decision submitted") print(f" Pending: {state.pending_decision}") # Resolve play print("\n5. Resolving play...") result = await game_engine.resolve_play(game_id) print(f" ✅ Play resolved!") print(f" Outcome: {result.outcome}") print(f" Description: {result.description}") print(f" AB Roll: {result.ab_roll}") print(f" Outs Recorded: {result.outs_recorded}") print(f" Runs Scored: {result.runs_scored}") print(f" Is Hit: {result.is_hit}") print(f" Is Out: {result.is_out}") # Check final state print("\n6. Checking final state...") final_state = await game_engine.get_game_state(game_id) print(f" 📊 Game State:") print(f" Inning: {final_state.inning} {final_state.half}") print(f" Outs: {final_state.outs}") print(f" Score: Away {final_state.away_score} - Home {final_state.home_score}") print(f" Runners: {len(final_state.runners)}") if final_state.runners: for runner in final_state.runners: print(f" - Runner on {runner.on_base}B") print(f" Play Count: {final_state.play_count}") print(f" Last Result: {final_state.last_play_result}") print("\n" + "=" * 60) print("✅ SINGLE AT-BAT TEST PASSED") print("=" * 60) return game_id, final_state async def test_full_inning(): """Test a complete half-inning (3 outs)""" print("\n\n") print("=" * 60) print("TESTING FULL HALF-INNING (3 OUTS)") print("=" * 60) # Create and start game game_id = uuid4() print(f"\n1. Creating and starting game {game_id}...") # Create in database first db_ops = DatabaseOperations() await db_ops.create_game( game_id=game_id, league_id="sba", home_team_id=1, away_team_id=2, game_mode="friendly", visibility="public" ) # Create dummy lineups for testing positions = ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF"] # Away team lineup for i in range(1, 10): await db_ops.add_sba_lineup_player( game_id=game_id, team_id=2, # Away team player_id=100 + i, position=positions[i-1], batting_order=i ) # Home team lineup for i in range(1, 10): await db_ops.add_sba_lineup_player( game_id=game_id, team_id=1, # Home team player_id=200 + i, position=positions[i-1], batting_order=i ) # Then create in state manager state = await state_manager.create_game( game_id=game_id, league_id="sba", home_team_id=1, away_team_id=2 ) await game_engine.start_game(game_id) print(f" ✅ Game started with lineups") at_bat_num = 1 # Keep playing until 3 outs while True: state = await game_engine.get_game_state(game_id) if state.outs >= 3: print(f"\n 🎯 3 outs reached - inning over!") break print(f"\n{at_bat_num}. At-Bat #{at_bat_num} (Inning {state.inning} {state.half}, {state.outs} outs)...") # Submit decisions def_decision = DefensiveDecision(alignment="normal") await game_engine.submit_defensive_decision(game_id, def_decision) off_decision = OffensiveDecision(approach="normal") await game_engine.submit_offensive_decision(game_id, off_decision) # Resolve result = await game_engine.resolve_play(game_id) print(f" Result: {result.description}") print(f" Roll: {result.ab_roll.check_d20} (d20)") print(f" Outs: {result.outs_recorded}, Runs: {result.runs_scored}") at_bat_num += 1 # Safety check if at_bat_num > 50: print(" ⚠️ Safety limit reached - stopping test") break # Check final state final_state = await game_engine.get_game_state(game_id) print(f"\n📊 Final State:") print(f" Inning: {final_state.inning} {final_state.half}") print(f" Total At-Bats: {at_bat_num - 1}") print(f" Score: Away {final_state.away_score} - Home {final_state.home_score}") print(f" Total Plays: {final_state.play_count}") print("\n" + "=" * 60) print("✅ FULL HALF-INNING TEST PASSED") print("=" * 60) async def main(): """Run all tests""" print("\n🎮 GAME ENGINE FLOW TESTING") print("Testing complete gameplay flow with GameEngine\n") try: # Test 1: Single at-bat await test_single_at_bat() # Test 2: Full inning await test_full_inning() print("\n\n🎉 ALL TESTS PASSED!") print("\nGameEngine is working correctly:") print(" ✅ Game lifecycle management") print(" ✅ Decision submission") print(" ✅ Play resolution with AbRoll system") print(" ✅ State management and persistence") print(" ✅ Inning advancement") print(" ✅ Score tracking") except Exception as e: print(f"\n❌ TEST FAILED: {e}") import traceback traceback.print_exc() sys.exit(1) if __name__ == "__main__": asyncio.run(main())