""" Controlled single-cycle integration test: Runs 1 full cycle starting from TOWER_LOBBY: 1. Detect TOWER_LOBBY 2. Read trophies and chests 3. Enter Fight 4. Handle IN_GAME until outcome (Victory / Defeat / Surrender) 5. Handle Result screen (Collect / OK / Remove chest if no slots) 6. Verify clean return to TOWER_LOBBY """ import json import logging import sys import time from bot_core import DirtyLeagueBot, GameState logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", handlers=[logging.StreamHandler(sys.stdout)] ) def run_single_cycle_test(timeout_sec: int = 180): with open("config.json", "r", encoding="utf-8") as f: config = json.load(f) bot = DirtyLeagueBot(config) logging.info("=== Starting Controlled Full Cycle Test ===") logging.info(f"Timeout: {timeout_sec}s. Press Ctrl+C to abort.") start_time = time.time() initial_lobby_confirmed = False in_game_reached = False result_handled = False cycle_complete = False while time.time() - start_time < timeout_sec: frame = bot.wm.capture_frame(client_only=True) # 1. Global offer popup check if bot.check_and_dismiss_offer_popup(frame): time.sleep(1.0) continue state = bot.detect_state(frame) if state != bot.state: logging.info(f"[FSM TRANSITION] {bot.state.value} -> {state.value}") bot.state = state if state == GameState.TOWER_LOBBY: if not initial_lobby_confirmed: logging.info("[STEP 1] Confirmed TOWER_LOBBY start.") initial_lobby_confirmed = True bot.handle_lobby(frame) elif in_game_reached and result_handled: logging.info("[SUCCESS] Successfully completed full cycle and returned to TOWER_LOBBY!") cycle_complete = True break else: # If we are still in lobby before entering game, try handle_lobby again bot.handle_lobby(frame) elif state == GameState.IN_GAME: in_game_reached = True bot.handle_in_game(frame) elif state == GameState.VICTORY_SCREEN: logging.info("[STEP] Handling VICTORY_SCREEN...") bot.handle_victory(frame) result_handled = True elif state == GameState.DEFEAT_SCREEN: logging.info("[STEP] Handling DEFEAT_SCREEN...") bot.handle_defeat(frame) result_handled = True elif state == GameState.NO_FREE_SLOTS_SCREEN: logging.info("[STEP] Handling NO_FREE_SLOTS_SCREEN...") bot.handle_no_free_slots(frame) result_handled = True elif state == GameState.CHEST_OPEN_SCREEN: logging.info("[STEP] Handling CHEST_OPEN_SCREEN...") bot.handle_chest_open_screen(frame) elif state == GameState.MAIN_MENU: logging.info("[STEP] Handling MAIN_MENU...") bot.handle_main_menu(frame) time.sleep(bot.poll_interval) elapsed = time.time() - start_time if cycle_complete: logging.info(f"=== FULL CYCLE TEST PASSED in {elapsed:.1f}s ===") return True else: logging.warning(f"=== TEST TIMEOUT or INTERRUPTED after {elapsed:.1f}s ===") return False if __name__ == "__main__": run_single_cycle_test()