import unittest from scripts.balance_lab import ( aggregate_class_abilities, aggregate_class_specs, automatic_parties, coverage_parties, random_party, random_party_capacity, readiness_eligible_builds, resolve_build, runtime_session_command, search_bosses, tuning_label, ) class BalanceLabControllerTests(unittest.TestCase): def test_class_spec_selector_prefers_the_named_default_build(self) -> None: builds = [ {"id": "fire-default", "classId": "mage", "className": "Mage", "role": "damage", "specialization": "Fire", "label": "Mage Fire Playerbots", "defaultTalentBuild": True}, {"id": "fire-alt", "classId": "mage", "className": "Mage", "role": "damage", "specialization": "Fire", "label": "Mage Fire Executable", "defaultTalentBuild": False}, ] self.assertEqual(resolve_build("mage:fire", builds)["id"], "fire-default") def test_headless_runtime_uses_the_no_watch_vite_mode(self) -> None: command = runtime_session_command("wow", 40) self.assertEqual(command[1:3], ["--mode", "balance-lab"]) self.assertEqual(command[-4:], ["--source", "wow", "--level", "40"]) def test_random_party_is_repeatable_and_complete(self) -> None: builds = [ {"id": "tank-a", "role": "tank"}, {"id": "tank-b", "role": "tank"}, {"id": "healer-a", "role": "healer"}, {"id": "healer-b", "role": "healer"}, *({"id": f"damage-{index}", "role": "damage"} for index in range(6)), ] first = random_party(builds, 17) second = random_party(builds, 17) self.assertEqual(first, second) self.assertEqual([member["role"] for member in first], [ "tank", "healer", "damage", "damage", "damage", ]) self.assertEqual(len({member["id"] for member in first[2:]}), 3) def test_random_party_uses_named_default_profiles(self) -> None: builds = [ {"id": "tank-default", "role": "tank", "defaultTalentBuild": True}, {"id": "tank-alt", "role": "tank", "defaultTalentBuild": False}, {"id": "healer-default", "role": "healer", "defaultTalentBuild": True}, {"id": "healer-alt", "role": "healer", "defaultTalentBuild": False}, *({"id": f"damage-default-{index}", "role": "damage", "defaultTalentBuild": True} for index in range(3)), *({"id": f"damage-alt-{index}", "role": "damage", "defaultTalentBuild": False} for index in range(3)), ] party = random_party(builds, 17) self.assertTrue(all(member["defaultTalentBuild"] for member in party)) def test_tuning_flags_keep_both_sides_of_the_median(self) -> None: self.assertEqual(tuning_label(1.51), "very high") self.assertEqual(tuning_label(1.25), "high") self.assertEqual(tuning_label(1.0), "baseline") self.assertEqual(tuning_label(0.75), "low") self.assertEqual(tuning_label(0.49), "very low") self.assertEqual(tuning_label(None), "no baseline") def test_automatic_parties_are_unique_repeatable_and_source_isolated(self) -> None: builds = [] for source in ("wow", "coa"): builds.extend([ {"id": f"{source}-tank-a", "source": source, "role": "tank"}, {"id": f"{source}-tank-b", "source": source, "role": "tank"}, {"id": f"{source}-healer-a", "source": source, "role": "healer"}, {"id": f"{source}-healer-b", "source": source, "role": "healer"}, *({"id": f"{source}-damage-{index}", "source": source, "role": "damage"} for index in range(6)), ]) first = automatic_parties(builds, ("wow", "coa"), 4, 29) second = automatic_parties(builds, ("wow", "coa"), 4, 29) self.assertEqual(first, second) self.assertEqual(len(first), 8) self.assertEqual(len({configuration["id"] for configuration in first}), 8) for configuration in first: self.assertTrue(all(member["source"] == configuration["source"] for member in configuration["party"])) self.assertEqual([member["role"] for member in configuration["party"]], [ "tank", "healer", "damage", "damage", "damage", ]) def test_automatic_parties_cap_to_the_unique_ready_pool(self) -> None: builds = [ {"id": "ready-tank", "source": "wow", "role": "tank", "defaultTalentBuild": True}, {"id": "ready-healer", "source": "wow", "role": "healer", "defaultTalentBuild": True}, *({"id": f"ready-damage-{index}", "source": "wow", "role": "damage", "defaultTalentBuild": True} for index in range(3)), {"id": "testing-tank-alt", "source": "wow", "role": "tank", "defaultTalentBuild": False}, ] self.assertEqual(random_party_capacity(builds), 1) configurations = automatic_parties(builds, ("wow",), 10, 29) self.assertEqual(len(configurations), 1) self.assertEqual(len({member["id"] for member in configurations[0]["party"]}), 5) def test_coverage_parties_include_every_build_with_minimum_unique_parties(self) -> None: builds = [ {"id": "tank-a", "source": "wow", "role": "tank"}, {"id": "tank-b", "source": "wow", "role": "tank"}, {"id": "healer-a", "source": "wow", "role": "healer"}, {"id": "healer-b", "source": "wow", "role": "healer"}, *({"id": f"damage-{index}", "source": "wow", "role": "damage"} for index in range(7)), ] first = coverage_parties(builds, ("wow",), None, 19) second = coverage_parties(builds, ("wow",), None, 19) self.assertEqual(first, second) self.assertEqual(len(first), 3) covered = {member["id"] for configuration in first for member in configuration["party"]} self.assertEqual(covered, {build["id"] for build in builds}) signatures = {tuple(member["id"] for member in configuration["party"]) for configuration in first} self.assertEqual(len(signatures), 3) for configuration in first: self.assertEqual([member["role"] for member in configuration["party"]], [ "tank", "healer", "damage", "damage", "damage", ]) self.assertEqual(len({member["id"] for member in configuration["party"]}), 5) def test_specific_coverage_uses_fillers_but_guarantees_selected_builds(self) -> None: builds = [ {"id": "tank-a", "source": "wow", "role": "tank"}, {"id": "tank-b", "source": "wow", "role": "tank"}, {"id": "healer-a", "source": "wow", "role": "healer"}, {"id": "healer-b", "source": "wow", "role": "healer"}, *({"id": f"damage-{index}", "source": "wow", "role": "damage"} for index in range(5)), ] selected = ["tank-a", "tank-b", "damage-4"] configurations = coverage_parties(builds, ("wow",), selected, 7) self.assertEqual(len(configurations), 2) observed = [member["id"] for configuration in configurations for member in configuration["party"]] covered = set(observed) self.assertTrue(set(selected).issubset(covered)) self.assertTrue(all(observed.count(build_id) == 1 for build_id in selected)) def test_readiness_filters_every_source_and_beta_requires_opt_in(self) -> None: builds = [ {"id": "ready-tank", "source": "wow", "specializationId": "warrior:protection"}, {"id": "beta-damage", "source": "wow", "specializationId": "paladin:retribution"}, {"id": "testing-damage", "source": "wow", "specializationId": "priest:shadow"}, {"id": "rom-damage", "source": "rom", "specializationId": "mage:primary"}, ] policy = {"config": {"statuses": { "warrior:protection": "ready", "paladin:retribution": "beta", "priest:shadow": "needs-testing", }}} self.assertEqual( [build["id"] for build in readiness_eligible_builds(builds, policy, False)], ["ready-tank"], ) self.assertEqual( [build["id"] for build in readiness_eligible_builds(builds, policy, True)], ["ready-tank", "beta-damage"], ) def test_targeted_needs_testing_build_uses_ready_fillers(self) -> None: builds = [ {"id": "ready-tank", "source": "wow", "role": "tank", "specializationId": "warrior:protection", "readinessStatus": "ready", "defaultTalentBuild": True}, {"id": "ready-healer", "source": "wow", "role": "healer", "specializationId": "priest:discipline", "readinessStatus": "ready", "defaultTalentBuild": True}, {"id": "ready-hunter", "source": "wow", "role": "damage", "specializationId": "hunter:marksmanship", "readinessStatus": "ready", "defaultTalentBuild": True}, {"id": "ready-mage", "source": "wow", "role": "damage", "specializationId": "mage:fire", "readinessStatus": "ready", "defaultTalentBuild": True}, {"id": "ready-rogue", "source": "wow", "role": "damage", "specializationId": "rogue:assassination", "readinessStatus": "ready", "defaultTalentBuild": True}, {"id": "testing-shadow", "source": "wow", "role": "damage", "specializationId": "priest:shadow", "readinessStatus": "needs-testing", "defaultTalentBuild": True}, ] eligible = readiness_eligible_builds(builds, None, False) parties = coverage_parties(builds, ("wow",), ["testing-shadow"], 13, eligible) self.assertEqual(len(parties), 1) ids = [member["id"] for member in parties[0]["party"]] self.assertIn("testing-shadow", ids) self.assertTrue(all(build_id == "testing-shadow" or build_id.startswith("ready-") for build_id in ids)) def test_targeted_non_wow_build_uses_ready_wow_fillers(self) -> None: ready = [ {"id": "ready-tank", "source": "wow", "role": "tank", "readinessStatus": "ready", "defaultTalentBuild": True}, {"id": "ready-healer", "source": "wow", "role": "healer", "readinessStatus": "ready", "defaultTalentBuild": True}, *( {"id": f"ready-damage-{index}", "source": "wow", "role": "damage", "readinessStatus": "ready", "defaultTalentBuild": True} for index in range(3) ), ] target = {"id": "coa-target", "source": "coa", "role": "damage", "readinessStatus": "needs-testing", "defaultTalentBuild": True} parties = coverage_parties([*ready, target], ("coa",), ["coa-target"], 21, ready) ids = [member["id"] for member in parties[0]["party"]] self.assertIn("coa-target", ids) self.assertEqual(sum(build_id.startswith("ready-") for build_id in ids), 4) def test_boss_search_matches_name_dungeon_key_and_source(self) -> None: bosses = [ {"key": "gundrak/eck", "name": "Eck the Ferocious", "dungeonTitle": "Gundrak", "category": "wow"}, {"key": "abbey/duke", "name": "Duke", "dungeonTitle": "Forsaken Abbey", "category": "rom"}, ] self.assertEqual([boss["key"] for boss in search_bosses("ferocious", bosses)], ["gundrak/eck"]) self.assertEqual([boss["key"] for boss in search_bosses("forsaken", bosses)], ["abbey/duke"]) self.assertEqual([boss["key"] for boss in search_bosses("rom", bosses)], ["abbey/duke"]) def test_class_spec_aggregate_keeps_damage_and_healing_received_metrics(self) -> None: key = ("wow", "priest-holy", "priest", "Priest", "Holy", "healer") rows = aggregate_class_specs({key: [ { "partyConfigurationId": "wow-party-001", "elapsedSeconds": 10, "damage": 200, "bossDamage": 180, "healing": 500, "healingReceived": 300, "damageTaken": 120, "absorbs": 25, "deathEvents": 0, }, { "partyConfigurationId": "wow-party-002", "elapsedSeconds": 20, "damage": 400, "bossDamage": 360, "healing": 900, "healingReceived": 600, "damageTaken": 330, "absorbs": 50, "deathEvents": 1, }, ]}) self.assertEqual(len(rows), 1) self.assertEqual(rows[0]["dtps"], 15) self.assertEqual(rows[0]["totalDamageTaken"], 450) self.assertEqual(rows[0]["hpsReceived"], 30) self.assertEqual(rows[0]["totalHealingReceived"], 900) def test_ability_aggregate_keeps_used_and_available_but_unused_rows(self) -> None: class_key = ("wow", "mage-fire", "mage", "Mage", "Fire", "damage") class_runs = [ {"partyConfigurationId": "party-1", "bossKey": "boss-1", "elapsedSeconds": 10, "damage": 100}, {"partyConfigurationId": "party-2", "bossKey": "boss-2", "elapsedSeconds": 10, "damage": 100}, ] base = { "abilityName": "Fireball", "icon": "/fireball.png", "categories": ["damage"], "cooldownSeconds": 0, "available": True, "casts": 0, "hits": 0, "rawDamage": 0, "effectiveDamage": 0, "rawHealing": 0, "effectiveHealing": 0, "overheal": 0, "absorbs": 0, } groups = { (*class_key, "mage-fireball"): [ {**base, "partyConfigurationId": "party-1", "bossKey": "boss-1", "elapsedSeconds": 10, "used": True, "casts": 1, "hits": 1, "rawDamage": 120, "effectiveDamage": 100}, {**base, "partyConfigurationId": "party-2", "bossKey": "boss-2", "elapsedSeconds": 10, "used": False}, ], (*class_key, "mage-unused-blast"): [ {**base, "abilityName": "Unused Blast", "partyConfigurationId": "party-1", "bossKey": "boss-1", "elapsedSeconds": 10, "used": False}, {**base, "abilityName": "Unused Blast", "partyConfigurationId": "party-2", "bossKey": "boss-2", "elapsedSeconds": 10, "used": False}, ], } rows = aggregate_class_abilities(groups, {class_key: class_runs}) by_id = {row["abilityId"]: row for row in rows} self.assertEqual(by_id["mage-fireball"]["activeRuns"], 1) self.assertEqual(by_id["mage-fireball"]["usageRate"], 0.5) self.assertEqual(by_id["mage-fireball"]["damageShare"], 0.5) self.assertTrue(by_id["mage-unused-blast"]["unusedAvailable"]) def test_missing_profile_action_requires_repeated_uncommitted_decisions(self) -> None: class_key = ("wow", "mage-fire", "mage", "Mage", "Fire", "damage") class_runs = [{"partyConfigurationId": "party-1", "bossKey": "boss-1", "elapsedSeconds": 10, "damage": 0}] base = { "abilityName": "Fireball", "icon": "", "categories": ["damage"], "cooldownSeconds": 0, "rotationProfileId": "mage:fire", "rotationPriority": 5, "expectedUsage": "profile", "available": True, "used": False, "casts": 0, "hits": 0, "rawDamage": 0, "effectiveDamage": 0, "rawHealing": 0, "effectiveHealing": 0, "overheal": 0, "absorbs": 0, "partyConfigurationId": "party-1", "bossKey": "boss-1", "elapsedSeconds": 10, } once = aggregate_class_abilities({(*class_key, "fireball"): [{**base, "rotationDecisions": 1}]}, {class_key: class_runs})[0] repeated = aggregate_class_abilities({(*class_key, "fireball"): [{**base, "rotationDecisions": 3}]}, {class_key: class_runs})[0] self.assertEqual(once["status"], "unused") self.assertEqual(repeated["status"], "missing-profile-action") if __name__ == "__main__": unittest.main()