Files
DirtyLeague_Bot/test_resolution_scaling.py

115 lines
4.5 KiB
Python

"""
Automated unit & integration test for Resolution Scaling and Relative Coordinates.
Tests that detect_state, OCR, and chest scanning correctly recognize all screens
at 4K, 1440p, 1080p, and 720p resolutions.
"""
import json
import os
import cv2
from bot_core import DirtyLeagueBot, GameState
import ocr_utils
CONFIG_PATH = "config.json"
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
config = json.load(f)
bot = DirtyLeagueBot(config)
SNAPSHOTS = {
"IN_GAME (Battle)": ("assets/battle_screen_snapshot.png", GameState.IN_GAME),
"IN_GAME (Leave)": ("assets/leave_screen_snapshot.png", GameState.IN_GAME),
"TOWER_LOBBY": ("assets/tower_screen_snapshot.png", GameState.TOWER_LOBBY),
"DEFEAT_SCREEN": ("assets/defeat_screen_snapshot.png", GameState.DEFEAT_SCREEN),
"VICTORY_SCREEN": ("assets/victory_screen_snapshot.png", GameState.VICTORY_SCREEN),
"NO_FREE_SLOTS": ("assets/no_free_slots_snapshot.png", GameState.NO_FREE_SLOTS_SCREEN),
"CHEST_OPEN": ("assets/chest_reward_snapshot.png", GameState.CHEST_OPEN_SCREEN),
}
RESOLUTIONS = [
("Native 4K", 3840, 2050),
("2K / 1440p", 2560, 1366),
("FullHD / 1080p", 1920, 1025),
("HD / 720p", 1280, 683),
]
def run_tests():
print("=" * 70)
print(" TESTING RESOLUTION INDEPENDENCE AND RELATIVE COORDINATES ")
print("=" * 70)
total_passed = 0
total_tests = 0
for res_name, target_w, target_h in RESOLUTIONS:
print(f"\n--- Testing at resolution: {res_name} ({target_w}x{target_h}) ---")
for screen_name, (path, expected_state) in SNAPSHOTS.items():
if not os.path.exists(path):
print(f"[SKIP] Snapshot not found: {path}")
continue
orig_img = cv2.imread(path)
if orig_img.shape[1] == target_w and orig_img.shape[0] == target_h:
tested_frame = orig_img
else:
tested_frame = cv2.resize(orig_img, (target_w, target_h), interpolation=cv2.INTER_AREA)
detected = bot.detect_state(tested_frame)
is_ok = (detected == expected_state)
status_str = "PASS" if is_ok else "FAIL"
print(f" [{status_str}] {screen_name:18} -> detected: {detected.value:20} (expected: {expected_state.value})")
total_tests += 1
if is_ok:
total_passed += 1
# Test OCR across resolutions
print("\n--- Testing OCR Scaling ---")
tower_4k = cv2.imread("assets/tower_screen_snapshot.png")
for res_name, target_w, target_h in RESOLUTIONS:
frame = cv2.resize(tower_4k, (target_w, target_h), interpolation=cv2.INTER_AREA)
trophies = ocr_utils.ocr_reader.read_trophies(frame)
is_ok = (trophies == (1925, 2300))
status_str = "PASS" if is_ok else "FAIL"
print(f" [{status_str}] {res_name:14} Trophies OCR: {trophies} (expected: (1925, 2300))")
total_tests += 1
if is_ok:
total_passed += 1
# Test Crown Chest Badge (5/5) across resolutions
print("\n--- Testing Crown Chest 5/5 Badge Scaling ---")
crown_4k = cv2.imread("assets/tower_lobby_crown_filled.png")
for res_name, target_w, target_h in RESOLUTIONS:
frame = cv2.resize(crown_4k, (target_w, target_h), interpolation=cv2.INTER_AREA)
crown = ocr_utils.ocr_reader.read_crown_chest(frame)
is_ok = (crown == (5, 5))
status_str = "PASS" if is_ok else "FAIL"
print(f" [{status_str}] {res_name:14} Crown 5/5 Badge: {crown} (expected: (5, 5))")
total_tests += 1
if is_ok:
total_passed += 1
# Test Bottom Chests Grid across resolutions
print("\n--- Testing Bottom Chests Grid Scanning ---")
for res_name, target_w, target_h in RESOLUTIONS:
frame = cv2.resize(tower_4k, (target_w, target_h), interpolation=cv2.INTER_AREA)
chests = bot.scan_bottom_chests(frame)
statuses = {k: v["status"] for k, v in chests.items()}
# Slots 1 and 3 are OPEN on tower_screen_snapshot
is_ok = (statuses[1] == "OPEN" and statuses[3] == "OPEN")
status_str = "PASS" if is_ok else "FAIL"
print(f" [{status_str}] {res_name:14} Chests: {statuses}")
total_tests += 1
if is_ok:
total_passed += 1
print("\n" + "=" * 70)
print(f" TOTAL RESULT: {total_passed} / {total_tests} tests passed ({total_passed / total_tests * 100:.1f}%)")
print("=" * 70)
assert total_passed == total_tests, f"Only {total_passed}/{total_tests} tests passed!"
if __name__ == "__main__":
run_tests()