Release Healer Man 0.1.46
This commit is contained in:
1 parent
f82daf1c13
commit
9ff574ac0b
73 files changed
+33486
-174
No files matched your search
@@ -0,0 +1,122 @@
|
||||
import unittest
|
||||
|
||||
from scripts.balance_lab import (
|
||||
aggregate_class_abilities,
|
||||
aggregate_class_specs,
|
||||
automatic_parties,
|
||||
random_party,
|
||||
search_bosses,
|
||||
tuning_label,
|
||||
)
|
||||
|
||||
|
||||
class BalanceLabControllerTests(unittest.TestCase):
|
||||
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_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_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_rate_and_absolute_damage_taken(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,
|
||||
"damageTaken": 120, "absorbs": 25, "deathEvents": 0,
|
||||
},
|
||||
{
|
||||
"partyConfigurationId": "wow-party-002", "elapsedSeconds": 20,
|
||||
"damage": 400, "bossDamage": 360, "healing": 900,
|
||||
"damageTaken": 330, "absorbs": 50, "deathEvents": 1,
|
||||
},
|
||||
]})
|
||||
self.assertEqual(len(rows), 1)
|
||||
self.assertEqual(rows[0]["dtps"], 15)
|
||||
self.assertEqual(rows[0]["totalDamageTaken"], 450)
|
||||
|
||||
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"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user