115 lines
4.5 KiB
Python
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()
|