From 7b361afaef482ed56bb848fc6211b86771251403 Mon Sep 17 00:00:00 2001 From: HornCopper Date: Thu, 5 Sep 2024 07:48:27 +0800 Subject: [PATCH] [feat]dujing dps calculator --- src/plugins/github/__init__.py | 2 +- src/plugins/jx3/attributes/api.py | 9 +- src/plugins/jx3/calculator/__init__.py | 39 ++++ src/plugins/jx3/calculator/dj.py | 186 ++++++++++++++++++ src/plugins/jx3/calculator/universe.py | 1 + src/plugins/jx3/calendar/__init__.py | 2 + src/plugins/jx3/jx3.py | 1 + src/plugins/jx3/serendipity/without_jx3api.py | 24 ++- src/tools/utils/path.py | 6 +- src/views/jx3/calculator/calculator.html | 167 ++++++++++++++++ 10 files changed, 427 insertions(+), 10 deletions(-) create mode 100644 src/plugins/jx3/calculator/__init__.py create mode 100644 src/plugins/jx3/calculator/dj.py create mode 100644 src/plugins/jx3/calculator/universe.py create mode 100644 src/views/jx3/calculator/calculator.html diff --git a/src/plugins/github/__init__.py b/src/plugins/github/__init__.py index 3e476a9c..fb7a4a03 100644 --- a/src/plugins/github/__init__.py +++ b/src/plugins/github/__init__.py @@ -116,7 +116,7 @@ async def recWebHook(req: Request): except Exception as e: msg = f"Event {event} has not been supported." return {"status": "500", "message": msg, "error": e} - bots: list = list(Config.bot_basic.bot_notice.__dict__) + bots: list = list(Config.bot_basic.bot_notice) for i in bots: bot = get_bot(i) await sendm(bot, message, repo) diff --git a/src/plugins/jx3/attributes/api.py b/src/plugins/jx3/attributes/api.py index 3f802334..81313fcd 100644 --- a/src/plugins/jx3/attributes/api.py +++ b/src/plugins/jx3/attributes/api.py @@ -220,7 +220,7 @@ def kungfu_mapping(kf) -> Union[str, bool]: return False -async def get_attr_main(server, id, group_id): +async def get_attr_main(server, id, group_id, exist_data: dict = {}): server = server_mapping(server, group_id) if not server: return [PROMPT.ServerNotExist] @@ -253,8 +253,11 @@ async def get_attr_main(server, id, group_id): "User-Agent": "SeasunGame/193 CFNetwork/1240.0.4 Darwin/20.6.0", "x-sk": xsk } - data = await post_url(url="https://m.pvp.xoyo.com/mine/equip/get-role-equip", data=param, headers=headers) - data = json.loads(data) + if exist_data: + data = exist_data + else: + data = await post_url(url="https://m.pvp.xoyo.com/mine/equip/get-role-equip", data=param, headers=headers) + data = json.loads(data) kfid = data["data"]["Kungfu"]["KungfuID"] kf = await get_personal_kf(kfid) if not kf: diff --git a/src/plugins/jx3/calculator/__init__.py b/src/plugins/jx3/calculator/__init__.py new file mode 100644 index 00000000..e9f27988 --- /dev/null +++ b/src/plugins/jx3/calculator/__init__.py @@ -0,0 +1,39 @@ +from nonebot import on_command +from nonebot.adapters import Message +from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageSegment as ms +from nonebot.params import CommandArg + +from src.tools.permission import checker, error +from src.tools.utils.file import get_content_local + +from src.plugins.sign import Sign + +from .universe import ( + dj_calculator +) + +calc = on_command("jx3_calculator_dj", aliases={"毒经计算器"}, priority=5) # 目前先对毒经的计算器进行响应,后续尽可能多地支持 + +@calc.handle() +async def _(event: GroupMessageEvent, args: Message = CommandArg()): + if args.extract_plain_text() == "": + return + if not checker(str(event.user_id), 10) and Sign.get_coin(str(event.user_id)) < 500: + await calc.finish(error(10)) + if not checker(str(event.user_id), 10): + Sign.reduce(str(event.user_id), 500) + arg = args.extract_plain_text().split(" ") + if len(arg) not in [1, 2]: + await calc.finish("唔……参数不正确哦,请检查后重试~") + if len(arg) == 1: + server = None + id = arg[0] + elif len(arg) == 2: + server = arg[0] + id = arg[1] + data = await dj_calculator(server, id, str(event.group_id)) + if isinstance(data, list): + await calc.finish(data[0]) + elif isinstance(data, str): + data = get_content_local(data) + await calc.finish(ms.image(data)) \ No newline at end of file diff --git a/src/plugins/jx3/calculator/dj.py b/src/plugins/jx3/calculator/dj.py new file mode 100644 index 00000000..aa1269af --- /dev/null +++ b/src/plugins/jx3/calculator/dj.py @@ -0,0 +1,186 @@ +from typing import List, Union, Literal, Optional +from jinja2 import Template +from pathlib import Path +from pydantic import BaseModel + +from src.tools.utils.request import post_url +from src.tools.basic.server import server_mapping, Zone_mapping +from src.tools.basic.prompts import PROMPT +from src.tools.basic.jx3 import gen_ts +from src.tools.utils.file import read, write +from src.tools.utils.path import ASSETS, CACHE, VIEWS +from src.tools.generate import get_uuid, generate +from src.tools.config import Config + +from src.plugins.jx3.bind.role 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 + +import json + +template_calculator_dujing = """ + + {{ skill }} + +
+
+ {{ percent }} +
+ + {{ count }} + {{ value }} +""" + +class ExcelRequest(BaseModel): + attrs: List[Union[int, str]] + weapon: Literal["", "墨语沉香", "13950水特效", "龙门飞剑", "小橙武特效"] + sash: Literal["", "秋风韵"] + enchant: List[bool] + suit: List[bool] + +inkarsuki_offical_token = Config.hidden.offcial_token + +async def get_calculated_data( + attrs: List[Union[int, str]], + weapon: Literal["", "墨语沉香", "13950水特效", "龙门飞剑", "小橙武特效"], + sash: Literal["", "秋风韵"], + enchant: List[bool], + suit: List[bool] +) -> dict: + params = { + "attrs": attrs, + "weapon": weapon, + "sash": sash, + "enchant": enchant, + "suit": suit + } + data = await post_url( + url = "http://117.50.178.116:2333/calculator", + json = params, + headers = { + "token": inkarsuki_offical_token + } + ) + return json.loads(data) + +def check_set_effects(equip_list): + skill_event_handler_activated = False + set_equipment_recipe_activated = False + + for equip in equip_list: + if "SetListMap" in equip and "Set" in equip: + equipped_set_pieces = len(equip["SetListMap"]) + + for effect in equip["Set"]: + set_num = int(effect.get("SetNum", 0)) + + if effect["Desc"] == "atSkillEventHandler" and equipped_set_pieces >= set_num: + skill_event_handler_activated = True + + if effect["Desc"] == "atSetEquipmentRecipe" and equipped_set_pieces >= set_num: + set_equipment_recipe_activated = True + + return [skill_event_handler_activated, set_equipment_recipe_activated] + +async def analyze_attrs(attrs_raw_data: dict) -> ExcelRequest: + weapon = "" + sash = "" + enchant = [] + suit = [] + for equip in attrs_raw_data["data"]["Equips"]: + if equip["Icon"]["Kind"] == "武器" and equip["Icon"]["SubKind"] != "投掷囊": + if equip["Name"] == "十方断魂笛·虫魂" and equip["Quality"] == "13200": + weapon = "龙门飞剑" + if equip["Name"] == "墨语沉香" and equip["Quality"] == "12500": + weapon = "墨语沉香" + if equip["Name"] == "悠哉乐土": + weapon = "13950水特效" + if equip["Name"] == "死生往复·牵丝" and equip["Quality"] == "11650": + weapon = "小橙武特效" + if equip["Icon"]["SubKind"] == "腰坠": + if equip["Name"] == "秋风韵": + sash = "秋风韵" + for place in ["帽子", "上衣", "腰带", "护臂", "鞋"]: + flag = False + for equip in attrs_raw_data["data"]["Equips"]: + if equip["Icon"]["SubKind"] == place: + if "WPermanentEnchant" in equip: + enchant.append(True) + flag = True + else: + enchant.append(False) + flag = True + if not flag: + enchant.append(False) + suit = check_set_effects(attrs_raw_data["data"]["Equips"]) + panel = attrs_raw_data["data"]["PersonalPanel"] + attrs = [] + for attr_name in ["根骨", "基础攻击力", "会心", "会心效果", "破防", "破招", "无双", "加速"]: + for attr_data in panel: + if attr_data["name"] == attr_name: + if attr_data["percent"] and attr_name != "加速": + attrs.append(str(attr_data["value"]) + "%") + if not attr_data["percent"] and attr_name != "加速": + attrs.append(attr_data["value"]) + if attr_name == "加速": + attrs.append("%.2f%%" % (attr_data["value"]/96483.75 * 100)) + return ExcelRequest( + attrs=attrs, + weapon=weapon, + sash=sash, + enchant=enchant, + suit=suit + ) + +async def generate_calculator_img_dujing(server: Optional[str], name: str, group_id: str = ""): + server = server_mapping(server, group_id) + if not server: + return [PROMPT.ServerNotExist] + role_data = await get_player_local_data(role_name=name, server_name=server) + if role_data.format_jx3api()["code"] != 200: + return [PROMPT.PlayerNotExist] + uid = role_data.format_jx3api()["data"]["roleId"] + param = { + "zone": Zone_mapping(server), + "server": server, + "game_role_id": uid, + "ts": gen_ts() + } + equip_data = await get_tuilan_data("https://m.pvp.xoyo.com/mine/equip/get-role-equip", param) + kungfu = await get_personal_kf(equip_data["data"]["Kungfu"]["KungfuID"]) + if kungfu != "毒经": + return ["唔……门派与计算器不匹配!"] + analyzed_data: ExcelRequest = await analyze_attrs(equip_data) + calculated_data = await get_calculated_data(**(analyzed_data.__dict__)) + tables = [] + max_dps = calculated_data["data"]["result"] # 理论DPS + avg_dps = max_dps*0.95 # 一般手法 + min_dps = max_dps*0.825 # 一键宏 + for skill_sort in range(len(calculated_data["data"]["skills"])): + tables.append( + Template(template_calculator_dujing).render(**{ + "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], + "value": calculated_data["data"]["damages"] + }) + ) + html = Template(read(VIEWS + "/jx3/calculator/calculator.html")).render(**{ + "font": ASSETS + "/font/custom.ttf", + "yozai": ASSETS + "/font/Yozai-Medium.ttf", + "max": max_dps, + "avg": avg_dps, + "min": min_dps, + "tables": "\n".join(tables), + "school": "毒经", + "server": server, + "name": name, + "calculator": "【雾海寻龙】毒经DPS计算器 20240530" + }) + final_html = CACHE + "/" + get_uuid() + ".html" + write(final_html, html) + final_path = await generate(final_html, False, "table", False) + if not isinstance(final_path, str): + return + return Path(final_path).as_uri() \ No newline at end of file diff --git a/src/plugins/jx3/calculator/universe.py b/src/plugins/jx3/calculator/universe.py new file mode 100644 index 00000000..c5eafd7c --- /dev/null +++ b/src/plugins/jx3/calculator/universe.py @@ -0,0 +1 @@ +from .dj import generate_calculator_img_dujing as dj_calculator \ No newline at end of file diff --git a/src/plugins/jx3/calendar/__init__.py b/src/plugins/jx3/calendar/__init__.py index 51ff735b..3fc5178e 100644 --- a/src/plugins/jx3/calendar/__init__.py +++ b/src/plugins/jx3/calendar/__init__.py @@ -14,5 +14,7 @@ async def _(event: GroupMessageEvent, args: Message = CommandArg()): if args.extract_plain_text() != "": return image = await getCalendar() + if not isinstance(image, str): + return image = get_content_local(image) await calendar.finish(ms.image(image)) \ No newline at end of file diff --git a/src/plugins/jx3/jx3.py b/src/plugins/jx3/jx3.py index 82bb09fc..314cc537 100644 --- a/src/plugins/jx3/jx3.py +++ b/src/plugins/jx3/jx3.py @@ -5,6 +5,7 @@ from .awesome import * from .bind import * from .buff import * +from .calculator import * from .calendar import * from .daily import * from .detail import * diff --git a/src/plugins/jx3/serendipity/without_jx3api.py b/src/plugins/jx3/serendipity/without_jx3api.py index 92d54fba..1804f3fe 100644 --- a/src/plugins/jx3/serendipity/without_jx3api.py +++ b/src/plugins/jx3/serendipity/without_jx3api.py @@ -1,10 +1,11 @@ from src.tools.config import Config -from src.tools.utils.request import post_url, get_api +from src.tools.utils.request import post_url, get_api, get_url from src.tools.basic.jx3 import gen_ts, gen_xsk, format_body from src.plugins.jx3.bind import get_player_local_data, Player import json +import re ticket = Config.jx3.api.ticket device_id = ticket.split("::")[-1] @@ -22,6 +23,7 @@ class JX3Serendipity: def __init__(self): self.tl = [] self.my = [] + self.jx3pet = [] def get_serendipity_level(self, serendipity_name: str) -> int: if serendipity_name.find("宠物奇缘") != -1: @@ -97,8 +99,24 @@ async def get_my_data(self, server: str, name: str): } serendipities.append(new) self.my = serendipities - + + async def get_jx3pet_data(self, server: str, name: str): + final_url = f"https://www.jx3pet.com/api/serendipity?server={server}&type=不限&serendipity=不限&name={name}&limit=30" + data = await get_url(final_url) + data = json.loads(re.search(r'\{.*\}', data, re.DOTALL)[0]) # type: ignore + serendipities = [] + for serendipity in data["data"]: + serendipities.append( + { + "name": serendipity["serendipity"], + "level": self.get_serendipity_level(serendipity["serendipity"]), + "time": serendipity["time"] + } + ) + self.jx3pet = serendipities + async def integration(self, server: str, name: str): await self.get_tuilan_data(server, name) await self.get_my_data(server, name) - return merge_dict_lists(self.tl, self.my) \ No newline at end of file + await self.get_jx3pet_data(server, name) + return merge_dict_lists(self.jx3pet, merge_dict_lists(self.tl, self.my)) \ No newline at end of file diff --git a/src/tools/utils/path.py b/src/tools/utils/path.py index 7573ef2c..80772ad6 100644 --- a/src/tools/utils/path.py +++ b/src/tools/utils/path.py @@ -1,11 +1,11 @@ import os -import pathlib2 +from pathlib import Path tools_path = f"{os.getcwd()}/src/tools" def get_path(path: str) -> str: - t = pathlib2.Path(tools_path) - return t.parent.joinpath(path).__str__() + t = Path(tools_path) + return str(t.parent.joinpath(path)) DATA = get_path("data") CACHE = get_path("cache") diff --git a/src/views/jx3/calculator/calculator.html b/src/views/jx3/calculator/calculator.html new file mode 100644 index 00000000..dac1a398 --- /dev/null +++ b/src/views/jx3/calculator/calculator.html @@ -0,0 +1,167 @@ + + + + + + + + + +
+
+
期望DPS
+
{{ max }}
+
+
+
一般手法
+
{{ avg }}
+
+
+
一键宏
+
{{ min }}
+
+
+ + + + + + + + + + + {{ tables }} + + + + + + +
技能占比次数伤害
© Inkar Suki · {{ school }}DPS计算器 · {{ server }} · {{ name }} · + 06:41
计算器数据来源:{{ calculator }} +
+ + + \ No newline at end of file