import json import platform from .numeric import numeric from .kemono import clean_skill_string, calculate_stats, fill_miracle, get_awaken_materials, get_skill_materials from .endpoints.item import Kingdom_Item from .endpoints.items import Kingdom_Items from .endpoints.update import Kingdom_Update from .endpoints.friend import Kingdom_Friend from .endpoints.friends import Kingdom_Friends #element 1-orange 2-blue 3-green #showSkillType 1-control 2-guard 3-heal 4-support 5-assault 6-aoe class Database: processed_friends = {} item_stages = {} def __init__(self, api) -> None: app = api.app if "Kingdom" in app.databases: del app.databases["Kingdom"] self.reload_data() app.databases["Kingdom"] = self api.add_resource(Kingdom_Friend, "/Kingdom/Friend/") api.add_resource(Kingdom_Friends, "/Kingdom/Friends") api.add_resource(Kingdom_Item, "/Kingdom/Item/") api.add_resource(Kingdom_Items, "/Kingdom/Items") api.add_resource(Kingdom_Update, "/Kingdom/Update") def reload_data(self): if platform.system() == "Windows": NUMERICPATH = "H:\\Apache\\Katworks\\KF\\assets\\Kingdom1\\NumericData" else: NUMERICPATH = "/var/www/html/Katworks/KF/assets/Kingdom1/NumericData" self.kfk_drop = numeric(NUMERICPATH +"/Drop.num", 0) self.kfk_combo = numeric(NUMERICPATH +"/Combo.num", 0) self.kfk_skill = numeric(NUMERICPATH +"/Skill.num", 0) self.kfk_equip = numeric(NUMERICPATH +"/Equip.num", 0) self.kfk_kemono = numeric(NUMERICPATH +"/Kemono.num", 0) self.kfk_stages = numeric(NUMERICPATH +"/Stage.num", 0) self.kfk_drop_group = numeric(NUMERICPATH +"/DropGroup.num", 0) self.kfk_trust_attri = numeric(NUMERICPATH +"/TrustAttri.num", 0) self.kfk_kemono_skill = numeric(NUMERICPATH +"/KemonoSkill.num", 0) self.kfk_kemono_power = numeric(NUMERICPATH +"/KemonoPower.num", 0) self.kfk_kemono_waken = numeric(NUMERICPATH +"/KemonoWaken.num", 0) self.kfk_en_item = numeric(NUMERICPATH + "/en/Item.ntxt", 1) self.kfk_en_equip = numeric(NUMERICPATH + "/en/Equip.ntxt", 1) self.kfk_en_skill = numeric(NUMERICPATH + "/en/Skill.ntxt", 1) self.kfk_en_combo = numeric(NUMERICPATH + "/en/Combo.ntxt", 1) self.kfk_en_kemono = numeric(NUMERICPATH + "/en/Kemono.ntxt", 1) self.kfk_en_kemono_WkPaDc = numeric(NUMERICPATH + "/en/KemonoWkPaDc.ntxt", 1) self.kfk_en_kemono_power = numeric(NUMERICPATH + "/en/KemonoPower.ntxt", 1) self.kfk_en_kemono_waken = numeric(NUMERICPATH + "/en/KemonoWaken.ntxt", 1) self.kfk_en_kemono_garden = numeric(NUMERICPATH + "/en/KemonoGarden.ntxt", 1) self.kfk_en_str = numeric(NUMERICPATH + "/en/Str.ntxt", 1) self.process_friends() self.process_stages() def process_friends(self): self.processed_friends = {} for friend_id in self.kfk_kemono.indexed_data: if friend_id > 19000: continue friend = self.kfk_kemono.get(friend_id) friend["comboSkill"] = "" combo_friends = [] for entry in friend["combo"]: combo = self.kfk_combo.get(entry) if combo is not None: combo_en = self.kfk_en_combo.get(combo["comboSkill"]) friend["comboSkill"] = {"name":combo_en["comboName"], "desc":combo_en["desc"]} for combo_friend_id in combo["comboKemono"]: combo_friend = self.kfk_en_kemono.get(combo_friend_id) if combo_friend is not None and "name" in combo_friend: combo_friends.append(combo_friend["name"]) else: combo_friends.append(combo_friend_id) friend["combo"] = combo_friends limit_breaks = [] for bk_value in self.kfk_kemono_power.indexed_data.values(): if len(limit_breaks) == 5: break if(bk_value["kemonosn"] == friend_id): if bk_value["effectType1"] == 0: pass if bk_value["effectType1"] == 1 or bk_value["effectType1"] == 3: lb = self.kfk_en_kemono_power.get(friend_id * 100 + bk_value["powerlevel"]) if "name" in lb: limit_breaks.append({"name": lb["name"], "desc": lb["describe"]}) else: limit_breaks.append({"name": None, "desc": lb["describe"]}) if bk_value["effectType1"] == 2: raise Exception() if bk_value["effectType1"] == 4: lb = self.kfk_en_kemono_WkPaDc.get(bk_value['effectParam1'][0] * 100) if lb is None: lb = {"name": None, "describe": None} limit_breaks.append({"name": lb["name"], "desc": clean_skill_string(lb["describe"])}) habits = [] for habit in friend["habitSn"]: hbt = self.kfk_en_kemono_WkPaDc.get(habit*100) if hbt is None: hbt = {"name": None, "describe": None} habits.append({"name":hbt["name"], "desc":hbt["describe"]}) for i in range (3): if len(habits) < i+1: habits.append({"name":None, "desc":None}) awakens = [] max_levels = [] for i in range(3): awaken_id = friend_id * 100 + i awaken = self.kfk_kemono_waken.get(awaken_id) awaken1 = self.kfk_en_kemono_waken.get(awaken_id) if awaken1 == None: awaken1 = {"describe":"missing", "brilliance":"missing"} if awaken != None and awaken1 != None: awaken["en"] = awaken1 awakens.append(awaken) max_levels.append(awaken["levelmax"]) def validateValue(obj, valName): if obj[valName] is None: obj[valName] = {"name": "", "desc": ""} if "desc" not in obj[valName]: obj[valName]["desc"] = None friend["name"] = self.kfk_en_kemono.get(friend_id)["name"] ele = friend["element"] friend["color"] = "Orange" if ele == 1 else "Green" if ele == 2 else "Blue" if ele == 3 else "Error" ele = friend["showSkillType"] friend["role"] = "Control" if ele == 1 else "Guard" if ele == 2 else "Healer" if ele == 3 else "Support" if ele == 4 else "Assault" if ele == 5 else "Assault (AOE)" if ele == 6 else "Error" friend["maxLvl"] = max_levels friend["awakenings"] = awakens friend["maxAwaken"] = max_awaken = len(awakens)-1 friend["base_stats"] = calculate_stats(friend, 0, 1) friend["max_stats"] = calculate_stats(friend, max_awaken, friend["maxLvl"][max_awaken], trust_percent=100, trustAttri= next((e for e in self.kfk_trust_attri.indexed_data.values() if e["kemonoSn"] == friend_id), None)) friend["max_miracle"] = 13 if friend["star"] == 6 or friend["star"] == 5 else 12 if friend["star"] == 4 else 11 friend["collisionSkill"] = self.kfk_en_skill.get(friend["collisionSkill"]) friend["gardenSpec1"] = self.kfk_en_kemono_garden.get(friend["gardenSpec1"]) friend["gardenSpec2"] = self.kfk_en_kemono_garden.get(friend["gardenSpec2"]) friend["gardenSpec3"] = self.kfk_en_kemono_garden.get(friend["gardenSpec3"]) friend["describe"] = self.kfk_en_str.get(friend["describe"]) friend["attack"] = self.kfk_en_skill.get(friend["attack"]) skill_id = friend["skill"] friend["skill"] = self.kfk_en_skill.get(skill_id) friend["skill1"] = self.kfk_en_skill.get(skill_id+1) if max_awaken >= 1 else None friend["skill2"] = self.kfk_en_skill.get(skill_id+2) if max_awaken >= 2 else None friend["spAttack"] = self.kfk_en_skill.get(friend["spAttack"]) friend["habitSn"] = habits friend["limitBreaks"] = limit_breaks validateValue(friend, "collisionSkill") validateValue(friend, "attack") validateValue(friend, "skill") validateValue(friend, "skill1") validateValue(friend, "skill2") validateValue(friend, "spAttack") self.processed_friends[friend_id] = friend def process_stages(self): self.item_stages = {} for stage in self.kfk_stages.indexed_data.values(): merged_array = stage["fastReward2_star3"] + stage["fastReward3_star3"] if len(merged_array) > 0: for drop_sn in merged_array: drop = self.kfk_drop.get(drop_sn) for drop_group_sn in drop["groupSn"]: drop_group = self.kfk_drop_group.get(drop_group_sn) if drop_group["type"] == 2 or drop_group["type"] == 1: #materials item_id = drop_group["content"] item = self.kfk_en_item.get(item_id) if item_id not in self.item_stages: self.item_stages[item_id] = [] if stage not in self.item_stages[item_id]: self.item_stages[item_id].append(stage) def get_chara(self, id : int): #return next(lambda f: f["sn"] == id, None) if id not in self.processed_friends: return None else: friend = self.processed_friends[id] data = { "id": friend["sn"], "name": friend["name"], "element": friend["color"], "role": friend["role"], "star": friend["star"], "combo": friend["combo"], "comboSkill": friend["comboSkill"], "describe": friend["describe"], "awakenings": friend["awakenings"], "max_miracle": friend["max_miracle"], "stats": { "base":friend["base_stats"], "max":friend["max_stats"] }, "collision": {"name": friend["collisionSkill"]["name"], "desc": clean_skill_string(friend["collisionSkill"]["desc"])}, "attack": {"name": friend["attack"]["name"], "desc": clean_skill_string(friend["attack"]["desc"])}, "skills":[ {"name": friend["skill"]["name"], "desc": fill_miracle(friend["skill"]["desc"], miracle_level=friend["max_miracle"], kemono_level=friend["maxLvl"][-1])}, {"name": friend["skill1"]["name"], "desc": fill_miracle(friend["skill1"]["desc"], miracle_level=friend["max_miracle"], kemono_level=friend["maxLvl"][-1])}, {"name": friend["skill2"]["name"], "desc": fill_miracle(friend["skill2"]["desc"], miracle_level=friend["max_miracle"], kemono_level=friend["maxLvl"][-1])}, ], "garden":[ friend["gardenSpec1"], friend["gardenSpec2"], friend["gardenSpec3"], ], "habits":[ {"name": friend["habitSn"][0]["name"], "desc": clean_skill_string(friend["habitSn"][0]["desc"])}, {"name": friend["habitSn"][1]["name"], "desc": clean_skill_string(friend["habitSn"][1]["desc"])}, {"name": friend["habitSn"][2]["name"], "desc": clean_skill_string(friend["habitSn"][2]["desc"])} ], "limitBreaks":[ friend["limitBreaks"][0], friend["limitBreaks"][1], friend["limitBreaks"][2], friend["limitBreaks"][3], friend["limitBreaks"][4] ], "awakenMaterials": get_awaken_materials(friend, self.kfk_kemono_waken, self.kfk_en_item), "skillMaterials": get_skill_materials(friend, self.kfk_kemono_skill, self.kfk_en_item) } return json.dumps(data, sort_keys=False, indent=1, ensure_ascii=False) def get_chara_wiki(self, id : int): friend = self.processed_friends[id] lines = [] lines.append("|name=" + friend["name"]) #stats lines.append("|maxLvls=" + ",".join([str(lvl) for lvl in friend["maxLvl"]])) lines.append("|hp=" + str(friend["base_stats"]["hp"])) lines.append("|maxhp=" + str(friend["max_stats"]["hp"])) lines.append("|atk=" + str(friend["base_stats"]["patk"])) lines.append("|maxatk=" + str(friend["max_stats"]["patk"])) lines.append("|satk=" + str(friend["base_stats"]["satk"])) lines.append("|maxsatk=" + str(friend["max_stats"]["satk"])) lines.append("|pdef=" + str(friend["base_stats"]["pdef"])) lines.append("|maxpdef=" + str(friend["max_stats"]["pdef"])) lines.append("|sdef=" + str(friend["base_stats"]["sdef"])) lines.append("|maxsdef=" + str(friend["max_stats"]["sdef"])) lines.append("|speed=" + str(friend["base_stats"]["speed"])) lines.append("|maxspeed=" + str(friend["max_stats"]["speed"])) #skills lines.append("|collisionSkill=" + friend["collisionSkill"]["name"]) lines.append("|collisionSkillEffect=" + clean_skill_string(friend["collisionSkill"]["desc"])) lines.append("|attack=" + friend["attack"]["name"]) lines.append("|attackEffect=" + clean_skill_string(friend["attack"]["desc"])) lines.append("|skill1=" + friend["skill"]["name"]) lines.append("|skill1Effect=" + clean_skill_string(friend["skill"]["desc"])) lines.append("|skill2=" + friend["skill1"]["name"]) lines.append("|skill2Effect=" + clean_skill_string(friend["skill1"]["desc"])) lines.append("|skill3=" + friend["skill2"]["name"]) lines.append("|skill3Effect=" + clean_skill_string(friend["skill2"]["desc"])) lines.append("|spAttack=" + friend["spAttack"]["name"]) lines.append("|spAttackEffect=" + clean_skill_string(friend["spAttack"]["desc"])) for i in range(0,5): lb = friend['limitBreaks'][i] if lb["name"] is None: lines.append(f"|b{i+1}={friend['limitBreaks'][i]['desc']}") else: lines.append(f"|b{i+1}='''{friend['limitBreaks'][i]['name']}'''\n{friend['limitBreaks'][i]['desc']}") return "\n".join(lines) def get_item(self, id): result = {"item": None, "stages": []} item = self.kfk_en_item.get(id) if item is None: return result result["item"] = item if id in self.item_stages: result["stages"] = self.item_stages[id] return json.dumps(result, sort_keys=False, indent=1, ensure_ascii=False)