diff --git a/fix_data.py b/fix_data.py index d539cb2..f3964f1 100644 --- a/fix_data.py +++ b/fix_data.py @@ -2,12 +2,14 @@ import asyncio from res_func.avatar import fix_avatar_config, fetch_text_map from res_func.light_cone import fix_light_cone_config +from res_func.relic import fetch_relic_config async def main(): text_map_data = await fetch_text_map() await fix_avatar_config(text_map_data) await fix_light_cone_config() + await fetch_relic_config(text_map_data) if __name__ == '__main__': diff --git a/func/fetch_relics.py b/func/fetch_relics.py index 69be725..3980ab3 100644 --- a/func/fetch_relics.py +++ b/func/fetch_relics.py @@ -52,6 +52,7 @@ async def dump_relics(path: Path): async def read_relics(path: Path): + all_relics.clear() async with aiofiles.open(path, "r", encoding="utf-8") as f: data = ujson.loads(await f.read()) for monster in data: diff --git a/models/enums.py b/models/enums.py index 28ce262..6f4e7aa 100644 --- a/models/enums.py +++ b/models/enums.py @@ -82,3 +82,48 @@ class PropType(str, Enum): Heal = "其他-治疗加成" OtherCritical = "其他-效果命中" Charge = "其他-能量充能效率" + + +class RelicAffix(str, Enum): + AttackAddedRatio: str = "AttackAddedRatio" + """ 攻击力 百分比 """ + AttackDelta: str = "AttackDelta" + """ 攻击力 """ + BreakDamageAddedRatioBase: str = "BreakDamageAddedRatioBase" + """ 击破特攻 """ + CriticalChanceBase: str = "CriticalChanceBase" + """ 暴击率 百分比 """ + CriticalDamageBase: str = "CriticalDamageBase" + """ 暴击伤害 百分比 """ + DefenceAddedRatio: str = "DefenceAddedRatio" + """ 防御力 百分比 """ + DefenceDelta: str = "DefenceDelta" + """ 防御力 """ + FireAddedRatio: str = "FireAddedRatio" + """ 火属性伤害提高 百分比 """ + HPAddedRatio: str = "HPAddedRatio" + """ 生命值 百分比 """ + HPDelta: str = "HPDelta" + """ 生命值 """ + HealRatioBase: str = "HealRatioBase" + """ 治疗量加成 百分比""" + IceAddedRatio: str = "IceAddedRatio" + """ 冰属性伤害提高 百分比 """ + ImaginaryAddedRatio: str = "ImaginaryAddedRatio" + """ 虚数属性伤害提高 百分比 """ + PhysicalAddedRatio: str = "PhysicalAddedRatio" + """ 物理属性伤害提高 百分比 """ + QuantumAddedRatio: str = "QuantumAddedRatio" + """ 量子属性伤害提高 百分比 """ + SpeedDelta: str = "SpeedDelta" + """ 速度 """ + SPRatioBase: str = "SPRatioBase" + """ 能量恢复效率 百分比 """ + StatusProbabilityBase: str = "StatusProbabilityBase" + """ 效果命中 百分比 """ + StatusResistanceBase: str = "StatusResistanceBase" + """ 效果抵抗 百分比 """ + ThunderAddedRatio: str = "ThunderAddedRatio" + """ 雷属性伤害提高 百分比 """ + WindAddedRatio: str = "WindAddedRatio" + """ 风属性伤害提高 百分比 """ diff --git a/models/relic_affix.py b/models/relic_affix.py new file mode 100644 index 0000000..3a6ba01 --- /dev/null +++ b/models/relic_affix.py @@ -0,0 +1,46 @@ +from decimal import Decimal +from typing import Optional, Dict + +from pydantic import BaseModel, root_validator + +from models.enums import RelicAffix + + +class SingleRelicAffix(BaseModel): + id: int + property: RelicAffix + base_value: float + level_value: Optional[float] = None + step_value: Optional[float] = None + is_main: bool + max_step: Optional[int] = None + + def get_value(self, level_or_step: int) -> float: + add_value = Decimal(self.level_value if self.is_main else self.base_value) + return float(Decimal(self.base_value) + add_value * Decimal(level_or_step)) + + +class RelicAffixAll(BaseModel): + id: int + main_affix_group: int + sub_affix_group: int + max_level: int + """ 最大等级 """ + main_affix: Dict[str, SingleRelicAffix] + """ 主词条 """ + sub_affix: Dict[str, SingleRelicAffix] + """ 副词条 """ + + @root_validator(pre=True) + def transform_dicts(cls, values): + for data in ["main_affix", "sub_affix"]: + affix = values.get(data) + if affix: + new_affix = {} + for key, value in affix.items(): + if isinstance(value, dict): + new_affix[key] = SingleRelicAffix(**value) + else: + new_affix[key] = value + values[data] = new_affix + return values diff --git a/res_func/relic.py b/res_func/relic.py new file mode 100644 index 0000000..3b62634 --- /dev/null +++ b/res_func/relic.py @@ -0,0 +1,108 @@ +from pathlib import Path +from typing import List, Dict + +import aiofiles +import ujson + +from models.enums import RelicAffix +from func.fetch_relics import read_relics, dump_relics, all_relics +from res_func.client import client +from res_func.url import relic_config, relic_main_affix_config, relic_sub_affix_config, relic_set_config +from models.relic_affix import RelicAffixAll, SingleRelicAffix + +final_datas: List[RelicAffixAll] = [] +final_datas_map: Dict[str, RelicAffixAll] = {} + + +async def fetch_all_relic(): + print("开始获取遗器配置") + relic_data_req = await client.get(relic_config) + relic_data = relic_data_req.json() + for key, value in relic_data.items(): + relic_affix_all = RelicAffixAll( + id=int(key), + main_affix_group=value["MainAffixGroup"], + sub_affix_group=value["SubAffixGroup"], + max_level=value["MaxLevel"], + main_affix={}, + sub_affix={}, + ) + final_datas.append(relic_affix_all) + final_datas_map[key] = relic_affix_all + print("遗器配置获取完毕") + + +async def fetch_main_affix(): + print("开始获取遗器主词条配置") + main_affix_req = await client.get(relic_main_affix_config) + main_affix_data = main_affix_req.json() + main_affix_groups_map: Dict[str, Dict[str, SingleRelicAffix]] = {} + for key, value in main_affix_data.items(): + data: Dict[str, SingleRelicAffix] = {} + for key2, value2 in value.items(): + data[key2] = SingleRelicAffix( + id=value2["AffixID"], + property=RelicAffix(value2["Property"]), + base_value=value2["BaseValue"]["Value"], + level_value=value2["LevelAdd"]["Value"], + is_main=True, + ) + main_affix_groups_map[key] = data + for final_data in final_datas: + final_data.main_affix = main_affix_groups_map[str(final_data.main_affix_group)] + print("遗器主词条配置获取完毕") + + +async def fetch_sub_affix(): + print("开始获取遗器副词条配置") + sub_affix_req = await client.get(relic_sub_affix_config) + sub_affix_data = sub_affix_req.json() + sub_affix_groups_map: Dict[str, Dict[str, SingleRelicAffix]] = {} + for key, value in sub_affix_data.items(): + data: Dict[str, SingleRelicAffix] = {} + for key2, value2 in value.items(): + data[key2] = SingleRelicAffix( + id=value2["AffixID"], + property=RelicAffix(value2["Property"]), + base_value=value2["BaseValue"]["Value"], + step_value=value2["StepValue"]["Value"], + is_main=False, + max_step=value2["StepNum"], + ) + sub_affix_groups_map[key] = data + for final_data in final_datas: + final_data.sub_affix = sub_affix_groups_map[str(final_data.sub_affix_group)] + print("遗器副词条配置获取完毕") + + +async def fix_set_id(text_map_data: Dict[str, str]): + print("开始修复遗器套装ID") + set_req = await client.get(relic_set_config) + set_data = set_req.json() + set_data_map: Dict[str, int] = {} + for key, value in set_data.items(): + set_data_map[text_map_data[str(value["SetName"]["Hash"])]] = value["SetID"] + await read_relics(Path("data") / "relics.json") + for relic_set in all_relics: + if set_id := set_data_map.get(relic_set.name): + relic_set.id = set_id + else: + print(f"套装{relic_set.name}没有找到对应的ID") + await dump_relics(Path("data") / "relics.json") + print("遗器套装ID修复完毕") + + +async def dump_relic_config(path: Path): + final_data = [data.dict() for data in final_datas] + final_data.sort(key=lambda x: x["id"]) + async with aiofiles.open(path, "w", encoding="utf-8") as f: + await f.write(ujson.dumps(final_data, indent=4, ensure_ascii=False)) + + +async def fetch_relic_config(text_map_data: Dict[str, str]): + await fetch_all_relic() + await fetch_main_affix() + await fetch_sub_affix() + data_path = Path("data") + await dump_relic_config(data_path / "relic_config.json") + await fix_set_id(text_map_data) diff --git a/res_func/url.py b/res_func/url.py index 0ad2229..ad70d21 100644 --- a/res_func/url.py +++ b/res_func/url.py @@ -5,6 +5,10 @@ base_data_url = base64.b64decode( ).decode("utf-8") avatar_config = f"{base_data_url}ExcelOutput/AvatarConfig.json" text_map = f"{base_data_url}TextMap/TextMapCN.json" +relic_config = f"{base_data_url}ExcelOutput/RelicConfig.json" +relic_main_affix_config = f"{base_data_url}ExcelOutput/RelicMainAffixConfig.json" +relic_sub_affix_config = f"{base_data_url}ExcelOutput/RelicSubAffixConfig.json" +relic_set_config = f"{base_data_url}ExcelOutput/RelicSetConfig.json" base_station_url = "https://starrailstation.com" avatar_url = f"{base_station_url}/cn/characters" light_cone_url = f"{base_station_url}/cn/equipment"