Skip to content

Commit 0144765

Browse files
committed
<jx3>[feat]zixiagong dps calculator
1 parent 3093bbb commit 0144765

File tree

6 files changed

+272
-5
lines changed

6 files changed

+272
-5
lines changed

src/plugins/jx3/calculator/__init__.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
wf_calculator, # 无方
1414
ylj_calculator, # 隐龙诀
1515
shxj_calculator, # 山海心诀
16+
zxg_calculator, # 紫霞功
1617
)
1718

1819
calc_dj = on_command("jx3_calculator_dj", aliases={"毒经计算器"}, priority=5, force_whitespace=True) # 目前先对毒经的计算器进行响应,后续尽可能多地支持
@@ -101,4 +102,26 @@ async def _(event: GroupMessageEvent, args: Message = CommandArg()):
101102
await calc_shxj.finish(data[0])
102103
elif isinstance(data, str):
103104
data = get_content_local(data)
104-
await calc_shxj.finish(ms.image(data))
105+
await calc_shxj.finish(ms.image(data))
106+
107+
calc_zxg = on_command("jx3_calculator_zxg", aliases={"气纯计算器"}, priority=5, force_whitespace=True) # 目前先对紫霞功的计算器进行响应,后续尽可能多地支持
108+
109+
@calc_zxg.handle()
110+
async def _(event: GroupMessageEvent, args: Message = CommandArg()):
111+
if args.extract_plain_text() == "":
112+
return
113+
arg = args.extract_plain_text().split(" ")
114+
if len(arg) not in [1, 2]:
115+
await calc_zxg.finish("唔……参数不正确哦,请检查后重试~")
116+
if len(arg) == 1:
117+
server = None
118+
id = arg[0]
119+
elif len(arg) == 2:
120+
server = arg[0]
121+
id = arg[1]
122+
data = await zxg_calculator(server, id, str(event.group_id))
123+
if isinstance(data, list):
124+
await calc_zxg.finish(data[0])
125+
elif isinstance(data, str):
126+
data = get_content_local(data)
127+
await calc_zxg.finish(ms.image(data))

src/plugins/jx3/calculator/dujing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ async def get_calculated_data(
7272
"qixue": qixue
7373
}
7474
data = await post_url(
75-
url = "http://117.50.178.116:2333/calculator",
75+
url = "http://117.50.178.116:2333/calculator_dj",
7676
json = params,
7777
headers = {
7878
"token": inkarsuki_offical_token
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .dujing import generate_calculator_img_dujing as dj_calculator
22
from .wufang import generate_calculator_img_wufang as wf_calculator
33
from .yinlongjue import generate_calculator_img_yinlongjue as ylj_calculator
4-
from .shanhaixinjue import generate_calculator_img_shanhaixinjue as shxj_calculator
4+
from .shanhaixinjue import generate_calculator_img_shanhaixinjue as shxj_calculator
5+
from .zixiagong import get_calculated_img_zixiagong as zxg_calculator

src/plugins/jx3/calculator/yinlongjue.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 隐龙诀
1+
# DPS计算器 隐龙诀
22

33
from typing import Tuple, Literal, Optional, List, Union, Dict, Callable
44
from jinja2 import Template
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# DPS计算器 紫霞功
2+
3+
from typing import Tuple, Literal, Optional, List, Union, Dict, Callable
4+
from jinja2 import Template
5+
from pathlib import Path
6+
7+
from src.constant.jx3 import color_list
8+
9+
from src.tools.basic.server import Zone_mapping, server_mapping
10+
from src.tools.utils.request import get_api, post_url
11+
from src.tools.utils.path import ASSETS, CACHE, VIEWS
12+
from src.tools.utils.file import read, write
13+
from src.tools.generate import generate, get_uuid
14+
from src.tools.basic.prompts import PROMPT
15+
from src.tools.config import Config
16+
17+
from src.plugins.jx3.detail.detail import get_tuilan_data
18+
from src.plugins.jx3.bind.role import get_player_local_data
19+
from src.plugins.jx3.attributes.api import get_personal_kf, enchant_mapping
20+
21+
import json
22+
23+
inkarsuki_offical_token = Config.hidden.offcial_token
24+
25+
msgbox_dujing = """
26+
<div class="element">
27+
<div class="cell-title"><span>理论DPS</span></div>
28+
<div class="cell">{{ max }}</div>
29+
</div>
30+
<div class="element">
31+
<div class="cell-title"><span>脸黑DPS</span></div>
32+
<div class="cell">{{ min }}</div>
33+
</div>"""
34+
35+
template_calculator_dujing = """
36+
<tr>
37+
<td class="short-column">{{ skill }}</td>
38+
<td class="short-column">
39+
<div class="progress-bar" style="margin: 0 auto;">
40+
<div class="progress" style="width: {{ display }};"></div>
41+
<span class="progress-text">{{ percent }}</span>
42+
</div>
43+
</td>
44+
<td class="short-column">{{ count }}</td>
45+
<td class="short-column">{{ value }}</td>
46+
</tr>"""
47+
48+
def process_skill_data(skills, counts, damages, percent):
49+
combined_list = [
50+
{
51+
"skill": skill,
52+
"count": count,
53+
"damage": damage,
54+
"percent": percent
55+
}
56+
for skill, count, damage, percent in zip(skills, counts, damages, percent)
57+
]
58+
59+
filtered_list = [item for item in combined_list if item["damage"] > 0]
60+
sorted_list = sorted(filtered_list, key=lambda x: x["damage"], reverse=True)
61+
return sorted_list
62+
63+
class ZiXiaGongAttributes:
64+
enchant_map = {
65+
"天堑奇珵": "15400",
66+
"天堑奇玿": "13950",
67+
"天堑奇瑛": "12450"
68+
}
69+
70+
def __init__(self, data: dict):
71+
self.data = data["data"]
72+
73+
@property
74+
def is_xcw(self) -> bool:
75+
for equip in self.data["Equips"]:
76+
if equip["Name"] == "愧琼瑰·珠沉" and equip["Quality"] in ["11650", "10900"]:
77+
return True
78+
return False
79+
80+
@property
81+
def is_dcw(self) -> bool:
82+
for equip in self.data["Equips"]:
83+
if equip["Name"] == "苍冥游" and equip["Quality"] != "1":
84+
return True
85+
return False
86+
87+
@property
88+
def is_belt_enchant(self) -> bool:
89+
for equip in self.data["Equips"]:
90+
if equip["Icon"]["SubKind"] == "腰带":
91+
if "WPermanentEnchant" in equip:
92+
return True
93+
return False
94+
95+
@property
96+
def is_wristband_enchant(self) -> str:
97+
for equip in self.data["Equips"]:
98+
if equip["Icon"]["SubKind"] == "护臂":
99+
if "WPermanentEnchant" in equip:
100+
enchant_name = enchant_mapping(equip["Quality"])
101+
if not isinstance(enchant_name, str):
102+
raise ValueError("Unknown enchant of \"" + equip["Name"] + "(" + equip["Quality"] + ")`.")
103+
return self.enchant_map[enchant_name]
104+
return "无"
105+
106+
@property
107+
def is_shoe_enchant(self) -> str:
108+
for equip in self.data["Equips"]:
109+
if equip["Icon"]["SubKind"] == "鞋":
110+
if "WPermanentEnchant" in equip:
111+
enchant_name = enchant_mapping(equip["Quality"])
112+
if not isinstance(enchant_name, str):
113+
raise ValueError("Unknown enchant of \"" + equip["Name"] + "(" + equip["Quality"] + ")`.")
114+
return self.enchant_map[enchant_name]
115+
return "无"
116+
117+
@property
118+
def is_special_weapon(self) -> str:
119+
for equip in self.data["Equips"]:
120+
if equip["Name"] in ["仙家楼阁", "伴雪声", "岁载空"]:
121+
return "水特效·" + equip["Quality"]
122+
return "无"
123+
124+
@property
125+
def is_special_sash(self) -> str:
126+
for equip in self.data["Equips"]:
127+
if equip["Name"] in ["暮天阳", "池上雨", "秋风韵"]:
128+
return equip["Name"] + "·" + equip["Quality"]
129+
return "无"
130+
131+
@property
132+
def attributes(self) -> List[str]:
133+
result = []
134+
for attr_type in ["基础攻击力", "攻击力", "会心", "会心效果", "破防", "无双", "破招"]:
135+
for attr_data in self.data["PersonalPanel"]:
136+
if attr_data["name"] == attr_type:
137+
if attr_data["percent"]:
138+
result.append(str(attr_data["value"]) + "%")
139+
else:
140+
result.append(attr_data["value"])
141+
return result
142+
143+
144+
@property
145+
def check_set_effects(self) -> Tuple[bool, bool]:
146+
attr_event = False
147+
damage_event = False
148+
for equip in self.data["Equips"]:
149+
if "SetListMap" in equip and "Set" in equip:
150+
set_count = len(equip["SetListMap"])
151+
for effect in equip["Set"]:
152+
set_num = int(effect.get("SetNum", 0))
153+
if effect["Desc"] == "atSkillEventHandler" and set_count >= set_num:
154+
attr_event = True
155+
if effect["Desc"] == "atSetEquipmentRecipe" and set_count >= set_num:
156+
damage_event = True
157+
return attr_event, damage_event
158+
159+
def check_qixue(self, name: str) -> bool:
160+
for qixue in self.data["Person"]["qixueList"]:
161+
if qixue["name"] == name:
162+
return True
163+
return False
164+
165+
async def get_calculated_img_zixiagong(server: Optional[str], name: str, group_id: Optional[str]):
166+
server_ = server_mapping(server, group_id)
167+
if not server_:
168+
return [PROMPT.ServerNotExist]
169+
player_data = await get_player_local_data(role_name=name, server_name=server_)
170+
if player_data.format_jx3api()["code"] != 200:
171+
return [PROMPT.PlayerNotExist]
172+
params = {
173+
"zone": Zone_mapping(server_),
174+
"server": server_,
175+
"game_role_id": player_data.format_jx3api()["data"]["roleId"]
176+
}
177+
tuilan_data = await get_tuilan_data("https://m.pvp.xoyo.com/mine/equip/get-role-equip", params=params)
178+
school = await get_personal_kf(tuilan_data["data"]["Kungfu"]["KungfuID"])
179+
if school != "紫霞功":
180+
return ["唔……门派与计算器不匹配!"]
181+
data_obj = ZiXiaGongAttributes(tuilan_data)
182+
attrs = data_obj.attributes
183+
cw = [data_obj.is_dcw, data_obj.is_xcw]
184+
suit = list(data_obj.check_set_effects)
185+
belt = "无"
186+
if data_obj.is_belt_enchant:
187+
belt = "全等级腰带大附魔"
188+
enchant = [belt, data_obj.is_wristband_enchant, data_obj.is_shoe_enchant]
189+
sash = data_obj.is_special_sash
190+
weapon = data_obj.is_special_weapon
191+
qixue: List[bool] = []
192+
for qixue_name in ["万物", "正气", "破势", "抱阳", "若冲"]:
193+
qixue.append(data_obj.check_qixue(qixue_name))
194+
params = {
195+
"attrs": attrs,
196+
"cw": cw,
197+
"suit": suit,
198+
"enchant": enchant,
199+
"sash": sash,
200+
"weapon": weapon,
201+
"qixue": qixue
202+
}
203+
calculated_data = await post_url("http://117.50.178.116:2333/calculator_zxg", json=params, headers={"token": inkarsuki_offical_token}, timeout=10000)
204+
calculated_data = json.loads(calculated_data)
205+
dps = calculated_data["data"]["result"]
206+
bad_dps = calculated_data["data"]["bad_result"]
207+
final_data = process_skill_data(
208+
skills=calculated_data["data"]["skills"],
209+
counts=calculated_data["data"]["counts"],
210+
damages=calculated_data["data"]["damages"],
211+
percent=calculated_data["data"]["percent"]
212+
)
213+
tables = []
214+
for skill in final_data:
215+
tables.append(
216+
Template(template_calculator_dujing).render(**{
217+
"skill": skill["skill"],
218+
"display": str(round(skill["damage"]/final_data[0]["damage"]*100, 2)) + "%",
219+
"percent": skill["percent"],
220+
"count": str(skill["count"]),
221+
"value": str(skill["damage"])
222+
})
223+
)
224+
html = Template(read(VIEWS + "/jx3/calculator/calculator.html")).render(**{
225+
"font": ASSETS + "/font/custom.ttf",
226+
"yozai": ASSETS + "/font/Yozai-Medium.ttf",
227+
"msgbox": Template(msgbox_dujing).render(**{
228+
"max": dps,
229+
"min": bad_dps
230+
}),
231+
"tables": "\n".join(tables),
232+
"school": "紫霞功",
233+
"color": color_list["紫霞功"],
234+
"server": server,
235+
"name": name,
236+
"calculator": "【雾海寻龙】气纯dps计算器 v1.247(240912) by @月慕青尘"
237+
})
238+
final_html = CACHE + "/" + get_uuid() + ".html"
239+
write(final_html, html)
240+
final_path = await generate(final_html, False, ".total", False)
241+
if not isinstance(final_path, str):
242+
return
243+
return Path(final_path).as_uri()

src/plugins/jx3/detail/detail.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
ticket = Config.jx3.api.ticket
1919
device_id = ticket.split("::")[-1]
2020

21-
async def get_tuilan_data(url: str, params: Union[dict, None] = None):
21+
async def get_tuilan_data(url: str, params: Union[dict, None] = None) -> dict:
2222
if params is None:
2323
params = {"ts": gen_ts()}
2424
if "ts" not in params:

0 commit comments

Comments
 (0)