def _set_enchanted_stat_type(self, substats): """ Set rune enchantment type if the rune is enchanted """ for stat in substats: if RuneParser.is_stat_enchanted(stat): self.enchant_type, self.enchant_value = RuneParser.get_rune_stat( stat) break
def apply_enchantgems(self, enchantgems, runes): """ :param enchantgems: usable enchantgems :type enchantgems: list :param runes: usable runes :type runes: list :return: list of runes and corresponding enchantgems :rtype: list """ self.sort_enchants(enchantgems) checked_and_failed = RuneParser.create_substats_map(default=False) for enchantgem in enchantgems: is_applicable = False # By pass if the subs checked and failed if checked_and_failed[enchantgem.stat]: continue for rune in runes: if self.enchant_applicable(enchantgem, rune): # If it's applicable, format and append the result self.enchant_result += self.format_applying_enchant( enchantgem, rune) is_applicable = True # If this kind of rune is unusable, skip those which has same stats, and is same or even lower grade if not is_applicable: checked_and_failed[enchantgem.stat] = True
def parse_runes_and_monster_eff(self): """ Parse runes and calculate monster efficiency """ monster_eff_map = {} monster_exp_eff_map = {} for rune in self.rune_list: current_rune = Rune(rune) current_rune.set_loc( RuneParser.get_rune_user(self.monster_list, rune["occupied_id"])) self.parsed_rune_result += self.format_rune(current_rune) # Can't calculate monster eff if the rune is not equipped on a monster if not current_rune.is_equiped(): continue monster_eff_map = self.increment_dict_value( monster_eff_map, current_rune.loc, current_rune.efficiency) monster_exp_eff_map = self.increment_dict_value( monster_exp_eff_map, current_rune.loc, current_rune.exp_efficiency_15) # Average it for monster in monster_eff_map: average_real_efficiency = monster_eff_map[monster] / 6 average_expected_efficiency = monster_exp_eff_map[monster] / 6 self.monster_eff_result.append((monster, average_real_efficiency, average_expected_efficiency))
def _get_RTA_rune_owner(self, rune_id): if rune_id not in self.RTA_rune_owner_mapping: return "" user_id = self.RTA_rune_owner_mapping[rune_id] user = RuneParser.get_rune_user(self.monster_list, user_id) return "(RTA) {}".format(user)
def _compute_innate_score(self): """ Get partial efficiency score based on innate stat """ if self.innate is not None: return self.innate[1] / RuneParser.max_roll_substats( self.innate[0]) else: return 0
def get_combined_rune_owner(self, rune): rta_rune_user = self._get_RTA_rune_owner(rune["rune_id"]) rune_user = RuneParser.get_rune_user(self.monster_list, rune["occupied_id"]) if rta_rune_user == "": return rune_user elif rune_user == "": return rta_rune_user else: return "{} | {}".format(rta_rune_user, rune_user)
def construct_rune_inventory(self): """ Parse runes and sort by rune set """ inventory = self.rune_inventory for rune in self.rune_list: current_rune = Rune(rune) rune_user = RuneParser.get_rune_user( self.monster_list, rune["occupied_id"]) current_rune.set_loc(rune_user) inventory = self.group_item_by_set(current_rune, inventory)
def __init__(self, rune): self.slot = rune['slot_no'] self.stars = RuneParser.get_rune_stars(rune['class']) self.level = rune['upgrade_curr'] self.grade = RuneParser.get_rune_grade_shorten(rune['rank']) self.base_grade = RuneParser.get_rune_grade_shorten(rune['extra']) self.main = RuneParser.get_rune_stat(rune['pri_eff']) self.is_ancient = None self.rune_set = None self.loc = None self.innate = None self.substats = [] self.substats_without_grind = [] self.dense_substats = None self.grind_values = None self.enchant_type = None self.enchant_value = 0 self.efficiency = 0 self.exp_efficiency_12 = 0 self.exp_efficiency_15 = 0 self.efficiency_without_grind = 0 self.exp_efficiency_12_without_grind = 0 self.exp_efficiency_15_without_grind = 0 self.enhance_coeficient = 0 self._set_is_ancient(rune['rank']) self._set_rune_set(rune['set_id']) self._set_innate_if_available(rune['prefix_eff']) self._set_substats_with_grind(rune['sec_eff']) self._set_substats_without_grind(rune['sec_eff']) self._set_dense_substats() self._set_grind_values(rune['sec_eff']) self._set_enchanted_stat_type(rune['sec_eff']) self._set_rune_efficiencies() self._set_rune_expected_efficiency() self._set_rune_enhance_coeficient()
def _compute_roll_score(self, include_grind): """ Calculate partial rune efficiency based on roll (substat upgrade) results :param include_grind: if set True, applied grind will be counted in efficiency :type include_grind: bool :return: partial rune efficiency :rtype: float """ substats_roll_score = 0 substats = self._select_substats_according_to(include_grind) for substat in substats: substats_roll_score += substat[1] / RuneParser.max_roll_substats( substat[0]) return substats_roll_score
def apply_grindstones(self, grindstones, runes): """ :param grindstones: usable grindstones :type grindstones: list :param runes: usable runes :type runes: list :return: list of runes and corresponding grindstones :rtype: list """ self.sort_grindstones_and_runes(grindstones, runes) is_checked_and_failed_table = RuneParser.create_substats_map( default=False) for grindstone in grindstones: is_applicable = False # By pass if the subs checked and failed if is_checked_and_failed_table[grindstone.stat]: continue for rune in runes: if self.grind_applicable(grindstone, rune): # If it's applicable, format and append the result self.grind_result += self.format_applying_grind( grindstone, rune) # Make sure same substat from a rune won't get grind using two different grind self.virtually_apply_grind(grindstone, rune) is_applicable = True # Continue to next grindstone break # If this kind of rune is unusable, skip those which has same stats, same or even lower grade if not is_applicable: is_checked_and_failed_table[grindstone.stat] = True
def _set_grind_value(self, stat): sub_type = RuneParser.get_rune_stat_type(stat) if DataMappingCollection.is_substat_grindable(sub_type): self.grind_values[sub_type] = RuneParser.get_rune_grind_value(stat)
def _set_grind_values(self, substats): self.grind_values = RuneParser.create_substats_map() for stat in substats: self._set_grind_value(stat)
def _set_dense_substats(self): self.dense_substats = RuneParser.substats_to_dense_form(self.substats)
def _set_innate_if_available(self, innate): self.innate = RuneParser.get_rune_stat(innate) self._remove_innate_if_none()
def _compute_primary_score(self): """ Get partial efficiency score based on primary stat """ return self.main[1] / RuneParser.max_roll(self.main[0])
def _set_substats_without_grind(self, rune_substat_raw): for raw_substat in rune_substat_raw: substat = RuneParser.get_rune_stat_without_grind(raw_substat) self.substats_without_grind.append(substat)
def _set_rune_set(self, set_id): _ancient = "Ancient-" if self.is_ancient else "" _set = RuneParser.get_rune_set(set_id) self.rune_set = "{}{}".format(_ancient, _set)