@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.
- package/changelog.md +22 -0
- package/lib/index.js +127 -94
- package/{queries → lib/queries}/MatchInfo.graphql +13 -0
- package/lib/templates/common/components/building_icons.ejs +20 -0
- package/lib/templates/common/styles/normalize.min.css +1 -0
- package/lib/templates/hero/hero_1.ejs +69 -0
- package/lib/templates/images/7.38_simple_minimap.png +0 -0
- package/lib/templates/item/item/recipe.ejs +9 -0
- package/lib/templates/item/item/style.css +1 -0
- package/lib/templates/item/item.ejs +52 -0
- package/lib/templates/item/itemlist.ejs +11 -0
- package/lib/templates/match/match_1/base.css +1 -0
- package/lib/templates/match/match_1/item.ejs +1 -0
- package/lib/templates/match/match_1/main.ejs +8 -0
- package/lib/templates/match/match_1/player.ejs +1 -0
- package/lib/templates/match/match_1/style.css +1 -0
- package/lib/templates/match/match_1.ejs +18 -0
- package/lib/templates/match/match_2/original.css +1 -0
- package/lib/templates/match/match_2/original.ejs +10 -0
- package/lib/templates/match/match_2+/charts.ejs +1 -0
- package/lib/templates/match/match_2+/extra.css +1 -0
- package/lib/templates/match/match_2+/lane_outcome.ejs +56 -0
- package/lib/templates/match/match_2+/map.ejs +160 -0
- package/lib/templates/match/match_2+.ejs +1 -0
- package/lib/templates/match/match_2.ejs +1 -0
- package/lib/templates/player/player_1/base.css +1 -0
- package/lib/templates/player/player_1/private.ejs +1 -0
- package/lib/templates/player/player_1.ejs +78 -0
- package/lib/templates/rank/rank_fun.ejs +1 -0
- package/lib/templates/report/daily/base.css +1 -0
- package/lib/templates/report/daily.ejs +29 -0
- package/package.json +2 -2
- package/template/hero/hero_1.ejs +0 -900
- package/template/item/item/recipe.ejs +0 -51
- package/template/item/item/style.css +0 -244
- package/template/item/item.ejs +0 -140
- package/template/item/itemlist.ejs +0 -99
- package/template/match/match_1/item.ejs +0 -11
- package/template/match/match_1/main.ejs +0 -37
- package/template/match/match_1/player.ejs +0 -154
- package/template/match/match_1/style.css +0 -764
- package/template/match/match_1.ejs +0 -56
- package/template/match/match_2/original.css +0 -463
- package/template/match/match_2/original.ejs +0 -192
- package/template/match/match_2+/charts.ejs +0 -261
- package/template/match/match_2+/extra.css +0 -143
- package/template/match/match_2+/lane_outcome.ejs +0 -157
- package/template/match/match_2+.ejs +0 -27
- package/template/match/match_2.ejs +0 -18
- package/template/player/player_1/private.ejs +0 -5
- package/template/player/player_1.ejs +0 -654
- package/template/rank/rank_fun.ejs +0 -131
- package/template/report/daily.ejs +0 -191
- /package/{queries → lib/queries}/Constants.graphql +0 -0
- /package/{queries → lib/queries}/GetWeeklyMetaByPosition.graphql +0 -0
- /package/{queries → lib/queries}/PlayerExtraInfo.graphql +0 -0
- /package/{queries → lib/queries}/PlayerInfoWith25Matches.graphql +0 -0
- /package/{queries → lib/queries}/PlayerPerformanceForHeroRecommendation.graphql +0 -0
- /package/{queries → lib/queries}/PlayersInfoWith10MatchesForGuild.graphql +0 -0
- /package/{queries → lib/queries}/PlayersLastmatchRankinfo.graphql +0 -0
- /package/{queries → lib/queries}/PlayersMatchesForDaily.graphql +0 -0
- /package/{queries → lib/queries}/RequestMatchDataAnalysis.graphql +0 -0
- /package/{queries → lib/queries}/VerifyingPlayer.graphql +0 -0
- /package/{template → lib/templates}/images/bei.jpg +0 -0
- /package/{template → lib/templates}/images/disconnected.png +0 -0
- /package/{template → lib/templates}/images/flag_dire.png +0 -0
- /package/{template → lib/templates}/images/flag_radiant.png +0 -0
- /package/{template → lib/templates}/images/hero_badge_1.png +0 -0
- /package/{template → lib/templates}/images/hero_badge_2.png +0 -0
- /package/{template → lib/templates}/images/hero_badge_3.png +0 -0
- /package/{template → lib/templates}/images/hero_badge_4.png +0 -0
- /package/{template → lib/templates}/images/hero_badge_5.png +0 -0
- /package/{template → lib/templates}/images/hero_badge_6.png +0 -0
- /package/{template → lib/templates}/images/lane_fail.svg +0 -0
- /package/{template → lib/templates}/images/lane_jungle.svg +0 -0
- /package/{template → lib/templates}/images/lane_stomp.svg +0 -0
- /package/{template → lib/templates}/images/lane_stomped.svg +0 -0
- /package/{template → lib/templates}/images/lane_tie.svg +0 -0
- /package/{template → lib/templates}/images/lane_victory.svg +0 -0
- /package/{template → lib/templates}/images/logo_dire.png +0 -0
- /package/{template → lib/templates}/images/logo_radiant.png +0 -0
- /package/{template → lib/templates}/images/medal_0.png +0 -0
- /package/{template → lib/templates}/images/medal_1.png +0 -0
- /package/{template → lib/templates}/images/medal_2.png +0 -0
- /package/{template → lib/templates}/images/medal_3.png +0 -0
- /package/{template → lib/templates}/images/medal_4.png +0 -0
- /package/{template → lib/templates}/images/medal_5.png +0 -0
- /package/{template → lib/templates}/images/medal_6.png +0 -0
- /package/{template → lib/templates}/images/medal_7.png +0 -0
- /package/{template → lib/templates}/images/medal_8.png +0 -0
- /package/{template → lib/templates}/images/medal_8b.png +0 -0
- /package/{template → lib/templates}/images/medal_8c.png +0 -0
- /package/{template → lib/templates}/images/scepter.png +0 -0
- /package/{template → lib/templates}/images/scepter_0.png +0 -0
- /package/{template → lib/templates}/images/scepter_1.png +0 -0
- /package/{template → lib/templates}/images/shard.png +0 -0
- /package/{template → lib/templates}/images/shard_0.png +0 -0
- /package/{template → lib/templates}/images/shard_1.png +0 -0
- /package/{template → lib/templates}/images/star_0.png +0 -0
- /package/{template → lib/templates}/images/star_1.png +0 -0
- /package/{template → lib/templates}/images/star_2.png +0 -0
- /package/{template → lib/templates}/images/star_3.png +0 -0
- /package/{template → lib/templates}/images/star_4.png +0 -0
- /package/{template → lib/templates}/images/star_5.png +0 -0
- /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
|
-
} */
|
package/template/item/item.ejs
DELETED
|
@@ -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>
|