Spaces:
Runtime error
Runtime error
File size: 7,966 Bytes
1cc60af c145eab 1cc60af c145eab 1cc60af c145eab d26e0de c145eab 1cc60af d26e0de c145eab 1cc60af c145eab 1cc60af c145eab 1cc60af c145eab 1cc60af d26e0de 1cc60af c145eab 1cc60af d26e0de 1cc60af c145eab 1cc60af c145eab 1cc60af c145eab 1cc60af c145eab 1cc60af d26e0de 1cc60af c145eab 1cc60af c145eab d26e0de 1cc60af c145eab 1cc60af d26e0de 1cc60af d26e0de 1cc60af d26e0de 1cc60af d26e0de |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
import pandas as pd
from gr.components.combat import CombatComponent
from assets.constant import ATTR_TYPE_TRANSLATE
# from gr.scripts.bonuses import Bonuses
# from gr.scripts.consumables import Consumables
from gr.scripts.top import Parser
from gr.scripts.equipments import Equipments
from gr.scripts.recipes import Recipes
from gr.scripts.talents import Talents
from utils.analyzer import analyze_records
import gradio as gr
FULL_SPACE = "\u3000"
BUFF_CONCAT = ":"
class Detail:
records: pd.DataFrame = pd.DataFrame()
skill: str = ""
status_set: list = []
@property
def current_records(self):
records = self.records
if self.skill:
records = records[records.skill == self.skill]
if self.status_set:
for buff in self.status_set:
column, stack = buff.split(BUFF_CONCAT)
records = records[records[column] == int(stack)]
return records
@property
def available_status(self):
status_set = []
records = self.current_records
for column in records.columns:
if "#" not in column:
continue
for stack in records[column].unique():
if not stack:
continue
status_set.append(f"{column}{BUFF_CONCAT}{stack:.0f}")
return status_set
def attribute_content(display_attrs, attribute):
content = []
for attr, name in display_attrs.items():
value = getattr(attribute, attr)
if isinstance(value, int):
content.append(name.ljust(10, FULL_SPACE) + str(value))
else:
content.append(name.ljust(10, FULL_SPACE) + f"{value * 100:.2f}%")
return "\n".join(content)
def summary_content(records, total_damage):
content = {}
group_records = records.groupby("skill_name")
sum_expected_damage = group_records.expected_damage.sum()
mean_critical_strike = group_records.critical_strike.mean()
for skill_name, count in group_records.skill_name.count().items():
critical_strike = mean_critical_strike[skill_name]
critical_count = critical_strike * count
hit = 1 - critical_strike
hit_count = count - critical_strike
expected_damage = sum_expected_damage[skill_name]
content[expected_damage] = (
[f"{skill_name}/{count}",
f"{hit_count:.2f}/{hit * 100:.2f}%", f"{critical_count:.2f}/{critical_strike * 100:.2f}%",
f"{expected_damage:.2f}/{expected_damage / total_damage:.2f}%"]
)
content = [content[k] for k in sorted(content, reverse=True)]
return content
def gradient_content(records, attribute, total_damage):
content = []
for attr in attribute.grad_attrs:
gradient = records[attr].sum() / total_damage - 1
content.append(ATTR_TYPE_TRANSLATE[attr].ljust(10, FULL_SPACE) + f"{gradient * 100:.2f}")
return "\n".join(content)
def detail_content(records):
damage_detail = "\n".join([
"统计数量".ljust(10) + f"{len(records)}",
"命中伤害".ljust(10) + f"{records.damage.mean():.0f}",
"会心伤害".ljust(10) + f"{records.critical_damage.mean():.0f}",
"期望伤害".ljust(10) + f"{records.expected_damage.mean():.0f}",
"实际伤害".ljust(10) + f"{records.actual_damage.mean():.0f}",
"期望会心".ljust(10) + f"{records.critical_strike.mean() * 100:.2f}%",
"实际会心".ljust(10) + f"{records.actual_critical_strike.mean() * 100:.2f}%"
])
# damage_gradient = gradient_content(records, attribute, records.expected_damage.sum())
return damage_detail
def timeline_content(records):
columns = [column for column in records.columns if "#" in column]
return records[["time", "skill"] + columns].rename(columns={"time": "时间", "skill": "技能"})
def combat_script(
parser: Parser,
talents: Talents, recipes: Recipes, equipments: Equipments,
# consumables: Consumables, bonuses: Bonuses
combat_component: CombatComponent,
):
detail = Detail()
def formulate(target_level, duration):
combat_update = {}
school = parser.current_school
attribute = school.attribute()
attribute.target_level = target_level
for attr, value in equipments.attrs.items():
setattr(attribute, attr, getattr(attribute, attr) + value)
combat_update[combat_component.init_attribute] = gr.update(
value=attribute_content(school.display_attrs, attribute)
)
# for attr, value in consumables.attrs.items():
# setattr(attribute, attr, getattr(attribute, attr) + value)
equipment_gains = [school.gains[gain] for gain in equipments.gains]
talent_gains = [school.talent_gains[school.talent_encoder[talent]] for talent in talents.gains]
recipe_gains = [
school.recipe_gains[skill][recipe]
for i, skill in enumerate(school.recipe_gains)
for recipe in recipes.gains[i]
]
gains = equipment_gains + talent_gains + recipe_gains # + bonuses.gains
for gain in gains:
gain.add(attribute, school.skills, school.buffs)
combat_update[combat_component.final_attribute] = gr.update(
value=attribute_content(school.display_attrs, attribute)
)
records = analyze_records(parser, duration, attribute)
for gain in gains:
gain.sub(attribute, school.skills, school.buffs)
total_damage = records.expected_damage.sum()
combat_update[combat_component.dps] = gr.update(value=f"{total_damage / duration:.0f}")
combat_update[combat_component.gradient] = gradient_content(records, attribute, total_damage)
combat_update[combat_component.summary] = summary_content(records, total_damage)
detail.records = records
combat_update[combat_component.skill_select] = gr.update(choices=list(records.skill.unique()))
if detail.current_records.empty:
detail.status_set = []
records = detail.current_records
combat_update[combat_component.status_select] = gr.update(choices=detail.available_status)
combat_update[combat_component.damage_detail] = gr.update(value=detail_content(records), visible=True)
combat_update[combat_component.damage_timeline] = gr.update(value=timeline_content(records), visible=True)
return combat_update
combat_component.formulate.click(
formulate,
[combat_component.target_level, combat_component.combat_duration],
[combat_component.init_attribute, combat_component.final_attribute,
combat_component.dps, combat_component.gradient, combat_component.summary,
combat_component.skill_select, combat_component.status_select,
combat_component.damage_detail, combat_component.damage_timeline]
)
def skill_changed(skill):
detail.skill = skill
if detail.current_records.empty:
detail.status_set = []
records = detail.current_records
return gr.update(choices=detail.available_status), detail_content(records), timeline_content(records)
combat_component.skill_select.change(
skill_changed, combat_component.skill_select,
[combat_component.status_select, combat_component.damage_detail, combat_component.damage_timeline]
)
def status_changed(status_set):
detail.status_set = status_set
records = detail.current_records
if records.empty:
return gr.update(visible=False), gr.update(visible=False)
return (gr.update(value=detail_content(records), visible=True),
gr.update(value=timeline_content(records), visible=True))
combat_component.status_select.change(
status_changed, combat_component.status_select,
[combat_component.damage_detail, combat_component.damage_timeline]
)
|