def group_lines_for_spell(spell_id, lines, spell_powers): total_heals = [] total_overheals = [] total_underheals = [] count_heals = [] nn_underheals = [] nn_overheals = [] nn_full_overheals = [] coefficient = sd.spell_coefficient(spell_id) base_heal = sd.spell_heal(spell_id) for i, sp in enumerate(spell_powers): data = process_lines_for_spell(lines, -sp * coefficient, base_heal) n_h, n_oh, n_f_oh, n_oh_nc, total_h, total_oh, total_h_nc, total_oh_nc = data total_heals.append(total_h / n_h) total_overheals.append(total_oh / n_h) total_underheals.append((total_h - total_oh) / n_h) count_heals.append(n_h) nn_underheals.append((n_h - n_oh) / n_h) nn_overheals.append(n_oh / n_h) nn_full_overheals.append(n_f_oh / n_h) return (total_heals, total_overheals, total_underheals, count_heals, nn_underheals, nn_overheals, nn_full_overheals)
def process_spell(spell_id, spell_lines, spell_power): base_heal = sd.spell_heal(spell_id) coeff = sd.spell_coefficient(spell_id) if base_heal == 0 or coeff == 0: return extra_heal = coeff * spell_power base_heal_fraction = base_heal / (base_heal + extra_heal) n_heal = 0 n_underheal = 0 n_overheal = 0 n_downrank = 0 n_drop_h = 0 for h, oh, crit in spell_lines: h_fraction = 1.0 - oh / h n_heal += 1 if h_fraction >= 1: n_underheal += 1 elif h_fraction <= 0: n_overheal += 1 elif h_fraction < base_heal_fraction: n_downrank += 1 else: n_drop_h += 1 return n_heal, n_underheal, n_overheal, n_downrank, n_drop_h
def process_spell(player_name, spell_id, spell_lines, spell_power=None, show=True, path=None): spell_name = sd.spell_name(spell_id) relative_underheal = [] is_crit = [] for h, oh, crit in spell_lines: relative_underheal.append(1.0 - oh / h) is_crit.append(1 if crit else 0) cast_fraction = np.linspace(0, 1, len(relative_underheal)) relative_underheal = np.array(relative_underheal) relative_underheal = np.sort(relative_underheal) # is_crit = np.array(is_crit) plt.figure(constrained_layout=True) plt.fill_between(cast_fraction, relative_underheal, label="Underheal") plt.fill_between(cast_fraction, 1, relative_underheal, label="Overheal") # add base heal line if spell-power is included base_heal = sd.spell_heal(spell_id) coeff = sd.spell_coefficient(spell_id) if spell_power and base_heal > 0 and coeff > 0: extra_heal = coeff * spell_power base_heal_fraction = base_heal / (base_heal + extra_heal) plt.axhline(base_heal_fraction, linestyle="--", color="k", label="Base heal") plt.title(f"{spell_name}, {len(spell_lines)} casts") plt.xlabel("Fraction of casts") plt.ylabel("Fraction of heal (orange overheal, blue underheal)") plt.xlim((0, 1)) plt.ylim((0, 1)) plt.legend() if path is None: path = "figs/cdf" plt.savefig(f"{path}/{player_name}_cdf_{spell_id}.png") # plt.figure(constrained_layout=True) # plt.fill_between(relative_underheal, 1 - cast_fraction, label="Underheal") # plt.fill_between(relative_underheal, 1, 1 - cast_fraction, label="Overheal") # plt.title(spell_name) # plt.ylabel("Fraction of casts") # plt.xlabel("Fraction of overheals (orange overheal, blue underheal)") # plt.xlim((0, 1)) # plt.ylim((0, 1)) # plt.legend() if show: plt.show()
def pick_spell(self, deficit, mana, h, **_): # pick spell by deficit choices = { "10917": "Flash Heal (Rank 7)", # "10916": "Flash Heal (Rank 6)", # "10915": "Flash Heal (Rank 5)", "9474": "Flash Heal (Rank 4)", # "9473": "Flash Heal (Rank 3)", # "9472": "Flash Heal (Rank 2)", # "2061": "Flash Heal (Rank 1)", # "2053": "Lesser Heal (Rank 3)", # "10965": "Greater Heal (Rank 4)", # "10964": "Greater Heal (Rank 3)", # "10963": "Greater Heal (Rank 2)", # "2060": "Greater Heal (Rank 1)", # "6064": "Heal (Rank 4)", # "6063": "Heal (Rank 3)", # "2055": "Heal (Rank 2)", # "2054": "Heal (Rank 1)", }.keys() # filter choices by mana available choices = filter( lambda sid: sd.spell_mana(sid, talents=self.talents) < mana, choices) # convert to healing heals = map( lambda sid: (sid, sd.spell_heal(sid) + sd.spell_coefficient(sid) * h), choices) # pick max heal with small amount of overhealing heals = filter(lambda x: 0.80 * x[1] < -deficit, heals) try: spell_id, heal = max(heals, key=lambda x: x[1]) except ValueError: return 0, 0, 0 mana = sd.spell_mana(spell_id) cast_time = 1.5 if "Flash" in sd.spell_name(spell_id) else 2.5 return heal, mana, cast_time
def process_spell(spell_id, spell_lines, heal_increase=0.0): spell_name = sd.spell_name(spell_id) n_heals = 0 n_crits = 0 raw_heals = [] for h, _, crit in spell_lines: n_heals += 1 if crit: n_crits += 1 h /= 1.5 raw_heals.append(h) raw_heals = np.array(raw_heals) raw_heals = filter_out_reduced_healing(raw_heals) sample_size = len(raw_heals) median_heal = np.median(raw_heals) crit_rate = n_crits / n_heals # Include heal increase from Improved Renew or Spiritual Healing spell_heal = sd.spell_heal(spell_id) spell_heal *= 1.0 + heal_increase if spell_heal == 0: # Unknown or 0 base heal, cannot estimate +heal extra_heal = 0.0 else: extra_heal = median_heal - spell_heal coefficient = sd.spell_coefficient(spell_id) if coefficient == 0: # Unknown or 0 coefficient, cannot estimate +heal est_plus_heal = 0 else: est_plus_heal = extra_heal / coefficient print( f" {spell_id:>5s} {spell_name:>26s} {sample_size:3d} {spell_heal:+7.1f} {median_heal:+7.1f}" f" {extra_heal:+6.1f} {est_plus_heal:+7.1f} {crit_rate:5.1%}") return est_plus_heal, n_heals, n_crits
def pick_spell(self, deficit, mana, h, **_): # pick spell by deficit spell_id = self.spell_id base_heal = sd.spell_heal(spell_id) coef = sd.spell_coefficient(spell_id) spell_mana = sd.spell_mana(spell_id, talents=self.talents) if spell_mana > mana: # print(f"{spell_mana} > {mana}") # could not cast return 0, 0, 0 heal = base_heal + h * coef # include random variation and crit maybe? cast_time = 1.5 if "Flash" in sd.spell_name(spell_id) else 2.5 return heal, spell_mana, cast_time