@sjtdev/koishi-plugin-dota2tracker 2.2.3 → 2.3.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 (105) hide show
  1. package/changelog.md +22 -0
  2. package/lib/index.js +127 -94
  3. package/{queries → lib/queries}/MatchInfo.graphql +13 -0
  4. package/lib/templates/common/components/building_icons.ejs +20 -0
  5. package/lib/templates/common/styles/normalize.min.css +1 -0
  6. package/lib/templates/hero/hero_1.ejs +69 -0
  7. package/lib/templates/images/7.38_simple_minimap.png +0 -0
  8. package/lib/templates/item/item/recipe.ejs +9 -0
  9. package/lib/templates/item/item/style.css +1 -0
  10. package/lib/templates/item/item.ejs +52 -0
  11. package/lib/templates/item/itemlist.ejs +11 -0
  12. package/lib/templates/match/match_1/base.css +1 -0
  13. package/lib/templates/match/match_1/item.ejs +1 -0
  14. package/lib/templates/match/match_1/main.ejs +8 -0
  15. package/lib/templates/match/match_1/player.ejs +1 -0
  16. package/lib/templates/match/match_1/style.css +1 -0
  17. package/lib/templates/match/match_1.ejs +18 -0
  18. package/lib/templates/match/match_2/original.css +1 -0
  19. package/lib/templates/match/match_2/original.ejs +10 -0
  20. package/lib/templates/match/match_2+/charts.ejs +1 -0
  21. package/lib/templates/match/match_2+/extra.css +1 -0
  22. package/lib/templates/match/match_2+/lane_outcome.ejs +56 -0
  23. package/lib/templates/match/match_2+/map.ejs +160 -0
  24. package/lib/templates/match/match_2+.ejs +1 -0
  25. package/lib/templates/match/match_2.ejs +1 -0
  26. package/lib/templates/player/player_1/base.css +1 -0
  27. package/lib/templates/player/player_1/private.ejs +1 -0
  28. package/lib/templates/player/player_1.ejs +78 -0
  29. package/lib/templates/rank/rank_fun.ejs +1 -0
  30. package/lib/templates/report/daily/base.css +1 -0
  31. package/lib/templates/report/daily.ejs +29 -0
  32. package/package.json +2 -2
  33. package/template/hero/hero_1.ejs +0 -900
  34. package/template/item/item/recipe.ejs +0 -51
  35. package/template/item/item/style.css +0 -244
  36. package/template/item/item.ejs +0 -140
  37. package/template/item/itemlist.ejs +0 -99
  38. package/template/match/match_1/item.ejs +0 -11
  39. package/template/match/match_1/main.ejs +0 -37
  40. package/template/match/match_1/player.ejs +0 -154
  41. package/template/match/match_1/style.css +0 -764
  42. package/template/match/match_1.ejs +0 -56
  43. package/template/match/match_2/original.css +0 -463
  44. package/template/match/match_2/original.ejs +0 -192
  45. package/template/match/match_2+/charts.ejs +0 -261
  46. package/template/match/match_2+/extra.css +0 -143
  47. package/template/match/match_2+/lane_outcome.ejs +0 -157
  48. package/template/match/match_2+.ejs +0 -27
  49. package/template/match/match_2.ejs +0 -18
  50. package/template/player/player_1/private.ejs +0 -5
  51. package/template/player/player_1.ejs +0 -654
  52. package/template/rank/rank_fun.ejs +0 -131
  53. package/template/report/daily.ejs +0 -191
  54. /package/{queries → lib/queries}/Constants.graphql +0 -0
  55. /package/{queries → lib/queries}/GetWeeklyMetaByPosition.graphql +0 -0
  56. /package/{queries → lib/queries}/PlayerExtraInfo.graphql +0 -0
  57. /package/{queries → lib/queries}/PlayerInfoWith25Matches.graphql +0 -0
  58. /package/{queries → lib/queries}/PlayerPerformanceForHeroRecommendation.graphql +0 -0
  59. /package/{queries → lib/queries}/PlayersInfoWith10MatchesForGuild.graphql +0 -0
  60. /package/{queries → lib/queries}/PlayersLastmatchRankinfo.graphql +0 -0
  61. /package/{queries → lib/queries}/PlayersMatchesForDaily.graphql +0 -0
  62. /package/{queries → lib/queries}/RequestMatchDataAnalysis.graphql +0 -0
  63. /package/{queries → lib/queries}/VerifyingPlayer.graphql +0 -0
  64. /package/{template → lib/templates}/images/bei.jpg +0 -0
  65. /package/{template → lib/templates}/images/disconnected.png +0 -0
  66. /package/{template → lib/templates}/images/flag_dire.png +0 -0
  67. /package/{template → lib/templates}/images/flag_radiant.png +0 -0
  68. /package/{template → lib/templates}/images/hero_badge_1.png +0 -0
  69. /package/{template → lib/templates}/images/hero_badge_2.png +0 -0
  70. /package/{template → lib/templates}/images/hero_badge_3.png +0 -0
  71. /package/{template → lib/templates}/images/hero_badge_4.png +0 -0
  72. /package/{template → lib/templates}/images/hero_badge_5.png +0 -0
  73. /package/{template → lib/templates}/images/hero_badge_6.png +0 -0
  74. /package/{template → lib/templates}/images/lane_fail.svg +0 -0
  75. /package/{template → lib/templates}/images/lane_jungle.svg +0 -0
  76. /package/{template → lib/templates}/images/lane_stomp.svg +0 -0
  77. /package/{template → lib/templates}/images/lane_stomped.svg +0 -0
  78. /package/{template → lib/templates}/images/lane_tie.svg +0 -0
  79. /package/{template → lib/templates}/images/lane_victory.svg +0 -0
  80. /package/{template → lib/templates}/images/logo_dire.png +0 -0
  81. /package/{template → lib/templates}/images/logo_radiant.png +0 -0
  82. /package/{template → lib/templates}/images/medal_0.png +0 -0
  83. /package/{template → lib/templates}/images/medal_1.png +0 -0
  84. /package/{template → lib/templates}/images/medal_2.png +0 -0
  85. /package/{template → lib/templates}/images/medal_3.png +0 -0
  86. /package/{template → lib/templates}/images/medal_4.png +0 -0
  87. /package/{template → lib/templates}/images/medal_5.png +0 -0
  88. /package/{template → lib/templates}/images/medal_6.png +0 -0
  89. /package/{template → lib/templates}/images/medal_7.png +0 -0
  90. /package/{template → lib/templates}/images/medal_8.png +0 -0
  91. /package/{template → lib/templates}/images/medal_8b.png +0 -0
  92. /package/{template → lib/templates}/images/medal_8c.png +0 -0
  93. /package/{template → lib/templates}/images/scepter.png +0 -0
  94. /package/{template → lib/templates}/images/scepter_0.png +0 -0
  95. /package/{template → lib/templates}/images/scepter_1.png +0 -0
  96. /package/{template → lib/templates}/images/shard.png +0 -0
  97. /package/{template → lib/templates}/images/shard_0.png +0 -0
  98. /package/{template → lib/templates}/images/shard_1.png +0 -0
  99. /package/{template → lib/templates}/images/star_0.png +0 -0
  100. /package/{template → lib/templates}/images/star_1.png +0 -0
  101. /package/{template → lib/templates}/images/star_2.png +0 -0
  102. /package/{template → lib/templates}/images/star_3.png +0 -0
  103. /package/{template → lib/templates}/images/star_4.png +0 -0
  104. /package/{template → lib/templates}/images/star_5.png +0 -0
  105. /package/{template → lib/templates}/images/xi.jpg +0 -0
@@ -1,51 +0,0 @@
1
- <% const item = data; %>
2
- <% (item.recipes.length ? item.recipes : [undefined]).forEach(recipe => { %>
3
- <div class="recipes">
4
- <% if (item.builds_into.length) { %>
5
- <% const multiple = item.builds_into.length > 1 ? " multiple" : ""; %>
6
- <div class="upper<%= multiple %>">
7
- <% item.builds_into.forEach(item => { %>
8
- <div class="item">
9
- <img src="<%= getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
10
- <p><%= item.name_loc %></p>
11
- </div>
12
- <% }) %>
13
- </div>
14
-
15
- <div class="vline<%= multiple %>">
16
- <% for( let index = 0; index < item.builds_into.length; index++ ) { %>
17
- <div class="item line"></div>
18
- <% } %>
19
- </div>
20
- <div class="hline<%= multiple %>"></div>
21
- <div class="vline<%= multiple ? " direct" : "" %>"><div class="item line"></div></div>
22
- <% } %>
23
- <div class="middle">
24
- <div class="item">
25
- <img src="<%= getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
26
- <p><%= item.name_loc %></p>
27
- </div>
28
- </div>
29
- <% if (item.recipes.length) { %>
30
- <% if (dotaconstants.items["recipe_"+item.name]) {
31
- recipe.items = recipe.items.concat([{name:"recipe",name_loc:$t("dota2tracker.template.recipe")}])
32
- } %>
33
- <% const multiple = recipe.items.length > 1 ? " multiple" : ""; %>
34
- <div class="vline<%= multiple ? " direct" : "" %>"><div class="item line"></div></div>
35
- <div class="hline<%= multiple %>"></div>
36
- <div class="vline<%= multiple %>">
37
- <% for( let index = 0; index < recipe.items.length; index++ ) { %>
38
- <div class="item line"></div>
39
- <% } %>
40
- </div>
41
- <div class="lower<%= multiple %>">
42
- <% recipe.items.forEach(item => { %>
43
- <div class="item">
44
- <img src="<%= getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
45
- <p><%= item.name_loc %></p>
46
- </div>
47
- <% }) %>
48
- </div>
49
- <% } %>
50
- </div>
51
- <% }) %>
@@ -1,244 +0,0 @@
1
- * {
2
- margin: 0;
3
- padding: 0;
4
- }
5
-
6
- html,
7
- body {
8
- background-color: #000;
9
- font-size: 16px;
10
- width: 404px;
11
- }
12
-
13
- .container {
14
- margin: 2px;
15
- background-color: #222d35;
16
- width: 400px;
17
- overflow: hidden;
18
- }
19
-
20
- .container > * {
21
- padding: 10px;
22
- }
23
-
24
- .container > *.empty {
25
- padding: 0;
26
- }
27
-
28
- .header {
29
- position: relative;
30
- background-color: #32424e;
31
- color: #fff;
32
- display: flex;
33
- }
34
-
35
- .header > img {
36
- width: 70px;
37
- height: auto;
38
- vertical-align: middle;
39
- position: relative;
40
- }
41
-
42
- .header div {
43
- margin-left: 10px;
44
- }
45
-
46
- .header .name {
47
- font-family: "KaiTi", "楷体", "楷体_GB2312", "STKaiti", serif;
48
- text-shadow: 1px 1px 2px #111;
49
- }
50
-
51
- .header .name .item_id {
52
- color: #999;
53
- }
54
-
55
- .header .cost {
56
- display: flex;
57
- color: #f4d652;
58
- align-items: center;
59
- }
60
-
61
- .stats {
62
- padding: 5px;
63
- color: #667e9b;
64
- font-size: 14px;
65
- margin: 0 10px;
66
- border-block: 1px solid #405159;
67
- white-space: nowrap;
68
- }
69
-
70
- .stats p {
71
- display: flex;
72
- }
73
-
74
- .stats .dmg_type span.Physical {
75
- color: #ae2f28;
76
- }
77
-
78
- .stats .dmg_type span.Magical {
79
- color: #5b93d1;
80
- }
81
-
82
- .stats .dmg_type span.Pure {
83
- color: #c29c4a;
84
- }
85
-
86
- .stats .dispellable span.Yes {
87
- /* color: #c29c4a; */
88
- }
89
-
90
- .stats .dispellable span.No {
91
- color: #f00;
92
- }
93
-
94
- .stats .dispellable span.Strong {
95
- color: #9828ae;
96
- }
97
-
98
- .stats .bkbpierce span.Yes {
99
- color: #6add71;
100
- }
101
-
102
- .container > .attrs {
103
- color: #aabbd2;
104
- text-shadow: 1px 1px 0 #333;
105
- /* padding-bottom: 0; */
106
- }
107
-
108
- .value {
109
- color: #fff;
110
- font-weight: bold;
111
- }
112
-
113
- .abilities {
114
- font-size: 14px;
115
- margin: 10px;
116
- padding: 0;
117
- display: flex;
118
- flex-direction: column;
119
- gap: 6px;
120
- }
121
-
122
- .ability.passive {
123
- background-color: #2d3c49;
124
- color: #7e8b9e;
125
- }
126
- .ability.passive h1 {
127
- color: #cce2ff;
128
- background-image: linear-gradient(to right, #3b505e, #2b3c47);
129
- }
130
-
131
- .ability.active {
132
- background-color: #2a3550;
133
- color: #9ba2d4;
134
- }
135
- .ability.active h1 {
136
- color: #AAAAFF;
137
- background-image: linear-gradient(to right, #5155b9, #2a3550);
138
- display: flex;
139
- justify-content: space-between;
140
- }
141
-
142
- .ability h1 {
143
- font-size: 14px;
144
- padding: 6px 8px;
145
- text-shadow: 1px 1px 2px #111;
146
- font-weight: normal;
147
- display: flex;
148
- justify-content: space-between;
149
- align-items: center;
150
- }
151
-
152
- .ability > p {
153
- padding: 8px;
154
- text-shadow: 1px 1px 2px #000;
155
- }
156
-
157
- .ability .attrs {
158
- display: flex;
159
- gap: 10px;
160
- flex-wrap: wrap;
161
- justify-content: flex-end;
162
- max-width: 50%;
163
- }
164
-
165
- .ability .attr {
166
- display: flex;
167
- gap: 6px;
168
- align-items: center;
169
- }
170
-
171
- .ability .attr > .icon {
172
- width: 16px;
173
- height: 16px;
174
- border-radius: 4px;
175
- border: 1px solid #000;
176
- }
177
-
178
- .notes {
179
- font-size: 14px;
180
- margin: 10px;
181
- color: #beddf0;
182
- background-color: #3b5566;
183
- }
184
-
185
- .lore {
186
- margin: 10px;
187
- /* margin-top: 20px; */
188
- font-size: 12px;
189
- color: #566d7e;
190
- background-color: #172025;
191
- }
192
-
193
- .recipes {
194
- overflow: hidden;
195
- font-size: 12px;
196
- color: #fff;
197
- padding: 20px 50px;
198
- }
199
-
200
- .recipes > * {
201
- display: flex;
202
- width: 100%;
203
- justify-content: center;
204
- }
205
-
206
- .recipes > *.multiple {
207
- justify-content: space-between;
208
- }
209
-
210
- .recipes .item {
211
- width: 60px;
212
- text-align: center;
213
- }
214
-
215
- .recipes .item img {
216
- width: 100%;
217
- }
218
-
219
- .hline.multiple {
220
- width: calc(100% - 59px);
221
- background-color: #fff;
222
- height: 1px;
223
- margin-left: 30px;
224
- }
225
-
226
- .recipes .line {
227
- height: 5px;
228
- background: linear-gradient(0deg, #fff, #fff) no-repeat center/1px 100%;
229
- }
230
-
231
- .recipes *.multiple .line,.recipes *.direct .line {
232
- height: 10px;
233
- }
234
-
235
- /* .middle .item::after {
236
- content: "";
237
- display: block;
238
- width: 1px;
239
- height: 100%;
240
- background-color: #fff;
241
- position: absolute;
242
- top: 0;
243
- right: 0;
244
- } */
@@ -1,140 +0,0 @@
1
- <% const item = data; %>
2
- <%
3
- // 构建占位符字典(兼容数值类型和百分比类型)
4
- const valueMap = item.special_values.reduce((map, val) => {
5
- map[val.name] = val.is_percentage ?
6
- `${val.values_float.join("/")}%` : // 百分比类型加%后缀
7
- val.values_float.join("/") // 普通数值直接取用
8
- return map
9
- }, {})
10
- %>
11
- <% function parseAbilityDesc(desc) {
12
- const abilityRegExp = /<h1>(.*?)<\/h1>((?:(?!<h1>).|\n)*)/g;
13
- return Array.from(desc.matchAll(abilityRegExp)).map(match => ({
14
- name: match[1].trim(),
15
- desc: match[2]
16
- // 保留原有替换逻辑
17
- // .replace(/<br>\s*<br>/g, '\n')
18
- .replace(/%(\w+)%/g, (_, key) =>
19
- `<span class="value">${valueMap[key] ?? `[${key}]`}</span>`
20
- )
21
- .replace(/%%/g, '<span class="value">%</span>')
22
- .trim()
23
- }));
24
- } %>
25
- <% function capitalize(str) {
26
- return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
27
- } %>
28
- <% function toArray(obj) {
29
- return Array.isArray(obj) ? obj : [obj];
30
- } %>
31
- <!DOCTYPE html>
32
- <html lang="<%= languageTag %>">
33
- <head>
34
- <meta charset="UTF-8">
35
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
36
- <%- `<style>` %>
37
- <%- include('./item/style.css') %>
38
- <% if (fontFamily) { %>
39
- <%- `body { font-family: ${fontFamily}; }` %>
40
- <% } %>
41
- <%- `</style>` %>
42
- </head>
43
- <body>
44
- <div class="container">
45
- <div class="header">
46
- <img src="<%= getImageUrl(item.name, ImageType.Items) %>">
47
- <div>
48
- <p class="name"><%= item.name_loc %> <span class="item_id"><%= item.name %></span></p>
49
- <% if (item.item_cost) { %>
50
- <p class="cost"><img style="height: 20px; width: auto; margin-right: 4px;" src="<%= getImageUrl("gold", ImageType.Icons) %>"> <%= item.item_cost %></p>
51
- <% } %>
52
- </div>
53
- </div>
54
- <% const citem = dotaconstants.items[item.name]; %>
55
- <% if (citem?.abilities?.length) { %>
56
- <div class="stats">
57
- <p class="behavior">
58
- <%= $t("dota2tracker.template.ability") %><!--
59
- --><% if (citem.abilities.some(ability => capitalize(ability.type) === 'Active')) { %><!--
60
- --><%= toArray(citem.behavior).map((beh)=>$t("dota2tracker.template.behavior."+beh)).join("/") %><!--
61
- --><% } else { %><!--
62
- --><%= $t("dota2tracker.template.behavior.Passive") %><!--
63
- --><% } %>
64
- </p>
65
- <% if (citem.target_team && citem.target_team.length) { %>
66
- <p class="target_team"><%= $t("dota2tracker.template.affects") %><%= toArray(citem.target_team).map((tt) => $t("dota2tracker.template.target_team."+tt)).join("/") %></p>
67
- <% } %>
68
- <% if (citem.dmg_type) { %>
69
- <p class="dmg_type"><%= $t("dota2tracker.template.damage_type") %><span class="<%= citem.dmg_type %>"><%= $t("dota2tracker.template.damage_type_"+citem.dmg_type) %></span></p>
70
- <% } %>
71
- <% if (citem.dispellable) { %>
72
- <p class="dispellable"><%= $t("dota2tracker.template.dispellable") %><span class="<%= citem.dispellable %>"><%= $t("dota2tracker.template."+(citem.dispellable == "Strong Dispels Only" ? "dispellable_Strong" : citem.dispellable)) %></span></p>
73
- <% } %>
74
- <% if (citem.bkbpierce) { %>
75
- <p class="bkbpierce"><%= $t("dota2tracker.template.bkbpierce") %><span class="<%= citem.bkbpierce %>"><%= $t("dota2tracker.template."+citem.bkbpierce) %></span></p>
76
- <% } %>
77
- </div>
78
- <% } %>
79
- <div class="attrs">
80
- <% item.special_values.filter(value=>value.heading_loc).forEach(value=>{ %>
81
- <%
82
- const [_, sign = '+', rawText] = value.heading_loc.match(/^([+-]?)(.*)/) || [];
83
- const processedText = rawText.replace(/\$(\w+)/, (_, p1) => $t(`dota2tracker.template.item_token.${p1}`));
84
- %>
85
- <p class="attr_item <%= value.values_float[0] > 0 ? "positive" : "negative" %>">
86
- <%= sign %>
87
- <span class="value"><%= value.values_float.map(v=>v+(value.is_percentage?"%":"")).join("/") %></span>
88
- <span class="desc"><%= processedText %></span>
89
- </p>
90
- <% }) %>
91
- </div>
92
- <% const abilities = parseAbilityDesc(item.desc_loc, valueMap); %>
93
- <% if (abilities.length) { %>
94
- <div class="abilities">
95
- <% abilities.forEach(ability => { %>
96
- <% const type = ability.name.startsWith($t("dota2tracker.template.behavior.Passive")) ? "passive" : "active"; %>
97
- <div class="ability <%= type %>">
98
- <h1>
99
- <p class="name"><%= ability.name %></p>
100
- <% if (type === "active") { %>
101
- <div class="attrs">
102
- <% if (item.mana_costs && item.mana_costs[0]) { %>
103
- <div class="attr">
104
- <div class="icon" style="background: linear-gradient(#00A4DB, #007196);"></div>
105
- <span class="value"><%= item.mana_costs.join("/") %></span>
106
- </div>
107
- <% } %>
108
- <% if (item.cooldowns && item.cooldowns[0]) { %>
109
- <div class="attr">
110
- <img class="icon" src="<%= getImageUrl("cooldown", ImageType.Icons) %>">
111
- <span class="value"><%= item.cooldowns.join("/") %></span>
112
- </div>
113
- <% } %>
114
- </div>
115
- <% } %>
116
- </h1>
117
- <p><%- ability.desc %></p>
118
- </div>
119
- <% }); %>
120
- </div>
121
- <% } %>
122
- <% const notes = item.notes_loc.map(note => note.replace(/%(\w+)%/g, (_, key) => `<span class="value">${valueMap[key] ?? `[${key}]`}</span>`).replace(/%%/g, '<span class="value">%</span>').trim()); %>
123
- <% if (notes && notes.length) { %>
124
- <div class="notes">
125
- <% notes.forEach(note => { %>
126
- <p class="note"><%- note %></p>
127
- <% }) %>
128
- </div>
129
- <% } %>
130
- <% if (item.lore_loc) { %>
131
- <div class="lore">
132
- <p><%= item.lore_loc %></p>
133
- </div>
134
- <% } %>
135
- </div>
136
- <% if (item.recipes.length || item.builds_into.length) { %>
137
- <%- include("./item/recipe") %>
138
- <% } %>
139
- </body>
140
- </html>
@@ -1,99 +0,0 @@
1
- <%
2
- function calculateFontSize(text) {
3
- // 中文字符正则(包含常见中文符号)
4
- const chineseRegex = /[\u4e00-\u9fa5\u3000-\u303f\uff00-\uffef]/g
5
- // 计算等效字符数(中文按2单位,其他按1单位)
6
- const totalUnits = text.split('').reduce((acc, char) => {
7
- return acc + (chineseRegex.test(char) ? 2 : 1)
8
- }, 0)
9
-
10
- // 容器可用宽度(根据.item的48px减去2px边距)
11
- const maxWidth = 44
12
- // 根据经验公式计算字号(系数需实际调试)
13
- let fontSize = Math.floor((maxWidth / totalUnits) * 1.8)
14
-
15
- // 边界限制
16
- return Math.min(12, Math.max(6, fontSize))
17
- }
18
- %>
19
- <!DOCTYPE html>
20
- <html lang="en">
21
- <head>
22
- <meta charset="UTF-8" />
23
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
24
- <style>
25
- * {
26
- margin: 0;
27
- padding: 0;
28
- }
29
-
30
- html,
31
- body {
32
- height: auto;
33
- background-color: #000;
34
- color: #fff;
35
- }
36
-
37
- html {
38
- width: 232px;
39
- }
40
-
41
- body {
42
- width: 220px;
43
- margin: 6px;
44
- }
45
-
46
- .container {
47
- width: 220px;
48
- display: flex;
49
- flex-wrap: wrap;
50
- justify-content: space-between;
51
- align-items: center;
52
- row-gap: 8px;
53
- }
54
-
55
- .container img {
56
- width: 44px;
57
- height: 32px;
58
- }
59
-
60
- .container .item {
61
- width: 48px;
62
- height: 54px;
63
- display: flex;
64
- flex-direction: column;
65
- font-size: 12px;
66
- align-items: center;
67
- justify-content: space-around;
68
- }
69
-
70
- .name {
71
- /* white-space: nowrap; */
72
- overflow: hidden;
73
- text-overflow: ellipsis;
74
- text-align: center;
75
- line-height: 1.2;
76
- min-height: 12px;
77
- }
78
- </style>
79
-
80
- <% if (fontFamily) { %>
81
- <%- "<style>" %>
82
- <%- `body { font-family: ${fontFamily}; }` %>
83
- <%- "</style>" %>
84
- <% } %>
85
- </head>
86
- <body>
87
- <% const items = data; %>
88
- <div class="container">
89
- <% items.forEach(function(item) { %>
90
- <div class="item">
91
- <img src="<%= getImageUrl(item.name, ImageType.Items) %>" />
92
- <div class="name" <%- `style="font-size: ${calculateFontSize(item.name_loc)}px"` %>>
93
- <%= item.name_loc %>
94
- </div>
95
- </div>
96
- <% }); %>
97
- </div>
98
- </body>
99
- </html>
@@ -1,11 +0,0 @@
1
- <% const isRecipe = item?.isRecipe ? ` style="background-image: url('${getImageUrl("recipe", ImageType.Items)}');"` : ''; %>
2
- <div class="relative <%= style %>"<%- isRecipe %>>
3
- <% if (item) { %>
4
- <% if (!isNeutral) { %>
5
- <img class="w-full h-full object-cover aspect-[11/8] <%= item.isRecipe ? "opacity-75 scale-[0.6] origin-top-right" : '' %>" src="<%= getImageUrl(item.name, ImageType.Items) %>">
6
- <p class="absolute w-full text-[#ccc] text-center bottom-0 leading-[1] text-xs bg-stone-700/50"><%= item.time %></p>
7
- <% } else { %>
8
- <img class="w-full h-full object-contain" src="<%= getImageUrl(dotaconstants.item_ids[player.neutral0Id], ImageType.Items) %>">
9
- <% } %>
10
- <% } %>
11
- </div>
@@ -1,37 +0,0 @@
1
- <div class="w-[790px] h-[100px] flex justify-between box m-[5px]">
2
- <div class="flag w-[100px] h-full flex justify-center items-end bg-cover <%= !match.didRadiantWin ? 'grayscale' : "" %>" style="background-image: url('<%= getImageUrl("flag_radiant") %>')"><%= match.didRadiantWin ? $t("dota2tracker.template.won") : "" %></div>
3
- <div class="details grow relative flex-col flex">
4
- <p class="w-full flex justify-around">
5
- <span><%= $t("dota2tracker.template.match_id_") %><%= match.id %></span>
6
- <span><%= $t("dota2tracker.template.game_mode_") %><%= $t("dota2tracker.template.lobby_types." + match.lobbyType) || match.lobbyType %> / <%= $t("dota2tracker.template.game_modes." + match.gameMode) || match.gameMode %></span>
7
- <span><%= $t("dota2tracker.template.region_") %><%= $t("dota2tracker.template.regions." + match.regionId) %></span>
8
- </p>
9
- <p class="w-full flex justify-around">
10
- <span><%= $t("dota2tracker.template.start_time_") %><%= DateTime.fromSeconds(match.startDateTime).toFormat("yyyy-MM-dd HH:mm:ss").slice(2) %></span>
11
- <span><%= $t("dota2tracker.template.end_time_") %><%= DateTime.fromSeconds(match.endDateTime).toFormat("yyyy-MM-dd HH:mm:ss").slice(2) %></span>
12
- </p>
13
- <p class="w-full grow score flex justify-evenly items-end">
14
- <span class="score radiant text-3xl"><%= match.radiant.killsCount %></span>
15
- <span class="time text-sm"><%= match.durationTime %></span>
16
- <span class="score dire text-3xl"><%= match.dire.killsCount %></span>
17
- </p>
18
- <div class="rank absolute w-[64px] h-[64px] bottom-[10px] left-1/2 -translate-x-1/2<%- match.odParsed && match.lobbyType !== "RANKED" ? ` grayscale` : "" %>">
19
- <img class="star absolute w-full" src="<%= getImageUrl('star_' + (match.rank ? match.rank.toString().split('')[1] : '')) %>">
20
- <img class="medal absolute w-full" src="<%= getImageUrl('medal_' + (match.rank ? match.rank.toString().split('')[0] : '')) %>">
21
- </div>
22
- </div>
23
- <div class="flag w-[100px] h-full flex justify-center items-end bg-cover <%= match.didRadiantWin ? 'grayscale' : "" %>" style="background-image: url('<%= getImageUrl("flag_dire") %>')"><%= !match.didRadiantWin ? $t("dota2tracker.template.won") : "" %></div>
24
- </div>
25
- <div class="w-[790px] grid grid-cols-2 gap-[5px] mx-[5px]">
26
- <% for( let index = 0; index < match.players.length; index++ ) { %>
27
- <%- include(`./player.ejs`, { match, player: match.players[index], kcndcStyle, laneSVG, facetColor, partyColor }) %>
28
- <% } %>
29
- </div>
30
- <div class="ban_list box m-[5px] flex flex-wrap">
31
- <% for (const hero of (match.pickBans ?? []).filter(x => !x.isPick)) { %>
32
- <div class="ban_hero relative w-[10%]">
33
- <i class="absolute w-full h-full z-1" style="background-image: linear-gradient(to bottom left, transparent calc(50% - 1px), red calc(50% - 1px), black calc(50% + 1px), transparent calc(50% + 1px));"></i>
34
- <img class="grayscale" src="<%= getImageUrl(/^npc_dota_hero_(?<name>.+)$/.exec(dotaconstants.heroes[hero.bannedHeroId].name)[1], ImageType.Heroes) %>" alt="" />
35
- </div>
36
- <% } %>
37
- </div>