@sjtdev/koishi-plugin-dota2tracker 1.0.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +559 -1038
- package/package.json +2 -1
- package/readme.md +9 -7
- package/template/{hero.html → hero/hero_1.ejs} +543 -516
- package/template/images/logo_dire.png +0 -0
- package/template/images/logo_radiant.png +0 -0
- package/template/images/scepter.png +0 -0
- package/template/images/scepter_0.png +0 -0
- package/template/images/scepter_1.png +0 -0
- package/template/images/shard.png +0 -0
- package/template/images/shard_0.png +0 -0
- package/template/images/shard_1.png +0 -0
- package/template/match/match_1.ejs +997 -0
- package/template/match/match_2.ejs +440 -0
- package/template/player/player_1.ejs +543 -0
- package/template/match.html +0 -1027
- package/template/player.html +0 -414
- /package/{images → template/images}/flag_dire.png +0 -0
- /package/{images → template/images}/flag_radiant.png +0 -0
- /package/{images → template/images}/hero_badge_1.png +0 -0
- /package/{images → template/images}/hero_badge_2.png +0 -0
- /package/{images → template/images}/hero_badge_3.png +0 -0
- /package/{images → template/images}/hero_badge_4.png +0 -0
- /package/{images → template/images}/hero_badge_5.png +0 -0
- /package/{images → template/images}/hero_badge_6.png +0 -0
- /package/{images → template/images}/medal_0.png +0 -0
- /package/{images → template/images}/medal_1.png +0 -0
- /package/{images → template/images}/medal_2.png +0 -0
- /package/{images → template/images}/medal_3.png +0 -0
- /package/{images → template/images}/medal_4.png +0 -0
- /package/{images → template/images}/medal_5.png +0 -0
- /package/{images → template/images}/medal_6.png +0 -0
- /package/{images → template/images}/medal_7.png +0 -0
- /package/{images → template/images}/medal_8.png +0 -0
- /package/{images → template/images}/medal_8b.png +0 -0
- /package/{images → template/images}/medal_8c.png +0 -0
- /package/{images → template/images}/star_0.png +0 -0
- /package/{images → template/images}/star_1.png +0 -0
- /package/{images → template/images}/star_2.png +0 -0
- /package/{images → template/images}/star_3.png +0 -0
- /package/{images → template/images}/star_4.png +0 -0
- /package/{images → template/images}/star_5.png +0 -0
package/lib/index.js
CHANGED
|
@@ -40,259 +40,26 @@ module.exports = __toCommonJS(src_exports);
|
|
|
40
40
|
var import_koishi = require("koishi");
|
|
41
41
|
|
|
42
42
|
// src/utils.ts
|
|
43
|
+
var utils_exports = {};
|
|
44
|
+
__export(utils_exports, {
|
|
45
|
+
CONFIGS: () => CONFIGS,
|
|
46
|
+
ImageType: () => ImageType,
|
|
47
|
+
formatNumber: () => formatNumber,
|
|
48
|
+
getFormattedMatchData: () => getFormattedMatchData,
|
|
49
|
+
getImageUrl: () => getImageUrl,
|
|
50
|
+
playerisValid: () => playerisValid,
|
|
51
|
+
query: () => query,
|
|
52
|
+
readDirectoryFilesSync: () => readDirectoryFilesSync,
|
|
53
|
+
sec2time: () => sec2time,
|
|
54
|
+
winRateColor: () => winRateColor
|
|
55
|
+
});
|
|
43
56
|
var import_axios = __toESM(require("axios"));
|
|
44
57
|
var import_fs = __toESM(require("fs"));
|
|
45
|
-
var
|
|
46
|
-
var
|
|
47
|
-
async function query(query_str) {
|
|
48
|
-
return await import_axios.default.post(CONFIGS.STRATZ_API.URL, query_str, {
|
|
49
|
-
headers: {
|
|
50
|
-
"Content-Type": "application/graphql",
|
|
51
|
-
Authorization: `Bearer ${CONFIGS.STRATZ_API.TOKEN}`
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
__name(query, "query");
|
|
56
|
-
function getImageUrl(image, type = "local" /* Local */) {
|
|
57
|
-
if (type === "local" /* Local */) {
|
|
58
|
-
try {
|
|
59
|
-
const imageData = import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/images/${image}.png`);
|
|
60
|
-
const base64Data = imageData.toString("base64");
|
|
61
|
-
return `data:image/png;base64,${base64Data}`;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.error(error);
|
|
64
|
-
return "";
|
|
65
|
-
}
|
|
66
|
-
} else
|
|
67
|
-
return `https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/${type}/${image}.png`;
|
|
68
|
-
}
|
|
69
|
-
__name(getImageUrl, "getImageUrl");
|
|
70
|
-
function getFormattedMatchData(match) {
|
|
71
|
-
match.radiantKillsCount = match.radiantKills ? match.radiantKills.reduce((acc, cva) => acc + cva, 0) : 0;
|
|
72
|
-
match.direKillsCount = match.direKills ? match.direKills.reduce((acc, cva) => acc + cva, 0) : 0;
|
|
73
|
-
match.party = {};
|
|
74
|
-
let party_index = 0;
|
|
75
|
-
const party_mark = ["I", "II", "III", "IV"];
|
|
76
|
-
let heroOrderList = {};
|
|
77
|
-
for (let hero of match.pickBans) {
|
|
78
|
-
if (hero.isPick)
|
|
79
|
-
heroOrderList[hero.heroId] = hero.order;
|
|
80
|
-
}
|
|
81
|
-
let processLaneOutcome = /* @__PURE__ */ __name(function(outcome) {
|
|
82
|
-
switch (outcome) {
|
|
83
|
-
case "RADIANT_VICTORY":
|
|
84
|
-
return { radiant: "victory", dire: "fail" };
|
|
85
|
-
case "RADIANT_STOMP":
|
|
86
|
-
return { radiant: "stomp", dire: "stomped" };
|
|
87
|
-
case "DIRE_VICTORY":
|
|
88
|
-
return { radiant: "fail", dire: "victory" };
|
|
89
|
-
case "DIRE_STOMP":
|
|
90
|
-
return { radiant: "stomped", dire: "stomp" };
|
|
91
|
-
default:
|
|
92
|
-
return { radiant: "tie", dire: "tie" };
|
|
93
|
-
}
|
|
94
|
-
}, "processLaneOutcome");
|
|
95
|
-
let laneResult = { top: {}, mid: {}, bottom: {} };
|
|
96
|
-
laneResult.top = processLaneOutcome(match.topLaneOutcome);
|
|
97
|
-
laneResult.mid = processLaneOutcome(match.midLaneOutcome);
|
|
98
|
-
laneResult.bottom = processLaneOutcome(match.bottomLaneOutcome);
|
|
99
|
-
match.players.forEach((player) => {
|
|
100
|
-
player.killContribution = (player.kills + player.assists) / (player.isRadiant ? match.radiantKillsCount : match.direKillsCount);
|
|
101
|
-
player.deathContribution = player.deaths / (player.isRadiant ? match.direKillsCount : match.radiantKillsCount);
|
|
102
|
-
player.titles = [];
|
|
103
|
-
player.mvpScore = // 计算MVP分数
|
|
104
|
-
player.kills * 5 + player.assists * 3 + player.stats.heroDamageReport.dealtTotal.stunDuration / 100 * 0.1 + (player.stats.heroDamageReport.dealtTotal.slowDuration + player.stats.heroDamageReport.dealtTotal.disableDuration) / 100 * 0.05 + player.heroDamage * 1e-3 + player.towerDamage * 0.01 + player.heroHealing * 2e-3 + player.imp * 0.25;
|
|
105
|
-
player.order = heroOrderList[player.hero.id];
|
|
106
|
-
if (player.partyId != null) {
|
|
107
|
-
if (!match.party[player.partyId])
|
|
108
|
-
match.party[player.partyId] = party_mark[party_index++];
|
|
109
|
-
}
|
|
110
|
-
const maxStackCountsByAbilityOrItem = player.stats.matchPlayerBuffEvent.reduce((acc, event) => {
|
|
111
|
-
const key = event.abilityId !== null ? `ability-${event.abilityId}` : `item-${event.itemId}`;
|
|
112
|
-
if (!acc[key] || event.stackCount > acc[key].stackCount) {
|
|
113
|
-
acc[key] = event;
|
|
114
|
-
}
|
|
115
|
-
return acc;
|
|
116
|
-
}, {});
|
|
117
|
-
player.stats.matchPlayerBuffEvent.splice(0, player.stats.matchPlayerBuffEvent.length, ...Object.values(maxStackCountsByAbilityOrItem));
|
|
118
|
-
switch (player.lane) {
|
|
119
|
-
case "SAFE_LANE":
|
|
120
|
-
player.laneResult = laneResult[player.isRadiant ? "bottom" : "top"][player.isRadiant ? "radiant" : "dire"];
|
|
121
|
-
break;
|
|
122
|
-
case "OFF_LANE":
|
|
123
|
-
player.laneResult = laneResult[!player.isRadiant ? "bottom" : "top"][player.isRadiant ? "radiant" : "dire"];
|
|
124
|
-
break;
|
|
125
|
-
default:
|
|
126
|
-
player.laneResult = laneResult.mid[player.isRadiant ? "radiant" : "dire"];
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
let items_timelist = {};
|
|
130
|
-
player.supportItemsCount = { 30: 0, 40: 0, 42: 0, 43: 0, 188: 0 };
|
|
131
|
-
if (player.playbackData) {
|
|
132
|
-
for (let item of player.playbackData.purchaseEvents) {
|
|
133
|
-
items_timelist[item.itemId] = item.time;
|
|
134
|
-
if (item.itemId == 42 || item.itemId == 43)
|
|
135
|
-
items_timelist[218] = item.time;
|
|
136
|
-
switch (item.itemId) {
|
|
137
|
-
case 30:
|
|
138
|
-
case 40:
|
|
139
|
-
case 42:
|
|
140
|
-
case 43:
|
|
141
|
-
case 188:
|
|
142
|
-
player.supportItemsCount[item.itemId]++;
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
player.items = [];
|
|
148
|
-
player.backpacks = [];
|
|
149
|
-
const prefix = "recipe_";
|
|
150
|
-
for (let i = 0; i <= 5; i++) {
|
|
151
|
-
const key = `item${i}Id`;
|
|
152
|
-
const itemId = player[key];
|
|
153
|
-
if (itemId === void 0 || itemId === null) {
|
|
154
|
-
player.items.push(null);
|
|
155
|
-
} else if (dotaconstants.item_ids[itemId]) {
|
|
156
|
-
const name2 = dotaconstants.item_ids[itemId];
|
|
157
|
-
const isRecipe = name2.startsWith(prefix);
|
|
158
|
-
const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
|
|
159
|
-
player.items.push({
|
|
160
|
-
id: itemId,
|
|
161
|
-
name: cleanName,
|
|
162
|
-
time: items_timelist[itemId],
|
|
163
|
-
isRecipe
|
|
164
|
-
});
|
|
165
|
-
} else {
|
|
166
|
-
player.items.push(null);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
for (let i = 0; i <= 2; i++) {
|
|
170
|
-
const key = `backpack${i}Id`;
|
|
171
|
-
const itemId = player[key];
|
|
172
|
-
if (itemId === void 0 || itemId === null) {
|
|
173
|
-
player.backpacks.push(null);
|
|
174
|
-
} else if (dotaconstants.item_ids[itemId]) {
|
|
175
|
-
const name2 = dotaconstants.item_ids[itemId];
|
|
176
|
-
const isRecipe = name2.startsWith(prefix);
|
|
177
|
-
const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
|
|
178
|
-
player.backpacks.push({
|
|
179
|
-
id: itemId,
|
|
180
|
-
name: cleanName,
|
|
181
|
-
time: items_timelist[itemId],
|
|
182
|
-
isRecipe
|
|
183
|
-
});
|
|
184
|
-
} else {
|
|
185
|
-
player.backpacks.push(null);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
if (player.additionalUnit) {
|
|
189
|
-
player.unitItems = [];
|
|
190
|
-
player.unitBackpacks = [];
|
|
191
|
-
const prefix2 = "recipe_";
|
|
192
|
-
for (let i = 0; i <= 5; i++) {
|
|
193
|
-
const key = `item${i}Id`;
|
|
194
|
-
const itemId = player.additionalUnit[key];
|
|
195
|
-
if (itemId === void 0 || itemId === null) {
|
|
196
|
-
player.unitItems.push(null);
|
|
197
|
-
} else if (dotaconstants.item_ids[itemId]) {
|
|
198
|
-
const name2 = dotaconstants.item_ids[itemId];
|
|
199
|
-
const isRecipe = name2.startsWith(prefix2);
|
|
200
|
-
const cleanName = isRecipe ? name2.substring(prefix2.length) : name2;
|
|
201
|
-
player.unitItems.push({
|
|
202
|
-
id: itemId,
|
|
203
|
-
name: cleanName,
|
|
204
|
-
time: items_timelist[itemId],
|
|
205
|
-
isRecipe
|
|
206
|
-
});
|
|
207
|
-
} else {
|
|
208
|
-
player.unitItems.push(null);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
for (let i = 0; i <= 2; i++) {
|
|
212
|
-
const key = `backpack${i}Id`;
|
|
213
|
-
const itemId = player.additionalUnit[key];
|
|
214
|
-
if (itemId === void 0 || itemId === null) {
|
|
215
|
-
player.unitBackpacks.push(null);
|
|
216
|
-
} else if (dotaconstants.item_ids[itemId]) {
|
|
217
|
-
const name2 = dotaconstants.item_ids[itemId];
|
|
218
|
-
const isRecipe = name2.startsWith(prefix2);
|
|
219
|
-
const cleanName = isRecipe ? name2.substring(prefix2.length) : name2;
|
|
220
|
-
player.unitBackpacks.push({
|
|
221
|
-
id: itemId,
|
|
222
|
-
name: cleanName,
|
|
223
|
-
time: items_timelist[itemId],
|
|
224
|
-
isRecipe
|
|
225
|
-
});
|
|
226
|
-
} else {
|
|
227
|
-
player.unitBackpacks.push(null);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
let ComparisonMode;
|
|
233
|
-
((ComparisonMode2) => {
|
|
234
|
-
ComparisonMode2["Max"] = "max";
|
|
235
|
-
ComparisonMode2["Min"] = "min";
|
|
236
|
-
})(ComparisonMode || (ComparisonMode = {}));
|
|
237
|
-
function findMaxByProperty(primaryProperty, secondaryProperty = null, players = match.players, primaryMode = "max" /* Max */, secondaryMode = "max" /* Max */) {
|
|
238
|
-
return players.reduce((result, player) => {
|
|
239
|
-
const primaryComparison = primaryMode === "max" /* Max */ ? player[primaryProperty] > result[primaryProperty] : player[primaryProperty] < result[primaryProperty];
|
|
240
|
-
const secondaryComparison = secondaryMode === "max" /* Max */ ? player[secondaryProperty] > result[secondaryProperty] : player[secondaryProperty] < result[secondaryProperty];
|
|
241
|
-
if (primaryComparison) {
|
|
242
|
-
return player;
|
|
243
|
-
} else if (player[primaryProperty] === result[primaryProperty] && secondaryProperty && secondaryComparison) {
|
|
244
|
-
return player;
|
|
245
|
-
}
|
|
246
|
-
return result;
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
__name(findMaxByProperty, "findMaxByProperty");
|
|
250
|
-
findMaxByProperty(
|
|
251
|
-
"mvpScore",
|
|
252
|
-
void 0,
|
|
253
|
-
match.players.filter((player) => match.didRadiantWin == player.isRadiant)
|
|
254
|
-
).titles.push({ name: "MVP", color: "#FFA500" });
|
|
255
|
-
findMaxByProperty(
|
|
256
|
-
"mvpScore",
|
|
257
|
-
void 0,
|
|
258
|
-
match.players.filter((player) => match.didRadiantWin != player.isRadiant)
|
|
259
|
-
).titles.push({ name: "魂", color: "#6cf" });
|
|
260
|
-
findMaxByProperty("networth").titles.push({ name: "富", color: "#FFD700" });
|
|
261
|
-
findMaxByProperty("experiencePerMinute").titles.push({ name: "睿", color: "#8888FF" });
|
|
262
|
-
match.players.reduce(
|
|
263
|
-
(max, player) => player.stats.heroDamageReport.dealtTotal.stunDuration + player.stats.heroDamageReport.dealtTotal.disableDuration + player.stats.heroDamageReport.dealtTotal.slowDuration / 2 > max.stats.heroDamageReport.dealtTotal.stunDuration + max.stats.heroDamageReport.dealtTotal.disableDuration + max.stats.heroDamageReport.dealtTotal.slowDuration / 2 ? player : max
|
|
264
|
-
).titles.push({ name: "控", color: "#FF00FF" });
|
|
265
|
-
findMaxByProperty("heroDamage").titles.push({ name: "爆", color: "#CC0088" });
|
|
266
|
-
findMaxByProperty("kills", "heroDamage").titles.push({ name: "破", color: "#DD0000" });
|
|
267
|
-
findMaxByProperty("deaths", "networth", void 0, void 0, "min" /* Min */).titles.push({ name: "鬼", color: "#CCCCCC" });
|
|
268
|
-
findMaxByProperty("assists", "heroDamage").titles.push({ name: "助", color: "#006400" });
|
|
269
|
-
findMaxByProperty("towerDamage", "heroDamage").titles.push({ name: "拆", color: "#FEDCBA" });
|
|
270
|
-
findMaxByProperty("heroHealing").titles.push({ name: "奶", color: "#00FF00" });
|
|
271
|
-
match.players.reduce(
|
|
272
|
-
(max, player) => player.stats.heroDamageReport.receivedTotal.physicalDamage + player.stats.heroDamageReport.receivedTotal.magicalDamage + player.stats.heroDamageReport.receivedTotal.pureDamage > max.stats.heroDamageReport.receivedTotal.physicalDamage + max.stats.heroDamageReport.receivedTotal.magicalDamage + max.stats.heroDamageReport.receivedTotal.pureDamage ? player : max
|
|
273
|
-
).titles.push({ name: "耐", color: "#84A1C7" });
|
|
274
|
-
match.players.reduce((lowest, player) => {
|
|
275
|
-
const currentContribution = (player.kills + player.assists) / (player.isRadiant ? match.radiantKillsCount : match.direKillsCount);
|
|
276
|
-
const lowestContribution = (lowest.kills + lowest.assists) / (lowest.isRadiant ? match.radiantKillsCount : match.direKillsCount);
|
|
277
|
-
if (currentContribution < lowestContribution) {
|
|
278
|
-
return player;
|
|
279
|
-
} else if (currentContribution === lowestContribution) {
|
|
280
|
-
const currentPlayerScore = player.kills + player.assists;
|
|
281
|
-
const lowestPlayerScore = lowest.kills + lowest.assists;
|
|
282
|
-
if (currentPlayerScore < lowestPlayerScore) {
|
|
283
|
-
return player;
|
|
284
|
-
} else if (currentPlayerScore === lowestPlayerScore) {
|
|
285
|
-
return player.heroDamage < lowest.heroDamage ? player : lowest;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
return lowest;
|
|
289
|
-
}).titles.push({ name: "摸", color: "#DDDDDD" });
|
|
290
|
-
return match;
|
|
291
|
-
}
|
|
292
|
-
__name(getFormattedMatchData, "getFormattedMatchData");
|
|
58
|
+
var dotaconstants2 = __toESM(require("dotaconstants"));
|
|
59
|
+
var import_path = __toESM(require("path"));
|
|
293
60
|
|
|
294
61
|
// src/queries.ts
|
|
295
|
-
var
|
|
62
|
+
var dotaconstants = __toESM(require("dotaconstants"));
|
|
296
63
|
function MATCH_INFO(matchId) {
|
|
297
64
|
return `
|
|
298
65
|
{
|
|
@@ -498,6 +265,7 @@ function PLAYER_INFO_WITH_25_MATCHES(steamAccountId) {
|
|
|
498
265
|
kills
|
|
499
266
|
deaths
|
|
500
267
|
assists
|
|
268
|
+
position
|
|
501
269
|
award
|
|
502
270
|
imp
|
|
503
271
|
hero {
|
|
@@ -531,133 +299,474 @@ function PLAYER_EXTRA_INFO(steamAccountId, matchCount, totalHeroCount) {
|
|
|
531
299
|
}
|
|
532
300
|
}
|
|
533
301
|
}
|
|
534
|
-
`;
|
|
302
|
+
`;
|
|
303
|
+
}
|
|
304
|
+
__name(PLAYER_EXTRA_INFO, "PLAYER_EXTRA_INFO");
|
|
305
|
+
function CURRENT_GAMEVERSION() {
|
|
306
|
+
return `
|
|
307
|
+
{
|
|
308
|
+
constants {
|
|
309
|
+
gameVersions{name id}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
`;
|
|
314
|
+
}
|
|
315
|
+
__name(CURRENT_GAMEVERSION, "CURRENT_GAMEVERSION");
|
|
316
|
+
function ALL_ABILITIES_CHINESE_NAME() {
|
|
317
|
+
return `
|
|
318
|
+
{
|
|
319
|
+
constants {
|
|
320
|
+
abilities(language:S_CHINESE){
|
|
321
|
+
id
|
|
322
|
+
language{displayName}
|
|
323
|
+
}
|
|
324
|
+
gameVersions{name id}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
`;
|
|
329
|
+
}
|
|
330
|
+
__name(ALL_ABILITIES_CHINESE_NAME, "ALL_ABILITIES_CHINESE_NAME");
|
|
331
|
+
function HERO_INFO(heroId) {
|
|
332
|
+
return `
|
|
333
|
+
{
|
|
334
|
+
constants {
|
|
335
|
+
hero(id: ${heroId}, language: S_CHINESE) {
|
|
336
|
+
id
|
|
337
|
+
name
|
|
338
|
+
shortName
|
|
339
|
+
aliases
|
|
340
|
+
roles {
|
|
341
|
+
roleId
|
|
342
|
+
level
|
|
343
|
+
}
|
|
344
|
+
language {
|
|
345
|
+
displayName
|
|
346
|
+
lore
|
|
347
|
+
hype
|
|
348
|
+
}
|
|
349
|
+
abilities {
|
|
350
|
+
ability(language: S_CHINESE) {
|
|
351
|
+
name
|
|
352
|
+
language {
|
|
353
|
+
displayName
|
|
354
|
+
description
|
|
355
|
+
attributes
|
|
356
|
+
lore
|
|
357
|
+
aghanimDescription
|
|
358
|
+
shardDescription
|
|
359
|
+
notes
|
|
360
|
+
}
|
|
361
|
+
stat {
|
|
362
|
+
type
|
|
363
|
+
behavior
|
|
364
|
+
unitTargetType
|
|
365
|
+
unitTargetTeam
|
|
366
|
+
unitTargetFlags
|
|
367
|
+
unitDamageType
|
|
368
|
+
cooldown
|
|
369
|
+
manaCost
|
|
370
|
+
spellImmunity
|
|
371
|
+
isOnCastbar
|
|
372
|
+
isGrantedByShard
|
|
373
|
+
isGrantedByScepter
|
|
374
|
+
hasShardUpgrade
|
|
375
|
+
hasScepterUpgrade
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
talents {
|
|
380
|
+
abilityId
|
|
381
|
+
slot
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
`;
|
|
388
|
+
}
|
|
389
|
+
__name(HERO_INFO, "HERO_INFO");
|
|
390
|
+
function HERO_MATCHUP_WINRATE(heroId) {
|
|
391
|
+
return `
|
|
392
|
+
{
|
|
393
|
+
heroStats {
|
|
394
|
+
matchUp(heroId: ${heroId}, take: ${Object.keys(dotaconstants.heroes).length - 1},bracketBasicIds:LEGEND_ANCIENT) {
|
|
395
|
+
heroId
|
|
396
|
+
matchCountWith
|
|
397
|
+
matchCountVs
|
|
398
|
+
with {
|
|
399
|
+
heroId1
|
|
400
|
+
winRateHeroId1
|
|
401
|
+
heroId2
|
|
402
|
+
winRateHeroId2
|
|
403
|
+
winCount
|
|
404
|
+
matchCount
|
|
405
|
+
}
|
|
406
|
+
vs {
|
|
407
|
+
heroId1
|
|
408
|
+
winRateHeroId1
|
|
409
|
+
heroId2
|
|
410
|
+
winRateHeroId2
|
|
411
|
+
winCount
|
|
412
|
+
matchCount
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
`;
|
|
419
|
+
}
|
|
420
|
+
__name(HERO_MATCHUP_WINRATE, "HERO_MATCHUP_WINRATE");
|
|
421
|
+
|
|
422
|
+
// src/utils.ts
|
|
423
|
+
var CONFIGS = { STRATZ_API: { URL: "https://api.stratz.com/graphql", TOKEN: "" } };
|
|
424
|
+
async function query(query_str) {
|
|
425
|
+
return await import_axios.default.post(CONFIGS.STRATZ_API.URL, query_str, {
|
|
426
|
+
headers: {
|
|
427
|
+
"Content-Type": "application/graphql",
|
|
428
|
+
Authorization: `Bearer ${CONFIGS.STRATZ_API.TOKEN}`
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
__name(query, "query");
|
|
433
|
+
var ImageType = /* @__PURE__ */ ((ImageType2) => {
|
|
434
|
+
ImageType2["Icons"] = "icons";
|
|
435
|
+
ImageType2["Heroes"] = "heroes";
|
|
436
|
+
ImageType2["HeroIcons"] = "heroes/icons";
|
|
437
|
+
ImageType2["Items"] = "items";
|
|
438
|
+
ImageType2["Abilities"] = "abilities";
|
|
439
|
+
ImageType2["Local"] = "local";
|
|
440
|
+
return ImageType2;
|
|
441
|
+
})(ImageType || {});
|
|
442
|
+
function getImageUrl(image, type = "local" /* Local */) {
|
|
443
|
+
if (type === "local" /* Local */) {
|
|
444
|
+
try {
|
|
445
|
+
const imageData = import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}.png`);
|
|
446
|
+
const base64Data = imageData.toString("base64");
|
|
447
|
+
return `data:image/png;base64,${base64Data}`;
|
|
448
|
+
} catch (error) {
|
|
449
|
+
console.error(error);
|
|
450
|
+
return "";
|
|
451
|
+
}
|
|
452
|
+
} else
|
|
453
|
+
return `https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/${type}/${image}.png`;
|
|
454
|
+
}
|
|
455
|
+
__name(getImageUrl, "getImageUrl");
|
|
456
|
+
function getFormattedMatchData(match) {
|
|
457
|
+
["radiant", "dire"].forEach((team) => {
|
|
458
|
+
match[team] = { killsCount: match[team + "Kills"]?.reduce((acc, cva) => acc + cva, 0) ?? 0, damageReceived: 0, heroDamage: 0, networth: 0, experience: 0 };
|
|
459
|
+
});
|
|
460
|
+
match.party = {};
|
|
461
|
+
let party_index = 0;
|
|
462
|
+
const party_mark = ["I", "II", "III", "IV"];
|
|
463
|
+
let heroOrderList = {};
|
|
464
|
+
for (let hero of match.pickBans) {
|
|
465
|
+
if (hero.isPick)
|
|
466
|
+
heroOrderList[hero.heroId] = hero.order;
|
|
467
|
+
}
|
|
468
|
+
let processLaneOutcome = /* @__PURE__ */ __name(function(outcome) {
|
|
469
|
+
switch (outcome) {
|
|
470
|
+
case "RADIANT_VICTORY":
|
|
471
|
+
return { radiant: "victory", dire: "fail" };
|
|
472
|
+
case "RADIANT_STOMP":
|
|
473
|
+
return { radiant: "stomp", dire: "stomped" };
|
|
474
|
+
case "DIRE_VICTORY":
|
|
475
|
+
return { radiant: "fail", dire: "victory" };
|
|
476
|
+
case "DIRE_STOMP":
|
|
477
|
+
return { radiant: "stomped", dire: "stomp" };
|
|
478
|
+
default:
|
|
479
|
+
return { radiant: "tie", dire: "tie" };
|
|
480
|
+
}
|
|
481
|
+
}, "processLaneOutcome");
|
|
482
|
+
let laneResult = { top: {}, mid: {}, bottom: {} };
|
|
483
|
+
laneResult.top = processLaneOutcome(match.topLaneOutcome);
|
|
484
|
+
laneResult.mid = processLaneOutcome(match.midLaneOutcome);
|
|
485
|
+
laneResult.bottom = processLaneOutcome(match.bottomLaneOutcome);
|
|
486
|
+
match.players.forEach((player) => {
|
|
487
|
+
player.team = player.isRadiant ? "radiant" : "dire";
|
|
488
|
+
player.rank = {
|
|
489
|
+
medal: parseInt(player.steamAccount.seasonRank?.toString().split("")[0] ?? 0),
|
|
490
|
+
star: parseInt(player.steamAccount.seasonRank?.toString().split("")[1] ?? 0),
|
|
491
|
+
leaderboard: player.steamAccount.seasonLeaderboardRank,
|
|
492
|
+
inTop100: player.steamAccount.seasonLeaderboardRank ? player.steamAccount.seasonLeaderboardRank <= 10 ? "8c" : player.steamAccount.seasonLeaderboardRank <= 100 ? "8b" : void 0 : void 0
|
|
493
|
+
};
|
|
494
|
+
player.killContribution = (player.kills + player.assists) / match[player.team].killsCount;
|
|
495
|
+
player.deathContribution = player.deaths / match[player.team === "radiant" ? "dire" : player.team].killsCount;
|
|
496
|
+
player.damageReceived = player.stats?.heroDamageReport?.receivedTotal.physicalDamage + player.stats?.heroDamageReport?.receivedTotal.magicalDamage + player.stats?.heroDamageReport?.receivedTotal.pureDamage;
|
|
497
|
+
match[player.team].heroDamage = (match[player.team].heroDamage ?? 0) + player.heroDamage;
|
|
498
|
+
match[player.team].damageReceived = (match[player.team].damageReceived ?? 0) + player.damageReceived;
|
|
499
|
+
match[player.team].networth += player.networth;
|
|
500
|
+
match[player.team].experience += Math.floor(player.experiencePerMinute / 60 * match.durationSeconds);
|
|
501
|
+
player.titles = [];
|
|
502
|
+
player.mvpScore = // 计算MVP分数
|
|
503
|
+
player.kills * 5 + player.assists * 3 + player.stats.heroDamageReport.dealtTotal.stunDuration / 100 * 0.1 + (player.stats.heroDamageReport.dealtTotal.slowDuration + player.stats.heroDamageReport.dealtTotal.disableDuration) / 100 * 0.05 + player.heroDamage * 1e-3 + player.towerDamage * 0.01 + player.heroHealing * 2e-3 + player.imp * 0.25;
|
|
504
|
+
player.order = heroOrderList[player.hero.id];
|
|
505
|
+
if (player.partyId != null) {
|
|
506
|
+
if (!match.party[player.partyId])
|
|
507
|
+
match.party[player.partyId] = party_mark[party_index++];
|
|
508
|
+
}
|
|
509
|
+
const maxStackCountsByAbilityOrItem = player.stats.matchPlayerBuffEvent.reduce((acc, event) => {
|
|
510
|
+
const key = event.abilityId !== null ? `ability-${event.abilityId}` : `item-${event.itemId}`;
|
|
511
|
+
if (!acc[key] || event.stackCount > acc[key].stackCount) {
|
|
512
|
+
acc[key] = event;
|
|
513
|
+
}
|
|
514
|
+
return acc;
|
|
515
|
+
}, {});
|
|
516
|
+
player.stats.matchPlayerBuffEvent.splice(0, player.stats.matchPlayerBuffEvent.length, ...Object.values(maxStackCountsByAbilityOrItem));
|
|
517
|
+
switch (player.lane) {
|
|
518
|
+
case "SAFE_LANE":
|
|
519
|
+
player.laneResult = laneResult[player.isRadiant ? "bottom" : "top"][player.team];
|
|
520
|
+
break;
|
|
521
|
+
case "OFF_LANE":
|
|
522
|
+
player.laneResult = laneResult[!player.isRadiant ? "bottom" : "top"][player.team];
|
|
523
|
+
break;
|
|
524
|
+
default:
|
|
525
|
+
player.laneResult = laneResult.mid[player.team];
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
528
|
+
let items_timelist = {};
|
|
529
|
+
player.supportItemsCount = { 30: 0, 40: 0, 42: 0, 43: 0, 188: 0 };
|
|
530
|
+
if (player.playbackData) {
|
|
531
|
+
for (let item of player.playbackData.purchaseEvents) {
|
|
532
|
+
items_timelist[item.itemId] = item.time;
|
|
533
|
+
if (item.itemId == 42 || item.itemId == 43)
|
|
534
|
+
items_timelist[218] = item.time;
|
|
535
|
+
switch (item.itemId) {
|
|
536
|
+
case 30:
|
|
537
|
+
case 40:
|
|
538
|
+
case 42:
|
|
539
|
+
case 43:
|
|
540
|
+
case 188:
|
|
541
|
+
player.supportItemsCount[item.itemId]++;
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
player.items = [];
|
|
547
|
+
player.backpacks = [];
|
|
548
|
+
const prefix = "recipe_";
|
|
549
|
+
for (let i = 0; i <= 5; i++) {
|
|
550
|
+
const key = `item${i}Id`;
|
|
551
|
+
const itemId = player[key];
|
|
552
|
+
if (itemId === void 0 || itemId === null) {
|
|
553
|
+
player.items.push(null);
|
|
554
|
+
} else if (dotaconstants2.item_ids[itemId]) {
|
|
555
|
+
const name2 = dotaconstants2.item_ids[itemId];
|
|
556
|
+
const isRecipe = name2.startsWith(prefix);
|
|
557
|
+
const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
|
|
558
|
+
player.items.push({
|
|
559
|
+
id: itemId,
|
|
560
|
+
name: cleanName,
|
|
561
|
+
time: items_timelist[itemId],
|
|
562
|
+
isRecipe
|
|
563
|
+
});
|
|
564
|
+
} else {
|
|
565
|
+
player.items.push(null);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
for (let i = 0; i <= 2; i++) {
|
|
569
|
+
const key = `backpack${i}Id`;
|
|
570
|
+
const itemId = player[key];
|
|
571
|
+
if (itemId === void 0 || itemId === null) {
|
|
572
|
+
player.backpacks.push(null);
|
|
573
|
+
} else if (dotaconstants2.item_ids[itemId]) {
|
|
574
|
+
const name2 = dotaconstants2.item_ids[itemId];
|
|
575
|
+
const isRecipe = name2.startsWith(prefix);
|
|
576
|
+
const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
|
|
577
|
+
player.backpacks.push({
|
|
578
|
+
id: itemId,
|
|
579
|
+
name: cleanName,
|
|
580
|
+
time: items_timelist[itemId],
|
|
581
|
+
isRecipe
|
|
582
|
+
});
|
|
583
|
+
} else {
|
|
584
|
+
player.backpacks.push(null);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (player.additionalUnit) {
|
|
588
|
+
player.unitItems = [];
|
|
589
|
+
player.unitBackpacks = [];
|
|
590
|
+
const prefix2 = "recipe_";
|
|
591
|
+
for (let i = 0; i <= 5; i++) {
|
|
592
|
+
const key = `item${i}Id`;
|
|
593
|
+
const itemId = player.additionalUnit[key];
|
|
594
|
+
if (itemId === void 0 || itemId === null) {
|
|
595
|
+
player.unitItems.push(null);
|
|
596
|
+
} else if (dotaconstants2.item_ids[itemId]) {
|
|
597
|
+
const name2 = dotaconstants2.item_ids[itemId];
|
|
598
|
+
const isRecipe = name2.startsWith(prefix2);
|
|
599
|
+
const cleanName = isRecipe ? name2.substring(prefix2.length) : name2;
|
|
600
|
+
player.unitItems.push({
|
|
601
|
+
id: itemId,
|
|
602
|
+
name: cleanName,
|
|
603
|
+
time: items_timelist[itemId],
|
|
604
|
+
isRecipe
|
|
605
|
+
});
|
|
606
|
+
} else {
|
|
607
|
+
player.unitItems.push(null);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
for (let i = 0; i <= 2; i++) {
|
|
611
|
+
const key = `backpack${i}Id`;
|
|
612
|
+
const itemId = player.additionalUnit[key];
|
|
613
|
+
if (itemId === void 0 || itemId === null) {
|
|
614
|
+
player.unitBackpacks.push(null);
|
|
615
|
+
} else if (dotaconstants2.item_ids[itemId]) {
|
|
616
|
+
const name2 = dotaconstants2.item_ids[itemId];
|
|
617
|
+
const isRecipe = name2.startsWith(prefix2);
|
|
618
|
+
const cleanName = isRecipe ? name2.substring(prefix2.length) : name2;
|
|
619
|
+
player.unitBackpacks.push({
|
|
620
|
+
id: itemId,
|
|
621
|
+
name: cleanName,
|
|
622
|
+
time: items_timelist[itemId],
|
|
623
|
+
isRecipe
|
|
624
|
+
});
|
|
625
|
+
} else {
|
|
626
|
+
player.unitBackpacks.push(null);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
let ComparisonMode;
|
|
632
|
+
((ComparisonMode2) => {
|
|
633
|
+
ComparisonMode2["Max"] = "max";
|
|
634
|
+
ComparisonMode2["Min"] = "min";
|
|
635
|
+
})(ComparisonMode || (ComparisonMode = {}));
|
|
636
|
+
function findMaxByProperty(primaryProperty, secondaryProperty = null, players = match.players, primaryMode = "max" /* Max */, secondaryMode = "max" /* Max */) {
|
|
637
|
+
return players.reduce((result, player) => {
|
|
638
|
+
const primaryComparison = primaryMode === "max" /* Max */ ? player[primaryProperty] > result[primaryProperty] : player[primaryProperty] < result[primaryProperty];
|
|
639
|
+
const secondaryComparison = secondaryMode === "max" /* Max */ ? player[secondaryProperty] > result[secondaryProperty] : player[secondaryProperty] < result[secondaryProperty];
|
|
640
|
+
if (primaryComparison) {
|
|
641
|
+
return player;
|
|
642
|
+
} else if (player[primaryProperty] === result[primaryProperty] && secondaryProperty && secondaryComparison) {
|
|
643
|
+
return player;
|
|
644
|
+
}
|
|
645
|
+
return result;
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
__name(findMaxByProperty, "findMaxByProperty");
|
|
649
|
+
findMaxByProperty(
|
|
650
|
+
"mvpScore",
|
|
651
|
+
void 0,
|
|
652
|
+
match.players.filter((player) => match.didRadiantWin == player.isRadiant)
|
|
653
|
+
).titles.push({ name: "MVP", color: "#FFA500" });
|
|
654
|
+
findMaxByProperty(
|
|
655
|
+
"mvpScore",
|
|
656
|
+
void 0,
|
|
657
|
+
match.players.filter((player) => match.didRadiantWin != player.isRadiant)
|
|
658
|
+
).titles.push({ name: "魂", color: "#6cf" });
|
|
659
|
+
findMaxByProperty("networth").titles.push({ name: "富", color: "#FFD700" });
|
|
660
|
+
findMaxByProperty("experiencePerMinute").titles.push({ name: "睿", color: "#8888FF" });
|
|
661
|
+
match.players.reduce(
|
|
662
|
+
(max, player) => player.stats.heroDamageReport.dealtTotal.stunDuration + player.stats.heroDamageReport.dealtTotal.disableDuration + player.stats.heroDamageReport.dealtTotal.slowDuration / 2 > max.stats.heroDamageReport.dealtTotal.stunDuration + max.stats.heroDamageReport.dealtTotal.disableDuration + max.stats.heroDamageReport.dealtTotal.slowDuration / 2 ? player : max
|
|
663
|
+
).titles.push({ name: "控", color: "#FF00FF" });
|
|
664
|
+
findMaxByProperty("heroDamage").titles.push({ name: "爆", color: "#CC0088" });
|
|
665
|
+
findMaxByProperty("kills", "heroDamage").titles.push({ name: "破", color: "#DD0000" });
|
|
666
|
+
findMaxByProperty("deaths", "networth", void 0, void 0, "min" /* Min */).titles.push({ name: "鬼", color: "#CCCCCC" });
|
|
667
|
+
findMaxByProperty("assists", "heroDamage").titles.push({ name: "助", color: "#006400" });
|
|
668
|
+
findMaxByProperty("towerDamage", "heroDamage").titles.push({ name: "拆", color: "#FEDCBA" });
|
|
669
|
+
findMaxByProperty("heroHealing").titles.push({ name: "奶", color: "#00FF00" });
|
|
670
|
+
match.players.reduce(
|
|
671
|
+
(max, player) => player.stats.heroDamageReport.receivedTotal.physicalDamage + player.stats.heroDamageReport.receivedTotal.magicalDamage + player.stats.heroDamageReport.receivedTotal.pureDamage > max.stats.heroDamageReport.receivedTotal.physicalDamage + max.stats.heroDamageReport.receivedTotal.magicalDamage + max.stats.heroDamageReport.receivedTotal.pureDamage ? player : max
|
|
672
|
+
).titles.push({ name: "耐", color: "#84A1C7" });
|
|
673
|
+
match.players.reduce((lowest, player) => {
|
|
674
|
+
const currentContribution = (player.kills + player.assists) / match[player.team].KillsCount;
|
|
675
|
+
const lowestContribution = (lowest.kills + lowest.assists) / match[lowest.team].KillsCount;
|
|
676
|
+
if (currentContribution < lowestContribution) {
|
|
677
|
+
return player;
|
|
678
|
+
} else if (currentContribution === lowestContribution) {
|
|
679
|
+
const currentPlayerScore = player.kills + player.assists;
|
|
680
|
+
const lowestPlayerScore = lowest.kills + lowest.assists;
|
|
681
|
+
if (currentPlayerScore < lowestPlayerScore) {
|
|
682
|
+
return player;
|
|
683
|
+
} else if (currentPlayerScore === lowestPlayerScore) {
|
|
684
|
+
return player.heroDamage < lowest.heroDamage ? player : lowest;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return lowest;
|
|
688
|
+
}).titles.push({ name: "摸", color: "#DDDDDD" });
|
|
689
|
+
return match;
|
|
535
690
|
}
|
|
536
|
-
__name(
|
|
537
|
-
function
|
|
538
|
-
return
|
|
539
|
-
{
|
|
540
|
-
constants {
|
|
541
|
-
gameVersions{name id}
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
`;
|
|
691
|
+
__name(getFormattedMatchData, "getFormattedMatchData");
|
|
692
|
+
function sec2time(sec) {
|
|
693
|
+
return sec ? (sec < 0 ? "-" : "") + Math.floor(Math.abs(sec) / 60) + ":" + ("00" + Math.abs(sec) % 60).slice(-2) : "--:--";
|
|
546
694
|
}
|
|
547
|
-
__name(
|
|
548
|
-
function
|
|
549
|
-
return
|
|
550
|
-
{
|
|
551
|
-
constants {
|
|
552
|
-
abilities(language:S_CHINESE){
|
|
553
|
-
id
|
|
554
|
-
language{displayName}
|
|
555
|
-
}
|
|
556
|
-
gameVersions{name id}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
`;
|
|
695
|
+
__name(sec2time, "sec2time");
|
|
696
|
+
function formatNumber(num) {
|
|
697
|
+
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
561
698
|
}
|
|
562
|
-
__name(
|
|
563
|
-
function
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
roles {
|
|
573
|
-
roleId
|
|
574
|
-
level
|
|
575
|
-
}
|
|
576
|
-
language {
|
|
577
|
-
displayName
|
|
578
|
-
lore
|
|
579
|
-
hype
|
|
580
|
-
}
|
|
581
|
-
abilities {
|
|
582
|
-
ability(language: S_CHINESE) {
|
|
583
|
-
name
|
|
584
|
-
language {
|
|
585
|
-
displayName
|
|
586
|
-
description
|
|
587
|
-
attributes
|
|
588
|
-
lore
|
|
589
|
-
aghanimDescription
|
|
590
|
-
shardDescription
|
|
591
|
-
notes
|
|
592
|
-
}
|
|
593
|
-
stat {
|
|
594
|
-
type
|
|
595
|
-
behavior
|
|
596
|
-
unitTargetType
|
|
597
|
-
unitTargetTeam
|
|
598
|
-
unitTargetFlags
|
|
599
|
-
unitDamageType
|
|
600
|
-
cooldown
|
|
601
|
-
manaCost
|
|
602
|
-
spellImmunity
|
|
603
|
-
isOnCastbar
|
|
604
|
-
isGrantedByShard
|
|
605
|
-
isGrantedByScepter
|
|
606
|
-
hasShardUpgrade
|
|
607
|
-
hasScepterUpgrade
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
talents {
|
|
612
|
-
abilityId
|
|
613
|
-
slot
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
`;
|
|
699
|
+
__name(formatNumber, "formatNumber");
|
|
700
|
+
function readDirectoryFilesSync(directoryPath) {
|
|
701
|
+
try {
|
|
702
|
+
const files = import_fs.default.readdirSync(directoryPath);
|
|
703
|
+
const fileNames = files.map((file) => import_path.default.basename(file, import_path.default.extname(file)));
|
|
704
|
+
return fileNames;
|
|
705
|
+
} catch (error) {
|
|
706
|
+
console.error("Error reading directory:", error);
|
|
707
|
+
return [];
|
|
708
|
+
}
|
|
620
709
|
}
|
|
621
|
-
__name(
|
|
622
|
-
function
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
heroId1
|
|
640
|
-
winRateHeroId1
|
|
641
|
-
heroId2
|
|
642
|
-
winRateHeroId2
|
|
643
|
-
winCount
|
|
644
|
-
matchCount
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
`;
|
|
710
|
+
__name(readDirectoryFilesSync, "readDirectoryFilesSync");
|
|
711
|
+
function winRateColor(value) {
|
|
712
|
+
value = value * 100;
|
|
713
|
+
value = Math.max(0, Math.min(100, value));
|
|
714
|
+
let red, green, blue;
|
|
715
|
+
if (value <= 50) {
|
|
716
|
+
let scale = Math.round(255 * (value / 50));
|
|
717
|
+
red = 255;
|
|
718
|
+
green = scale;
|
|
719
|
+
blue = scale;
|
|
720
|
+
} else {
|
|
721
|
+
let scale = Math.round(255 * ((value - 50) / 50));
|
|
722
|
+
red = 255 - scale;
|
|
723
|
+
green = 255;
|
|
724
|
+
blue = 255 - scale;
|
|
725
|
+
}
|
|
726
|
+
const toHex = /* @__PURE__ */ __name((color) => color.toString(16).padStart(2, "0").toUpperCase(), "toHex");
|
|
727
|
+
return `#${toHex(red)}${toHex(green)}${toHex(blue)}`;
|
|
651
728
|
}
|
|
652
|
-
__name(
|
|
729
|
+
__name(winRateColor, "winRateColor");
|
|
730
|
+
async function playerisValid(steamAccountId) {
|
|
731
|
+
try {
|
|
732
|
+
let queryRes = await query(VERIFYING_PLAYER(steamAccountId));
|
|
733
|
+
if (queryRes.status == 200) {
|
|
734
|
+
if (queryRes.data.data.player.matchCount != null)
|
|
735
|
+
return { isValid: true };
|
|
736
|
+
else
|
|
737
|
+
return { isValid: false, reason: "SteamID无效或无任何场次。" };
|
|
738
|
+
}
|
|
739
|
+
} catch (error) {
|
|
740
|
+
console.error(error);
|
|
741
|
+
return { isValid: false, reason: "网络状况不佳SteamID验证失败,请稍后重试。" };
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
__name(playerisValid, "playerisValid");
|
|
653
745
|
|
|
654
746
|
// src/index.ts
|
|
655
747
|
var import_fs2 = __toESM(require("fs"));
|
|
656
|
-
var cheerio = __toESM(require("cheerio"));
|
|
657
748
|
var import_moment = __toESM(require("moment"));
|
|
658
749
|
var dotaconstants3 = __toESM(require("dotaconstants"));
|
|
659
750
|
|
|
660
751
|
// src/dotaconstants_add.json
|
|
752
|
+
var dotaconstants_add_exports = {};
|
|
753
|
+
__export(dotaconstants_add_exports, {
|
|
754
|
+
HEROES_CHINESE: () => HEROES_CHINESE,
|
|
755
|
+
LOSE_NEGATIVE: () => LOSE_NEGATIVE,
|
|
756
|
+
LOSE_POSITIVE: () => LOSE_POSITIVE,
|
|
757
|
+
WIN_NEGATIVE: () => WIN_NEGATIVE,
|
|
758
|
+
WIN_POSITIVE: () => WIN_POSITIVE,
|
|
759
|
+
behavior: () => behavior,
|
|
760
|
+
default: () => dotaconstants_add_default,
|
|
761
|
+
gameMode: () => gameMode,
|
|
762
|
+
lobbyTypes: () => lobbyTypes,
|
|
763
|
+
position: () => position,
|
|
764
|
+
primary_attrs: () => primary_attrs,
|
|
765
|
+
rank: () => rank,
|
|
766
|
+
region: () => region,
|
|
767
|
+
roles: () => roles,
|
|
768
|
+
target_team: () => target_team
|
|
769
|
+
});
|
|
661
770
|
var gameMode = {
|
|
662
771
|
NONE: "",
|
|
663
772
|
ALL_PICK: "全英雄选择",
|
|
@@ -732,6 +841,17 @@ var position = {
|
|
|
732
841
|
"4": "采灵芝",
|
|
733
842
|
"5": "工具人"
|
|
734
843
|
};
|
|
844
|
+
var rank = {
|
|
845
|
+
"0": "未知",
|
|
846
|
+
"1": "先锋",
|
|
847
|
+
"2": "卫士",
|
|
848
|
+
"3": "中军",
|
|
849
|
+
"4": "统帅",
|
|
850
|
+
"5": "传奇",
|
|
851
|
+
"6": "万古流芳",
|
|
852
|
+
"7": "超凡入圣",
|
|
853
|
+
"8": "冠绝一世"
|
|
854
|
+
};
|
|
735
855
|
var roles = { CARRY: "核心", ESCAPE: "逃生", NUKER: "爆发", INITIATOR: "先手", DURABLE: "耐久", DISABLER: "控制", JUNGLER: "打野", SUPPORT: "辅助", PUSHER: "推进" };
|
|
736
856
|
var primary_attrs = { all: "hero_universal", str: "hero_strength", agi: "hero_agility", int: "hero_intelligence" };
|
|
737
857
|
var behavior = {
|
|
@@ -877,15 +997,40 @@ var WIN_NEGATIVE = ["侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺
|
|
|
877
997
|
var WIN_POSITIVE = ["带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"];
|
|
878
998
|
var LOSE_NEGATIVE = ["被人按在地上摩擦, 输掉了这场比赛", "悲惨地输掉了比赛", "头都被打歪了, 心态爆炸地输掉了比赛", "捕鱼被鱼吃了, 输掉了比赛", "打的是个几把", "直接进行一个比赛的输"];
|
|
879
999
|
var LOSE_POSITIVE = ["无力回天输掉了比赛", "尽力了, 但还是输了比赛", "背靠世界树, 虽败犹荣", "带不动队友, 输了比赛", "又输了, 很难受, 宁愿输的是我"];
|
|
1000
|
+
var dotaconstants_add_default = {
|
|
1001
|
+
gameMode,
|
|
1002
|
+
lobbyTypes,
|
|
1003
|
+
region,
|
|
1004
|
+
position,
|
|
1005
|
+
rank,
|
|
1006
|
+
roles,
|
|
1007
|
+
primary_attrs,
|
|
1008
|
+
behavior,
|
|
1009
|
+
target_team,
|
|
1010
|
+
HEROES_CHINESE,
|
|
1011
|
+
WIN_NEGATIVE,
|
|
1012
|
+
WIN_POSITIVE,
|
|
1013
|
+
LOSE_NEGATIVE,
|
|
1014
|
+
LOSE_POSITIVE
|
|
1015
|
+
};
|
|
880
1016
|
|
|
881
1017
|
// src/index.ts
|
|
882
1018
|
var import_koishi2 = require("koishi");
|
|
1019
|
+
var ejs = __toESM(require("ejs"));
|
|
1020
|
+
var import_path2 = __toESM(require("path"));
|
|
883
1021
|
var name = "dota2tracker";
|
|
884
1022
|
var usage = "DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑定),以及一系列查询功能。";
|
|
885
1023
|
var inject = ["database", "puppeteer", "cron"];
|
|
886
|
-
var Config = import_koishi.Schema.
|
|
887
|
-
|
|
888
|
-
|
|
1024
|
+
var Config = import_koishi.Schema.intersect([
|
|
1025
|
+
import_koishi.Schema.object({
|
|
1026
|
+
STRATZ_API_TOKEN: import_koishi.Schema.string().required().description("※必须。stratz.com的API TOKEN,可在 https://stratz.com/api 获取")
|
|
1027
|
+
}).description("基础设置"),
|
|
1028
|
+
import_koishi.Schema.object({
|
|
1029
|
+
template_match: import_koishi.Schema.union([...readDirectoryFilesSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/match`)]).default("match_1").description("生成比赛信息图片使用的模板,见 https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki 有模板展示。"),
|
|
1030
|
+
template_player: import_koishi.Schema.union([...readDirectoryFilesSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/player`)]).default("player_1").description("生成玩家信息图片使用的模板。(目前仅有一张模板)"),
|
|
1031
|
+
template_hero: import_koishi.Schema.union([...readDirectoryFilesSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/hero`)]).default("hero_1").description("生成英雄信息图片使用的模板。(目前仅有一张模板)")
|
|
1032
|
+
}).description("模板设置")
|
|
1033
|
+
]);
|
|
889
1034
|
var pendingMatches = [];
|
|
890
1035
|
var random = new import_koishi2.Random(() => Math.random());
|
|
891
1036
|
async function apply(ctx, config) {
|
|
@@ -930,8 +1075,8 @@ async function apply(ctx, config) {
|
|
|
930
1075
|
);
|
|
931
1076
|
return;
|
|
932
1077
|
}
|
|
933
|
-
let verifyRes = await
|
|
934
|
-
if (!verifyRes.
|
|
1078
|
+
let verifyRes = await playerisValid(steam_id);
|
|
1079
|
+
if (!verifyRes.isValid) {
|
|
935
1080
|
session.send(`绑定失败,${verifyRes.reason}`);
|
|
936
1081
|
return;
|
|
937
1082
|
}
|
|
@@ -977,39 +1122,45 @@ async function apply(ctx, config) {
|
|
|
977
1122
|
session.send("开发中,未来此功能会重写。\n" + queryRes.map((item) => `${item.nickName ?? ""},ID:${item.userId},SteamID:${item.steamId}`).join("\n"));
|
|
978
1123
|
}
|
|
979
1124
|
});
|
|
980
|
-
|
|
981
|
-
if (!match_id) {
|
|
982
|
-
session.send("请输入比赛ID。");
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
985
|
-
if (!/^\d{10}$/.test(match_id)) {
|
|
986
|
-
session.send("比赛ID无效。");
|
|
987
|
-
return;
|
|
988
|
-
}
|
|
989
|
-
session.send("正在搜索对局详情,请稍后...");
|
|
1125
|
+
async function queryAndDisplayMatch(session, matchId) {
|
|
990
1126
|
try {
|
|
991
1127
|
let match;
|
|
992
|
-
let queryLocal = await ctx.database.get("dt_previous_query_results",
|
|
1128
|
+
let queryLocal = await ctx.database.get("dt_previous_query_results", matchId, ["data"]);
|
|
993
1129
|
if (queryLocal.length > 0) {
|
|
994
1130
|
match = queryLocal[0].data;
|
|
995
1131
|
ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
|
|
996
1132
|
} else {
|
|
997
|
-
let queryRes = await query(MATCH_INFO(
|
|
1133
|
+
let queryRes = await query(MATCH_INFO(matchId));
|
|
998
1134
|
if (queryRes.status == 200) {
|
|
999
1135
|
match = getFormattedMatchData(queryRes.data.data.match);
|
|
1000
1136
|
}
|
|
1001
1137
|
}
|
|
1002
|
-
if (match.parsedDateTime) {
|
|
1003
|
-
session.send(await ctx.puppeteer.render(
|
|
1138
|
+
if (match && match.parsedDateTime) {
|
|
1139
|
+
session.send(await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */)));
|
|
1004
1140
|
ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
|
|
1005
1141
|
} else {
|
|
1006
|
-
pendingMatches.push({ matchId
|
|
1142
|
+
pendingMatches.push({ matchId, platform: session.event.platform, guildId: session.event.guild.id });
|
|
1007
1143
|
session.send("比赛尚未解析,将在解析完成后发布。");
|
|
1008
1144
|
}
|
|
1009
1145
|
} catch (error) {
|
|
1010
1146
|
console.error(error);
|
|
1011
1147
|
session.send("获取比赛信息失败。");
|
|
1148
|
+
ctx.database.remove("dt_previous_query_results", { matchId: parseInt(matchId) });
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
__name(queryAndDisplayMatch, "queryAndDisplayMatch");
|
|
1152
|
+
ctx.command("查询比赛 <match_id>", "查询比赛ID").usage("查询指定比赛ID的比赛数据,生成图片发布。").example("-查询比赛 1234567890").action(async ({ session }, match_id) => {
|
|
1153
|
+
if (!match_id) {
|
|
1154
|
+
session.send("请输入比赛ID。");
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
JSON.stringify;
|
|
1158
|
+
if (!/^\d{10}$/.test(match_id)) {
|
|
1159
|
+
session.send("比赛ID无效。");
|
|
1160
|
+
return;
|
|
1012
1161
|
}
|
|
1162
|
+
session.send("正在搜索对局详情,请稍后...");
|
|
1163
|
+
queryAndDisplayMatch(session, match_id);
|
|
1013
1164
|
});
|
|
1014
1165
|
ctx.command("查询最近比赛 [input_data]", "查询玩家的最近比赛").usage("查询指定玩家的最近一场比赛的比赛数据,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").example("-查询最近比赛 123456789").example("-查询最近比赛 张三").action(async ({ session }, input_data) => {
|
|
1015
1166
|
if (session.guild) {
|
|
@@ -1035,28 +1186,7 @@ async function apply(ctx, config) {
|
|
|
1035
1186
|
session.send("获取玩家最近比赛失败。");
|
|
1036
1187
|
return;
|
|
1037
1188
|
}
|
|
1038
|
-
|
|
1039
|
-
let match;
|
|
1040
|
-
let queryLocal = await ctx.database.get("dt_previous_query_results", lastMatchId, ["data"]);
|
|
1041
|
-
if (queryLocal.length > 0) {
|
|
1042
|
-
match = queryLocal[0].data;
|
|
1043
|
-
} else {
|
|
1044
|
-
let queryRes = await query(MATCH_INFO(lastMatchId));
|
|
1045
|
-
if (queryRes.status == 200) {
|
|
1046
|
-
match = getFormattedMatchData(queryRes.data.data.match);
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
if (match.parsedDateTime) {
|
|
1050
|
-
session.send(await ctx.puppeteer.render(genMatchImageHTML(match)));
|
|
1051
|
-
ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
|
|
1052
|
-
} else {
|
|
1053
|
-
pendingMatches.push({ matchId: lastMatchId, platform: session.event.platform, guildId: session.event.guild.id });
|
|
1054
|
-
session.send("比赛尚未解析,将在解析完成后发布。");
|
|
1055
|
-
}
|
|
1056
|
-
} catch (error) {
|
|
1057
|
-
console.error(error);
|
|
1058
|
-
session.send("获取比赛信息失败。");
|
|
1059
|
-
}
|
|
1189
|
+
queryAndDisplayMatch(session, lastMatchId);
|
|
1060
1190
|
}
|
|
1061
1191
|
});
|
|
1062
1192
|
ctx.command("查询玩家 <input_data>", "查询玩家信息").usage("查询指定玩家的个人信息与最近战绩,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").example("-查询玩家 123456789").example("-查询玩家 张三").action(async ({ session }, input_data) => {
|
|
@@ -1112,7 +1242,7 @@ async function apply(ctx, config) {
|
|
|
1112
1242
|
player.heroesPerformanceTop10 = playerExtra.heroesPerformance.slice(0, 10);
|
|
1113
1243
|
} else
|
|
1114
1244
|
throw 0;
|
|
1115
|
-
session.send(await ctx.puppeteer.render(
|
|
1245
|
+
session.send(await ctx.puppeteer.render(genImageHTML(player, config.template_player, "player" /* Player */)));
|
|
1116
1246
|
} catch (error) {
|
|
1117
1247
|
console.error(error);
|
|
1118
1248
|
session.send("获取玩家信息失败。");
|
|
@@ -1165,7 +1295,7 @@ async function apply(ctx, config) {
|
|
|
1165
1295
|
if (queryRes3.status == 200) {
|
|
1166
1296
|
let hero = queryRes3.data.data.constants.hero;
|
|
1167
1297
|
hero.talents.forEach((talent) => talent.name_cn = AbilitiesConstantsCN.data.abilities.find((item) => item.id == talent.abilityId).language.displayName);
|
|
1168
|
-
await session.send(await ctx.puppeteer.render(
|
|
1298
|
+
await session.send(await ctx.puppeteer.render(genImageHTML(hero, config.template_hero, "hero" /* Hero */)));
|
|
1169
1299
|
} else
|
|
1170
1300
|
throw 0;
|
|
1171
1301
|
} catch (error) {
|
|
@@ -1292,7 +1422,7 @@ async function apply(ctx, config) {
|
|
|
1292
1422
|
const commingMatches = scanningMatches.filter((item) => item.matchId == match.id);
|
|
1293
1423
|
const realCommingMatches = commingMatches.filter((commingMatch, index, self) => index === self.findIndex((t) => t.guildId === commingMatch.guildId && t.platform === commingMatch.platform));
|
|
1294
1424
|
let broadMatchMessage = "";
|
|
1295
|
-
const img = await ctx.puppeteer.render(
|
|
1425
|
+
const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
|
|
1296
1426
|
for (let comming of realCommingMatches) {
|
|
1297
1427
|
let commingSubscribedPlayers = subscribedPlayersInGuild.filter((item) => item.platform == comming.platform && item.guildId == comming.guildId);
|
|
1298
1428
|
let idsToFind = commingSubscribedPlayers.map((item) => item.steamId);
|
|
@@ -1311,7 +1441,7 @@ async function apply(ctx, config) {
|
|
|
1311
1441
|
broadPlayerMessage += random.pick(LOSE_NEGATIVE);
|
|
1312
1442
|
}
|
|
1313
1443
|
broadPlayerMessage += `。
|
|
1314
|
-
KDA:${((player.kills + player.assists) /
|
|
1444
|
+
KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${player.kills}/${player.deaths}/${player.assists}],GPM/XPM:${player.goldPerMinute}/${player.experiencePerMinute},补刀数:${player.numLastHits}/${player.numDenies},伤害/塔伤:${player.heroDamage}/${player.towerDamage},参战/参葬率:${(player.killContribution * 100).toFixed(2)}%/${(player.deathContribution * 100).toFixed(2)}%`;
|
|
1315
1445
|
broadMatchMessage += broadPlayerMessage + "\n";
|
|
1316
1446
|
}
|
|
1317
1447
|
await ctx.broadcast([`${comming.platform}:${comming.guildId}`], broadMatchMessage + img);
|
|
@@ -1322,6 +1452,7 @@ KDA:${((player.kills + player.assists) / Math.max(1, player.deaths)).toFixed(2
|
|
|
1322
1452
|
ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", match.id);
|
|
1323
1453
|
} catch (error) {
|
|
1324
1454
|
console.error(error);
|
|
1455
|
+
ctx.database.remove("dt_previous_query_results", { matchId: pendingMatch.matchId });
|
|
1325
1456
|
}
|
|
1326
1457
|
}
|
|
1327
1458
|
});
|
|
@@ -1330,638 +1461,28 @@ KDA:${((player.kills + player.assists) / Math.max(1, player.deaths)).toFixed(2
|
|
|
1330
1461
|
});
|
|
1331
1462
|
}
|
|
1332
1463
|
__name(apply, "apply");
|
|
1333
|
-
function
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
return `rgb(${gray},${gray},${gray})`;
|
|
1343
|
-
}
|
|
1344
|
-
};
|
|
1345
|
-
const laneSVG = {
|
|
1346
|
-
stomp: `<svg viewBox="0 0 24 24" class="hitagi__sc-1apuy4g-0 hmhZOG"><path d="M8.05731 22.3674L9.60454 22.8002L11.5974 21.6551L12.043 20.0773L13.5902 20.51L15.583 19.3649L16.0287 17.7871L17.5759 18.2199L19.5687 17.0748L20.0143 15.4969L21.5615 15.9297L23.5544 14.7846L24 13.2068L23.4492 12.2014L7.50651 21.3621L8.05731 22.3674ZM12.1328 3.50265L11.0312 1.49196C10.8798 1.21549 10.5316 1.11811 10.2576 1.27556L0.29345 7.00098C0.0194354 7.15843 -0.0808273 7.51346 0.0706444 7.78993L1.44766 10.3033L11.91 4.29159C12.184 4.13414 12.2843 3.77912 12.1328 3.50265ZM18.3935 8.4063L14.1658 9.60458L12.4221 10.6065C12.2851 10.6853 12.111 10.6366 12.0353 10.4983L11.7599 9.99565C11.6842 9.85742 11.7343 9.6799 11.8713 9.60118L13.615 8.59924L13.0642 7.59389L11.3205 8.59584C11.1835 8.67456 11.0094 8.62587 10.9337 8.48765L10.6583 7.98497C10.5826 7.84673 10.6327 7.66922 10.7697 7.5905L12.5134 6.58855L11.9626 5.58321L1.99846 11.3086L6.9557 20.3567L22.8984 11.196L22.2615 10.0336C21.5024 8.64813 19.9073 7.97847 18.3935 8.4063Z"></path></svg>`,
|
|
1347
|
-
victory: `<svg viewBox="0 0 512 512"><path d="M198.844 64.75c-.985 0-1.974.03-2.97.094-15.915 1.015-32.046 11.534-37.78 26.937-34.072 91.532-51.085 128.865-61.5 222.876 14.633 13.49 31.63 26.45 50.25 38.125l66.406-196.467 17.688 5.968L163.28 362.5c19.51 10.877 40.43 20.234 62 27.28l75.407-201.53 17.5 6.53-74.937 200.282c19.454 5.096 39.205 8.2 58.78 8.875L381.345 225.5l17.094 7.594-75.875 170.656c21.82-1.237 43.205-5.768 63.437-14.28 43.317-53.844 72.633-109.784 84.5-172.69 5.092-26.992-14.762-53.124-54.22-54.81l-6.155-.282-2.188-5.75c-8.45-22.388-19.75-30.093-31.5-32.47-11.75-2.376-25.267 1.535-35.468 7.376l-13.064 7.47-.906-15c-.99-16.396-10.343-29.597-24.313-35.626-13.97-6.03-33.064-5.232-54.812 9.906l-10.438 7.25-3.812-12.125c-6.517-20.766-20.007-27.985-34.78-27.97zM103.28 188.344C71.143 233.448 47.728 299.56 51.407 359.656c27.54 21.84 54.61 33.693 80.063 35.438 14.155.97 27.94-1.085 41.405-6.438-35.445-17.235-67.36-39.533-92.594-63.53l-3.343-3.157.5-4.595c5.794-54.638 13.946-91.5 25.844-129.03z"/></svg>`,
|
|
1348
|
-
fail: `<svg viewBox="0 0 36 36"><path fill="#ff6961" d="M36 32a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4v28z"></path><circle fill="#FFF" cx="27" cy="7" r="3"></circle><path fill="#FFF" d="M13.06 13.06l2.367-2.366l3.859 1.158l-2.635 2.847a10.018 10.018 0 0 1 4.392 3.379l5.017-5.017a1.5 1.5 0 0 0-.63-2.497l-9.999-3a1.495 1.495 0 0 0-1.492.376l-3 3a1.5 1.5 0 1 0 2.121 2.12zm16.065 4.949a1.496 1.496 0 0 0-1.262-.503l-6.786.617a9.966 9.966 0 0 1 1.464 2.879l3.548-.322l-1.554 6.995a1.499 1.499 0 1 0 2.928.65l2-9a1.5 1.5 0 0 0-.338-1.316zM13 16a8 8 0 1 0 0 16a8 8 0 0 0 0-16zm0 14a6 6 0 1 1 .002-12.002A6 6 0 0 1 13 30z"></path></svg>`,
|
|
1349
|
-
stomped: `<svg viewBox="-1 0 19 19"><path d="M16.417 9.579A7.917 7.917 0 1 1 8.5 1.662a7.917 7.917 0 0 1 7.917 7.917zm-2.458 2.96a.396.396 0 0 0-.396-.397h-.667a1.527 1.527 0 0 0-1.249-1.114.777.777 0 0 0 .014-.145V9.378a.794.794 0 0 0-.792-.792H8.201a2.984 2.984 0 0 0-1.682-.516l-.11.002V7.42h2.997a.396.396 0 1 0 0-.792H6.41v-1.3a.396.396 0 0 0-.396-.397H4.891a.396.396 0 0 0 0 .792h.727V8.21a2.997 2.997 0 1 0 3.836 3.466h.71a1.526 1.526 0 1 0 2.732 1.26h.667a.396.396 0 0 0 .396-.397zM8.078 9.507a2.205 2.205 0 1 1-1.559-.646 2.19 2.19 0 0 1 1.559.646zm4.078 3.03a.734.734 0 1 1-.733-.734.735.735 0 0 1 .733.733z"/></svg>`,
|
|
1350
|
-
tie: `<svg fill="#fff" viewBox="0 0 512.001 512.001"><g><g><path d="M120.988,239.868c-4.496,10.625-5.122,20.183-5.157,20.811c-0.267,4.607,3.243,8.547,7.849,8.829 c4.618,0.29,8.574-3.228,8.873-7.833c0.265-4.771,2.339-13.092,5.884-19.44C137.421,242.113,141.397,242.649,120.988,239.868z"/></g></g><g><g><path d="M391.178,255.418c-0.211,8.054-2.458,17.62-6.74,28.398c-1.708,4.299,0.393,9.168,4.692,10.875 c4.293,1.708,9.167-0.39,10.875-4.692c5.103-12.842,7.74-24.392,7.943-34.581H391.178z"/></g></g><g><g><path d="M164.769,210.51c1.046,3.339,1.397,6.953,0.893,10.65c-0.293,2.146-0.857,4.188-1.648,6.1c0,0,51.266,3.416,198.065,3.949 c-0.086-6.331,2.19-12.199,6.244-16.732C217.627,214.046,164.769,210.51,164.769,210.51z"/></g></g><g><g><circle cx="37.179" cy="128.669" r="29.491"/></g></g><g><g><path d="M510.146,391.511l-37.916-66.985c14.35-49.173,20.678-68.137,20.678-68.137l8.949-67.014 c1.502-10.977-6.248-21.075-17.235-22.468l-18.183-2.305c-10.984-1.393-20.996,6.445-22.293,17.431l-1.884,15.955l28.718-21.317 l-37.91,42.278h-46.432c-6.571,0-11.898,5.328-11.898,11.898c0,6.57,5.328,11.898,11.898,11.898h51.744 c3.381,0,6.601-1.438,8.859-3.956l41.456-46.234l-32.023,54.694c-5.28,9.018-14.374,8.169-18.293,8.167c-1.959,0-3.31,0-5.295,0 c-0.399,0.898,3.152-7.399-24.44,57.181c-0.548,1.284-0.907,2.642-1.06,4.031l-8.934,80.338 c-0.939,8.447,5.667,15.857,14.208,15.857c7.179,0,13.361-5.401,14.172-12.701l8.702-78.244l21.512-50.353l-14.121,50.463 c-1.158,3.756-0.718,7.823,1.218,11.243l40.949,72.345c3.885,6.864,12.596,9.276,19.459,5.392 C511.615,407.085,514.03,398.373,510.146,391.511z"/></g></g><g><g><circle cx="464.865" cy="128.702" r="29.491"/></g></g><g><g><path d="M142.923,206.051l-59.556-8.118l-39.135-18.451l13.626,2.292c-1.422-10.945-11.411-18.577-22.254-17.202l-18.182,2.305 C6.43,168.271-1.315,178.374,0.186,189.345l9.12,68.689l21.865,70.857l5.829,70.795c0.646,7.848,7.527,13.705,15.401,13.057 c7.859-0.647,13.705-7.542,13.058-15.401l-5.956-72.345c-0.084-1.031-0.281-2.05-0.585-3.039l-14.123-50.463l21.514,50.353 l8.702,78.244c0.873,7.86,7.96,13.486,15.768,12.612c7.838-0.871,13.483-7.931,12.612-15.768l-8.934-80.338 c-0.154-1.388-0.511-2.747-1.06-4.032l-27.336-61.43l-2.945-24.951l-29.029-25.179l40.79,19.231 c1.097,0.517,2.266,0.862,3.468,1.027l61.369,8.365c6.521,0.887,12.509-3.68,13.396-10.183 C153.994,212.936,149.435,206.939,142.923,206.051z"/></g></g></svg>`
|
|
1351
|
-
};
|
|
1352
|
-
let matchInfo_html = `
|
|
1353
|
-
<img src="${getImageUrl("flag_radiant")}" alt="" class="flag radiant${match.didRadiantWin ? " won" : ""}" style="order: 1" />
|
|
1354
|
-
<img src="${getImageUrl("flag_dire")}" alt="" class="flag dire${match.didRadiantWin ? "" : " won"}" style="order: 3" />
|
|
1355
|
-
<p class="won${match.didRadiantWin ? " radiant" : ""}">获胜</p>
|
|
1356
|
-
<div class="details" style="order: 2">
|
|
1357
|
-
<p>比赛编号:<span class="match_id">${match.id}</span></p>
|
|
1358
|
-
<p>模式:<span class="mode">${lobbyTypes[match.lobbyType] || match.lobbyType}/${gameMode[match.gameMode] || match.gameMode}</span></p>
|
|
1359
|
-
<p>服务器:<span class="server">${region[match.regionId]}</span></p>
|
|
1360
|
-
<p>起始时间:<span class="start_time">${(0, import_moment.default)(new Date(match.startDateTime * 1e3)).format("YYYY-MM-DD HH:mm:ss").slice(2)}</span></p>
|
|
1361
|
-
<img src="${getImageUrl("star_" + match.rank?.toString().split("")[1])}" alt="" class="star">
|
|
1362
|
-
<img src="${getImageUrl("medal_" + match.rank?.toString().split("")[0])}" alt="" class="rank">
|
|
1363
|
-
<p>结束时间:<span class="end_time">${(0, import_moment.default)(new Date(match.endDateTime * 1e3)).format("YYYY-MM-DD HH:mm:ss").slice(2)}</span></p>
|
|
1364
|
-
<div class="score">
|
|
1365
|
-
<p class="score radiant">${match.radiantKillsCount}</p>
|
|
1366
|
-
<p class="time">${sec2time(match.durationSeconds)}</p>
|
|
1367
|
-
<p class="score dire">${match.direKillsCount}</p>
|
|
1368
|
-
</div>
|
|
1369
|
-
</div>
|
|
1370
|
-
`;
|
|
1371
|
-
$(".match_info").html(matchInfo_html);
|
|
1372
|
-
let players_html = { radiant: "", dire: "" };
|
|
1373
|
-
match.players.forEach((player) => {
|
|
1374
|
-
players_html[player.isRadiant ? "radiant" : "dire"] += sanitizeHTML`
|
|
1375
|
-
<div class="player${player.hero.id == 80 ? " bear" : ""}${player.leaverStatus != "NONE" && player.leaverStatus != "DISCONNECTED" ? " giveup" : ""}" style="order:${player.position?.slice(-1)}">
|
|
1376
|
-
<div class="hero">
|
|
1377
|
-
<div class="player_avatar">
|
|
1378
|
-
<img alt="" src="${getImageUrl(player.hero.shortName, "heroes" /* Heroes */)}" />
|
|
1379
|
-
<p class="party_line${player.partyId != null ? " party_" + match.party[player.partyId] : ""}"></p>
|
|
1380
|
-
<p class="party_mark${player.partyId != null ? " party_" + match.party[player.partyId] : ""}"></p>
|
|
1381
|
-
<p class="position p${Math.floor(player.order / 4) + 1}">${player.isRandom ? "随机" : `第<span>${player.order ? player.order + 1 : "-"}</span>手`}<br/>${position[player.position?.slice(-1)]}</p>
|
|
1382
|
-
<p class="level">${player.level}</p>
|
|
1383
|
-
</div>
|
|
1384
|
-
<div class="player_info">
|
|
1385
|
-
<summary class="player_name">${player.steamAccount.name}</summary>
|
|
1386
|
-
<summary class="player_performance">
|
|
1387
|
-
<span class="kda">${player.kills}/${player.deaths}/${player.assists}</span>
|
|
1388
|
-
<span class="kc" style="color:${kcndcStyle.kc(player.killContribution * 100)}">${Math.floor(player.killContribution * 100)}%</span>
|
|
1389
|
-
<span class="dc" style="color:${kcndcStyle.dc(player.deathContribution * 100)}">${Math.floor(player.deathContribution * 100)}%</span></summary>
|
|
1390
|
-
<summary class="player_net"><span class="networth">${player.networth}</span> <span class="score">${(player.heroDamage / player.networth)?.toFixed(2)}</span></summary>
|
|
1391
|
-
</div>
|
|
1392
|
-
<div class="player_lane ${player.laneResult}">
|
|
1393
|
-
${laneSVG[player.laneResult]}
|
|
1394
|
-
</div>
|
|
1395
|
-
<div class="player_rank">
|
|
1396
|
-
${player.steamAccount.seasonRank ? `
|
|
1397
|
-
<div class="rank">
|
|
1398
|
-
<img class="medal" src="${getImageUrl(
|
|
1399
|
-
"medal_" + (player.steamAccount.seasonLeaderboardRank ? player.steamAccount.seasonLeaderboardRank <= 100 ? player.steamAccount.seasonLeaderboardRank <= 10 ? "8c" : "8b" : player.steamAccount.seasonRank.toString().split("")[0] : player.steamAccount.seasonRank.toString().split("")[0])
|
|
1400
|
-
)}" alt="" />
|
|
1401
|
-
${!player.steamAccount.seasonLeaderboardRank ? `
|
|
1402
|
-
<img class="star" src="${getImageUrl("star_" + player.steamAccount.seasonRank.toString().split("")[1])}" alt="" />` : `
|
|
1403
|
-
<p>${player.steamAccount.seasonLeaderboardRank}</p>`}
|
|
1404
|
-
</div>` : `
|
|
1405
|
-
<div class="norank">
|
|
1406
|
-
<img class="medal" src="${getImageUrl("medal_0")}" alt="" />
|
|
1407
|
-
</div>`}
|
|
1408
|
-
<div class="dotaPlusLevel"${!player.dotaPlus ? ` style="display:none"` : ""}>
|
|
1409
|
-
<img src="${getImageUrl("hero_badge_" + (player.dotaPlus ? Math.ceil((player.dotaPlus?.level + 1) / 6) : 1))}" alt="" class="badge">
|
|
1410
|
-
<p class="level">${player.dotaPlus?.level}</p>
|
|
1411
|
-
</div>
|
|
1412
|
-
</div>
|
|
1413
|
-
</div>
|
|
1414
|
-
<div class="titles">
|
|
1415
|
-
${player.titles.map((item) => `<span style="color: ${item.color};">${item.name}</span>`).join(" ")}
|
|
1416
|
-
</div>
|
|
1417
|
-
${player.hero.id != 80 ? `
|
|
1418
|
-
<div class="items">
|
|
1419
|
-
<div class="items_normal">
|
|
1420
|
-
${player.items.map(
|
|
1421
|
-
(item) => item ? `
|
|
1422
|
-
<div class="item${item.isRecipe ? " recipe" : ""}">
|
|
1423
|
-
<img src="${getImageUrl(item.name, "items" /* Items */)}" alt="" />
|
|
1424
|
-
<p class="time">${sec2time(item.time)}</p>
|
|
1425
|
-
</div>` : `
|
|
1426
|
-
<div class="item" style="visibility:hidden"}">
|
|
1427
|
-
<img src="${getImageUrl("blink", "items" /* Items */)}" alt="" />
|
|
1428
|
-
<p class="time">--:--</p>
|
|
1429
|
-
</div>`
|
|
1430
|
-
).join("")}
|
|
1431
|
-
</div>
|
|
1432
|
-
<div class="items_backpack">
|
|
1433
|
-
${player.backpacks.map(
|
|
1434
|
-
(item) => item ? `
|
|
1435
|
-
<div class="item back${item.isRecipe ? " recipe" : ""}">
|
|
1436
|
-
<img src="${getImageUrl(item.name, "items" /* Items */)}" alt="" />
|
|
1437
|
-
<p class="time">${sec2time(item.time)}</p>
|
|
1438
|
-
</div>` : `
|
|
1439
|
-
<div class="item back" style="visibility:hidden"}">
|
|
1440
|
-
<img src="${getImageUrl("blink", "items" /* Items */)}" alt="" />
|
|
1441
|
-
<p class="time">--:--</p>
|
|
1442
|
-
</div>`
|
|
1443
|
-
).join("")}
|
|
1444
|
-
</div>
|
|
1445
|
-
<div class="item neutral" style="background-image: url(${getImageUrl(dotaconstants3.item_ids[player.neutral0Id], "items" /* Items */)})"></div>
|
|
1446
|
-
</div>
|
|
1447
|
-
<div class="buffs">
|
|
1448
|
-
<section>
|
|
1449
|
-
${player.stats?.matchPlayerBuffEvent?.map(
|
|
1450
|
-
(buff) => `
|
|
1451
|
-
<div class="buff">
|
|
1452
|
-
<img src="${getImageUrl(dotaconstants3[buff.abilityId ? "ability_ids" : "item_ids"][buff.abilityId ?? buff.itemId], buff.abilityId ? "abilities" /* Abilities */ : "items" /* Items */)}" alt="" />
|
|
1453
|
-
<p>${buff.stackCount ?? ""}</p>
|
|
1454
|
-
</div>`
|
|
1455
|
-
).join("")}
|
|
1456
|
-
</section>
|
|
1457
|
-
<section>
|
|
1458
|
-
<div class="support_item"${player.supportItemsCount[30] > 0 ? "" : ' style="display:none"'}>
|
|
1459
|
-
<img src="${getImageUrl("gem", "items" /* Items */)}" alt="" />
|
|
1460
|
-
<p>${player.supportItemsCount[30]}</p>
|
|
1461
|
-
</div>
|
|
1462
|
-
<div class="support_item"${player.supportItemsCount[40] > 0 ? "" : ' style="display:none"'}>
|
|
1463
|
-
<img src="${getImageUrl("dust", "items" /* Items */)}" alt="" />
|
|
1464
|
-
<p>${player.supportItemsCount[40]}</p>
|
|
1465
|
-
</div>
|
|
1466
|
-
<div class="support_item"${player.supportItemsCount[42] > 0 ? "" : ' style="display:none"'}>
|
|
1467
|
-
<img src="${getImageUrl("ward_observer", "items" /* Items */)}" alt="" />
|
|
1468
|
-
<p>${player.supportItemsCount[42]}</p>
|
|
1469
|
-
</div>
|
|
1470
|
-
<div class="support_item"${player.supportItemsCount[43] > 0 ? "" : ' style="display:none"'}>
|
|
1471
|
-
<img src="${getImageUrl("ward_sentry", "items" /* Items */)}" alt="" />
|
|
1472
|
-
<p>${player.supportItemsCount[43]}</p>
|
|
1473
|
-
</div>
|
|
1474
|
-
<div class="support_item"${player.supportItemsCount[188] > 0 ? "" : ' style="display:none"'}>
|
|
1475
|
-
<img src="${getImageUrl("smoke_of_deceit", "items" /* Items */)}" alt="" />
|
|
1476
|
-
<p>${player.supportItemsCount[188]}</p>
|
|
1477
|
-
</div>
|
|
1478
|
-
</section>
|
|
1479
|
-
</div>` : `
|
|
1480
|
-
<div class="items_buffs master">
|
|
1481
|
-
<div class="items master">
|
|
1482
|
-
${player.items.map(
|
|
1483
|
-
(item) => item ? `
|
|
1484
|
-
<div class="item${item.isRecipe ? " recipe" : ""}">
|
|
1485
|
-
<img src="${getImageUrl(item.name, "items" /* Items */)}" alt="" />
|
|
1486
|
-
<p class="time">${sec2time(item.time)}</p>
|
|
1487
|
-
</div>` : `
|
|
1488
|
-
<div class="item" style="visibility:hidden"}">
|
|
1489
|
-
<img src="${getImageUrl("blink", "items" /* Items */)}" alt="" />>
|
|
1490
|
-
<p class="time">--:--</p>
|
|
1491
|
-
</div>`
|
|
1492
|
-
).join("")}
|
|
1493
|
-
${player.backpacks.map(
|
|
1494
|
-
(item) => item ? `
|
|
1495
|
-
<div class="item back${item.isRecipe ? " recipe" : ""}">
|
|
1496
|
-
<img src="${getImageUrl(item.name, "items" /* Items */)}" alt="" />
|
|
1497
|
-
<p class="time">${sec2time(item.time)}</p>
|
|
1498
|
-
</div>` : `
|
|
1499
|
-
<div class="item back" style="visibility:hidden"}">
|
|
1500
|
-
<img src="${getImageUrl("blink", "items" /* Items */)}" alt="" />
|
|
1501
|
-
<p class="time">--:--</p>
|
|
1502
|
-
</div>`
|
|
1503
|
-
).join("")}
|
|
1504
|
-
<div class="item neutral">
|
|
1505
|
-
<img src="${getImageUrl(dotaconstants3.item_ids[player.neutral0Id], "items" /* Items */)}" alt="" />
|
|
1506
|
-
</div>
|
|
1507
|
-
</div>
|
|
1508
|
-
<div class="buffs master">
|
|
1509
|
-
${player.stats?.matchPlayerBuffEvent?.map(
|
|
1510
|
-
(buff) => `
|
|
1511
|
-
<div class="buff">
|
|
1512
|
-
<img src="${getImageUrl(dotaconstants3[buff.abilityId ? "ability_ids" : "item_ids"][buff.abilityId ?? buff.itemId], buff.abilityId ? "abilities" /* Abilities */ : "items" /* Items */)}" alt="" />
|
|
1513
|
-
<p>${buff.stackCount ?? ""}</p>
|
|
1514
|
-
</div>`
|
|
1515
|
-
).join("")}
|
|
1516
|
-
</div>
|
|
1517
|
-
</div>
|
|
1518
|
-
<div class="items_buffs slave">
|
|
1519
|
-
<div class="items slave">
|
|
1520
|
-
${player.unitItems.map(
|
|
1521
|
-
(item) => item ? `
|
|
1522
|
-
<div class="item${item.isRecipe ? " recipe" : ""}">
|
|
1523
|
-
<img src="${getImageUrl(item.name, "items" /* Items */)}" alt="" />
|
|
1524
|
-
<p class="time">${sec2time(item.time)}</p>
|
|
1525
|
-
</div>` : `
|
|
1526
|
-
<div class="item" style="visibility:hidden"}">
|
|
1527
|
-
<img src="${getImageUrl("blink", "items" /* Items */)}" alt="" />>
|
|
1528
|
-
<p class="time">--:--</p>
|
|
1529
|
-
</div>`
|
|
1530
|
-
).join("")}
|
|
1531
|
-
${player.unitBackpacks.map(
|
|
1532
|
-
(item) => item ? `
|
|
1533
|
-
<div class="item back${item.isRecipe ? " recipe" : ""}">
|
|
1534
|
-
<img src="${getImageUrl(item.name, "items" /* Items */)}" alt="" />
|
|
1535
|
-
<p class="time">${sec2time(item.time)}</p>
|
|
1536
|
-
</div>` : `
|
|
1537
|
-
<div class="item back" style="visibility:hidden"}">
|
|
1538
|
-
<img src="${getImageUrl("blink", "items" /* Items */)}" alt="" />
|
|
1539
|
-
<p class="time">--:--</p>
|
|
1540
|
-
</div>`
|
|
1541
|
-
).join("")}
|
|
1542
|
-
<div class="item neutral">
|
|
1543
|
-
<img src="${getImageUrl(dotaconstants3.item_ids[player.additionalUnit.neutral0Id], "items" /* Items */)}" alt="" />
|
|
1544
|
-
</div>
|
|
1545
|
-
</div>
|
|
1546
|
-
<div class="buffs_supportItems slave">
|
|
1547
|
-
<div class="buffs">
|
|
1548
|
-
<!-- 无有效API获取熊灵buff -->
|
|
1549
|
-
</div>
|
|
1550
|
-
<div class="support_items">
|
|
1551
|
-
<div class="support_item"${player.supportItemsCount[30] > 0 ? "" : ' style="display:none"'}>
|
|
1552
|
-
<img src="${getImageUrl("gem", "items" /* Items */)}" alt="" />
|
|
1553
|
-
<p>${player.supportItemsCount[30]}</p>
|
|
1554
|
-
</div>
|
|
1555
|
-
<div class="support_item"${player.supportItemsCount[40] > 0 ? "" : ' style="display:none"'}>
|
|
1556
|
-
<img src="${getImageUrl("dust", "items" /* Items */)}" alt="" />
|
|
1557
|
-
<p>${player.supportItemsCount[40]}</p>
|
|
1558
|
-
</div>
|
|
1559
|
-
<div class="support_item"${player.supportItemsCount[42] > 0 ? "" : ' style="display:none"'}>
|
|
1560
|
-
<img src="${getImageUrl("ward_observer", "items" /* Items */)}" alt="" />
|
|
1561
|
-
<p>${player.supportItemsCount[42]}</p>
|
|
1562
|
-
</div>
|
|
1563
|
-
<div class="support_item"${player.supportItemsCount[43] > 0 ? "" : ' style="display:none"'}>
|
|
1564
|
-
<img src="${getImageUrl("ward_sentry", "items" /* Items */)}" alt="" />
|
|
1565
|
-
<p>${player.supportItemsCount[43]}</p>
|
|
1566
|
-
</div>
|
|
1567
|
-
<div class="support_item"${player.supportItemsCount[188] > 0 ? "" : ' style="display:none"'}>
|
|
1568
|
-
<img src="${getImageUrl("smoke_of_deceit", "items" /* Items */)}" alt="" />
|
|
1569
|
-
<p>${player.supportItemsCount[188]}</p>
|
|
1570
|
-
</div>
|
|
1571
|
-
</div>
|
|
1572
|
-
</div>
|
|
1573
|
-
</div>`}
|
|
1574
|
-
<div class="details">
|
|
1575
|
-
<section>英雄伤害:<span class="hero_damage">${player.heroDamage}</span></section>
|
|
1576
|
-
<section>建筑伤害:<span class="building_damage">${player.towerDamage}</span></section>
|
|
1577
|
-
<section>受到伤害(减免后):<span class="tak">${player.stats?.heroDamageReport?.receivedTotal.physicalDamage + player.stats?.heroDamageReport?.receivedTotal.magicalDamage + player.stats?.heroDamageReport?.receivedTotal.pureDamage}</span></section>
|
|
1578
|
-
<section>补刀:<span class="lh">${player.numLastHits}</span>/<span class="dn">${player.numDenies}</span></section>
|
|
1579
|
-
<section>GPM/XPM:<span class="gpm">${player.goldPerMinute}</span>/<span class="xpm">${player.experiencePerMinute}</span></section>
|
|
1580
|
-
<section>治疗量:<span class="heal">${player.heroHealing}</span></section>
|
|
1581
|
-
<section>控制时间:<span class="building_damage">${(player.stats?.heroDamageReport?.dealtTotal.stunDuration / 100).toFixed(2)}/${(player.stats?.heroDamageReport?.dealtTotal.slowDuration / 100).toFixed(2)}/${(player.stats?.heroDamageReport?.dealtTotal.disableDuration / 100).toFixed(2)}</span>s</section>
|
|
1582
|
-
</div>
|
|
1583
|
-
</div>`;
|
|
1584
|
-
});
|
|
1585
|
-
$(".radiant_players").html(players_html.radiant);
|
|
1586
|
-
$(".dire_players").html(players_html.dire);
|
|
1587
|
-
$(".ban_list").html(
|
|
1588
|
-
match.pickBans.filter((hero) => !hero.isPick).map((hero) => `<div class="ban_hero"><img src="${getImageUrl(/^npc_dota_hero_(?<name>.+)$/.exec(dotaconstants3.heroes[hero.bannedHeroId].name)[1], "heroes" /* Heroes */)}" alt="" /></div>`).join("")
|
|
1589
|
-
);
|
|
1590
|
-
if (process.env.NODE_ENV === "development")
|
|
1591
|
-
import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html", $.html());
|
|
1592
|
-
return $.html();
|
|
1593
|
-
}
|
|
1594
|
-
__name(genMatchImageHTML, "genMatchImageHTML");
|
|
1595
|
-
function genHeroHTML(hero) {
|
|
1596
|
-
let $ = cheerio.load(import_fs2.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/hero.html`, "utf-8"));
|
|
1597
|
-
let html = `
|
|
1598
|
-
<div class="hero" id="${hero.id}">
|
|
1599
|
-
<img src="${getImageUrl(hero.shortName, "heroes" /* Heroes */)}" alt="" />
|
|
1600
|
-
<img class="pri_attr" src="${getImageUrl(primary_attrs[dotaconstants3.heroes[hero.id].primary_attr], "icons" /* Icons */)}" alt="" />
|
|
1601
|
-
<div class="info">
|
|
1602
|
-
<p class="name">${hero.language.displayName}</p>
|
|
1603
|
-
<p class="roles">
|
|
1604
|
-
${hero.roles.map((item) => `<span class="role level${item.level}">${roles[item.roleId]}</span>`).join("")}
|
|
1605
|
-
</p>
|
|
1606
|
-
<p class="attrs">
|
|
1607
|
-
<span class="str">${dotaconstants3.heroes[hero.id].base_str} <span class="gain">+${dotaconstants3.heroes[hero.id].str_gain.toFixed(1)}</span></span>
|
|
1608
|
-
<span class="agi">${dotaconstants3.heroes[hero.id].base_agi} <span class="gain">+${dotaconstants3.heroes[hero.id].agi_gain.toFixed(1)}</span></span>
|
|
1609
|
-
<span class="int">${dotaconstants3.heroes[hero.id].base_int} <span class="gain">+${dotaconstants3.heroes[hero.id].int_gain.toFixed(1)}</span></span>
|
|
1610
|
-
</p>
|
|
1611
|
-
</div>
|
|
1612
|
-
</div>
|
|
1613
|
-
<div class="details">
|
|
1614
|
-
<div class="hype_talents">
|
|
1615
|
-
<div class="hype">
|
|
1616
|
-
${hero.language.hype}
|
|
1617
|
-
</div>
|
|
1618
|
-
<div class="talents">
|
|
1619
|
-
<div class="talent">
|
|
1620
|
-
<div class="left">${hero.talents[7].name_cn}</div>
|
|
1621
|
-
<div class="level">25</div>
|
|
1622
|
-
<div class="right">${hero.talents[6].name_cn}</div>
|
|
1623
|
-
</div>
|
|
1624
|
-
<div class="talent">
|
|
1625
|
-
<div class="left">${hero.talents[5].name_cn}</div>
|
|
1626
|
-
<div class="level">20</div>
|
|
1627
|
-
<div class="right">${hero.talents[4].name_cn}</div>
|
|
1628
|
-
</div>
|
|
1629
|
-
<div class="talent">
|
|
1630
|
-
<div class="left">${hero.talents[3].name_cn}</div>
|
|
1631
|
-
<div class="level">15</div>
|
|
1632
|
-
<div class="right">${hero.talents[2].name_cn}</div>
|
|
1633
|
-
</div>
|
|
1634
|
-
<div class="talent">
|
|
1635
|
-
<div class="left">${hero.talents[1].name_cn}</div>
|
|
1636
|
-
<div class="level">10</div>
|
|
1637
|
-
<div class="right">${hero.talents[0].name_cn}</div>
|
|
1638
|
-
</div>
|
|
1639
|
-
</div>
|
|
1640
|
-
</div>
|
|
1641
|
-
<table class="list">
|
|
1642
|
-
<tbody>
|
|
1643
|
-
<tr>
|
|
1644
|
-
<td>初始生命值</td>
|
|
1645
|
-
<td>${dotaconstants3.heroes[hero.id].base_health + dotaconstants3.heroes[hero.id].base_str * 22}</td>
|
|
1646
|
-
</tr>
|
|
1647
|
-
<tr>
|
|
1648
|
-
<td>初始生命回复</td>
|
|
1649
|
-
<td>${dotaconstants3.heroes[hero.id].base_health_regen}</td>
|
|
1650
|
-
</tr>
|
|
1651
|
-
<tr>
|
|
1652
|
-
<td>初始魔法值</td>
|
|
1653
|
-
<td>${dotaconstants3.heroes[hero.id].base_mana + dotaconstants3.heroes[hero.id].base_int * 12}</td>
|
|
1654
|
-
</tr>
|
|
1655
|
-
<tr>
|
|
1656
|
-
<td>初始魔法回复</td>
|
|
1657
|
-
<td>${dotaconstants3.heroes[hero.id].base_mana_regen}</td>
|
|
1658
|
-
</tr>
|
|
1659
|
-
<tr>
|
|
1660
|
-
<td>初始攻击力</td>
|
|
1661
|
-
<td>${dotaconstants3.heroes[hero.id].base_mr + Math.round(
|
|
1662
|
-
dotaconstants3.heroes[hero.id].primary_attr == "all" ? (dotaconstants3.heroes[hero.id].base_str + dotaconstants3.heroes[hero.id].base_agi + dotaconstants3.heroes[hero.id].base_int) * 0.7 : dotaconstants3.heroes[hero.id]["base_" + dotaconstants3.heroes[hero.id].primary_attr]
|
|
1663
|
-
)}(${dotaconstants3.heroes[hero.id].base_attack_min + Math.round(
|
|
1664
|
-
dotaconstants3.heroes[hero.id].primary_attr == "all" ? (dotaconstants3.heroes[hero.id].base_str + dotaconstants3.heroes[hero.id].base_agi + dotaconstants3.heroes[hero.id].base_int) * 0.7 : dotaconstants3.heroes[hero.id]["base_" + dotaconstants3.heroes[hero.id].primary_attr]
|
|
1665
|
-
)}~${dotaconstants3.heroes[hero.id].base_attack_max + Math.round(
|
|
1666
|
-
dotaconstants3.heroes[hero.id].primary_attr == "all" ? (dotaconstants3.heroes[hero.id].base_str + dotaconstants3.heroes[hero.id].base_agi + dotaconstants3.heroes[hero.id].base_int) * 0.7 : dotaconstants3.heroes[hero.id]["base_" + dotaconstants3.heroes[hero.id].primary_attr]
|
|
1667
|
-
)})</td>
|
|
1668
|
-
</tr>
|
|
1669
|
-
<tr>
|
|
1670
|
-
<td>基础攻击间隔</td>
|
|
1671
|
-
<td>${dotaconstants3.heroes[hero.id].attack_rate.toFixed(1)}</td>
|
|
1672
|
-
</tr>
|
|
1673
|
-
<tr>
|
|
1674
|
-
<td>基础攻击前摇</td>
|
|
1675
|
-
<td>${dotaconstants3.heroes[hero.id].attack_point.toFixed(1)}</td>
|
|
1676
|
-
</tr>
|
|
1677
|
-
<tr>
|
|
1678
|
-
<td>攻击范围</td>
|
|
1679
|
-
<td>${dotaconstants3.heroes[hero.id].attack_range}</td>
|
|
1680
|
-
</tr>
|
|
1681
|
-
<tr>
|
|
1682
|
-
<td>护甲</td>
|
|
1683
|
-
<td>${(Math.round((dotaconstants3.heroes[hero.id].base_armor + dotaconstants3.heroes[hero.id].base_agi * 0.167) * 10) / 10).toFixed(1)}</td>
|
|
1684
|
-
</tr>
|
|
1685
|
-
<tr>
|
|
1686
|
-
<td>移动速度</td>
|
|
1687
|
-
<td>${dotaconstants3.heroes[hero.id].move_speed}</td>
|
|
1688
|
-
</tr>
|
|
1689
|
-
<tr>
|
|
1690
|
-
<td>视野范围</td>
|
|
1691
|
-
<td>${dotaconstants3.heroes[hero.id].day_vision}(${dotaconstants3.heroes[hero.id].night_vision})</td>
|
|
1692
|
-
</tr>
|
|
1693
|
-
</tbody>
|
|
1694
|
-
</table>
|
|
1695
|
-
</div>
|
|
1696
|
-
<div class="skills">
|
|
1697
|
-
${hero.abilities.filter((item) => dotaconstants3.abilities[item.ability.name].behavior != "Hidden").map(
|
|
1698
|
-
(item) => `
|
|
1699
|
-
<div class="skill">
|
|
1700
|
-
<p class="title">${item.ability.language.displayName}</p>
|
|
1701
|
-
${item.ability.stat.isGrantedByScepter ? `<svg class="scepter" viewBox="0 0 19 20" fill="hsla(0,0%,100%,0.16)" width="24"><path d="M4.795 14.99a2.06 2.06 0 00-.96-.388c-1.668-.204-2.506.518-3.107 1.008.464.128.879.364.867.97 2.347-1.605 4.159.84 2.415 2.666-.14.147.65.929.767.718.203-.365.79-1.064 1.445-1.064.964 0 1.529.68 1.823.838.267.144.793-.372.642-.675-.03-.06-.229-.204-.569-.438-1.407-.197-1.935-1.093-2.37-2.026-.276-.593-.503-1.206-.953-1.61zm9.41 0a2.06 2.06 0 01.96-.388c1.668-.204 2.507.518 3.107 1.008-.464.128-.879.364-.867.97-2.347-1.605-4.158.84-2.415 2.666.14.147-.65.929-.768.718-.202-.365-.79-1.064-1.444-1.064-.965 0-1.529.68-1.823.838-.267.144-.793-.372-.642-.675.03-.06.229-.204.569-.438 1.407-.197 1.935-1.093 2.37-2.026.276-.593.503-1.206.953-1.61zm-3.919-2.211c0-.233-.175-.423-.392-.423h-.788c-.217 0-.392.19-.392.423v5.665c0 .232.175.421.392.421h.788c.216 0 .392-.189.392-.421v-5.665zm-1.989 2.543c-.553-.139-2.074-.563-2.702-1.17-.814-.784-1.107-3.135-2.655-3.52-1.29-.32-2.448.27-2.924 1.05-.06.101.055.241.252.178 2.786-.884 2.957 1.674 2.672 2.215a.275.275 0 00-.024.057c.87-.106 1.462.043 1.893.328.447.294.732.738.975 1.231.515 1.042.822 2.335 2.513 2.512v-2.88zm2.406 0c.553-.139 2.074-.563 2.703-1.17.812-.784 1.106-3.135 2.654-3.52 1.29-.32 2.448.27 2.924 1.05.06.101-.055.241-.252.178-2.786-.884-2.957 1.674-2.672 2.215a.27.27 0 01.024.057c-.87-.106-1.462.043-1.893.328-.447.294-.732.738-.975 1.231-.515 1.042-.822 2.335-2.513 2.512v-2.88z" fill="hsla(0,0%,100%,0.6)"></path><path d="M9.753.093a.39.39 0 00-.506 0C8.461.747 6.08 2.946 5.515 3.417a.434.434 0 00-.15.262c-.162.895-.949 4.817-1.12 5.764a.46.46 0 00.067.333c.37.564 1.665 2.752 2.071 3.37a.404.404 0 00.336.187h.768c.19 0 .356-.14.4-.337l.35-1.577a.416.416 0 01.399-.336h1.728c.19 0 .356.139.399.336l.35 1.577a.416.416 0 00.4.337h.768c.133 0 .259-.07.336-.187.406-.618 1.7-2.806 2.07-3.37a.457.457 0 00.067-.333c-.17-.947-.957-4.87-1.118-5.764a.435.435 0 00-.15-.262C12.92 2.946 10.537.747 9.752.093z" fill="url(#activeAghanimScepterGradient)"></path><defs><radialGradient id="activeAghanimScepterGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(9.03623 10.4684) rotate(-90) scale(9.38905 7.0456)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient></defs></svg>` : ""}
|
|
1702
|
-
${item.ability.stat.isGrantedByShard ? `<svg class="shard" viewBox="0 0 19 10" fill="hsla(0,0%,100%,0.16)" width="24"><path d="M0.259504 4.54746C0.272981 4.60325 0.326002 4.64198 0.386194 4.64198C0.831857 4.62418 2.60461 4.45628 3.91732 2.90727C4.49956 2.22054 4.37916 1.21884 3.64777 0.671532C2.91819 0.125197 1.85256 0.238284 1.27032 0.924899C-0.0423919 2.47305 0.17864 4.13525 0.259504 4.54746Z" fill="url(#activeAghanimLeftShardGradient)"></path><path d="M9.46713 9.98081C9.42698 10.0064 9.37572 10.0064 9.33559 9.98081C8.88968 9.67166 6.33212 7.75166 6.33212 4.38581C6.33212 2.96661 7.70742 1.81406 9.40136 1.81406C11.0953 1.81406 12.4706 2.96661 12.4706 4.38581C12.4706 7.75166 9.91303 9.67166 9.46713 9.98081Z" fill="url(#activeAghanimMidShardGradient)"></path><path d="M18.6888 4.54746C18.6753 4.60325 18.6232 4.64198 18.5631 4.64198C18.1173 4.62418 16.3445 4.45628 15.0317 2.90727C14.4494 2.22054 14.5697 1.21884 15.3003 0.671532C16.0308 0.125197 17.0966 0.238284 17.6788 0.924899C18.9917 2.47305 18.7707 4.13525 18.6888 4.54746Z" fill="url(#activeAghanimRightShardGradient)"></path><defs><radialGradient id="activeAghanimMidShardGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(9.01787 2.49983) rotate(90) scale(7.50029 5.21143)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient><radialGradient id="activeAghanimLeftShardGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(3.98746 0.625367) rotate(128.66) scale(6.00315 4.79432)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient><radialGradient id="activeAghanimRightShardGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(14.2996 0.625367) rotate(51.3402) scale(6.00316 4.7942)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient></defs></svg>` : ""}
|
|
1703
|
-
<div class="img_stats">
|
|
1704
|
-
<img src="${getImageUrl(item.ability.name, "abilities" /* Abilities */)}" alt="" />
|
|
1705
|
-
<div class="stats">
|
|
1706
|
-
<p class="behavior">技能:${(Array.isArray(dotaconstants3.abilities[item.ability.name].behavior) ? dotaconstants3.abilities[item.ability.name].behavior : [dotaconstants3.abilities[item.ability.name].behavior]).filter((beh) => beh !== "Hidden" || !(item.ability.stat.isGrantedByShard || item.ability.stat.isGrantedByScepter)).map((beh) => behavior[beh]).join("/")}</p>
|
|
1707
|
-
${dotaconstants3.abilities[item.ability.name].target_team ? `<p class="target_team">影响:${(Array.isArray(dotaconstants3.abilities[item.ability.name].target_team) ? dotaconstants3.abilities[item.ability.name].target_team : [dotaconstants3.abilities[item.ability.name].target_team]).map((tt) => target_team[tt]).join("/")}</p>` : ""}
|
|
1708
|
-
${!Array.isArray(dotaconstants3.abilities[item.ability.name].dmg_type) && dotaconstants3.abilities[item.ability.name].dmg_type ? `<p class="dmg_type ${dotaconstants3.abilities[item.ability.name].dmg_type}">伤害类型:</p>` : ""}
|
|
1709
|
-
${dotaconstants3.abilities[item.ability.name].dispellable ? `<p class="dispellable ${dotaconstants3.abilities[item.ability.name].dispellable == "Strong Dispels Only" ? "Strong" : dotaconstants3.abilities[item.ability.name].dispellable}">能否驱散:</p>` : ""}
|
|
1710
|
-
${!Array.isArray(dotaconstants3.abilities[item.ability.name].bkbpierce) && dotaconstants3.abilities[item.ability.name].bkbpierce ? `<p class="bkbpierce">无视减益免疫: ${dotaconstants3.abilities[item.ability.name].bkbpierce == "Yes" ? "是" : "否"}</p>` : ""}
|
|
1711
|
-
</div>
|
|
1712
|
-
</div>
|
|
1713
|
-
${item.ability.language.description.map((desc) => `<p class="description">${desc}</p>`).join("")}
|
|
1714
|
-
${item.ability.language.aghanimDescription ? `<p class="aghanim_description"><span class="title"><svg viewBox="0 0 19 20" fill="hsla(0,0%,100%,0.16)" width="24"><path d="M4.795 14.99a2.06 2.06 0 00-.96-.388c-1.668-.204-2.506.518-3.107 1.008.464.128.879.364.867.97 2.347-1.605 4.159.84 2.415 2.666-.14.147.65.929.767.718.203-.365.79-1.064 1.445-1.064.964 0 1.529.68 1.823.838.267.144.793-.372.642-.675-.03-.06-.229-.204-.569-.438-1.407-.197-1.935-1.093-2.37-2.026-.276-.593-.503-1.206-.953-1.61zm9.41 0a2.06 2.06 0 01.96-.388c1.668-.204 2.507.518 3.107 1.008-.464.128-.879.364-.867.97-2.347-1.605-4.158.84-2.415 2.666.14.147-.65.929-.768.718-.202-.365-.79-1.064-1.444-1.064-.965 0-1.529.68-1.823.838-.267.144-.793-.372-.642-.675.03-.06.229-.204.569-.438 1.407-.197 1.935-1.093 2.37-2.026.276-.593.503-1.206.953-1.61zm-3.919-2.211c0-.233-.175-.423-.392-.423h-.788c-.217 0-.392.19-.392.423v5.665c0 .232.175.421.392.421h.788c.216 0 .392-.189.392-.421v-5.665zm-1.989 2.543c-.553-.139-2.074-.563-2.702-1.17-.814-.784-1.107-3.135-2.655-3.52-1.29-.32-2.448.27-2.924 1.05-.06.101.055.241.252.178 2.786-.884 2.957 1.674 2.672 2.215a.275.275 0 00-.024.057c.87-.106 1.462.043 1.893.328.447.294.732.738.975 1.231.515 1.042.822 2.335 2.513 2.512v-2.88zm2.406 0c.553-.139 2.074-.563 2.703-1.17.812-.784 1.106-3.135 2.654-3.52 1.29-.32 2.448.27 2.924 1.05.06.101-.055.241-.252.178-2.786-.884-2.957 1.674-2.672 2.215a.27.27 0 01.024.057c-.87-.106-1.462.043-1.893.328-.447.294-.732.738-.975 1.231-.515 1.042-.822 2.335-2.513 2.512v-2.88z" fill="hsla(0,0%,100%,0.6)"></path><path d="M9.753.093a.39.39 0 00-.506 0C8.461.747 6.08 2.946 5.515 3.417a.434.434 0 00-.15.262c-.162.895-.949 4.817-1.12 5.764a.46.46 0 00.067.333c.37.564 1.665 2.752 2.071 3.37a.404.404 0 00.336.187h.768c.19 0 .356-.14.4-.337l.35-1.577a.416.416 0 01.399-.336h1.728c.19 0 .356.139.399.336l.35 1.577a.416.416 0 00.4.337h.768c.133 0 .259-.07.336-.187.406-.618 1.7-2.806 2.07-3.37a.457.457 0 00.067-.333c-.17-.947-.957-4.87-1.118-5.764a.435.435 0 00-.15-.262C12.92 2.946 10.537.747 9.752.093z" fill="url(#activeAghanimScepterGradient)"></path><defs><radialGradient id="activeAghanimScepterGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(9.03623 10.4684) rotate(-90) scale(9.38905 7.0456)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient></defs></svg>
|
|
1715
|
-
阿哈利姆神杖</span><span class="desc">${item.ability.language.aghanimDescription}</span></p>` : ""}
|
|
1716
|
-
${item.ability.language.shardDescription ? `<p class="aghanim_description"><span class="title"><svg viewBox="0 0 19 10" fill="hsla(0,0%,100%,0.16)" width="24"><path d="M0.259504 4.54746C0.272981 4.60325 0.326002 4.64198 0.386194 4.64198C0.831857 4.62418 2.60461 4.45628 3.91732 2.90727C4.49956 2.22054 4.37916 1.21884 3.64777 0.671532C2.91819 0.125197 1.85256 0.238284 1.27032 0.924899C-0.0423919 2.47305 0.17864 4.13525 0.259504 4.54746Z" fill="url(#activeAghanimLeftShardGradient)"></path><path d="M9.46713 9.98081C9.42698 10.0064 9.37572 10.0064 9.33559 9.98081C8.88968 9.67166 6.33212 7.75166 6.33212 4.38581C6.33212 2.96661 7.70742 1.81406 9.40136 1.81406C11.0953 1.81406 12.4706 2.96661 12.4706 4.38581C12.4706 7.75166 9.91303 9.67166 9.46713 9.98081Z" fill="url(#activeAghanimMidShardGradient)"></path><path d="M18.6888 4.54746C18.6753 4.60325 18.6232 4.64198 18.5631 4.64198C18.1173 4.62418 16.3445 4.45628 15.0317 2.90727C14.4494 2.22054 14.5697 1.21884 15.3003 0.671532C16.0308 0.125197 17.0966 0.238284 17.6788 0.924899C18.9917 2.47305 18.7707 4.13525 18.6888 4.54746Z" fill="url(#activeAghanimRightShardGradient)"></path><defs><radialGradient id="activeAghanimMidShardGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(9.01787 2.49983) rotate(90) scale(7.50029 5.21143)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient><radialGradient id="activeAghanimLeftShardGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(3.98746 0.625367) rotate(128.66) scale(6.00315 4.79432)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient><radialGradient id="activeAghanimRightShardGradient" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(14.2996 0.625367) rotate(51.3402) scale(6.00316 4.7942)"><stop stop-color="#00CEFF"></stop><stop offset="1" stop-color="#3443C4"></stop></radialGradient></defs></svg>
|
|
1717
|
-
阿哈利姆魔晶</span><span class="desc">${item.ability.language.shardDescription}</span></p>` : ""}
|
|
1718
|
-
<div class="notes"${!item.ability.language.notes.length ? ` style="display:none;"` : ""}>
|
|
1719
|
-
${item.ability.language.notes.map((note) => `<p>${note}</p>`).join("")}
|
|
1720
|
-
</div>
|
|
1721
|
-
<div class="attributes">
|
|
1722
|
-
${item.ability.language.attributes.map((attr) => {
|
|
1723
|
-
const parts = attr.split(":");
|
|
1724
|
-
return `<p><span class="item">${parts[0]}</span><span class="values">${parts[1]}</span></p>`;
|
|
1725
|
-
}).join("")}
|
|
1726
|
-
</div>
|
|
1727
|
-
<p>
|
|
1728
|
-
${dotaconstants3.abilities[item.ability.name].cd ? `<span class="cooldown"> ${(Array.isArray(dotaconstants3.abilities[item.ability.name].cd) ? dotaconstants3.abilities[item.ability.name].cd : [dotaconstants3.abilities[item.ability.name].cd]).join(
|
|
1729
|
-
" / "
|
|
1730
|
-
)} </span>` : ""}
|
|
1731
|
-
${dotaconstants3.abilities[item.ability.name].mc ? `<span class="mana_cost"> ${(Array.isArray(dotaconstants3.abilities[item.ability.name].mc) ? dotaconstants3.abilities[item.ability.name].mc : [dotaconstants3.abilities[item.ability.name].mc]).join(
|
|
1732
|
-
" / "
|
|
1733
|
-
)} </span>` : ""}
|
|
1734
|
-
</p>
|
|
1735
|
-
<p class="lore"${!item.ability.language.lore ? ` style="display:none;"` : ""}>${item.ability.language.lore}</p>
|
|
1736
|
-
</div>
|
|
1737
|
-
`
|
|
1738
|
-
).join("")}
|
|
1739
|
-
</div>
|
|
1740
|
-
<div class="lore">
|
|
1741
|
-
${hero.language.lore}
|
|
1742
|
-
</div>
|
|
1743
|
-
`;
|
|
1744
|
-
$(".wrapper").html(html);
|
|
1745
|
-
if (process.env.NODE_ENV === "development")
|
|
1746
|
-
import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html", $.html());
|
|
1747
|
-
return $.html();
|
|
1748
|
-
}
|
|
1749
|
-
__name(genHeroHTML, "genHeroHTML");
|
|
1750
|
-
function genPlayerHTML(player) {
|
|
1751
|
-
let $ = cheerio.load(import_fs2.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/player.html`, "utf-8"));
|
|
1752
|
-
const guildLevel = /* @__PURE__ */ __name((percent) => {
|
|
1753
|
-
if (percent <= 25) {
|
|
1754
|
-
return "Copper";
|
|
1755
|
-
} else if (percent <= 50) {
|
|
1756
|
-
return "Silver";
|
|
1757
|
-
} else if (percent <= 75) {
|
|
1758
|
-
return "Gold";
|
|
1759
|
-
} else {
|
|
1760
|
-
return "Diamond";
|
|
1761
|
-
}
|
|
1762
|
-
}, "guildLevel");
|
|
1763
|
-
const laneSVG = {
|
|
1764
|
-
stomp: `<svg viewBox="0 0 24 24" class="hitagi__sc-1apuy4g-0 hmhZOG"><path d="M8.05731 22.3674L9.60454 22.8002L11.5974 21.6551L12.043 20.0773L13.5902 20.51L15.583 19.3649L16.0287 17.7871L17.5759 18.2199L19.5687 17.0748L20.0143 15.4969L21.5615 15.9297L23.5544 14.7846L24 13.2068L23.4492 12.2014L7.50651 21.3621L8.05731 22.3674ZM12.1328 3.50265L11.0312 1.49196C10.8798 1.21549 10.5316 1.11811 10.2576 1.27556L0.29345 7.00098C0.0194354 7.15843 -0.0808273 7.51346 0.0706444 7.78993L1.44766 10.3033L11.91 4.29159C12.184 4.13414 12.2843 3.77912 12.1328 3.50265ZM18.3935 8.4063L14.1658 9.60458L12.4221 10.6065C12.2851 10.6853 12.111 10.6366 12.0353 10.4983L11.7599 9.99565C11.6842 9.85742 11.7343 9.6799 11.8713 9.60118L13.615 8.59924L13.0642 7.59389L11.3205 8.59584C11.1835 8.67456 11.0094 8.62587 10.9337 8.48765L10.6583 7.98497C10.5826 7.84673 10.6327 7.66922 10.7697 7.5905L12.5134 6.58855L11.9626 5.58321L1.99846 11.3086L6.9557 20.3567L22.8984 11.196L22.2615 10.0336C21.5024 8.64813 19.9073 7.97847 18.3935 8.4063Z"></path></svg>`,
|
|
1765
|
-
victory: `<svg viewBox="0 0 512 512"><path d="M198.844 64.75c-.985 0-1.974.03-2.97.094-15.915 1.015-32.046 11.534-37.78 26.937-34.072 91.532-51.085 128.865-61.5 222.876 14.633 13.49 31.63 26.45 50.25 38.125l66.406-196.467 17.688 5.968L163.28 362.5c19.51 10.877 40.43 20.234 62 27.28l75.407-201.53 17.5 6.53-74.937 200.282c19.454 5.096 39.205 8.2 58.78 8.875L381.345 225.5l17.094 7.594-75.875 170.656c21.82-1.237 43.205-5.768 63.437-14.28 43.317-53.844 72.633-109.784 84.5-172.69 5.092-26.992-14.762-53.124-54.22-54.81l-6.155-.282-2.188-5.75c-8.45-22.388-19.75-30.093-31.5-32.47-11.75-2.376-25.267 1.535-35.468 7.376l-13.064 7.47-.906-15c-.99-16.396-10.343-29.597-24.313-35.626-13.97-6.03-33.064-5.232-54.812 9.906l-10.438 7.25-3.812-12.125c-6.517-20.766-20.007-27.985-34.78-27.97zM103.28 188.344C71.143 233.448 47.728 299.56 51.407 359.656c27.54 21.84 54.61 33.693 80.063 35.438 14.155.97 27.94-1.085 41.405-6.438-35.445-17.235-67.36-39.533-92.594-63.53l-3.343-3.157.5-4.595c5.794-54.638 13.946-91.5 25.844-129.03z"/></svg>`,
|
|
1766
|
-
fail: `<svg viewBox="0 0 36 36"><path fill="#ff6961" d="M36 32a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4v28z"></path><circle fill="#FFF" cx="27" cy="7" r="3"></circle><path fill="#FFF" d="M13.06 13.06l2.367-2.366l3.859 1.158l-2.635 2.847a10.018 10.018 0 0 1 4.392 3.379l5.017-5.017a1.5 1.5 0 0 0-.63-2.497l-9.999-3a1.495 1.495 0 0 0-1.492.376l-3 3a1.5 1.5 0 1 0 2.121 2.12zm16.065 4.949a1.496 1.496 0 0 0-1.262-.503l-6.786.617a9.966 9.966 0 0 1 1.464 2.879l3.548-.322l-1.554 6.995a1.499 1.499 0 1 0 2.928.65l2-9a1.5 1.5 0 0 0-.338-1.316zM13 16a8 8 0 1 0 0 16a8 8 0 0 0 0-16zm0 14a6 6 0 1 1 .002-12.002A6 6 0 0 1 13 30z"></path></svg>`,
|
|
1767
|
-
stomped: `<svg viewBox="-1 0 19 19"><path d="M16.417 9.579A7.917 7.917 0 1 1 8.5 1.662a7.917 7.917 0 0 1 7.917 7.917zm-2.458 2.96a.396.396 0 0 0-.396-.397h-.667a1.527 1.527 0 0 0-1.249-1.114.777.777 0 0 0 .014-.145V9.378a.794.794 0 0 0-.792-.792H8.201a2.984 2.984 0 0 0-1.682-.516l-.11.002V7.42h2.997a.396.396 0 1 0 0-.792H6.41v-1.3a.396.396 0 0 0-.396-.397H4.891a.396.396 0 0 0 0 .792h.727V8.21a2.997 2.997 0 1 0 3.836 3.466h.71a1.526 1.526 0 1 0 2.732 1.26h.667a.396.396 0 0 0 .396-.397zM8.078 9.507a2.205 2.205 0 1 1-1.559-.646 2.19 2.19 0 0 1 1.559.646zm4.078 3.03a.734.734 0 1 1-.733-.734.735.735 0 0 1 .733.733z"/></svg>`,
|
|
1768
|
-
tie: `<svg fill="#fff" viewBox="0 0 512.001 512.001"><g><g><path d="M120.988,239.868c-4.496,10.625-5.122,20.183-5.157,20.811c-0.267,4.607,3.243,8.547,7.849,8.829 c4.618,0.29,8.574-3.228,8.873-7.833c0.265-4.771,2.339-13.092,5.884-19.44C137.421,242.113,141.397,242.649,120.988,239.868z"/></g></g><g><g><path d="M391.178,255.418c-0.211,8.054-2.458,17.62-6.74,28.398c-1.708,4.299,0.393,9.168,4.692,10.875 c4.293,1.708,9.167-0.39,10.875-4.692c5.103-12.842,7.74-24.392,7.943-34.581H391.178z"/></g></g><g><g><path d="M164.769,210.51c1.046,3.339,1.397,6.953,0.893,10.65c-0.293,2.146-0.857,4.188-1.648,6.1c0,0,51.266,3.416,198.065,3.949 c-0.086-6.331,2.19-12.199,6.244-16.732C217.627,214.046,164.769,210.51,164.769,210.51z"/></g></g><g><g><circle cx="37.179" cy="128.669" r="29.491"/></g></g><g><g><path d="M510.146,391.511l-37.916-66.985c14.35-49.173,20.678-68.137,20.678-68.137l8.949-67.014 c1.502-10.977-6.248-21.075-17.235-22.468l-18.183-2.305c-10.984-1.393-20.996,6.445-22.293,17.431l-1.884,15.955l28.718-21.317 l-37.91,42.278h-46.432c-6.571,0-11.898,5.328-11.898,11.898c0,6.57,5.328,11.898,11.898,11.898h51.744 c3.381,0,6.601-1.438,8.859-3.956l41.456-46.234l-32.023,54.694c-5.28,9.018-14.374,8.169-18.293,8.167c-1.959,0-3.31,0-5.295,0 c-0.399,0.898,3.152-7.399-24.44,57.181c-0.548,1.284-0.907,2.642-1.06,4.031l-8.934,80.338 c-0.939,8.447,5.667,15.857,14.208,15.857c7.179,0,13.361-5.401,14.172-12.701l8.702-78.244l21.512-50.353l-14.121,50.463 c-1.158,3.756-0.718,7.823,1.218,11.243l40.949,72.345c3.885,6.864,12.596,9.276,19.459,5.392 C511.615,407.085,514.03,398.373,510.146,391.511z"/></g></g><g><g><circle cx="464.865" cy="128.702" r="29.491"/></g></g><g><g><path d="M142.923,206.051l-59.556-8.118l-39.135-18.451l13.626,2.292c-1.422-10.945-11.411-18.577-22.254-17.202l-18.182,2.305 C6.43,168.271-1.315,178.374,0.186,189.345l9.12,68.689l21.865,70.857l5.829,70.795c0.646,7.848,7.527,13.705,15.401,13.057 c7.859-0.647,13.705-7.542,13.058-15.401l-5.956-72.345c-0.084-1.031-0.281-2.05-0.585-3.039l-14.123-50.463l21.514,50.353 l8.702,78.244c0.873,7.86,7.96,13.486,15.768,12.612c7.838-0.871,13.483-7.931,12.612-15.768l-8.934-80.338 c-0.154-1.388-0.511-2.747-1.06-4.032l-27.336-61.43l-2.945-24.951l-29.029-25.179l40.79,19.231 c1.097,0.517,2.266,0.862,3.468,1.027l61.369,8.365c6.521,0.887,12.509-3.68,13.396-10.183 C153.994,212.936,149.435,206.939,142.923,206.051z"/></g></g></svg>`
|
|
1769
|
-
};
|
|
1770
|
-
const outcomeCounts = {
|
|
1771
|
-
victory: 0,
|
|
1772
|
-
stomp: 0,
|
|
1773
|
-
fail: 0,
|
|
1774
|
-
stomped: 0,
|
|
1775
|
-
tie: 0
|
|
1464
|
+
function genImageHTML(data, template, type) {
|
|
1465
|
+
const templatePath = import_path2.default.join(`./node_modules/@sjtdev/koishi-plugin-${name}/template/${type}`, template + ".ejs");
|
|
1466
|
+
const templateData = {
|
|
1467
|
+
data,
|
|
1468
|
+
utils: utils_exports,
|
|
1469
|
+
ImageType,
|
|
1470
|
+
d2a: dotaconstants_add_exports,
|
|
1471
|
+
dotaconstants: dotaconstants3,
|
|
1472
|
+
moment: import_moment.default
|
|
1776
1473
|
};
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
case "DIRE_VICTORY":
|
|
1784
|
-
return { radiant: "fail", dire: "victory" };
|
|
1785
|
-
case "DIRE_STOMP":
|
|
1786
|
-
return { radiant: "stomped", dire: "stomp" };
|
|
1787
|
-
default:
|
|
1788
|
-
return { radiant: "tie", dire: "tie" };
|
|
1789
|
-
}
|
|
1790
|
-
}, "processLaneOutcome");
|
|
1791
|
-
let nearMatchCount = 25, nearWinCount = 0, streak = 0;
|
|
1792
|
-
player.matches.forEach((match) => {
|
|
1793
|
-
const innerPlayer = match.players[0];
|
|
1794
|
-
nearWinCount += match.didRadiantWin == innerPlayer.isRadiant ? 1 : 0;
|
|
1795
|
-
const didWin = match.didRadiantWin === innerPlayer.isRadiant;
|
|
1796
|
-
if (!player.streak) {
|
|
1797
|
-
if (streak != 0) {
|
|
1798
|
-
if (didWin && streak > 0)
|
|
1799
|
-
streak++;
|
|
1800
|
-
else if (!didWin && streak < 0)
|
|
1801
|
-
streak--;
|
|
1802
|
-
else
|
|
1803
|
-
player.streak = streak;
|
|
1804
|
-
} else
|
|
1805
|
-
streak = didWin ? 1 : -1;
|
|
1806
|
-
}
|
|
1807
|
-
const laneResult = {
|
|
1808
|
-
top: processLaneOutcome(match.topLaneOutcome),
|
|
1809
|
-
mid: processLaneOutcome(match.midLaneOutcome),
|
|
1810
|
-
bottom: processLaneOutcome(match.bottomLaneOutcome)
|
|
1811
|
-
};
|
|
1812
|
-
let laneKey = "mid";
|
|
1813
|
-
if (innerPlayer.lane === "SAFE_LANE") {
|
|
1814
|
-
laneKey = innerPlayer.isRadiant ? "bottom" : "top";
|
|
1815
|
-
} else if (innerPlayer.lane === "OFF_LANE") {
|
|
1816
|
-
laneKey = innerPlayer.isRadiant ? "top" : "bottom";
|
|
1817
|
-
}
|
|
1818
|
-
match.laneResult = laneResult[laneKey][innerPlayer.isRadiant ? "radiant" : "dire"];
|
|
1819
|
-
if (match.laneResult in outcomeCounts) {
|
|
1820
|
-
outcomeCounts[match.laneResult]++;
|
|
1821
|
-
}
|
|
1474
|
+
let result = "";
|
|
1475
|
+
ejs.renderFile(templatePath, templateData, (err, html) => {
|
|
1476
|
+
if (err)
|
|
1477
|
+
throw err;
|
|
1478
|
+
else
|
|
1479
|
+
result = html;
|
|
1822
1480
|
});
|
|
1823
|
-
const playerHTML = `
|
|
1824
|
-
<div class="avatar"><img src="${player.steamAccount.avatar}" alt="" /></div>
|
|
1825
|
-
<div class="info">
|
|
1826
|
-
<p class="name">${player.steamAccount.name}${player.guildMember ? ` <span class="guild ${guildLevel(player.guildMember.guild.currentPercentile)}">[${player.guildMember.guild.tag}]</span></p>` : ""}
|
|
1827
|
-
<p class="matches"><span>场次:${player.matchCount}(<span class="win">${player.winCount}</span>/<span class="lose">${player.matchCount - player.winCount}</span>)</span>胜率:<span style="color:${winRateColor(
|
|
1828
|
-
player.winCount / player.matchCount
|
|
1829
|
-
)};">${(player.winCount / player.matchCount * 100).toFixed(2)}%</span></p>
|
|
1830
|
-
<p class="matches"><span>最近25场:<span class="win">${nearWinCount}</span>/<span class="lose">${nearMatchCount - nearWinCount}</span></span><span>胜率:<span style="color:${winRateColor(nearWinCount / nearMatchCount)};">${(nearWinCount / nearMatchCount * 100).toFixed(2)}%</span></span><span>评分:${player.performance.imp}</span></span></p>
|
|
1831
|
-
<p class="matches"><span>对线:<span class="victory">${outcomeCounts.victory + outcomeCounts.stomp}(<span class="stomp">${outcomeCounts.stomp}</span>)</span>-<span class="tie">${outcomeCounts.tie}</span>-<span class="fail">${outcomeCounts.fail + outcomeCounts.stomped}(<span class="stomped">${outcomeCounts.stomped}</span>)</span></span><span>线优:<span style="color:${winRateColor(
|
|
1832
|
-
(outcomeCounts.victory + outcomeCounts.stomp + outcomeCounts.tie / 2) / (outcomeCounts.victory + outcomeCounts.stomp + outcomeCounts.tie + outcomeCounts.fail + outcomeCounts.stomped)
|
|
1833
|
-
)};">${((outcomeCounts.victory + outcomeCounts.stomp) / (outcomeCounts.victory + outcomeCounts.stomp + outcomeCounts.fail + outcomeCounts.stomped) * 100).toFixed(2)}%</span></span></p>
|
|
1834
|
-
</div>
|
|
1835
|
-
${player.steamAccount.seasonRank ? `
|
|
1836
|
-
<div class="rank">
|
|
1837
|
-
<img class="medal" src="${getImageUrl(
|
|
1838
|
-
"medal_" + (player.steamAccount.seasonLeaderboardRank ? player.steamAccount.seasonLeaderboardRank <= 100 ? player.steamAccount.seasonLeaderboardRank <= 10 ? "8c" : "8b" : player.steamAccount.seasonRank.toString().split("")[0] : player.steamAccount.seasonRank.toString().split("")[0])
|
|
1839
|
-
)}" alt="" />
|
|
1840
|
-
${!player.steamAccount.seasonLeaderboardRank ? `
|
|
1841
|
-
<img class="star" src="${getImageUrl("star_" + player.steamAccount.seasonRank.toString().split("")[1])}" alt="" />` : `
|
|
1842
|
-
<p>${player.steamAccount.seasonLeaderboardRank}</p>`}
|
|
1843
|
-
</div>` : `
|
|
1844
|
-
<div class="rank">
|
|
1845
|
-
<img class="medal" src="${getImageUrl("medal_0")}" alt="" />
|
|
1846
|
-
</div>`}`;
|
|
1847
|
-
const heroesCountPixels = 800 - ($(".tip:not(.row):not(.win_count):not(.lose_count)").length + 1) * 40;
|
|
1848
|
-
const highestCountsTotal = {
|
|
1849
|
-
winCount: Math.max(...player.heroesPerformanceTop10.map((hero) => hero.winCount)),
|
|
1850
|
-
loseCount: Math.max(...player.heroesPerformanceTop10.map((hero) => hero.matchCount - hero.winCount))
|
|
1851
|
-
};
|
|
1852
|
-
const pixelOfPerMatchInTotal = heroesCountPixels / (highestCountsTotal.winCount + highestCountsTotal.loseCount);
|
|
1853
|
-
const highestCountsNear = {
|
|
1854
|
-
winCount: Math.max(...player.heroesPerformance?.filter((hero) => hero.matchCount > 1)?.map((hero) => hero.winCount)),
|
|
1855
|
-
loseCount: Math.max(...player.heroesPerformance?.filter((hero) => hero.matchCount > 1)?.map((hero) => hero.matchCount - hero.winCount))
|
|
1856
|
-
};
|
|
1857
|
-
const nearAdjustmentFactor = Math.min(highestCountsTotal.winCount / (highestCountsTotal.winCount + highestCountsTotal.loseCount), highestCountsTotal.loseCount / (highestCountsTotal.winCount + highestCountsTotal.loseCount));
|
|
1858
|
-
const pixelOfPerMatchInNear = heroesCountPixels / (highestCountsNear?.winCount + highestCountsNear?.loseCount) * nearAdjustmentFactor;
|
|
1859
|
-
const heroesTotalHTML = player.heroesPerformanceTop10.map(
|
|
1860
|
-
(hero) => `
|
|
1861
|
-
<span><img alt="" src="${getImageUrl(hero.hero.shortName, "heroes/icons" /* HeroIcons */)}" /></span>
|
|
1862
|
-
<span class="count">${hero.matchCount}</span>
|
|
1863
|
-
<span class="win_rate">${(hero.winCount / hero.matchCount * 100).toFixed(0)}%</span>
|
|
1864
|
-
<span class="imp">${(hero.imp > 0 ? "+" : "") + hero.imp}</span>
|
|
1865
|
-
<span class="win" style="${hero.winCount == 0 ? "visibility:hidden;" : ""}width: ${hero.winCount * pixelOfPerMatchInTotal}px">${hero.winCount}</span>
|
|
1866
|
-
<span class="lose" style="${hero.matchCount - hero.winCount == 0 ? "visibility:hidden;" : ""}width: ${(hero.matchCount - hero.winCount) * pixelOfPerMatchInTotal}px">${hero.matchCount - hero.winCount}</span>`
|
|
1867
|
-
).join("") + player.heroesPerformance.filter((hero) => hero.matchCount > 1).map(
|
|
1868
|
-
(hero, index) => `
|
|
1869
|
-
<span style="order:${index + 1};"><img alt="" src="${getImageUrl(hero.hero.shortName, "heroes/icons" /* HeroIcons */)}" /></span>
|
|
1870
|
-
<span style="order:${index + 1};" class="count">${hero.matchCount}</span>
|
|
1871
|
-
<span style="order:${index + 1};" class="win_rate">${(hero.winCount / hero.matchCount * 100).toFixed(0)}%</span>
|
|
1872
|
-
<span style="order:${index + 1};" class="imp">${(hero.imp > 0 ? "+" : "") + hero.imp}</span>
|
|
1873
|
-
<span class="win" style="order:${index + 1};${hero.winCount == 0 ? "visibility:hidden;" : ""}width: ${hero.winCount * pixelOfPerMatchInNear}px">${hero.winCount}</span>
|
|
1874
|
-
<span class="lose" style="order:${index + 1};${hero.matchCount - hero.winCount == 0 ? "visibility:hidden;" : ""}width: ${(hero.matchCount - hero.winCount) * pixelOfPerMatchInNear}px">${hero.matchCount - hero.winCount}</span>`
|
|
1875
|
-
).join("");
|
|
1876
|
-
const streakHTML = `<div class="streak" style="box-shadow:none;color:${winRateColor((player.streak + 10) / 20)};">${Math.abs(player.streak) + (player.streak > 0 ? "连胜" : "连败")}</div>`;
|
|
1877
|
-
const matchesHTML = player.matches.map(
|
|
1878
|
-
(match) => `
|
|
1879
|
-
<tr class="match ${match.didRadiantWin == match.players[0].isRadiant ? "win" : "lose"}">
|
|
1880
|
-
<td>${match.id}</td>
|
|
1881
|
-
<td>
|
|
1882
|
-
<p>${lobbyTypes[match.lobbyType] || match.lobbyType}</p>
|
|
1883
|
-
<p>${gameMode[match.gameMode] || match.gameMode}</p>
|
|
1884
|
-
</td>
|
|
1885
|
-
<td><img alt="" src="${getImageUrl(match.players[0].hero.shortName, "heroes/icons" /* HeroIcons */)}" /></td>
|
|
1886
|
-
<td style="line-height: 20px">
|
|
1887
|
-
<p>${((match.players[0].kills + match.players[0].assists) / Math.max(1, match.players[0].deaths)).toFixed(2)} (${((match.players[0].kills + match.players[0].assists) / (match.players[0].isRadiant ? match.radiantKills.reduce((acc, cva) => acc + cva, 0) : match.direKills.reduce((acc, cva) => acc + cva, 0)) * 100).toFixed(0)}%)</p>
|
|
1888
|
-
<p>${match.players[0].kills}/${match.players[0].deaths}/${match.players[0].assists}</p>
|
|
1889
|
-
</td>
|
|
1890
|
-
<td>
|
|
1891
|
-
<div class="player_lane ${match.laneResult}">${laneSVG[match.laneResult]}</div>
|
|
1892
|
-
</td>
|
|
1893
|
-
<td style="line-height: 20px">${(0, import_moment.default)(new Date(match.endDateTime * 1e3)).format("YYYY-MM-DD HH:mm:ss").slice(2)}</td>
|
|
1894
|
-
<td>${sec2time(match.durationSeconds)}</td>
|
|
1895
|
-
<td>${(match.players[0].imp > 0 ? "+" : "") + match.players[0].imp}</td>
|
|
1896
|
-
<td><img class="medal" src="${getImageUrl("medal_" + match.rank.toString().split("")[0])}" style="width: 100%" /></td>
|
|
1897
|
-
</tr>`
|
|
1898
|
-
).join("");
|
|
1899
|
-
const dotaPlusHTML = player.dotaPlus.map(
|
|
1900
|
-
(hero) => `
|
|
1901
|
-
<div class="hero">
|
|
1902
|
-
<img src="${getImageUrl(hero.shortName, "heroes" /* Heroes */)}" alt="" />
|
|
1903
|
-
<div class="level"><img src="${getImageUrl("hero_badge_" + Math.ceil((hero.level + 1) / 6))}" alt="" /><span>${hero.level}</span></div>
|
|
1904
|
-
<span>${(hero.winCount / hero.matchCount * 100).toFixed(2)}%</span>
|
|
1905
|
-
<span>${hero.matchCount}</span>
|
|
1906
|
-
</div>`
|
|
1907
|
-
).join("");
|
|
1908
|
-
$(".player").html(playerHTML);
|
|
1909
|
-
$(".heroes > span:not(.tip)").remove();
|
|
1910
|
-
$(".heroes .tip.near").before(heroesTotalHTML);
|
|
1911
|
-
if (player.streak > 1 || player.streak < -1)
|
|
1912
|
-
$(".streak").replaceWith(streakHTML);
|
|
1913
|
-
$(".matches tbody").html(matchesHTML);
|
|
1914
|
-
$(".plus").html(dotaPlusHTML);
|
|
1915
1481
|
if (process.env.NODE_ENV === "development")
|
|
1916
|
-
import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html",
|
|
1917
|
-
return
|
|
1918
|
-
}
|
|
1919
|
-
__name(genPlayerHTML, "genPlayerHTML");
|
|
1920
|
-
async function playerIsInvalid(steamAccountId) {
|
|
1921
|
-
try {
|
|
1922
|
-
let queryRes = await query(VERIFYING_PLAYER(steamAccountId));
|
|
1923
|
-
if (queryRes.status == 200) {
|
|
1924
|
-
if (queryRes.data.data.player.matchCount != null)
|
|
1925
|
-
return { isInvalid: true };
|
|
1926
|
-
else
|
|
1927
|
-
return { isInvalid: false, reason: "SteamID无效或无任何场次。" };
|
|
1928
|
-
}
|
|
1929
|
-
} catch (error) {
|
|
1930
|
-
console.error(error);
|
|
1931
|
-
return { isInvalid: false, reason: "网络状况不佳SteamID验证失败,请稍后重试。" };
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
__name(playerIsInvalid, "playerIsInvalid");
|
|
1935
|
-
function sec2time(sec) {
|
|
1936
|
-
return sec ? (sec < 0 ? "-" : "") + Math.floor(Math.abs(sec) / 60) + ":" + ("00" + Math.abs(sec) % 60).slice(-2) : "--:--";
|
|
1937
|
-
}
|
|
1938
|
-
__name(sec2time, "sec2time");
|
|
1939
|
-
function winRateColor(value) {
|
|
1940
|
-
value = value * 100;
|
|
1941
|
-
value = Math.max(0, Math.min(100, value));
|
|
1942
|
-
let red, green, blue;
|
|
1943
|
-
if (value <= 50) {
|
|
1944
|
-
let scale = Math.round(255 * (value / 50));
|
|
1945
|
-
red = 255;
|
|
1946
|
-
green = scale;
|
|
1947
|
-
blue = scale;
|
|
1948
|
-
} else {
|
|
1949
|
-
let scale = Math.round(255 * ((value - 50) / 50));
|
|
1950
|
-
red = 255 - scale;
|
|
1951
|
-
green = 255;
|
|
1952
|
-
blue = 255 - scale;
|
|
1953
|
-
}
|
|
1954
|
-
const toHex = /* @__PURE__ */ __name((color) => color.toString(16).padStart(2, "0").toUpperCase(), "toHex");
|
|
1955
|
-
return `#${toHex(red)}${toHex(green)}${toHex(blue)}`;
|
|
1956
|
-
}
|
|
1957
|
-
__name(winRateColor, "winRateColor");
|
|
1958
|
-
function sanitizeHTML(strings, ...values) {
|
|
1959
|
-
return strings.reduce((result, string, i) => {
|
|
1960
|
-
let value = values[i] ?? "--";
|
|
1961
|
-
return result + string + (i < values.length ? value : "");
|
|
1962
|
-
}, "");
|
|
1482
|
+
import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html", result);
|
|
1483
|
+
return result;
|
|
1963
1484
|
}
|
|
1964
|
-
__name(
|
|
1485
|
+
__name(genImageHTML, "genImageHTML");
|
|
1965
1486
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1966
1487
|
0 && (module.exports = {
|
|
1967
1488
|
Config,
|