@sjtdev/koishi-plugin-dota2tracker 1.0.3 → 1.1.0

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.
Files changed (37) hide show
  1. package/lib/index.js +152 -323
  2. package/package.json +3 -2
  3. package/readme.md +5 -2
  4. package/template/images/logo_dire.png +0 -0
  5. package/template/images/logo_radiant.png +0 -0
  6. package/template/images/scepter_0.png +0 -0
  7. package/template/images/scepter_1.png +0 -0
  8. package/template/images/shard_0.png +0 -0
  9. package/template/images/shard_1.png +0 -0
  10. package/template/match/match_1.ejs +996 -0
  11. package/template/match/match_2.ejs +438 -0
  12. package/template/{match.html → match_old.html} +3 -1
  13. /package/{images → template/images}/flag_dire.png +0 -0
  14. /package/{images → template/images}/flag_radiant.png +0 -0
  15. /package/{images → template/images}/hero_badge_1.png +0 -0
  16. /package/{images → template/images}/hero_badge_2.png +0 -0
  17. /package/{images → template/images}/hero_badge_3.png +0 -0
  18. /package/{images → template/images}/hero_badge_4.png +0 -0
  19. /package/{images → template/images}/hero_badge_5.png +0 -0
  20. /package/{images → template/images}/hero_badge_6.png +0 -0
  21. /package/{images → template/images}/medal_0.png +0 -0
  22. /package/{images → template/images}/medal_1.png +0 -0
  23. /package/{images → template/images}/medal_2.png +0 -0
  24. /package/{images → template/images}/medal_3.png +0 -0
  25. /package/{images → template/images}/medal_4.png +0 -0
  26. /package/{images → template/images}/medal_5.png +0 -0
  27. /package/{images → template/images}/medal_6.png +0 -0
  28. /package/{images → template/images}/medal_7.png +0 -0
  29. /package/{images → template/images}/medal_8.png +0 -0
  30. /package/{images → template/images}/medal_8b.png +0 -0
  31. /package/{images → template/images}/medal_8c.png +0 -0
  32. /package/{images → template/images}/star_0.png +0 -0
  33. /package/{images → template/images}/star_1.png +0 -0
  34. /package/{images → template/images}/star_2.png +0 -0
  35. /package/{images → template/images}/star_3.png +0 -0
  36. /package/{images → template/images}/star_4.png +0 -0
  37. /package/{images → template/images}/star_5.png +0 -0
@@ -0,0 +1,438 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Document</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" />
8
+ <style>
9
+ p {
10
+ margin: 0;
11
+ }
12
+
13
+ img {
14
+ width: 100%;
15
+ vertical-align: middle;
16
+ }
17
+
18
+ html,
19
+ body {
20
+ width: 800px;
21
+ }
22
+
23
+ nav {
24
+ font-size: 14px;
25
+ line-height: 1.8;
26
+ height: 72px;
27
+ color: #fff;
28
+ background-color: #000;
29
+ display: flex;
30
+ flex-direction: row;
31
+ justify-content: space-around;
32
+ align-items: center;
33
+ }
34
+
35
+ nav > div > p:first-of-type {
36
+ font-weight: bold;
37
+ }
38
+
39
+ nav .match_id p:first-of-type {
40
+ font-size: 16px;
41
+ }
42
+
43
+ nav > div.match_id > p.success::after {
44
+ content: "※录像分析成功";
45
+ color: #7ba334;
46
+ }
47
+ nav > div.match_id > p.fail::after {
48
+ content: "※分析结果不完整";
49
+ color: #ffb400;
50
+ }
51
+
52
+ .radiant {
53
+ color: #3c9028;
54
+ }
55
+
56
+ .dire {
57
+ color: #9c3628;
58
+ }
59
+
60
+ .match_result {
61
+ font-weight: bold;
62
+ height: 49px;
63
+ display: flex;
64
+ justify-content: center;
65
+ align-items: center;
66
+ }
67
+
68
+ .match_result .win {
69
+ margin: 0 25px;
70
+ }
71
+
72
+ .match_result .win.radiant::after {
73
+ content: "天辉获胜";
74
+ }
75
+
76
+ .match_result .win.dire::after {
77
+ content: "夜魇获胜";
78
+ }
79
+
80
+ .players {
81
+ display: flex;
82
+ flex-direction: column;
83
+ }
84
+
85
+ .panel,
86
+ .player {
87
+ padding: 0 10px;
88
+ }
89
+
90
+ .panel {
91
+ padding-top: 4px;
92
+ height: 40px;
93
+ border-top: 3px solid #fff;
94
+ font-size: 13.3px;
95
+ display: grid;
96
+ grid-template-columns: 32px 56px 378px repeat(4,1fr);
97
+ }
98
+ .panel.radiant {
99
+ border-color: #3c9028;
100
+ }
101
+ .panel.dire {
102
+ border-color: #9c3628;
103
+ }
104
+ .panel p{
105
+ line-height: 16px;
106
+ margin-left: 8px;
107
+ }
108
+ .panel .win{
109
+ font-size: 20px;
110
+ line-height: 32px;
111
+ }
112
+ .panel .data{
113
+ color: #aaa;
114
+ }
115
+
116
+ .player:not(:last-child) {
117
+ border-bottom: 1px solid #e1e1e1; /* 示例边框样式 */
118
+ }
119
+
120
+ .player {
121
+ color: #000;
122
+ width: 100%;
123
+ display: grid;
124
+ grid-template-columns: 64px 48px 88px 160px 112px 252px 36px 20px;
125
+ grid-template-rows: 19px 14px 14px 14px;
126
+ padding-bottom: 3px;
127
+ font-size: 12px;
128
+ line-height: 14px;
129
+ overflow: hidden;
130
+ }
131
+
132
+ .player > .row-1 {
133
+ margin-top: 6px;
134
+ }
135
+
136
+ .player > .hero_avatar {
137
+ margin-bottom: 5px;
138
+ width: 64px;
139
+ grid-row: 1 / span 3;
140
+ grid-column: 1;
141
+ position: relative;
142
+ }
143
+ .player > .hero_avatar > p {
144
+ width: 20px;
145
+ height: 15px;
146
+ background-color: #323232;
147
+ position: absolute;
148
+ bottom: 0;
149
+ right: 0;
150
+ font-size: 12px;
151
+ line-height: 15px;
152
+ color: #fff;
153
+ text-align: center;
154
+ }
155
+
156
+ .player > .rank {
157
+ position: relative;
158
+ grid-row: 1 / span 3;
159
+ grid-column: 2;
160
+ width: 48px;
161
+ height: 48px;
162
+ }
163
+ .player > .rank > img {
164
+ position: absolute;
165
+ }
166
+ .player > .rank > p {
167
+ position: absolute;
168
+ width: 100%;
169
+ bottom: 3px;
170
+ text-align: center;
171
+ font-size: 9px;
172
+ color: #fff;
173
+ text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000; /* 文字描边 */
174
+ }
175
+
176
+ .player > .titles {
177
+ grid-row: 4;
178
+ grid-column: 1 / span 3;
179
+ }
180
+
181
+ .player > .player_name {
182
+ grid-row: 1;
183
+ grid-column: 3 / span 2;
184
+ }
185
+ .player > .player_name > .rank {
186
+ color: #aaa;
187
+ }
188
+ .player.radiant > .player_name > .name {
189
+ color: #3c9028;
190
+ }
191
+ .player.dire > .player_name > .name {
192
+ color: #9c3628;
193
+ }
194
+
195
+ .player .pick {
196
+ grid-column: 3;
197
+ }
198
+
199
+ .player .networth {
200
+ grid-column: 3;
201
+ }
202
+ .player .networth .gold {
203
+ color: rgb(203, 176, 42);
204
+ text-shadow: 1px 1px 0 #888; /* 设置阴影颜色及偏移 */
205
+ }
206
+
207
+ .player .hero_damage {
208
+ grid-row: 2;
209
+ grid-column: 4;
210
+ }
211
+ .player .damage_received {
212
+ grid-row: 3;
213
+ grid-column: 4;
214
+ }
215
+ .player .tower_damage {
216
+ grid-row: 4;
217
+ grid-column: 4;
218
+ }
219
+ .player .kda {
220
+ grid-row: 1;
221
+ grid-column: 5;
222
+ }
223
+ .player .kill_contribution {
224
+ grid-row: 2;
225
+ grid-column: 5;
226
+ }
227
+ .player .stun_duration {
228
+ grid-row: 3;
229
+ grid-column: 5;
230
+ }
231
+ .player .heal {
232
+ grid-row: 4;
233
+ grid-column: 5;
234
+ }
235
+
236
+ .player .items {
237
+ grid-row: 1 / span 4;
238
+ grid-column: 6;
239
+ display: grid;
240
+ grid-template-columns: 24px 192px auto;
241
+ grid-template-rows: 32px 24px;
242
+ }
243
+ .player .items > div {
244
+ display: flex;
245
+ background-color: #c0c0c0;
246
+ }
247
+ .player .items .normal {
248
+ height: 32px;
249
+ grid-column: 1/-1;
250
+ grid-row: 1;
251
+ }
252
+ .player .items .backpack {
253
+ height: 24px;
254
+ width: 96px;
255
+ grid-row: 2;
256
+ /* grid-column: 1; */
257
+ }
258
+ .player .items .normal .item {
259
+ width: 40px;
260
+ height: 30px;
261
+ margin: 1px;
262
+ position: relative;
263
+ }
264
+ .player .items .time {
265
+ position: absolute;
266
+ width: 100%;
267
+ text-align: center;
268
+ bottom: 0;
269
+ height: 11px;
270
+ line-height: 11px;
271
+ color: #ccc;
272
+ background-color: #323232;
273
+ }
274
+ .player .items .backpack{
275
+ filter: grayscale(100%);
276
+ }
277
+ .player .items .backpack .item,
278
+ .player .items .bear .item {
279
+ width: 30px;
280
+ height: 22px;
281
+ margin: 1px;
282
+ position: relative;
283
+ }
284
+ .player .neutral_item {
285
+ grid-row: 1 / span 3;
286
+ grid-column: 7;
287
+ overflow: hidden;
288
+ height: 32px;
289
+ width: 32px;
290
+ border-radius: 50%;
291
+ background-size: auto 100%;
292
+ background-position: center;
293
+ margin-left: 2px;
294
+ }
295
+ .player .items .item.recipe {
296
+ background-image: url("https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/items/recipe.png");
297
+ background-size: 100%;
298
+ }
299
+
300
+ .player .ahgs {
301
+ grid-row: 1 / span 3;
302
+ grid-column: 8;
303
+ }
304
+ .player .items .bear{
305
+ height: 24px;
306
+ width: 192px;
307
+ grid-row: 2;
308
+ grid-column: 2;
309
+ }
310
+ .player.bear .items .bear .time{
311
+ font-size: 10px;
312
+ }
313
+ .player.bear .items .bear_icon{
314
+ grid-row: 2;
315
+ grid-column: 1;
316
+ }
317
+ .player.bear .items .neutral_item{
318
+ height: 24px;
319
+ width: 24px;
320
+ grid-row: 2;
321
+ grid-column: 3;
322
+ }
323
+ /* .player .items .backpack .item img{
324
+ height: 22px;
325
+ width: auto;
326
+ } */
327
+ </style>
328
+ </head>
329
+ <body>
330
+ <nav>
331
+ <div class="match_id">
332
+ <p>比赛 <%-match.id%></p>
333
+ <p class="<%-match.parsedDateTime?'success':'fail'%>"><!--伪类赋值:类名输入success时此处为※录像分析成功,fail为※分析结果不完整,同时自动应用字体颜色样式。--></p>
334
+ </div>
335
+ <div class="start_time">
336
+ <p>开始时间</p>
337
+ <p><%-moment(new Date(match.startDateTime * 1000)).format("YYYY-MM-DD HH:mm:ss").slice(2)%></p>
338
+ </div>
339
+ <div class="duration">
340
+ <p>持续时间</p>
341
+ <p><%-sec2time(match.durationSeconds)%></p>
342
+ </div>
343
+ <div class="region">
344
+ <p>地区</p>
345
+ <p><%-d2a.region[match.regionId]%></p>
346
+ </div>
347
+ <div class="mode">
348
+ <p>模式</p>
349
+ <p><%-d2a.lobbyTypes[match.lobbyType] || match.lobbyType%>/<%-d2a.gameMode[match.gameMode] || match.gameMode%></p>
350
+ </div>
351
+ <div class="rank">
352
+ <img width="48" height="48" src="<%-utils.getImageUrl('medal_' + match.rank?.toString().split('')[0])%>" alt="" />
353
+ </div>
354
+ </nav>
355
+ <section class="match_result">
356
+ <span class="kills radiant"><%-match.radiant.killsCount%></span>
357
+ <span class="win <%-match.didRadiantWin?'radiant':'dire'%>"><!--伪类赋值:类名输入radiant此处为天辉获胜,dire为夜魇获胜,同时自动应用字体颜色样式。--></span>
358
+ <span class="kills dire"><%-match.dire.killsCount%></span>
359
+ </section>
360
+ <section class="players">
361
+ <%- ['radiant','dire'].map(team=>`
362
+ <section class="panel ${team}" style="order: ${team==="radiant"?0:50}">
363
+ <img src="${utils.getImageUrl("logo_"+team)}" alt="">
364
+ <p>${(team==="radiant"?["Radiant","天辉"]:["Dire","夜魇"]).join("<br>")}</p>
365
+ ${((team==="radiant")===match.didRadiantWin)?`<p class="win">胜利</p>`:"<p></p>"}
366
+ <p class="data">击杀<br>${match[team].killsCount}</p>
367
+ <p class="data">总伤害<br>${match[team].heroDamage}</p>
368
+ <p class="data">总经济<br>${match[team].networth}</p>
369
+ <p class="data">总经验<br>${match[team].experience}</p><!--此处无有效API,仅能通过每分钟经验推算-->
370
+ </section>`).join("")
371
+ %>
372
+ <%- match.players.map(player=> `
373
+ <div class="player ${player.team}${player.hero.id==80?" bear":""}" style="order: ${player.team==="radiant"?1:100};">
374
+ <div class="hero_avatar row-1">
375
+ <img src="${utils.getImageUrl(player.hero.shortName, ImageType.Heroes)}" />
376
+ <p class="level">${player.level}</p>
377
+ </div>
378
+ <div class="rank">
379
+ <img
380
+ src="${utils.getImageUrl('medal_' +(player.inTop100??player.rank.medal))}"
381
+ class="medal"
382
+ />
383
+ <img src="${utils.getImageUrl('star_' + player.rank.star)}" class="stars" />
384
+ <p>${player.steamAccount.seasonLeaderboardRank??""}</p>
385
+ </div>
386
+ <div class="titles">${player.titles.map((item) => `<span style="color: ${item.color};">${item.name}</span>`).join('&nbsp;')}</div>
387
+ <div class="player_name row-1">
388
+ <span class="rank">${`[${d2a.rank[player.rank.medal]}${player.rank.star||""}]`}</span>
389
+ <span class="name">${player.steamAccount.name}</span>
390
+ </div>
391
+ <p class="pick">${player.isRandom?'随机':`第${player.order == null ? "-" : player.order + 1}手`} ${d2a.position[player.position?.slice(-1)]??''}</p>
392
+ <p class="networth">
393
+ <span class="gold">${formatNumber(player.networth)}</span>
394
+ (${(player.heroDamage / player.networth)?.toFixed(2)})
395
+ </p>
396
+ <p class="hero_damage">造成伤害:${player.heroDamage} (${(player.heroDamage/match[player.team].heroDamage*100).toFixed(2)}%)</p>
397
+ <p class="damage_received">承受伤害:${player.damageReceived} (${(player.damageReceived/match[player.team].damageReceived*100).toFixed(2)}%)</p>
398
+ <p class="tower_damage">建筑伤害:${player.towerDamage}</p>
399
+ <p class="kda row-1">${player.kills}/${player.deaths}/${player.assists} (${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)})</p>
400
+ <p class="kill_contribution">参战率:${(player.killContribution * 100).toFixed(2)}%</p>
401
+ <p class="stun_duration">控制时间:${(player.stats.heroDamageReport.dealtTotal.stunDuration / 100).toFixed(2)}s</p>
402
+ <p class="heal">治疗量:${player.heroHealing}</p>
403
+ <div class="items row-1">
404
+ <div class="normal">
405
+ ${player.items.map((item) =>`
406
+ <div class="item${item?.isRecipe ? " recipe" : ""}" data-id="${item?.id??0}">
407
+ <img src="${item ? utils.getImageUrl(item.name, ImageType.Items) : ""}" alt="" />
408
+ ${item ? `<p class="time">${sec2time(item?.time) ?? ""}</p>` : ""}
409
+ </div>`).join("")}
410
+ </div>
411
+ ${player.hero.id != 80?`
412
+ <div class="backpack">
413
+ ${player.backpacks.map((item) =>`
414
+ <div class="item${item?.isRecipe ? " recipe" : ""}">
415
+ <img src="${item ? utils.getImageUrl(item.name, ImageType.Items) : ""}" alt="" />
416
+ </div>`).join("")}
417
+ </div>`:`
418
+ <img class="bear_icon" src="https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/abilities/lone_druid_spirit_bear.png" alt="">
419
+ <div class="bear">
420
+ ${player.unitItems.map((item) =>`
421
+ <div class="item${item?.isRecipe ? " recipe" : ""}" data-id="${item?.id??0}">
422
+ <img src="${item ? utils.getImageUrl(item.name, ImageType.Items) : ""}" alt="" />
423
+ ${item ? `<p class="time">${sec2time(item?.time) ?? ""}</p>` : ""}
424
+ </div>`).join("")}
425
+ </div>
426
+ <div class="neutral_item" style="background-image: url(${utils.getImageUrl(dotaconstants.item_ids[player.additionalUnit.neutral0Id], ImageType.Items)})"></div>`
427
+ }
428
+ </div>
429
+ <div class="neutral_item row-1" style="background-image: url(${utils.getImageUrl(dotaconstants.item_ids[player.neutral0Id], ImageType.Items)})"></div>
430
+ <div class="ahgs row-1">
431
+ <img src="${utils.getImageUrl("scepter_"+((player.items.concat(player.backpacks).find(item=>item?.id==108)||player.stats.matchPlayerBuffEvent.find(buff=>buff.itemId==108))?1:0))}" alt="" />
432
+ <img src="${utils.getImageUrl("shard_"+(player.stats.matchPlayerBuffEvent.find(buff=>buff.itemId==609)?1:0))}" alt="" />
433
+ </div>
434
+ </div>
435
+ `).join("") %>
436
+ </section>
437
+ </body>
438
+ </html>
@@ -507,11 +507,13 @@
507
507
  }
508
508
 
509
509
  .player.bear .items {
510
- display: flex;
510
+ display: grid;
511
511
  height: 100%;
512
512
  flex-wrap: wrap;
513
513
  width: 250.74px;
514
514
  margin-right: 4px;
515
+ grid-template-columns: repeat(6,1fr);
516
+ grid-template-rows: repeat(2,40px);
515
517
  }
516
518
 
517
519
  .player.bear .items .item {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes