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 ()
0 commit comments