Skip to content

Commit

Permalink
<jx3>[feat]attributes converter;[feat]calculator display critical per…
Browse files Browse the repository at this point in the history
…cent;[feat]fix qixue file name
  • Loading branch information
HornCopper committed Sep 6, 2024
1 parent 2af509c commit b6bb519
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/plugins/jx3/calculator/dj.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ async def generate_calculator_img_dujing(server: Optional[str], name: str, group
"skill": calculated_data["data"]["skills"][skill_sort],
"display": str(int(round(float(calculated_data["data"]["percent"][skill_sort][:-1])/float(calculated_data["data"]["percent"][0][:-1]), 2)*100)) + "%",
"percent": calculated_data["data"]["percent"][skill_sort],
"count": calculated_data["data"]["counts"][skill_sort],
"count": str(calculated_data["data"]["counts"][skill_sort]) + "(" + calculated_data["data"]["critical"] + "会心)",
"value": calculated_data["data"]["damages"][skill_sort]
})
)
Expand Down
328 changes: 328 additions & 0 deletions src/plugins/jx3/calculator/ts_olcalc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
from typing import Optional, Union, Literal, List, Any
from pydantic import BaseModel, Field

from src.tools.basic.server import server_mapping, Zone_mapping
from src.tools.basic.prompts import PROMPT
from src.tools.utils.time import get_current_time

from src.plugins.jx3.bind import get_player_local_data
from src.plugins.jx3.detail.detail import get_tuilan_data
from src.plugins.jx3.attributes.api import get_personal_kf, enchant_mapping

async def get_tuilan_raw_data(server: str, uid: str) -> dict:
param = {
"zone": Zone_mapping(server),
"server": server,
"game_role_id": uid
}
equip_data = await get_tuilan_data("https://m.pvp.xoyo.com/mine/equip/get-role-equip", param)
return equip_data

async def get_local_data(server: Optional[str], name: str, group_id: Optional[str] = "") -> Union[dict, Literal[False]]:
server = server_mapping(server, group_id)
if not server:
return False
result = await get_player_local_data(role_name=name, server_name=server)
if result.format_jx3api()["code"] != 200:
return False
return result.format_jx3api()["data"]

def server_required(func):
def wrapper(self, *args, **kwargs):
if not isinstance(self.server, str):
return False
return func(self, *args, **kwargs)
return wrapper

def is_empty(value):
if value is None:
return True
if isinstance(value, bool):
return not value
if isinstance(value, (int, float)):
return value == 0
if isinstance(value, str):
return value == ""
if isinstance(value, list):
if not value:
return True
return is_empty(value[0])
if isinstance(value, dict):
if not value:
return True
return all(is_empty(v) for v in value.values())
return False

def check_key_empty(dictionary, key):
if key not in dictionary:
return True
return is_empty(dictionary[key])

class ModifyType(BaseModel):
name: str = ""
max: str = ""
min: str = ""
desc: str = ""
percent: bool = False

class FiveStone(BaseModel):
name: str = ""
level: str = ""
max: str = ""
min: str = ""
icon: str = ""
kind: str = ""
subKind: str = ""
desc: str = ""
percent: bool = False

class _EquipType(BaseModel):
Desc: str = ""
EquipUsage: str = ""
Icon: str = ""

class ColorStoneAttributes(BaseModel):
max: str = ""
min: str = ""
desc: str = ""
percent: bool = False

class ColorStone(BaseModel):
id: str = ""
name: str = ""
class_name: str = Field("", alias="class")
level: str = ""
icon: str = ""
kind: str = ""
subKind: str = ""
attribute: List[ColorStoneAttributes] = []

class PermanentEnchantAttributesDetail(BaseModel):
desc: str = ""

class PermanentEnchantAttributes(BaseModel):
max: str = ""
min: str = ""
attrib: List[PermanentEnchantAttributesDetail] = []

class PermanentEnchant(BaseModel):
id: str = ""
name: str = ""
level: str = ""
icon: str = ""
attributes: List[PermanentEnchantAttributes] = []

class CommonEnchant(BaseModel):
id: str = ""
name: str = ""
icon: str = ""
desc: str = ""

class Equip(BaseModel):
name: str = ""
class_name: str = Field("", alias="class")
icon: str = ""
kind: str = ""
subKind: str = ""
quality: str = ""
strengthLevel: str = ""
maxStrengthLevel: str = ""
color: str = ""
desc: str = ""
source: str = ""
modifyType: List[ModifyType] = []
fiveStone: List[FiveStone] = []
EquipType: _EquipType = _EquipType()
ID: str = ""
UID: str = ""
permanentEnchant: List[PermanentEnchant] = []
commonEnchant: CommonEnchant = CommonEnchant()
colorStone: ColorStone = ColorStone() # type: ignore

class JX3PlayerAttributes:
def __init__(self, server: Optional[str], name: str, group_id: Optional[str] = "", tl_data: dict = {}):
self.server = server_mapping(server, group_id)
self.name = name
self.tl_data: Optional[dict] = tl_data
self.role_data: Optional[dict] = None

@staticmethod
async def get_kungfu(kungfu_id: str) -> Union[str, Literal[False]]:
result = await get_personal_kf(kungfu_id)
return result if result else False

@staticmethod
def convert_to_dict(obj: Any) -> Any:
if isinstance(obj, BaseModel):
return obj.model_dump(by_alias=True)
elif isinstance(obj, list):
return [JX3PlayerAttributes.convert_to_dict(item) for item in obj]
elif isinstance(obj, dict):
return {k: JX3PlayerAttributes.convert_to_dict(v) for k, v in obj.items()}
return obj

@staticmethod
def sort_equipments(equip_list: list) -> list:
order = {
"项链": 3,
"腰坠": 2,
"戒指": 1
}

def get_priority(item):
sub_kind = item.get("subKind", "")
return order.get(sub_kind, 0)

weapons_and_pouches = []
last_four_gear = []
others = []

for item in equip_list:
if item.get("kind") == "武器" or item.get("class") == "投掷囊":
weapons_and_pouches.append(item)
else:
last_four_gear.append(item)

last_four_gear_sorted = sorted(last_four_gear, key=lambda x: get_priority(x), reverse=True)
final_last_four = last_four_gear_sorted[-4:]
final_last_four.sort(key=lambda x: ["项链", "腰坠", "戒指"].index(x.get("subKind", "")) if x.get("subKind") in ["项链", "腰坠", "戒指"] else len(["项链", "腰坠", "戒指"]))

other_gears = [item for item in last_four_gear_sorted if item not in final_last_four]

sorted_data = weapons_and_pouches + other_gears + final_last_four

return sorted_data

async def _fetch_data(self):
if not isinstance(self.server, str):
return False
role_data = await get_local_data(self.server, self.name)
if not isinstance(role_data, dict):
return False
self.role_data = role_data
return True

async def analyze_equip_list(self) -> Union[list, Literal[False]]:
if not self.tl_data:
if not await self._fetch_data():
return False

if not isinstance(self.tl_data, dict) or len(self.tl_data["data"]["Equips"]) < 12:
return False

kungfu_id = self.tl_data["data"]["Kungfu"]["KungfuID"]
if await self.get_kungfu(kungfu_id) in ["问水诀", "山居剑意"] and len(self.tl_data["data"]["Equips"]) != 13:
return False

equips = []
for equip in self.tl_data["data"]["Equips"]:
equip_data = Equip(
name=equip["Name"],
icon=equip["Icon"]["FileName"],
kind=equip["Icon"]["Kind"],
subKind=equip["Icon"]["SubKind"],
quality=equip["Quality"],
strengthLevel=equip["StrengthLevel"],
maxStrengthLevel=equip["MaxEquipBoxStrengthLevel"],
color=equip["Color"],
desc=equip["Desc"],
source="", # 请问意义是什么?
EquipType=_EquipType(**equip["EquipType"]),
ID=equip["ID"],
UID=equip["UID"],
fiveStone=[
FiveStone(
name=item["Name"],
level=item["Level"],
max=item["Param1Max"],
min=item["Param1Min"],
icon=item["Icon"]["FileName"],
kind=item["Icon"]["Kind"],
subKind=item["Icon"]["SubKind"],
desc=item["Attrib"]["GeneratedMagic"],
percent=False
) for item in equip["FiveStone"]
] if equip["Icon"]["SubKind"] != "戒指" else [],
permanentEnchant=[
PermanentEnchant(
id=equip["WPermanentEnchant"]["ID"],
name=equip["WPermanentEnchant"]["Name"],
level=equip["WPermanentEnchant"]["Level"],
icon="",
attributes=[
PermanentEnchantAttributes(
max=equip["WPermanentEnchant"]["Attributes"][0]["Attribute1Value1"],
min=equip["WPermanentEnchant"]["Attributes"][0]["Attribute1Value2"],
attrib=[
PermanentEnchantAttributesDetail(
desc=equip["WPermanentEnchant"]["Attributes"][0]["Attrib"]["GeneratedMagic"]
)
]
)
]
)
] if "WPermanentEnchant" in equip else [],
commonEnchant=CommonEnchant(
name=str(enchant_mapping(equip["Quality"])) + "·伤·" + "帽衣腰腕鞋"[["帽子", "上衣", "腰带", "护臂", "鞋"].index(equip["Icon"]["SubKind"])]
) if equip["Icon"]["SubKind"] in ["帽子", "上衣", "腰带", "护臂", "鞋"] else CommonEnchant(),
colorStone=ColorStone(
id=equip["ColorStone"]["ID"],
name=equip["ColorStone"]["Name"],
level=equip["ColorStone"]["Level"],
icon=equip["ColorStone"]["Icon"]["FileName"],
kind=equip["ColorStone"]["Icon"]["Kind"],
subKind=equip["ColorStone"]["Icon"]["SubKind"],
attribute=[
ColorStoneAttributes(
max=item["Attribute1Value1"],
min=item["Attribute1Value2"],
desc=item["Attrib"]["GeneratedMagic"],
percent=False
) for item in equip["ColorStone"]["Attributes"]
],
**{"class": equip["ColorStone"]["Type"]}
) if equip["Icon"]["Kind"] == "武器" and equip["Icon"]["SubKind"] != "投掷囊" else ColorStone(), # type: ignore
**{"class": equip["DetailType"]}
)
equips.append(self.convert_to_dict(equip_data))
return self.sort_equipments(equips)

async def get_panel(self) -> Union[dict, Literal[False]]:
if not self.tl_data:
if not await self._fetch_data():
return False
if isinstance(self.tl_data, dict):
return {
"score": self.tl_data["data"]["TotalEquipsScore"],
"panel": self.tl_data["data"]["PersonalPanel"]
}
return False

async def format_jx3api(self) -> Union[dict, Literal[False]]:
if not self.role_data:
if not await self._fetch_data():
return False

equip_data = await self.analyze_equip_list()
if equip_data is False:
return False

role_data = self.role_data
kungfu_name = await self.get_kungfu(self.tl_data["data"]["Kungfu"]["KungfuID"]) # type: ignore
panel_data = await self.get_panel()
for equip in equip_data:
if check_key_empty(equip, "permanentEnchant"):
equip.pop("permanentEnchant")
if check_key_empty(equip, "commonEnchant"):
equip.pop("commonEnchant")
return {
"code": 200,
"msg": "success",
"data": {
**role_data, # type: ignore
"kungfuName": kungfu_name,
"equipList": equip_data,
"panelList": panel_data
},
"time": get_current_time()
}
4 changes: 3 additions & 1 deletion src/plugins/jx3/calculator/universe.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from .dj import generate_calculator_img_dujing as dj_calculator
from .dj import generate_calculator_img_dujing as dj_calculator

from .ts_olcalc import JX3PlayerAttributes
2 changes: 2 additions & 0 deletions src/plugins/jx3/detail/detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
async def get_tuilan_data(url: str, params: Union[dict, None] = None):
if params is None:
params = {"ts": gen_ts()}
if "ts" not in params:
params["ts"] = gen_ts()
params_ = format_body(params)
xsk = gen_xsk(params_)
basic_headers = {
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/jx3/skill/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ async def _(event: GroupMessageEvent, args: Message = CommandArg()):
if os.path.exists(ASSETS + "/jx3/" + f"{ver}.json") is False:
final_url = f"https://data.jx3box.com/talent/{ver}.json"
data = await get_api(final_url)
write(ASSETS + "/jx3/" + f"v{ver}.json", json.dumps(data, ensure_ascii=False))
write(ASSETS + "/jx3/" + f"{ver}.json", json.dumps(data, ensure_ascii=False))
else:
data = json.loads(read(ASSETS + "/jx3/" + f"{ver}.json"))
try:
Expand Down

0 comments on commit b6bb519

Please sign in to comment.