Formulator / utils /analyzer.py
AngoHF's picture
04.13 commit
3ed500d
raw
history blame
3.57 kB
from base.attribute import Attribute
from qt.scripts.top import School
def refresh_status(existed_buffs, buffs, attribute: Attribute, school: School):
for buff in [buff for buff in existed_buffs if buff not in buffs]:
existed_buffs.remove(buff)
buff_id, buff_level, buff_stack = buff
buff = school.buffs[buff_id]
buff.buff_level, buff.buff_stack = buff_level, buff_stack
attribute = attribute - buff
school.skills = school.skills - buff
for buff in [buff for buff in buffs if buff not in existed_buffs]:
existed_buffs.append(buff)
buff_id, buff_level, buff_stack = buff
buff = school.buffs[buff_id]
buff.buff_level, buff.buff_stack = buff_level, buff_stack
attribute = attribute + buff
school.skills = school.skills + buff
def analyze_details(record, duration: int, attribute: Attribute, school: School):
details = {}
total_damage = 0
total_gradients = {attr: 0. for attr in attribute.grad_attrs}
duration *= 1000
existed_buffs = []
for skill, status in record.items():
skill_id, skill_level = skill
skill = school.skills[skill_id]
skill.skill_level = skill_level
skill_detail = {}
details[skill.display_name] = skill_detail
for buffs, timeline in status.items():
timeline = [t for t in timeline if t < duration]
if not timeline:
continue
refresh_status(existed_buffs, buffs, attribute, school)
damage, critical_strike, critical_damage, expected_damage = skill(attribute)
gradients = analyze_gradients(skill, attribute)
total_damage += expected_damage * len(timeline)
for attr, residual_damage in gradients.items():
total_gradients[attr] += residual_damage * len(timeline)
buffs = ";".join(school.buffs[buff_id].display_name for buff_id, _, _ in buffs)
if not buffs:
buffs = "~-~-~"
skill_detail[buffs] = dict(
damage=damage,
critical_strike=critical_strike,
critical_damage=critical_damage,
expected_damage=expected_damage,
# "timeline": [round(t / 1000, 3) for t in timeline],
count=len(timeline),
gradients=gradients
)
refresh_status(existed_buffs, [], attribute, school)
for attr, residual_damage in total_gradients.items():
total_gradients[attr] = round(residual_damage / total_damage * 100, 4)
summary = analyze_summary(details)
return total_damage, total_gradients, details, summary
def analyze_summary(details):
summary = {}
for skill, skill_detail in details.items():
skill = skill.split("/")[0]
if skill not in summary:
summary[skill] = {"count": 0, "hit": 0, "critical": 0, "damage": 0}
for buff, detail in skill_detail.items():
summary[skill]["count"] += detail['count']
summary[skill]["critical"] += detail['count'] * detail['critical_strike']
summary[skill]["damage"] += detail['count'] * detail['expected_damage']
return summary
def analyze_gradients(skill, attribute):
results = {}
for attr, value in attribute.grad_attrs.items():
origin_value = getattr(attribute, attr)
setattr(attribute, attr, origin_value + value)
_, _, _, results[attr] = skill(attribute)
setattr(attribute, attr, origin_value)
return results