@sjtdev/koishi-plugin-dota2tracker 2.5.2 → 2.5.4
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 +21 -0
- package/lib/index.js +140 -66
- package/lib/templates/hero/hero_1.ejs +1 -1
- package/lib/templates/item/item.ejs +1 -1
- package/lib/templates/item/itemlist.ejs +1 -1
- package/lib/templates/match/match_1.ejs +1 -1
- package/lib/templates/match/match_2+.ejs +1 -1
- package/lib/templates/match/match_2.ejs +1 -1
- package/lib/templates/player/player_1.ejs +1 -1
- package/lib/templates/rank/rank_fun.ejs +1 -1
- package/lib/templates/report/daily/style.css +1 -1
- package/lib/templates/report/daily.ejs +1 -1
- package/lib/templates/report/daily_legacy.ejs +1 -1
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
### [2.5.4](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.5.3...v2.5.4) (2026-02-26)
|
|
4
|
+
|
|
5
|
+
### 🚀 功能优化
|
|
6
|
+
|
|
7
|
+
* **database:** 增加缓存群友列表机制,加入对拉取有效群友时的检测,每小时更新缓存 ([1ac1df9](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/1ac1df9513a883b17031fdc3e912fccc0af8a3e2)), closes [#17](https://github.com/sjtdev/koishi-plugin-dota2tracker/issues/17)
|
|
8
|
+
|
|
9
|
+
### 🐛 Bug 修复
|
|
10
|
+
|
|
11
|
+
* **match-watcher:** 修复无有效群友时还会发送查询请求 ([a8d1e8c](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/a8d1e8c173d71b850516912729e398943d3ea391))
|
|
12
|
+
|
|
13
|
+
### [2.5.3](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.5.2...v2.5.3) (2026-02-23)
|
|
14
|
+
|
|
15
|
+
### 🎨 样式
|
|
16
|
+
|
|
17
|
+
* **report/daily:** 缩窄整体宽度 ([ef756e0](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/ef756e0f418715a63b50586653221f92c25afd91))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug 修复
|
|
20
|
+
|
|
21
|
+
* 尝试修复在**异常状态群组**中获取群友信息时失败导致流程阻塞的问题 ([f00841d](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/f00841dd82794afd69987926804147a4b49fbfee)), closes [#17](https://github.com/sjtdev/koishi-plugin-dota2tracker/issues/17)
|
|
22
|
+
* **database:** 修改`dt_match_extension`键类型定义排除某些可能的隐患 ([72c0bbe](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/72c0bbebc0faf540aea29c8e2e4ae8210ab13b3e))
|
|
23
|
+
|
|
3
24
|
### [2.5.2](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.5.1...v2.5.2) (2026-02-20)
|
|
4
25
|
|
|
5
26
|
### 🐛 Bug 修复
|
package/lib/index.js
CHANGED
|
@@ -1627,7 +1627,7 @@ var MatchService = class _MatchService extends import_koishi4.Service {
|
|
|
1627
1627
|
const facetData = await _MatchService.constantsInjectFacetData(constantsQuery, matchQuery, languageTag, this.ctx.dota2tracker.hero);
|
|
1628
1628
|
this.ctx.dota2tracker.cache.setFacetConstantsCache(languageTag, constantsQuery);
|
|
1629
1629
|
const match = _MatchService.extendMatchData(matchQuery, facetData, this.ctx.dota2tracker.dotaconstants);
|
|
1630
|
-
this.
|
|
1630
|
+
this.recordMatchExtension(match);
|
|
1631
1631
|
return match;
|
|
1632
1632
|
} catch (error) {
|
|
1633
1633
|
this.ctx.dota2tracker.cache.deleteFacetConstantsCache(languageTag);
|
|
@@ -1892,6 +1892,21 @@ var MatchService = class _MatchService extends import_koishi4.Service {
|
|
|
1892
1892
|
static isMatchParsed(matchQuery) {
|
|
1893
1893
|
return matchQuery?.match?.parsedDateTime && matchQuery?.match?.players.filter((player) => player?.stats?.heroDamageReport?.dealtTotal).length > 0;
|
|
1894
1894
|
}
|
|
1895
|
+
async recordMatchExtension(match) {
|
|
1896
|
+
const extensionData = { matchId: match.id, players: [] };
|
|
1897
|
+
for (const player of match.players) {
|
|
1898
|
+
extensionData.players.push({
|
|
1899
|
+
steamAccountId: player.steamAccountId,
|
|
1900
|
+
rankSnapshot: player.rank,
|
|
1901
|
+
mvpScore: player.mvpScore,
|
|
1902
|
+
titles: player.titles,
|
|
1903
|
+
utilityScore: player.utilityScore,
|
|
1904
|
+
laneResult: player.laneResult,
|
|
1905
|
+
partyId: player.partyId
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
this.ctx.dota2tracker.database.insertMatchExtension(extensionData.matchId, new Date(match.startDateTime * 1e3), extensionData);
|
|
1909
|
+
}
|
|
1895
1910
|
};
|
|
1896
1911
|
function createItemObject(itemId, purchaseTimesMap, purchaseTimeIndices, dotaconstants) {
|
|
1897
1912
|
if (itemId === void 0 || itemId === null) {
|
|
@@ -2298,13 +2313,13 @@ var DatabaseService = class extends import_koishi7.Service {
|
|
|
2298
2313
|
}
|
|
2299
2314
|
constructor(ctx) {
|
|
2300
2315
|
super(ctx, "dota2tracker.database", true);
|
|
2301
|
-
ctx.model.extend("dt_subscribed_guilds", { id: "unsigned",
|
|
2316
|
+
ctx.model.extend("dt_subscribed_guilds", { id: "unsigned", channelId: { type: "string", legacy: ["guildId"] }, platform: "string" }, { autoInc: true });
|
|
2302
2317
|
ctx.model.extend(
|
|
2303
2318
|
"dt_subscribed_players",
|
|
2304
2319
|
{
|
|
2305
2320
|
id: "unsigned",
|
|
2306
2321
|
userId: "string",
|
|
2307
|
-
|
|
2322
|
+
channelId: { type: "string", legacy: ["guildId"] },
|
|
2308
2323
|
platform: "string",
|
|
2309
2324
|
steamId: "integer",
|
|
2310
2325
|
nickName: "string",
|
|
@@ -2312,21 +2327,82 @@ var DatabaseService = class extends import_koishi7.Service {
|
|
|
2312
2327
|
},
|
|
2313
2328
|
{ autoInc: true }
|
|
2314
2329
|
);
|
|
2315
|
-
ctx.model.extend("dt_match_extension", { matchId: "
|
|
2330
|
+
ctx.model.extend("dt_match_extension", { matchId: "string", startTime: "timestamp", data: "json" }, { autoInc: false, primary: ["matchId"] });
|
|
2331
|
+
ctx.cron("0 * * * *", async () => {
|
|
2332
|
+
await this.refreshAllGuildMemberCaches();
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2335
|
+
/** 群成员列表内存缓存: Map<"platform:channelId", Set<userId>> */
|
|
2336
|
+
guildMemberCache = /* @__PURE__ */ new Map();
|
|
2337
|
+
/**
|
|
2338
|
+
* 刷新指定频道的群成员缓存。
|
|
2339
|
+
* 通过 channel 表获取 assignee(bot selfId),再调用 bot.getGuildMemberList。
|
|
2340
|
+
* 失败时记录 warn 并清除该 key(保守策略)。
|
|
2341
|
+
*/
|
|
2342
|
+
async refreshGuildMemberCache(platform, channelId) {
|
|
2343
|
+
const cacheKey = `${platform}:${channelId}`;
|
|
2344
|
+
try {
|
|
2345
|
+
const channelRow = (await this.ctx.database.get("channel", { id: channelId })).at(0);
|
|
2346
|
+
const selfId = channelRow?.assignee;
|
|
2347
|
+
const guildId = channelRow?.guildId ?? channelId;
|
|
2348
|
+
if (!selfId) {
|
|
2349
|
+
this.guildMemberCache.delete(cacheKey);
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
const bot = this.ctx.bots[`${platform}:${selfId}`];
|
|
2353
|
+
if (!bot) {
|
|
2354
|
+
this.guildMemberCache.delete(cacheKey);
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2357
|
+
const members = await bot.getGuildMemberList(guildId);
|
|
2358
|
+
const userIds = new Set(members.data.map((m) => m.user.id));
|
|
2359
|
+
this.guildMemberCache.set(cacheKey, userIds);
|
|
2360
|
+
} catch (error) {
|
|
2361
|
+
this.logger.warn(`获取频道 ${cacheKey} 成员列表失败,已清除对应缓存:` + error);
|
|
2362
|
+
this.guildMemberCache.delete(cacheKey);
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
/** 全量刷新所有已订阅频道的群成员缓存(每小时 cron 调用) */
|
|
2366
|
+
async refreshAllGuildMemberCaches() {
|
|
2367
|
+
const subscribedChannels = await this.ctx.database.get("dt_subscribed_guilds", void 0);
|
|
2368
|
+
await Promise.allSettled(subscribedChannels.map((ch) => this.refreshGuildMemberCache(ch.platform, ch.channelId)));
|
|
2369
|
+
}
|
|
2370
|
+
/**
|
|
2371
|
+
* 判断玩家是否仍在群组中。
|
|
2372
|
+
* 缓存未命中(冷启动阶段)时保守放行,返回 true。
|
|
2373
|
+
*/
|
|
2374
|
+
isPlayerInGuild(platform, channelId, userId) {
|
|
2375
|
+
const cached = this.guildMemberCache.get(`${platform}:${channelId}`);
|
|
2376
|
+
if (!cached) return true;
|
|
2377
|
+
return cached.has(userId);
|
|
2378
|
+
}
|
|
2379
|
+
/** 删除指定频道的群成员缓存(取消订阅时内部调用) */
|
|
2380
|
+
deleteGuildMemberCache(platform, channelId) {
|
|
2381
|
+
this.guildMemberCache.delete(`${platform}:${channelId}`);
|
|
2382
|
+
}
|
|
2383
|
+
/** 从缓存中移除单个用户(取消绑定时内部调用,保留频道内其他成员的缓存)*/
|
|
2384
|
+
removeUserFromGuildMemberCache(platform, channelId, userId) {
|
|
2385
|
+
const cached = this.guildMemberCache.get(`${platform}:${channelId}`);
|
|
2386
|
+
if (cached) cached.delete(userId);
|
|
2316
2387
|
}
|
|
2317
2388
|
async insertMatchExtension(matchId, startTime, data) {
|
|
2318
|
-
return this.ctx.database.upsert("dt_match_extension", [{ matchId, startTime, data }]);
|
|
2389
|
+
return this.ctx.database.upsert("dt_match_extension", [{ matchId: String(matchId), startTime, data }]);
|
|
2319
2390
|
}
|
|
2320
2391
|
async getMatchExtension(matchIds) {
|
|
2321
|
-
|
|
2392
|
+
const rows = await this.ctx.database.get("dt_match_extension", {
|
|
2393
|
+
matchId: matchIds.map((id) => String(id))
|
|
2394
|
+
});
|
|
2395
|
+
return rows.map((row) => ({
|
|
2396
|
+
...row,
|
|
2397
|
+
matchId: Number(row.matchId)
|
|
2398
|
+
}));
|
|
2322
2399
|
}
|
|
2323
2400
|
async setPlayerRank(playerId, rank) {
|
|
2324
2401
|
return this.ctx.database.set("dt_subscribed_players", playerId, { rank });
|
|
2325
2402
|
}
|
|
2326
2403
|
async getActiveSubscribedPlayers() {
|
|
2327
|
-
const
|
|
2328
|
-
|
|
2329
|
-
return subscribedPlayersInGuild;
|
|
2404
|
+
const subscribedChannels = await this.ctx.database.get("dt_subscribed_guilds", void 0);
|
|
2405
|
+
return (await this.ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedChannels.some((ch) => ch.channelId == player.channelId)).filter((player) => this.isPlayerInGuild(player.platform, player.channelId, player.userId));
|
|
2330
2406
|
}
|
|
2331
2407
|
async isUserBinded(session) {
|
|
2332
2408
|
const subscribedPlayer = await this.ctx.database.get("dt_subscribed_players", this.getUserQuery(session));
|
|
@@ -2337,23 +2413,32 @@ var DatabaseService = class extends import_koishi7.Service {
|
|
|
2337
2413
|
return subscribedPlayer.length > 0 ? subscribedPlayer[0] : null;
|
|
2338
2414
|
}
|
|
2339
2415
|
async bindUser(session, steamId, nickName) {
|
|
2340
|
-
|
|
2416
|
+
const result = await this.ctx.database.create("dt_subscribed_players", {
|
|
2341
2417
|
...this.getUserQuery(session),
|
|
2342
2418
|
steamId: Number(steamId),
|
|
2343
2419
|
nickName: nickName || ""
|
|
2344
2420
|
});
|
|
2421
|
+
this.refreshGuildMemberCache(session.event.platform, session.event.channel.id);
|
|
2422
|
+
return result;
|
|
2345
2423
|
}
|
|
2346
2424
|
async unbindUser(session) {
|
|
2425
|
+
this.removeUserFromGuildMemberCache(session.event.platform, session.event.channel.id, session.event.user.id);
|
|
2347
2426
|
return this.ctx.database.remove("dt_subscribed_players", this.getUserQuery(session));
|
|
2348
2427
|
}
|
|
2428
|
+
async renamePlayer(playerId, nickName) {
|
|
2429
|
+
return this.ctx.database.set("dt_subscribed_players", playerId, { nickName });
|
|
2430
|
+
}
|
|
2349
2431
|
async isChannelSubscribed(session) {
|
|
2350
2432
|
const subscribedChannels = await this.ctx.database.get("dt_subscribed_guilds", this.getChannelQuery(session));
|
|
2351
2433
|
return subscribedChannels.length > 0;
|
|
2352
2434
|
}
|
|
2353
2435
|
async subscribeChannel(session) {
|
|
2354
|
-
|
|
2436
|
+
const result = await this.ctx.database.create("dt_subscribed_guilds", this.getChannelQuery(session));
|
|
2437
|
+
this.refreshGuildMemberCache(session.event.platform, session.event.channel.id);
|
|
2438
|
+
return result;
|
|
2355
2439
|
}
|
|
2356
2440
|
async unSubscribeChannel(session) {
|
|
2441
|
+
this.deleteGuildMemberCache(session.event.platform, session.event.channel.id);
|
|
2357
2442
|
return this.ctx.database.remove("dt_subscribed_guilds", this.getChannelQuery(session));
|
|
2358
2443
|
}
|
|
2359
2444
|
async getSubscribedMembersInChannel(session) {
|
|
@@ -2364,13 +2449,13 @@ var DatabaseService = class extends import_koishi7.Service {
|
|
|
2364
2449
|
*/
|
|
2365
2450
|
getChannelQuery(session) {
|
|
2366
2451
|
return {
|
|
2367
|
-
|
|
2452
|
+
channelId: session.event.channel.id,
|
|
2368
2453
|
platform: session.event.platform
|
|
2369
2454
|
};
|
|
2370
2455
|
}
|
|
2371
2456
|
getUserQuery(session) {
|
|
2372
2457
|
return {
|
|
2373
|
-
|
|
2458
|
+
channelId: session.event.channel.id,
|
|
2374
2459
|
platform: session.event.platform,
|
|
2375
2460
|
userId: session.event.user.id
|
|
2376
2461
|
};
|
|
@@ -2378,14 +2463,14 @@ var DatabaseService = class extends import_koishi7.Service {
|
|
|
2378
2463
|
/** 从已订阅玩家中查找玩家返回SteamId,不需要以昵称匹配时仅需传入Session */
|
|
2379
2464
|
async getSubscribedPlayerByNickNameOrSession(session, nickName) {
|
|
2380
2465
|
const player = (await this.ctx.database.get("dt_subscribed_players", {
|
|
2381
|
-
|
|
2466
|
+
channelId: session.event.channel.id,
|
|
2382
2467
|
platform: session.event.platform,
|
|
2383
2468
|
...nickName ? { nickName } : { userId: session.event.user.id }
|
|
2384
2469
|
}))?.[0];
|
|
2385
2470
|
return player;
|
|
2386
2471
|
}
|
|
2387
|
-
getChannelInfo({ platform,
|
|
2388
|
-
return `${platform}:${
|
|
2472
|
+
getChannelInfo({ platform, channelId }) {
|
|
2473
|
+
return `${platform}:${channelId}`;
|
|
2389
2474
|
}
|
|
2390
2475
|
};
|
|
2391
2476
|
|
|
@@ -2752,7 +2837,6 @@ var ViewRenderer = class extends import_koishi10.Service {
|
|
|
2752
2837
|
$t: /* @__PURE__ */ __name((key, params) => this.ctx.dota2tracker.i18n.$t(languageTag, key, params), "$t"),
|
|
2753
2838
|
languageTag,
|
|
2754
2839
|
Random: import_koishi10.Random,
|
|
2755
|
-
fontFamily: this.config.templateFonts.map((f) => `${f}`).join(", "),
|
|
2756
2840
|
getImageUrl: this.getImageUrl.bind(this)
|
|
2757
2841
|
};
|
|
2758
2842
|
try {
|
|
@@ -3281,6 +3365,7 @@ var MatchWatcherTask = class extends import_koishi13.Service {
|
|
|
3281
3365
|
async discovery() {
|
|
3282
3366
|
try {
|
|
3283
3367
|
const activePlayers = await this.ctx.dota2tracker.database.getActiveSubscribedPlayers();
|
|
3368
|
+
if (activePlayers.length === 0) return;
|
|
3284
3369
|
const uniqueSteamIds = activePlayers.map((player) => player.steamId).filter((steamId, index, self) => self.indexOf(steamId) === index);
|
|
3285
3370
|
const playersData = (await this.ctx.dota2tracker.stratzAPI.queryPlayersLastMatchRankInfo({ steamAccountIds: uniqueSteamIds })).players;
|
|
3286
3371
|
await this.discoverNewMatches(playersData, activePlayers);
|
|
@@ -3300,10 +3385,10 @@ var MatchWatcherTask = class extends import_koishi13.Service {
|
|
|
3300
3385
|
}
|
|
3301
3386
|
const playersByGuild = /* @__PURE__ */ new Map();
|
|
3302
3387
|
for (const player of relevantActivePlayers) {
|
|
3303
|
-
const guildKey = `${player.platform}:${player.
|
|
3388
|
+
const guildKey = `${player.platform}:${player.channelId}`;
|
|
3304
3389
|
if (!playersByGuild.has(guildKey)) {
|
|
3305
3390
|
playersByGuild.set(guildKey, {
|
|
3306
|
-
guildInfo: { platform: player.platform, channelId: player.
|
|
3391
|
+
guildInfo: { platform: player.platform, channelId: player.channelId },
|
|
3307
3392
|
players: []
|
|
3308
3393
|
});
|
|
3309
3394
|
}
|
|
@@ -3324,7 +3409,7 @@ var MatchWatcherTask = class extends import_koishi13.Service {
|
|
|
3324
3409
|
});
|
|
3325
3410
|
messageToLogger.push({
|
|
3326
3411
|
platform: guildInfo.platform,
|
|
3327
|
-
guildId: guildInfo.
|
|
3412
|
+
guildId: guildInfo.channelId,
|
|
3328
3413
|
players
|
|
3329
3414
|
});
|
|
3330
3415
|
subscribers.push(subscriber);
|
|
@@ -3359,9 +3444,14 @@ var MatchWatcherTask = class extends import_koishi13.Service {
|
|
|
3359
3444
|
const prevRank = ranks["prevRank"];
|
|
3360
3445
|
const currRank = ranks["currRank"];
|
|
3361
3446
|
if (prevRank.medal !== currRank.medal || prevRank.star !== currRank.star && this.config.rankBroadStar || prevRank.leader !== currRank.leader && this.config.rankBroadLeader) {
|
|
3362
|
-
|
|
3447
|
+
let guildMember;
|
|
3448
|
+
try {
|
|
3449
|
+
guildMember = await this.ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember?.(subPlayer.channelId, subPlayer.userId);
|
|
3450
|
+
} catch (error) {
|
|
3451
|
+
this.logger.warn(this.ctx.dota2tracker.i18n.gt("dota2tracker.logger.fetch_guilds_failed") + error);
|
|
3452
|
+
}
|
|
3363
3453
|
const name2 = subPlayer.nickName ?? guildMember?.nick ?? playersData.find((player) => player.steamAccount.id == subPlayer.steamId)?.steamAccount.name ?? String(subPlayer.steamId);
|
|
3364
|
-
const languageTag = await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId: subPlayer.
|
|
3454
|
+
const languageTag = await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId: subPlayer.channelId });
|
|
3365
3455
|
if (this.config.rankBroadFun === true) {
|
|
3366
3456
|
const img = await this.ctx.dota2tracker.view.renderToImageByFile(
|
|
3367
3457
|
{
|
|
@@ -3376,13 +3466,13 @@ var MatchWatcherTask = class extends import_koishi13.Service {
|
|
|
3376
3466
|
"rank" /* Rank */,
|
|
3377
3467
|
languageTag
|
|
3378
3468
|
);
|
|
3379
|
-
await this.ctx.broadcast([`${subPlayer.platform}:${subPlayer.
|
|
3469
|
+
await this.ctx.broadcast([`${subPlayer.platform}:${subPlayer.channelId}`], img);
|
|
3380
3470
|
} else {
|
|
3381
3471
|
const message = this.ctx.dota2tracker.messageBuilder.buildRankChangedMessage(languageTag, name2, prevRank, currRank);
|
|
3382
|
-
await this.ctx.broadcast([`${subPlayer.platform}:${subPlayer.
|
|
3472
|
+
await this.ctx.broadcast([`${subPlayer.platform}:${subPlayer.channelId}`], message);
|
|
3383
3473
|
}
|
|
3384
3474
|
this.ctx.dota2tracker.database.setPlayerRank(subPlayer.id, rankMap.get(subPlayer.steamId));
|
|
3385
|
-
this.logger.info(this.ctx.dota2tracker.i18n.gt("dota2tracker.logger.rank_sent", { platform: subPlayer.platform, guildId: subPlayer.
|
|
3475
|
+
this.logger.info(this.ctx.dota2tracker.i18n.gt("dota2tracker.logger.rank_sent", { platform: subPlayer.platform, guildId: subPlayer.channelId, player: { nickName: subPlayer.nickName, steamId: subPlayer.steamId } }));
|
|
3386
3476
|
}
|
|
3387
3477
|
} else {
|
|
3388
3478
|
this.ctx.dota2tracker.database.setPlayerRank(subPlayer.id, rankMap.get(subPlayer.steamId));
|
|
@@ -3426,8 +3516,7 @@ var ParsePollingTask = class extends import_koishi14.Service {
|
|
|
3426
3516
|
source: "AUTOMATIC",
|
|
3427
3517
|
type: "CHANNEL",
|
|
3428
3518
|
platform: target.platform,
|
|
3429
|
-
channelId: target.channelId
|
|
3430
|
-
guildId: target.guildId
|
|
3519
|
+
channelId: target.channelId
|
|
3431
3520
|
};
|
|
3432
3521
|
}
|
|
3433
3522
|
add(matchId, subscribers) {
|
|
@@ -3529,15 +3618,15 @@ var ParsePollingTask = class extends import_koishi14.Service {
|
|
|
3529
3618
|
}
|
|
3530
3619
|
};
|
|
3531
3620
|
|
|
3532
|
-
// src/app/tasks/report.task.ts
|
|
3621
|
+
// src/app/tasks/daily-report.task.ts
|
|
3533
3622
|
var import_koishi15 = require("koishi");
|
|
3534
3623
|
var import_luxon9 = require("luxon");
|
|
3535
|
-
var
|
|
3624
|
+
var DailyReportTask = class extends import_koishi15.Service {
|
|
3536
3625
|
static {
|
|
3537
|
-
__name(this, "
|
|
3626
|
+
__name(this, "DailyReportTask");
|
|
3538
3627
|
}
|
|
3539
3628
|
constructor(ctx) {
|
|
3540
|
-
super(ctx, "dota2tracker.report-task", true);
|
|
3629
|
+
super(ctx, "dota2tracker.daily-report-task", true);
|
|
3541
3630
|
this.config = ctx.config;
|
|
3542
3631
|
if (this.config.dailyReportSwitch) {
|
|
3543
3632
|
ctx.cron(`0 ${this.config.dailyReportHours} * * *`, async () => {
|
|
@@ -3551,7 +3640,7 @@ var ReportTask = class extends import_koishi15.Service {
|
|
|
3551
3640
|
}
|
|
3552
3641
|
}
|
|
3553
3642
|
async runDailyJob() {
|
|
3554
|
-
const bundles = await this.ctx.dota2tracker.
|
|
3643
|
+
const bundles = await this.ctx.dota2tracker.dailyReport.generateDailyReportBundles();
|
|
3555
3644
|
for (const bundle of bundles) {
|
|
3556
3645
|
const image = await this.ctx.dota2tracker.view.renderToImageByFile(bundle.report, "daily", "report" /* Report */, await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId: bundle.channelId }));
|
|
3557
3646
|
await this.ctx.broadcast([`${bundle.platform}:${bundle.channelId}`], image);
|
|
@@ -3566,12 +3655,12 @@ var ReportTask = class extends import_koishi15.Service {
|
|
|
3566
3655
|
}
|
|
3567
3656
|
}
|
|
3568
3657
|
async report_legacy(timeAgo, titleKey, showCombi) {
|
|
3569
|
-
const
|
|
3570
|
-
const
|
|
3571
|
-
const steamIds =
|
|
3658
|
+
const subscribedChannels = await this.ctx.database.get("dt_subscribed_guilds", void 0);
|
|
3659
|
+
const subscribedPlayersInChannel = (await this.ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedChannels.some((ch) => ch.channelId == player.channelId));
|
|
3660
|
+
const steamIds = subscribedPlayersInChannel.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index);
|
|
3572
3661
|
const players = (await this.ctx.dota2tracker.stratzAPI.queryPlayersMatchesForDaily_legacy(steamIds, timeAgo)).players.filter((player) => player.matches?.length > 0);
|
|
3573
3662
|
const matches = players.map((player) => player.matches.map((match) => match)).flat().filter((item, index, self) => index === self.findIndex((t) => t.id === item.id));
|
|
3574
|
-
for (let subPlayer of
|
|
3663
|
+
for (let subPlayer of subscribedPlayersInChannel) {
|
|
3575
3664
|
let player = players.find((player2) => subPlayer.steamId == player2.steamAccount.id);
|
|
3576
3665
|
if (!player) continue;
|
|
3577
3666
|
let guildMember;
|
|
@@ -3590,8 +3679,8 @@ var ReportTask = class extends import_koishi15.Service {
|
|
|
3590
3679
|
player.avgImp = roundToDecimalPlaces(player.matches.reduce((acc, match) => acc + match.players.find((innerPlayer) => innerPlayer.steamAccount.id == player.steamAccount.id).imp, 0) / player.matches.length, 0);
|
|
3591
3680
|
subPlayer = Object.assign(subPlayer, player);
|
|
3592
3681
|
}
|
|
3593
|
-
for (let
|
|
3594
|
-
const currentsubscribedPlayers =
|
|
3682
|
+
for (let channel of subscribedChannels) {
|
|
3683
|
+
const currentsubscribedPlayers = subscribedPlayersInChannel.filter((player) => player.platform == channel.platform && player.channelId == channel.channelId && player.matches?.length);
|
|
3595
3684
|
if (currentsubscribedPlayers.length) {
|
|
3596
3685
|
const currentsubscribedPlayersIds = currentsubscribedPlayers.map((player) => player.steamId);
|
|
3597
3686
|
const combinationsMap = /* @__PURE__ */ new Map();
|
|
@@ -3617,9 +3706,9 @@ var ReportTask = class extends import_koishi15.Service {
|
|
|
3617
3706
|
});
|
|
3618
3707
|
const combinations = Array.from(combinationsMap.values());
|
|
3619
3708
|
try {
|
|
3620
|
-
const languageTag = await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId:
|
|
3709
|
+
const languageTag = await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId: channel.channelId });
|
|
3621
3710
|
await this.ctx.broadcast(
|
|
3622
|
-
[`${
|
|
3711
|
+
[`${channel.platform}:${channel.channelId}`],
|
|
3623
3712
|
await this.ctx.dota2tracker.view.renderToImageByFile(
|
|
3624
3713
|
{
|
|
3625
3714
|
title: this.ctx.dota2tracker.i18n.$t(languageTag, titleKey),
|
|
@@ -3636,7 +3725,7 @@ var ReportTask = class extends import_koishi15.Service {
|
|
|
3636
3725
|
languageTag
|
|
3637
3726
|
)
|
|
3638
3727
|
);
|
|
3639
|
-
this.logger.info(this.ctx.dota2tracker.i18n.gt("dota2tracker.logger.report_sent", { title: this.ctx.dota2tracker.i18n.$t(languageTag, titleKey), guildId:
|
|
3728
|
+
this.logger.info(this.ctx.dota2tracker.i18n.gt("dota2tracker.logger.report_sent", { title: this.ctx.dota2tracker.i18n.$t(languageTag, titleKey), guildId: channel.channelId, platform: channel.platform }));
|
|
3640
3729
|
} catch (error) {
|
|
3641
3730
|
this.logger.error(error);
|
|
3642
3731
|
}
|
|
@@ -4000,7 +4089,7 @@ function registerUserCommand(ctx) {
|
|
|
4000
4089
|
if (!session.isDirect) {
|
|
4001
4090
|
const sessionPlayer = await ctx.dota2tracker.database.getBindedUser(session);
|
|
4002
4091
|
if (sessionPlayer) {
|
|
4003
|
-
|
|
4092
|
+
ctx.dota2tracker.database.unbindUser(session);
|
|
4004
4093
|
return session.text(".unbind_success");
|
|
4005
4094
|
} else {
|
|
4006
4095
|
return session.text(".not_binded");
|
|
@@ -4020,7 +4109,7 @@ function registerUserCommand(ctx) {
|
|
|
4020
4109
|
if (nick_name === sessionPlayer.nickName) {
|
|
4021
4110
|
return session.text(".nick_name_same");
|
|
4022
4111
|
}
|
|
4023
|
-
await ctx.database.
|
|
4112
|
+
await ctx.dota2tracker.database.renamePlayer(sessionPlayer.id, nick_name);
|
|
4024
4113
|
return session.text(".rename_success", { nick_name });
|
|
4025
4114
|
} else {
|
|
4026
4115
|
return session.text(".not_binded");
|
|
@@ -4551,32 +4640,17 @@ function convertBuildingEvents(objectives) {
|
|
|
4551
4640
|
}
|
|
4552
4641
|
__name(convertBuildingEvents, "convertBuildingEvents");
|
|
4553
4642
|
|
|
4554
|
-
// src/app/core/report.service.ts
|
|
4643
|
+
// src/app/core/daily-report.service.ts
|
|
4555
4644
|
var import_koishi18 = require("koishi");
|
|
4556
4645
|
var import_luxon11 = require("luxon");
|
|
4557
|
-
var
|
|
4646
|
+
var DailyReportService = class _DailyReportService extends import_koishi18.Service {
|
|
4558
4647
|
static {
|
|
4559
|
-
__name(this, "
|
|
4648
|
+
__name(this, "DailyReportService");
|
|
4560
4649
|
}
|
|
4561
4650
|
constructor(ctx) {
|
|
4562
|
-
super(ctx, "dota2tracker.report", true);
|
|
4651
|
+
super(ctx, "dota2tracker.daily-report", true);
|
|
4563
4652
|
this.config = ctx.config;
|
|
4564
4653
|
}
|
|
4565
|
-
async recordMatchExtension(match) {
|
|
4566
|
-
const extensionData = { matchId: match.id, players: [] };
|
|
4567
|
-
for (const player of match.players) {
|
|
4568
|
-
extensionData.players.push({
|
|
4569
|
-
steamAccountId: player.steamAccountId,
|
|
4570
|
-
rankSnapshot: player.rank,
|
|
4571
|
-
mvpScore: player.mvpScore,
|
|
4572
|
-
titles: player.titles,
|
|
4573
|
-
utilityScore: player.utilityScore,
|
|
4574
|
-
laneResult: player.laneResult,
|
|
4575
|
-
partyId: player.partyId
|
|
4576
|
-
});
|
|
4577
|
-
}
|
|
4578
|
-
this.ctx.dota2tracker.database.insertMatchExtension(extensionData.matchId, new Date(match.startDateTime * 1e3), extensionData);
|
|
4579
|
-
}
|
|
4580
4654
|
/**
|
|
4581
4655
|
* 入口函数,返回报告数据
|
|
4582
4656
|
*/
|
|
@@ -4590,7 +4664,7 @@ var ReportService = class _ReportService extends import_koishi18.Service {
|
|
|
4590
4664
|
const allMatchIds = [...new Set(data.players.flatMap((p) => (p.matches || []).map((m) => m.id)))].map((id) => Number(id));
|
|
4591
4665
|
const extensions = await this.ctx.dota2tracker.database.getMatchExtension(allMatchIds);
|
|
4592
4666
|
const getImageUrl = this.ctx.dota2tracker.view.getImageUrl.bind(this.ctx.dota2tracker.view);
|
|
4593
|
-
return await
|
|
4667
|
+
return await _DailyReportService.formatDailyReportBundles(
|
|
4594
4668
|
data,
|
|
4595
4669
|
users,
|
|
4596
4670
|
extensions,
|
|
@@ -4673,7 +4747,7 @@ var ReportService = class _ReportService extends import_koishi18.Service {
|
|
|
4673
4747
|
static groupUsersByChannel(users) {
|
|
4674
4748
|
const groups = /* @__PURE__ */ new Map();
|
|
4675
4749
|
for (const user of users) {
|
|
4676
|
-
const key = `${user.platform}:${user.
|
|
4750
|
+
const key = `${user.platform}:${user.channelId}`;
|
|
4677
4751
|
if (!groups.has(key)) groups.set(key, []);
|
|
4678
4752
|
groups.get(key).push(user);
|
|
4679
4753
|
}
|
|
@@ -5001,7 +5075,7 @@ async function apply(ctx, config) {
|
|
|
5001
5075
|
if (ctx.cron) {
|
|
5002
5076
|
ctx.dota2tracker.matchWatcher = new MatchWatcherTask(ctx);
|
|
5003
5077
|
ctx.dota2tracker.parsePolling = new ParsePollingTask(ctx);
|
|
5004
|
-
ctx.dota2tracker.
|
|
5078
|
+
ctx.dota2tracker.dailyReportTask = new DailyReportTask(ctx);
|
|
5005
5079
|
ctx.cron("* * * * *", async () => {
|
|
5006
5080
|
await ctx.dota2tracker.matchWatcher.discovery();
|
|
5007
5081
|
await ctx.dota2tracker.parsePolling.polling();
|
|
@@ -5011,7 +5085,7 @@ async function apply(ctx, config) {
|
|
|
5011
5085
|
}
|
|
5012
5086
|
ctx.dota2tracker.hero = new HeroService(ctx);
|
|
5013
5087
|
ctx.dota2tracker.item = new ItemService(ctx);
|
|
5014
|
-
ctx.dota2tracker.
|
|
5088
|
+
ctx.dota2tracker.dailyReport = new DailyReportService(ctx);
|
|
5015
5089
|
ctx.dota2tracker.cache = new CacheService(ctx);
|
|
5016
5090
|
ctx.dota2tracker.database = new DatabaseService(ctx);
|
|
5017
5091
|
ctx.dota2tracker.valveAPI = new ValveAPI(ctx);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Document</title> <%- `<style>` %> <%- include("../common/styles/normalize.min.css") %> <%- include(`./hero_1/base.css`) %>
|
|
1
|
+
<!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Document</title> <%- `<style>` %> <%- include("../common/styles/normalize.min.css") %> <%- include(`./hero_1/base.css`) %> <%- `</style>` %> </head><body> <% let hero = data; %> <% if (hero.primary_attr==3) {
|
|
2
2
|
const base_damage = Math.floor((hero.str_base+hero.agi_base+hero.int_base)*0.45);
|
|
3
3
|
hero.damage_max+=base_damage;
|
|
4
4
|
hero.damage_min+=base_damage;
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
// 预计算数据
|
|
42
42
|
const parsedAbilities = parseAbilityDesc(item.desc_loc);
|
|
43
43
|
const processedNotes = (item.notes_loc || []).map(processText);
|
|
44
|
-
%> <!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"> <%- `<style>` %> <%- include('./item/style.css') %>
|
|
44
|
+
%> <!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"> <%- `<style>` %> <%- include('./item/style.css') %> <%- `</style>` %> </head><body><div class="container"><div class="header"><img src="<%= getImageUrl(item.name, ImageType.Items) %>"><div><p class="name"><%= item.name_loc %> <span class="item_id"><%= item.name %></span></p> <% if (item.item_cost) { %> <p class="cost"><img style="height:20px;width:auto;margin-right:4px" src="<%= getImageUrl("gold", ImageType.Icons) %>"> <%= item.item_cost %> </p> <% } %> </div></div> <% if (citem?.abilities?.length) { %> <div class="stats"><p class="behavior"> <%= $t("dota2tracker.template.ability") %> <% if (citem.abilities.some(ability => capitalize(ability.type) === 'Active')) { %> <%= toArray(citem.behavior).map((beh) => $t("dota2tracker.template.behavior." + beh)).join("/") %> <% } else { %> <%= $t("dota2tracker.template.behavior.Passive") %> <% } %> </p> <% if (citem.target_team && citem.target_team.length) { %> <p class="target_team"> <%= $t("dota2tracker.template.affects") %> <%= toArray(citem.target_team).map((tt) => $t("dota2tracker.template.target_team." + tt)).join("/") %> </p> <% } %> <% if (citem.dmg_type) { %> <p class="dmg_type"> <%= $t("dota2tracker.template.damage_type") %> <span class="<%= citem.dmg_type %>"><%= $t("dota2tracker.template.damage_type_" + citem.dmg_type) %></span></p> <% } %> <% if (citem.dispellable) { %> <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> <% } %> <% if (citem.bkbpierce) { %> <p class="bkbpierce"> <%= $t("dota2tracker.template.bkbpierce") %> <span class="<%= citem.bkbpierce %>"><%= $t("dota2tracker.template." + citem.bkbpierce) %></span></p> <% } %> </div> <% } %> <div class="attrs"> <% item.special_values.filter(value => value.heading_loc).forEach(value => {
|
|
45
45
|
const match = value.heading_loc.match(/^([+-]?)(.*)/) || [];
|
|
46
46
|
const sign = match[1] || '+';
|
|
47
47
|
const rawText = match[2];
|
|
@@ -8,4 +8,4 @@ function calculateFontSize(text) {
|
|
|
8
8
|
let fontSize = Math.floor((maxWidth / totalUnits) * 1.8);
|
|
9
9
|
return Math.min(12, Math.max(6, fontSize));
|
|
10
10
|
}
|
|
11
|
-
%> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/> <%- "<style>" %> * { margin: 0; padding: 0; } html, body { height: auto; background-color: #000; color: #fff; } html { width: 232px; } body { width: 220px; margin: 6px; } .container { width: 220px; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; row-gap: 8px; } .container img { width: 44px; height: 32px; } .container .item { width: 48px; height: 54px; display: flex; flex-direction: column; font-size: 12px; align-items: center; justify-content: space-around; } .name { overflow: hidden; text-overflow: ellipsis; text-align: center; line-height: 1.2; min-height: 12px; }
|
|
11
|
+
%> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/> <%- "<style>" %> * { margin: 0; padding: 0; } html, body { height: auto; background-color: #000; color: #fff; } html { width: 232px; } body { width: 220px; margin: 6px; } .container { width: 220px; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; row-gap: 8px; } .container img { width: 44px; height: 32px; } .container .item { width: 48px; height: 54px; display: flex; flex-direction: column; font-size: 12px; align-items: center; justify-content: space-around; } .name { overflow: hidden; text-overflow: ellipsis; text-align: center; line-height: 1.2; min-height: 12px; } <%- "</style>" %> </head><body><div class="container"> <% data.forEach(function(item) { %> <div class="item"><img src="<%= getImageUrl(item.name, ImageType.Items) %>"/><div class="name" <%- `style="font-size: ${calculateFontSize(item.name_loc)}px"` %>> <%= item.name_loc %> </div></div> <% }); %> </div></body></html>
|
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
tie: getImageUrl("lane_tie", undefined, ImageFormat.svg),
|
|
16
16
|
jungle: getImageUrl("lane_jungle", undefined, ImageFormat.svg),
|
|
17
17
|
};
|
|
18
|
-
%> <%- include("../common/utils/match") %> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Match</title> <%- `<style>` %> <%- include(`./match_1/base.css`) %> <%- include(`./match_1/style.css`) %>
|
|
18
|
+
%> <%- include("../common/utils/match") %> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Match</title> <%- `<style>` %> <%- include(`./match_1/base.css`) %> <%- include(`./match_1/style.css`) %> <%- `</style>` %> </head><body class="bg-black w-[800px] text-white"> <%- include(`./match_1/main.ejs`, { match, partyColor, facetColor, kc, dc, laneSVG }) %> </body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Match</title> <%- "<style>" %> <%- include("../common/styles/normalize.min.css") %> <%- include("./match_2/original.css") %> <%- include("./match_2+/extra.css") %>
|
|
1
|
+
<!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Match</title> <%- "<style>" %> <%- include("../common/styles/normalize.min.css") %> <%- include("./match_2/original.css") %> <%- include("./match_2+/extra.css") %> <%- "</style>" %> </head><body><section id="regular"><%- include('./match_2/original') %></section><section id="extra"> <% if (data.parsedDateTime && data.radiantNetworthLeads && data.radiantExperienceLeads) { %> <%- include('./match_2+/charts') %> <div class="container"> <%- include('./match_2+/map') %> <%- include('./match_2+/lane_outcome') %> </div> <% } else { %> <div class="tip"><%= $t("dota2tracker.template.empty_extra_info") %></div> <% } %> </section></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Match</title> <%- "<style>" %> <%- include("../common/styles/normalize.min.css") %> <%- include("./match_2/original.css") %>
|
|
1
|
+
<!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Match</title> <%- "<style>" %> <%- include("../common/styles/normalize.min.css") %> <%- include("./match_2/original.css") %> <%- "</style>" %> </head><body> <%- include('./match_2/original') %> </body></html>
|
|
@@ -75,4 +75,4 @@
|
|
|
75
75
|
const impAvg = posMatches.length > 0 ? Math.round(posMatches.reduce((acc, m) => acc + m.players.find(ip => ip.steamAccount.id == p.steamAccount.id).imp, 0) / posMatches.length) : "-";
|
|
76
76
|
p.positionPerformance.push({ pos: i + 1, icon: posIcons[i], matchCount: posMatches.length, winCount: wins, imp: impAvg });
|
|
77
77
|
}
|
|
78
|
-
%> <% const posScale = getScale(p.positionPerformance.filter(pos => pos.matchCount > 1), true); %> <!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Player</title> <%- `<style>` %> <%- include("../common/styles/normalize.min.css") %> <%- include(`./player_1/base.css`) %>
|
|
78
|
+
%> <% const posScale = getScale(p.positionPerformance.filter(pos => pos.matchCount > 1), true); %> <!DOCTYPE html><html lang="<%= languageTag %>"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Player</title> <%- `<style>` %> <%- include("../common/styles/normalize.min.css") %> <%- include(`./player_1/base.css`) %> <%- `</style>` %> </head><body><div class="wrapper"><div class="player"><div class="avatar"><img src="<%= p.steamAccount?.avatar %>" alt=""/></div><div class="info"><p class="name"> <%= p.steamAccount.name %> <% if (p.guildMember) { %> <span class="guild <%= getGuildClass(p.guildMember.guild.currentPercentile) %>"><%= p.guildMember.guild.tag %></span> <% } %> <% if (p.genHero) { %> <span class="hero_name"><%= p.genHero.name %></span> <% } %> </p><p class="matches"> <%= $t("dota2tracker.template.match_count_") %><%= p.matchCount %> (<span class="win"><%= p.winCount %></span>/<span class="lose"><%= p.matchCount - p.winCount %></span>) <%= $t("dota2tracker.template.winrate_") %> <span <%- `style="color:${getWinRateColor(p.winCount / p.matchCount)};"` %>><%= ((p.winCount / p.matchCount) * 100).toFixed(2) %>%</span></p><p class="matches<%= isAnon ? " blur" : "" %>"><span><%= $t("dota2tracker.template.last25matches_") %> <span class="win"><%= nearWin %></span>/<span class="lose"><%= nearCount - nearWin %></span></span> <span><%= $t("dota2tracker.template.winrate_") %> <span <%- `style="color:${getWinRateColor(nearWin / nearCount)};"` %>><%= ((nearWin / nearCount) * 100).toFixed(2) %>%</span> </span> <span><%= $t("dota2tracker.template.imp_") %><%= isAnon ? "?" : ((p.performance?.imp > 0 ? "+" : "") + p.performance?.imp) %></span></p><p class="matches<%= isAnon ? " blur" : "" %>"><span><%= $t("dota2tracker.template.lane") %> <span class="victory"><%= outcomes.victory + outcomes.stomp %>(<span class="stomp"><%= outcomes.stomp %></span>)</span>-<span class="tie"><%= outcomes.tie %></span>-<span class="fail"><%= outcomes.fail + outcomes.stomped %>(<span class="stomped"><%= outcomes.stomped %></span>)</span> </span> <% const laneTotal = outcomes.victory + outcomes.stomp + outcomes.tie + outcomes.fail + outcomes.stomped; %> <% const laneScore = (outcomes.victory + outcomes.stomp + outcomes.tie / 2) / laneTotal; %> <span><%= $t("dota2tracker.template.lane_advantage_rate_") %> <span <%- `style="color:${getWinRateColor(laneScore)};"` %>><%= isAnon ? "?" : (laneScore * 100).toFixed(2) %>%</span></span></p></div><div class="rank<%= p.isEstimatedRank ? " estimated" : "" %>"><img class="medal" src="<%= getImageUrl('medal_' + (p.rank.inTop100 ?? p.rank.medal)) %>" alt=""/> <img class="star" src="<%= getImageUrl('star_' + p.rank.star) %>" alt=""/><p><%= p.steamAccount.seasonLeaderboardRank ?? "" %></p></div></div><div class="hero_winrate"><div class="heroes"><p class="tip row total"><%= p.genHero ? $t("dota2tracker.template.all_matches_") : $t("dota2tracker.template.top10_") %></p><span class="tip"><%= $t("dota2tracker.template.hero") %></span><span class="tip" style="margin:0 4px"><%= $t("dota2tracker.template.match_count") %></span><span class="tip" style="margin:0 4px"><%= $t("dota2tracker.template.winrate") %></span><span class="tip" style="margin:0 4px"><%= $t("dota2tracker.template.imp") %></span><span class="tip win_count" style="justify-self:end;margin-right:2px"><%= $t("dota2tracker.template.win_count") %></span><span class="tip lose_count" style="justify-self:start;margin-left:2px"><%= $t("dota2tracker.template.lose_count") %></span> <% heroList.forEach(hero => { %> <span><img alt="" src="<%= getImageUrl(hero.hero.shortName, ImageType.HeroIcons) %>"/></span><span class="count"><%= hero.matchCount %></span><span class="win_rate"><%= ((hero.winCount / hero.matchCount) * 100).toFixed(0) %>%</span> <span class="imp"><%= (hero.imp > 0 ? "+" : "") + hero.imp %></span><span class="win" <%- `style="${hero.winCount == 0 ? "visibility:hidden;" : ""}width: ${hero.winCount * heroScale}px"` %>><%= hero.winCount %></span><span class="lose" <%- `style="${hero.matchCount - hero.winCount == 0 ? "visibility:hidden;" : ""}width: ${(hero.matchCount - hero.winCount) * heroScale}px"` %>><%= hero.matchCount - hero.winCount %></span> <% }); %> <p class="tip row near"><%= $t("dota2tracker.template.recently_positions") %></p><span class="tip"><%= $t("dota2tracker.template.position") %></span><span class="tip" style="margin:0 4px"><%= $t("dota2tracker.template.match_count") %></span><span class="tip" style="margin:0 4px"><%= $t("dota2tracker.template.winrate") %></span><span class="tip" style="margin:0 4px"><%= $t("dota2tracker.template.imp") %></span><span class="tip win_count" style="justify-self:end;margin-right:2px"><%= $t("dota2tracker.template.win_count") %></span><span class="tip lose_count" style="justify-self:start;margin-left:2px"><%= $t("dota2tracker.template.lose_count") %></span> <% p.positionPerformance.forEach(pos => { %> <span><img src="<%= getImageUrl(pos.icon, ImageType.IconsFacets) %>"></span><span class="count"><%= pos.matchCount %></span><span class="win_rate"><%= pos.matchCount > 0 ? ((pos.winCount / pos.matchCount) * 100).toFixed(0) : "-" %>%</span> <span class="imp"><%= (pos.imp > 0 ? "+" : "") + pos.imp %></span><span class="win" <%- `style="${pos.winCount == 0 ? "visibility:hidden;" : ""}width: ${pos.winCount * posScale}px"` %>><%= pos.winCount %></span><span class="lose" <%- `style="${pos.matchCount - pos.winCount == 0 ? "visibility:hidden;" : ""}width: ${(pos.matchCount - pos.winCount) * posScale}px"` %>><%= pos.matchCount - pos.winCount %></span> <% }); %> </div> <% if (isAnon) { %> <%- include("player_1/private", {$t, player: p}) %> <% } %> </div> <% if (Math.abs(p.streak) > 1 && !isAnon) { %> <div class="streak" <%- `style="box-shadow:none;color:${getWinRateColor((p.streak + 10) / 20)};"` %>> <%= Math.abs(p.streak) + (p.streak > 0 ? $t("dota2tracker.template.winning_streak") : $t("dota2tracker.template.losing_streak")) %> </div> <% } %> <div><table class="matches"><colgroup><col style="width:auto"/><col style="width:auto"/><col style="width:40px"/><col style="width:auto"/><col style="width:40px"/><col style="width:auto"/><col style="width:auto"/><col style="width:auto"/><col style="width:40px"/></colgroup><thead><tr><th><%= $t("dota2tracker.template.id") %></th><th><%= $t("dota2tracker.template.mode") %></th><th><%= $t("dota2tracker.template.hero") %></th><th><%= $t("dota2tracker.template.kda_kc") %></th><th><%= $t("dota2tracker.template.lane") %></th><th><%= $t("dota2tracker.template.time") %></th><th><%= $t("dota2tracker.template.duration") %></th><th><%= $t("dota2tracker.template.imp") %></th><th><%= $t("dota2tracker.template.rank") %></th></tr></thead><tbody> <% matchesData.forEach(m => { %> <tr class="match <%= m.didWin ? "win" : "lose" %>"><td><%- m.parsedDateTime ? m.id : `<p>${m.id}</p><p>${$t("dota2tracker.template.un_parsed")}</p>` %></td><td><p><%= $t("dota2tracker.template.lobby_types." + m.lobbyType) || m.lobbyType %></p><p><%= $t("dota2tracker.template.game_modes." + m.gameMode) || m.gameMode %></p></td><td><img alt="" src="<%= getImageUrl(m.inner.hero.shortName, ImageType.HeroIcons) %>"/></td><td style="line-height:20px"><p><%= m.kda %> (<%= (m.parsedDateTime ? "" : "≈") + m.kp %>%)</p><p><%= m.inner.kills %>/<%= m.inner.deaths %>/<%= m.inner.assists %></p></td><td><div class="player_lane <%= m.laneRes %>"><%- getImageUrl("lane_" + m.laneRes, undefined, ImageFormat.svg) %></div></td><td style="line-height:20px"><%= m.timeStr %></td><td><%= m.durationTime %></td><td><%= m.inner.imp != null ? ((m.inner.imp >= 0 ? "+" : "") + m.inner.imp) : "?" %></td><td><img class="medal" src="<%= getImageUrl("medal_" + m.rank?.toString().split("")[0]) %>" style="width:100%"/></td></tr> <% }); %> </tbody></table> <% if (isAnon) { %> <%- include("player_1/private", {$t, player: p}) %> <% } %> </div><div class="plus"> <% p.dotaPlus.forEach(hero => { %> <div class="hero"><img src="<%= getImageUrl(hero.shortName, ImageType.Heroes) %>" alt=""/><div class="level"><img src="<%= getImageUrl("hero_badge_" + Math.ceil((hero.level + 1) / 6)) %>" alt=""/><span><%= hero.level %></span></div><span><%= ((hero.winCount / hero.matchCount) * 100).toFixed(2) %>%</span> <span><%= hero.matchCount %></span></div> <% }); %> <% if (isAnon) { %> <%- include("player_1/private", {$t, player: p}) %> <% } %> </div></div></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<% const { name, avatar, isRising, prevRank, currRank, date } = data; %> <% const kind = isRising ? "xi" : "bei"; %> <% const avatarHtml = `<img src="${avatar}" />`; %> <% const prevHtml = `<span class="rank prev">${$t("dota2tracker.template.ranks." + prevRank.medal)}${prevRank.leader ?? prevRank.star}</span>`; %> <% const currHtml = `<span class="rank curr">${$t("dota2tracker.template.ranks." + currRank.medal)}${currRank.leader ?? currRank.star}</span>`; %> <% const msgKey = isRising ? "rank_fun_up_message" : "rank_fun_down_message"; %> <% const rawMsg = $t("dota2tracker.template." + msgKey, { name: name }); %> <% const finalMessage = rawMsg.replace('AVATAR_PLACEHOLDER', avatarHtml).replace('PREV_PLACEHOLDER', prevHtml).replace('CURR_PLACEHOLDER', currHtml); %> <!DOCTYPE html><html><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Rank Change</title> <%- `<style>` %> * { margin: 0; padding: 0; } html { width: 1024px; height: 768px; } body { background: no-repeat center center / cover; } .wrapper { padding: 80px; padding-top: 180px; } .wrapper > p { font-size: 32px; line-height: 48px; height: 48px; text-align: center; } body.xi p.bei, body.bei p.xi { display: none; } .wrapper > p > span { margin: 0 10px; } .wrapper > p > span.prev { color: gray; } .wrapper > p > span.curr { font-weight: bold; color: red; } .wrapper > p > img { width: 48px; height: 48px; vertical-align: middle; line-height: 48px; } .ranks { margin-top: 40px; display: flex; width: 100%; height: 256px; justify-content: space-evenly; } div.rank { position: relative; width: 256px; height: 256px; } div.rank > img { position: absolute; } div.rank.prev { filter: grayscale(1); } div.rank.curr { transform: scale(1.25); } div.rank p { font-size: 36px; bottom: 20px; width: 100%; text-align: center; color: #fff; position: absolute; }
|
|
1
|
+
<% const { name, avatar, isRising, prevRank, currRank, date } = data; %> <% const kind = isRising ? "xi" : "bei"; %> <% const avatarHtml = `<img src="${avatar}" />`; %> <% const prevHtml = `<span class="rank prev">${$t("dota2tracker.template.ranks." + prevRank.medal)}${prevRank.leader ?? prevRank.star}</span>`; %> <% const currHtml = `<span class="rank curr">${$t("dota2tracker.template.ranks." + currRank.medal)}${currRank.leader ?? currRank.star}</span>`; %> <% const msgKey = isRising ? "rank_fun_up_message" : "rank_fun_down_message"; %> <% const rawMsg = $t("dota2tracker.template." + msgKey, { name: name }); %> <% const finalMessage = rawMsg.replace('AVATAR_PLACEHOLDER', avatarHtml).replace('PREV_PLACEHOLDER', prevHtml).replace('CURR_PLACEHOLDER', currHtml); %> <!DOCTYPE html><html><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Rank Change</title> <%- `<style>` %> * { margin: 0; padding: 0; } html { width: 1024px; height: 768px; } body { background: no-repeat center center / cover; } .wrapper { padding: 80px; padding-top: 180px; } .wrapper > p { font-size: 32px; line-height: 48px; height: 48px; text-align: center; } body.xi p.bei, body.bei p.xi { display: none; } .wrapper > p > span { margin: 0 10px; } .wrapper > p > span.prev { color: gray; } .wrapper > p > span.curr { font-weight: bold; color: red; } .wrapper > p > img { width: 48px; height: 48px; vertical-align: middle; line-height: 48px; } .ranks { margin-top: 40px; display: flex; width: 100%; height: 256px; justify-content: space-evenly; } div.rank { position: relative; width: 256px; height: 256px; } div.rank > img { position: absolute; } div.rank.prev { filter: grayscale(1); } div.rank.curr { transform: scale(1.25); } div.rank p { font-size: 36px; bottom: 20px; width: 100%; text-align: center; color: #fff; position: absolute; } <%- `</style>` %> </head><body class="<%= kind %>" <%- `style="background-image: url(${getImageUrl(kind, undefined, "jpg")})"` %>><div class="wrapper"><p class="<%= kind %>"> <%- finalMessage %> </p><p></p><div class="ranks"><div class="rank prev"><img src="<%- getImageUrl('medal_' + (prevRank.inTop100 ?? prevRank.medal)) %>" alt=""/> <img src="<%- getImageUrl('star_' + prevRank.star) %>" alt=""/><p><%= prevRank.leader ?? "" %></p></div><div class="rank curr"><img src="<%- getImageUrl('medal_' + (currRank.inTop100 ?? currRank.medal)) %>" alt=""/> <img src="<%- getImageUrl('star_' + currRank.star) %>" alt=""/><p><%= currRank.leader ?? "" %></p></div></div><p style="text-align:right;margin-top:40px">—— <%= date %></p></div></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties;@layer theme,base,components,utilities;@layer theme{:root,:host{--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif: "Cinzel", serif;--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-orange-500: oklch(70.5% .213 47.604);--color-slate-300: oklch(86.9% .022 252.894);--color-slate-400: oklch(70.4% .04 256.788);--color-slate-500: oklch(55.4% .046 257.417);--color-slate-600: oklch(44.6% .043 257.281);--color-slate-700: oklch(37.2% .044 257.287);--color-slate-800: oklch(27.9% .041 260.031);--color-black: #000;--color-white: #fff;--spacing: .25rem;--container-md: 28rem;--text-xs: .75rem;--text-xs--line-height: calc(1 / .75);--text-sm: .875rem;--text-sm--line-height: calc(1.25 / .875);--text-base: 1rem;--text-base--line-height: 1.5 ;--text-lg: 1.125rem;--text-lg--line-height: calc(1.75 / 1.125);--text-xl: 1.25rem;--text-xl--line-height: calc(1.75 / 1.25);--text-2xl: 1.5rem;--text-2xl--line-height: calc(2 / 1.5);--text-3xl: 1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl: 2.25rem;--text-4xl--line-height: calc(2.5 / 2.25);--text-6xl: 3.75rem;--text-6xl--line-height: 1;--font-weight-medium: 500;--font-weight-bold: 700;--font-weight-black: 900;--tracking-tight: -.025em;--tracking-wider: .05em;--tracking-widest: .1em;--leading-tight: 1.25;--radius-lg: .5rem;--radius-xl: .75rem;--drop-shadow-md: 0 3px 3px rgb(0 0 0 / .12);--blur-sm: 8px;--default-transition-duration: .15s;--default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);--default-font-family: var(--font-sans);--default-mono-font-family: var(--font-mono);--color-primary: #137fec;--color-background-dark: #101922;--color-dota-red: #ff3c3c;--color-dota-gold: #e8bc56;--color-dota-green: #0bda5b;--color-card-dark: #16202c;--font-display: "Inter", sans-serif}}@layer base{*,:after,:before,::backdrop,::file-selector-button{box-sizing:border-box;margin:0;padding:0;border:0 solid}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings, normal);font-variation-settings:var(--default-font-variation-settings, normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings, normal);font-variation-settings:var(--default-mono-font-variation-settings, normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea,::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;border-radius:0;background-color:transparent;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px){::placeholder{color:currentcolor;@supports (color: color-mix(in lab,red,red)){color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]),::file-selector-button{appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.bottom-0{bottom:calc(var(--spacing) * 0)}.z-10{z-index:10}.col-span-1{grid-column:span 1 / span 1}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-span-4{grid-column:span 4 / span 4}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-auto{margin-top:auto}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-\[27px\]{height:27px}.h-full{height:100%}.min-h-\[22px\]{min-height:22px}.min-h-\[280px\]{min-height:280px}.min-h-screen{min-height:100vh}.w-1{width:calc(var(--spacing) * 1)}.w-6{width:calc(var(--spacing) * 6)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-\[48px\]{width:48px}.w-full{width:100%}.max-w-\[900px\]{max-width:900px}.max-w-md{max-width:var(--container-md)}.min-w-\[1000px\]{min-width:1000px}.flex-1{flex:1}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:calc(infinity * 1px)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dota-gold{border-color:var(--color-dota-gold)}.border-dota-red{border-color:var(--color-dota-red)}.border-slate-600{border-color:var(--color-slate-600)}.border-slate-700{border-color:var(--color-slate-700)}.border-white\/5{border-color:color-mix(in srgb,#fff 5%,transparent);@supports (color: color-mix(in lab,red,red)){border-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.border-white\/10{border-color:color-mix(in srgb,#fff 10%,transparent);@supports (color: color-mix(in lab,red,red)){border-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-\[\#0d141c\]{background-color:#0d141c}.bg-\[\#16202c\]{background-color:#16202c}.bg-black\/20{background-color:color-mix(in srgb,#000 20%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-black) 20%,transparent)}}.bg-black\/40{background-color:color-mix(in srgb,#000 40%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}.bg-card-dark{background-color:var(--color-card-dark)}.bg-dota-gold{background-color:var(--color-dota-gold)}.bg-dota-gold\/50{background-color:color-mix(in srgb,#e8bc56 50%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-dota-gold) 50%,transparent)}}.bg-dota-green\/50{background-color:color-mix(in srgb,#0bda5b 50%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-dota-green) 50%,transparent)}}.bg-dota-red{background-color:var(--color-dota-red)}.bg-dota-red\/50{background-color:color-mix(in srgb,#ff3c3c 50%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-dota-red) 50%,transparent)}}.bg-orange-500{background-color:var(--color-orange-500)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-gradient-to-t{--tw-gradient-position: to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-card-dark{--tw-gradient-from: var(--color-card-dark);--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-card-dark\/80{--tw-gradient-via: color-mix(in srgb, #16202c 80%, transparent);@supports (color: color-mix(in lab,red,red)){--tw-gradient-via: color-mix(in oklab, var(--color-card-dark) 80%, transparent)}--tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-via-stops)}.to-transparent{--tw-gradient-to: transparent;--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-cover{background-size:cover}.bg-center{background-position:center}.fill-current{fill:currentcolor}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-0\.5{padding-bottom:calc(var(--spacing) * .5)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-display{font-family:var(--font-display)}.font-mono{font-family:var(--font-mono)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading, var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading, var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading, var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading, var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading, var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading, var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading, var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading, var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.leading-none{--tw-leading: 1;line-height:1}.leading-tight{--tw-leading: var(--leading-tight);line-height:var(--leading-tight)}.font-black{--tw-font-weight: var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight: var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight: var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\[0\.2em\]{--tw-tracking: .2em;letter-spacing:.2em}.tracking-tight{--tw-tracking: var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking: var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking: var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-black{color:var(--color-black)}.text-dota-gold{color:var(--color-dota-gold)}.text-dota-green{color:var(--color-dota-green)}.text-dota-red{color:var(--color-dota-red)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-60{opacity:60%}.shadow-\[0_0_30px_rgba\(232\,188\,86\,0\.15\)\]{--tw-shadow: 0 0 30px var(--tw-shadow-color, rgba(232,188,86,.15));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_30px_rgba\(255\,60\,60\,0\.15\)\]{--tw-shadow: 0 0 30px var(--tw-shadow-color, rgba(255,60,60,.15));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-dota-gold\/20{--tw-shadow-color: color-mix(in srgb, #e8bc56 20%, transparent);@supports (color: color-mix(in lab,red,red)){--tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-dota-gold) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-dota-red\/20{--tw-shadow-color: color-mix(in srgb, #ff3c3c 20%, transparent);@supports (color: color-mix(in lab,red,red)){--tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-dota-red) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.drop-shadow-\[0_1px_2px_rgba\(0\,0\,0\,0\.8\)\]{--tw-drop-shadow-size: drop-shadow(0 1px 2px var(--tw-drop-shadow-color, rgba(0,0,0,.8)));--tw-drop-shadow: var(--tw-drop-shadow-size);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-\[0_2px_10px_rgba\(0\,0\,0\,0\.5\)\]{--tw-drop-shadow-size: drop-shadow(0 2px 10px var(--tw-drop-shadow-color, rgba(0,0,0,.5)));--tw-drop-shadow: var(--tw-drop-shadow-size);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-md{--tw-drop-shadow-size: drop-shadow(0 3px 3px var(--tw-drop-shadow-color, rgb(0 0 0 / .12)));--tw-drop-shadow: drop-shadow(var(--drop-shadow-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-sm{--tw-backdrop-blur: blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function));transition-duration:var(--tw-duration, var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function));transition-duration:var(--tw-duration, var(--default-transition-duration))}.duration-700{--tw-duration: .7s;transition-duration:.7s}.group-hover\:scale-105{&:is(:where(.group):hover *){@media (hover: hover){--tw-scale-x: 105%;--tw-scale-y: 105%;--tw-scale-z: 105%;scale:var(--tw-scale-x) var(--tw-scale-y)}}}.hover\:bg-white\/\[0\.02\]{&:hover{@media (hover: hover){background-color:color-mix(in srgb,#fff 2%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-white) 2%,transparent)}}}}.sm\:px-6{@media (width >= 40rem){padding-inline:calc(var(--spacing) * 6)}}.md\:grid{@media (width >= 48rem){display:grid}}.md\:grid-cols-4{@media (width >= 48rem){grid-template-columns:repeat(4,minmax(0,1fr))}}.md\:grid-cols-12{@media (width >= 48rem){grid-template-columns:repeat(12,minmax(0,1fr))}}.md\:flex-row{@media (width >= 48rem){flex-direction:row}}.md\:text-6xl{@media (width >= 48rem){font-size:var(--text-6xl);line-height:var(--tw-leading, var(--text-6xl--line-height))}}}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{background:var(--color-background-dark)}::-webkit-scrollbar-thumb{background:#233648;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--color-primary)}@property --tw-border-style{syntax: "*"; inherits: false; initial-value: solid;}@property --tw-gradient-position{syntax: "*"; inherits: false;}@property --tw-gradient-from{syntax: "<color>"; inherits: false; initial-value: #0000;}@property --tw-gradient-via{syntax: "<color>"; inherits: false; initial-value: #0000;}@property --tw-gradient-to{syntax: "<color>"; inherits: false; initial-value: #0000;}@property --tw-gradient-stops{syntax: "*"; inherits: false;}@property --tw-gradient-via-stops{syntax: "*"; inherits: false;}@property --tw-gradient-from-position{syntax: "<length-percentage>"; inherits: false; initial-value: 0%;}@property --tw-gradient-via-position{syntax: "<length-percentage>"; inherits: false; initial-value: 50%;}@property --tw-gradient-to-position{syntax: "<length-percentage>"; inherits: false; initial-value: 100%;}@property --tw-leading{syntax: "*"; inherits: false;}@property --tw-font-weight{syntax: "*"; inherits: false;}@property --tw-tracking{syntax: "*"; inherits: false;}@property --tw-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: "*"; inherits: false;}@property --tw-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: "*"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: "*"; inherits: false;}@property --tw-ring-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: "*"; inherits: false;}@property --tw-inset-ring-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: "*"; inherits: false;}@property --tw-ring-offset-width{syntax: "<length>"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: "*"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-blur{syntax: "*"; inherits: false;}@property --tw-brightness{syntax: "*"; inherits: false;}@property --tw-contrast{syntax: "*"; inherits: false;}@property --tw-grayscale{syntax: "*"; inherits: false;}@property --tw-hue-rotate{syntax: "*"; inherits: false;}@property --tw-invert{syntax: "*"; inherits: false;}@property --tw-opacity{syntax: "*"; inherits: false;}@property --tw-saturate{syntax: "*"; inherits: false;}@property --tw-sepia{syntax: "*"; inherits: false;}@property --tw-drop-shadow{syntax: "*"; inherits: false;}@property --tw-drop-shadow-color{syntax: "*"; inherits: false;}@property --tw-drop-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-drop-shadow-size{syntax: "*"; inherits: false;}@property --tw-backdrop-blur{syntax: "*"; inherits: false;}@property --tw-backdrop-brightness{syntax: "*"; inherits: false;}@property --tw-backdrop-contrast{syntax: "*"; inherits: false;}@property --tw-backdrop-grayscale{syntax: "*"; inherits: false;}@property --tw-backdrop-hue-rotate{syntax: "*"; inherits: false;}@property --tw-backdrop-invert{syntax: "*"; inherits: false;}@property --tw-backdrop-opacity{syntax: "*"; inherits: false;}@property --tw-backdrop-saturate{syntax: "*"; inherits: false;}@property --tw-backdrop-sepia{syntax: "*"; inherits: false;}@property --tw-duration{syntax: "*"; inherits: false;}@property --tw-scale-x{syntax: "*"; inherits: false; initial-value: 1;}@property --tw-scale-y{syntax: "*"; inherits: false; initial-value: 1;}@property --tw-scale-z{syntax: "*"; inherits: false; initial-value: 1;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-gradient-position: initial;--tw-gradient-from: #0000;--tw-gradient-via: #0000;--tw-gradient-to: #0000;--tw-gradient-stops: initial;--tw-gradient-via-stops: initial;--tw-gradient-from-position: 0%;--tw-gradient-via-position: 50%;--tw-gradient-to-position: 100%;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-blur: initial;--tw-brightness: initial;--tw-contrast: initial;--tw-grayscale: initial;--tw-hue-rotate: initial;--tw-invert: initial;--tw-opacity: initial;--tw-saturate: initial;--tw-sepia: initial;--tw-drop-shadow: initial;--tw-drop-shadow-color: initial;--tw-drop-shadow-alpha: 100%;--tw-drop-shadow-size: initial;--tw-backdrop-blur: initial;--tw-backdrop-brightness: initial;--tw-backdrop-contrast: initial;--tw-backdrop-grayscale: initial;--tw-backdrop-hue-rotate: initial;--tw-backdrop-invert: initial;--tw-backdrop-opacity: initial;--tw-backdrop-saturate: initial;--tw-backdrop-sepia: initial;--tw-duration: initial;--tw-scale-x: 1;--tw-scale-y: 1;--tw-scale-z: 1}}}
|
|
1
|
+
/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties;@layer theme,base,components,utilities;@layer theme{:root,:host{--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif: "Cinzel", serif;--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-orange-500: oklch(70.5% .213 47.604);--color-slate-300: oklch(86.9% .022 252.894);--color-slate-400: oklch(70.4% .04 256.788);--color-slate-500: oklch(55.4% .046 257.417);--color-slate-600: oklch(44.6% .043 257.281);--color-slate-700: oklch(37.2% .044 257.287);--color-slate-800: oklch(27.9% .041 260.031);--color-black: #000;--color-white: #fff;--spacing: .25rem;--container-md: 28rem;--text-xs: .75rem;--text-xs--line-height: calc(1 / .75);--text-sm: .875rem;--text-sm--line-height: calc(1.25 / .875);--text-base: 1rem;--text-base--line-height: 1.5 ;--text-lg: 1.125rem;--text-lg--line-height: calc(1.75 / 1.125);--text-xl: 1.25rem;--text-xl--line-height: calc(1.75 / 1.25);--text-2xl: 1.5rem;--text-2xl--line-height: calc(2 / 1.5);--text-3xl: 1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl: 2.25rem;--text-4xl--line-height: calc(2.5 / 2.25);--text-6xl: 3.75rem;--text-6xl--line-height: 1;--font-weight-medium: 500;--font-weight-bold: 700;--font-weight-black: 900;--tracking-tight: -.025em;--tracking-wider: .05em;--tracking-widest: .1em;--leading-tight: 1.25;--radius-lg: .5rem;--radius-xl: .75rem;--drop-shadow-md: 0 3px 3px rgb(0 0 0 / .12);--blur-sm: 8px;--default-transition-duration: .15s;--default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);--default-font-family: var(--font-sans);--default-mono-font-family: var(--font-mono);--color-primary: #137fec;--color-background-dark: #101922;--color-dota-red: #ff3c3c;--color-dota-gold: #e8bc56;--color-dota-green: #0bda5b;--color-card-dark: #16202c;--font-display: "Inter", sans-serif}}@layer base{*,:after,:before,::backdrop,::file-selector-button{box-sizing:border-box;margin:0;padding:0;border:0 solid}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings, normal);font-variation-settings:var(--default-font-variation-settings, normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings, normal);font-variation-settings:var(--default-mono-font-variation-settings, normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea,::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;border-radius:0;background-color:transparent;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px){::placeholder{color:currentcolor;@supports (color: color-mix(in lab,red,red)){color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]),::file-selector-button{appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.bottom-0{bottom:calc(var(--spacing) * 0)}.z-10{z-index:10}.col-span-1{grid-column:span 1 / span 1}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-span-4{grid-column:span 4 / span 4}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-auto{margin-top:auto}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-\[27px\]{height:27px}.h-full{height:100%}.min-h-\[22px\]{min-height:22px}.min-h-\[280px\]{min-height:280px}.min-h-screen{min-height:100vh}.w-1{width:calc(var(--spacing) * 1)}.w-6{width:calc(var(--spacing) * 6)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-\[48px\]{width:48px}.w-\[1024px\]{width:1024px}.w-full{width:100%}.max-w-\[900px\]{max-width:900px}.max-w-md{max-width:var(--container-md)}.min-w-\[1000px\]{min-width:1000px}.flex-1{flex:1}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:calc(infinity * 1px)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dota-gold{border-color:var(--color-dota-gold)}.border-dota-red{border-color:var(--color-dota-red)}.border-slate-600{border-color:var(--color-slate-600)}.border-slate-700{border-color:var(--color-slate-700)}.border-white\/5{border-color:color-mix(in srgb,#fff 5%,transparent);@supports (color: color-mix(in lab,red,red)){border-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.border-white\/10{border-color:color-mix(in srgb,#fff 10%,transparent);@supports (color: color-mix(in lab,red,red)){border-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-\[\#0d141c\]{background-color:#0d141c}.bg-\[\#16202c\]{background-color:#16202c}.bg-black\/20{background-color:color-mix(in srgb,#000 20%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-black) 20%,transparent)}}.bg-black\/40{background-color:color-mix(in srgb,#000 40%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}.bg-card-dark{background-color:var(--color-card-dark)}.bg-dota-gold{background-color:var(--color-dota-gold)}.bg-dota-gold\/50{background-color:color-mix(in srgb,#e8bc56 50%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-dota-gold) 50%,transparent)}}.bg-dota-green\/50{background-color:color-mix(in srgb,#0bda5b 50%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-dota-green) 50%,transparent)}}.bg-dota-red{background-color:var(--color-dota-red)}.bg-dota-red\/50{background-color:color-mix(in srgb,#ff3c3c 50%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-dota-red) 50%,transparent)}}.bg-orange-500{background-color:var(--color-orange-500)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-gradient-to-t{--tw-gradient-position: to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-card-dark{--tw-gradient-from: var(--color-card-dark);--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-card-dark\/80{--tw-gradient-via: color-mix(in srgb, #16202c 80%, transparent);@supports (color: color-mix(in lab,red,red)){--tw-gradient-via: color-mix(in oklab, var(--color-card-dark) 80%, transparent)}--tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-via-stops)}.to-transparent{--tw-gradient-to: transparent;--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-cover{background-size:cover}.bg-center{background-position:center}.fill-current{fill:currentcolor}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-0\.5{padding-bottom:calc(var(--spacing) * .5)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-display{font-family:var(--font-display)}.font-mono{font-family:var(--font-mono)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading, var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading, var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading, var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading, var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading, var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading, var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading, var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading, var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.leading-none{--tw-leading: 1;line-height:1}.leading-tight{--tw-leading: var(--leading-tight);line-height:var(--leading-tight)}.font-black{--tw-font-weight: var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight: var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight: var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\[0\.2em\]{--tw-tracking: .2em;letter-spacing:.2em}.tracking-tight{--tw-tracking: var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking: var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking: var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-black{color:var(--color-black)}.text-dota-gold{color:var(--color-dota-gold)}.text-dota-green{color:var(--color-dota-green)}.text-dota-red{color:var(--color-dota-red)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-60{opacity:60%}.shadow-\[0_0_30px_rgba\(232\,188\,86\,0\.15\)\]{--tw-shadow: 0 0 30px var(--tw-shadow-color, rgba(232,188,86,.15));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_30px_rgba\(255\,60\,60\,0\.15\)\]{--tw-shadow: 0 0 30px var(--tw-shadow-color, rgba(255,60,60,.15));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-dota-gold\/20{--tw-shadow-color: color-mix(in srgb, #e8bc56 20%, transparent);@supports (color: color-mix(in lab,red,red)){--tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-dota-gold) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-dota-red\/20{--tw-shadow-color: color-mix(in srgb, #ff3c3c 20%, transparent);@supports (color: color-mix(in lab,red,red)){--tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-dota-red) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.drop-shadow-\[0_1px_2px_rgba\(0\,0\,0\,0\.8\)\]{--tw-drop-shadow-size: drop-shadow(0 1px 2px var(--tw-drop-shadow-color, rgba(0,0,0,.8)));--tw-drop-shadow: var(--tw-drop-shadow-size);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-\[0_2px_10px_rgba\(0\,0\,0\,0\.5\)\]{--tw-drop-shadow-size: drop-shadow(0 2px 10px var(--tw-drop-shadow-color, rgba(0,0,0,.5)));--tw-drop-shadow: var(--tw-drop-shadow-size);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-md{--tw-drop-shadow-size: drop-shadow(0 3px 3px var(--tw-drop-shadow-color, rgb(0 0 0 / .12)));--tw-drop-shadow: drop-shadow(var(--drop-shadow-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-sm{--tw-backdrop-blur: blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function));transition-duration:var(--tw-duration, var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function));transition-duration:var(--tw-duration, var(--default-transition-duration))}.duration-700{--tw-duration: .7s;transition-duration:.7s}.group-hover\:scale-105{&:is(:where(.group):hover *){@media (hover: hover){--tw-scale-x: 105%;--tw-scale-y: 105%;--tw-scale-z: 105%;scale:var(--tw-scale-x) var(--tw-scale-y)}}}.hover\:bg-white\/\[0\.02\]{&:hover{@media (hover: hover){background-color:color-mix(in srgb,#fff 2%,transparent);@supports (color: color-mix(in lab,red,red)){background-color:color-mix(in oklab,var(--color-white) 2%,transparent)}}}}.sm\:px-6{@media (width >= 40rem){padding-inline:calc(var(--spacing) * 6)}}.md\:grid{@media (width >= 48rem){display:grid}}.md\:grid-cols-4{@media (width >= 48rem){grid-template-columns:repeat(4,minmax(0,1fr))}}.md\:grid-cols-12{@media (width >= 48rem){grid-template-columns:repeat(12,minmax(0,1fr))}}.md\:flex-row{@media (width >= 48rem){flex-direction:row}}.md\:text-6xl{@media (width >= 48rem){font-size:var(--text-6xl);line-height:var(--tw-leading, var(--text-6xl--line-height))}}}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{background:var(--color-background-dark)}::-webkit-scrollbar-thumb{background:#233648;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--color-primary)}@property --tw-border-style{syntax: "*"; inherits: false; initial-value: solid;}@property --tw-gradient-position{syntax: "*"; inherits: false;}@property --tw-gradient-from{syntax: "<color>"; inherits: false; initial-value: #0000;}@property --tw-gradient-via{syntax: "<color>"; inherits: false; initial-value: #0000;}@property --tw-gradient-to{syntax: "<color>"; inherits: false; initial-value: #0000;}@property --tw-gradient-stops{syntax: "*"; inherits: false;}@property --tw-gradient-via-stops{syntax: "*"; inherits: false;}@property --tw-gradient-from-position{syntax: "<length-percentage>"; inherits: false; initial-value: 0%;}@property --tw-gradient-via-position{syntax: "<length-percentage>"; inherits: false; initial-value: 50%;}@property --tw-gradient-to-position{syntax: "<length-percentage>"; inherits: false; initial-value: 100%;}@property --tw-leading{syntax: "*"; inherits: false;}@property --tw-font-weight{syntax: "*"; inherits: false;}@property --tw-tracking{syntax: "*"; inherits: false;}@property --tw-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: "*"; inherits: false;}@property --tw-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: "*"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: "*"; inherits: false;}@property --tw-ring-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: "*"; inherits: false;}@property --tw-inset-ring-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: "*"; inherits: false;}@property --tw-ring-offset-width{syntax: "<length>"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: "*"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-blur{syntax: "*"; inherits: false;}@property --tw-brightness{syntax: "*"; inherits: false;}@property --tw-contrast{syntax: "*"; inherits: false;}@property --tw-grayscale{syntax: "*"; inherits: false;}@property --tw-hue-rotate{syntax: "*"; inherits: false;}@property --tw-invert{syntax: "*"; inherits: false;}@property --tw-opacity{syntax: "*"; inherits: false;}@property --tw-saturate{syntax: "*"; inherits: false;}@property --tw-sepia{syntax: "*"; inherits: false;}@property --tw-drop-shadow{syntax: "*"; inherits: false;}@property --tw-drop-shadow-color{syntax: "*"; inherits: false;}@property --tw-drop-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-drop-shadow-size{syntax: "*"; inherits: false;}@property --tw-backdrop-blur{syntax: "*"; inherits: false;}@property --tw-backdrop-brightness{syntax: "*"; inherits: false;}@property --tw-backdrop-contrast{syntax: "*"; inherits: false;}@property --tw-backdrop-grayscale{syntax: "*"; inherits: false;}@property --tw-backdrop-hue-rotate{syntax: "*"; inherits: false;}@property --tw-backdrop-invert{syntax: "*"; inherits: false;}@property --tw-backdrop-opacity{syntax: "*"; inherits: false;}@property --tw-backdrop-saturate{syntax: "*"; inherits: false;}@property --tw-backdrop-sepia{syntax: "*"; inherits: false;}@property --tw-duration{syntax: "*"; inherits: false;}@property --tw-scale-x{syntax: "*"; inherits: false; initial-value: 1;}@property --tw-scale-y{syntax: "*"; inherits: false; initial-value: 1;}@property --tw-scale-z{syntax: "*"; inherits: false; initial-value: 1;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-gradient-position: initial;--tw-gradient-from: #0000;--tw-gradient-via: #0000;--tw-gradient-to: #0000;--tw-gradient-stops: initial;--tw-gradient-via-stops: initial;--tw-gradient-from-position: 0%;--tw-gradient-via-position: 50%;--tw-gradient-to-position: 100%;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-blur: initial;--tw-brightness: initial;--tw-contrast: initial;--tw-grayscale: initial;--tw-hue-rotate: initial;--tw-invert: initial;--tw-opacity: initial;--tw-saturate: initial;--tw-sepia: initial;--tw-drop-shadow: initial;--tw-drop-shadow-color: initial;--tw-drop-shadow-alpha: 100%;--tw-drop-shadow-size: initial;--tw-backdrop-blur: initial;--tw-backdrop-brightness: initial;--tw-backdrop-contrast: initial;--tw-backdrop-grayscale: initial;--tw-backdrop-hue-rotate: initial;--tw-backdrop-invert: initial;--tw-backdrop-opacity: initial;--tw-backdrop-saturate: initial;--tw-backdrop-sepia: initial;--tw-duration: initial;--tw-scale-x: 1;--tw-scale-y: 1;--tw-scale-z: 1}}}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="dark" lang="en"><head><meta charset="utf-8"/><meta content="width=device-width,initial-scale=1" name="viewport"/><title>Dota 2 Daily Recap</title> <%- `<style>` %> <%- include(`./daily/style.css`) %>
|
|
1
|
+
<!DOCTYPE html><html class="dark" lang="en"><head><meta charset="utf-8"/><meta content="width=device-width,initial-scale=1" name="viewport"/><title>Dota 2 Daily Recap</title> <%- `<style>` %> <%- include(`./daily/style.css`) %> <%- `</style>` %> <style>::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{background:#101922}::-webkit-scrollbar-thumb{background:#233648;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#137fec}.bg-texture{background-color:#101922;background-image:radial-gradient(at 0 0,rgba(19,127,236,.08) 0,transparent 50%),radial-gradient(at 100% 0,rgba(255,60,60,.05) 0,transparent 50%),radial-gradient(at 100% 100%,rgba(232,188,86,.05) 0,transparent 50%)}</style></head><body class="bg-texture font-display text-white overflow-x-hidden antialiased min-h-screen w-[1024px] min-w-[1000px]"><div class="w-full flex justify-center py-8 px-4 sm:px-6"><div class="w-full max-w-[900px] flex flex-col gap-8"><div class="flex flex-col items-center justify-center pt-2 pb-4 text-center"><div class="mb-3 border-b-2 border-dota-red pb-1"><span class="text-xs font-bold tracking-[0.2em] uppercase text-dota-gold drop-shadow-md"> <%= $t("dota2tracker.template.report.daily.plugin_name") %> </span></div><h1 class="text-4xl md:text-6xl font-serif font-black tracking-tight text-white uppercase drop-shadow-[0_2px_10px_rgba(0,0,0,0.5)] mb-2"> <%= $t("dota2tracker.template.report.daily.title") %> </h1><div class="flex flex-col items-center gap-1 text-slate-400 font-medium"><p class="text-lg tracking-widest uppercase text-slate-300"><%= data.meta.date %></p><p class="text-xs opacity-60 max-w-md mx-auto"> <%= data.meta.summary %> </p></div></div><div class="grid grid-cols-2 md:grid-cols-4 gap-3"><div class="flex flex-col items-center justify-center p-4 rounded bg-card-dark border border-white/5 shadow-lg relative overflow-hidden group"><span class="text-slate-500 text-[10px] font-bold uppercase tracking-widest mb-1"> <%= $t("dota2tracker.template.report.daily.stats.matches") %> </span><span class="text-3xl font-black text-white"><%= data.headerStats.matches.value %></span><span class="text-xs text-slate-400 mt-1"><%= data.headerStats.matches.subtext %></span></div><div class="flex flex-col items-center justify-center p-4 rounded bg-card-dark border border-white/5 shadow-lg relative overflow-hidden group"><div class="absolute inset-x-0 bottom-0 h-1 <%= data.headerStats.winRate.isWinRateAbove50 ? 'bg-dota-green/50' : 'bg-dota-red/50' %>"></div><span class="text-slate-500 text-[10px] font-bold uppercase tracking-widest mb-1"> <%= $t("dota2tracker.template.report.daily.stats.win_rate") %> </span><span class="text-3xl font-black <%= data.headerStats.winRate.isWinRateAbove50 ? 'text-dota-green' : 'text-dota-red' %>"><%= data.headerStats.winRate.value %></span><span class="text-xs mt-1 <%= data.headerStats.winRate.isPositive ? 'text-dota-green' : 'text-dota-red' %>"><%= data.headerStats.winRate.subtext %></span></div><div class="flex flex-col items-center justify-center p-4 rounded bg-card-dark border border-white/5 shadow-lg relative overflow-hidden group"><div class="absolute inset-x-0 bottom-0 h-1 bg-dota-red/50"></div><span class="text-slate-500 text-[10px] font-bold uppercase tracking-widest mb-1"> <%= $t("dota2tracker.template.report.daily.stats.kills") %> </span><span class="text-3xl font-black text-dota-red"><%= data.headerStats.kills.value %></span><span class="text-xs text-slate-400 mt-1"><%= data.headerStats.kills.subtext %></span></div><div class="flex flex-col items-center justify-center p-4 rounded bg-card-dark border border-white/5 shadow-lg relative overflow-hidden group"><div class="absolute inset-x-0 bottom-0 h-1 bg-dota-gold/50"></div><span class="text-slate-500 text-[10px] font-bold uppercase tracking-widest mb-1"> <%= $t("dota2tracker.template.report.daily.stats.duration") %> </span><span class="text-3xl font-black text-dota-gold"><%= data.headerStats.duration.value %></span><span class="text-xs text-slate-400 mt-1"> <%= data.headerStats.duration.subtext %> </span></div></div><div class="flex flex-col md:flex-row gap-6 mt-2"> <% const lights = [data.spotlights.mvp, data.spotlights.lvp]; %> <% lights.forEach(function(light) { %> <div class="flex-1 relative rounded-lg border <%= light.type === 'MVP' ? 'border-dota-gold shadow-[0_0_30px_rgba(232,188,86,0.15)]' : 'border-dota-red shadow-[0_0_30px_rgba(255,60,60,0.15)]' %> bg-card-dark overflow-hidden group"><div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105" style="background-image:url('<%= light.player.heroBannerUrl %>');opacity:.4"></div><div class="absolute inset-0 bg-gradient-to-t from-card-dark via-card-dark/80 to-transparent"></div><div class="relative z-10 p-6 flex flex-col h-full min-h-[280px]"><div class="flex justify-between items-center"><div class="<%= light.type === 'MVP' ? 'bg-dota-gold text-black shadow-dota-gold/20' : 'bg-dota-red text-white shadow-dota-red/20' %> text-xs font-black uppercase px-3 py-1 rounded shadow-lg"> <%= light.type === 'MVP' ? $t("dota2tracker.template.report.daily.spotlight.mvp_title") : $t("dota2tracker.template.report.daily.spotlight.lvp_title") %> </div><svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10 fill-current" viewBox="0 0 24 24"> <% if (light.type === 'MVP') { %> <path class="text-dota-gold" d="M19 5h-2V3H7v2H5c-1.1 0-2 .9-2 2v1c0 2.55 1.92 4.63 4.39 4.94.63 1.5 1.98 2.63 3.61 2.96V19H7v2h10v-2h-4v-3.1c1.63-.33 2.98-1.46 3.61-2.96C19.08 12.63 21 10.55 21 8V7c0-1.1-.9-2-2-2zM5 8V7h2v3.82C5.84 10.4 5 9.3 5 8zm14 0c0 1.3-.84 2.4-2 2.82V7h2v1z"/> <% } else { %> <path class="text-dota-red" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/> <% } %> </svg></div><div class="mt-auto"><h3 class="text-3xl font-serif font-bold text-white leading-none mb-1 drop-shadow-md"><%= light.player.name %></h3><p class="text-slate-300 text-sm font-medium leading-none mb-1"><%= light.player.heroName %></p><p class="text-slate-400 text-sm font-mono mb-3"><%= light.player.kda %></p><div class="bg-black/40 backdrop-blur-sm rounded-lg p-3 border border-white/10"><div class="flex flex-col gap-2"><div class="flex justify-between items-center border-b border-white/10 pb-2"><span class="text-xs text-slate-400 uppercase tracking-widest font-bold"> <%= light.score.label %> </span><span class="font-mono text-2xl font-bold <%= light.type === 'MVP' ? 'text-dota-gold' : 'text-dota-red' %>"><%= light.score.value %></span></div><div class="flex flex-wrap gap-2 pt-1 min-h-[22px]"> <% if (light.badges && light.badges.length > 0) { %> <% light.badges.forEach(function(badge) { %> <%
|
|
2
2
|
// Convert HEX to RGB for background opacity
|
|
3
3
|
const r = parseInt(badge.hexColor.slice(1, 3), 16);
|
|
4
4
|
const g = parseInt(badge.hexColor.slice(3, 5), 16);
|
|
@@ -18,4 +18,4 @@
|
|
|
18
18
|
rightStyle: `width: ${right}px`
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
|
-
%> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Daily Report</title> <%- `<style>` %> <%- include("../common/styles/normalize.min.css") %> <%- include("./daily_legacy/base.css") %>
|
|
21
|
+
%> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Daily Report</title> <%- `<style>` %> <%- include("../common/styles/normalize.min.css") %> <%- include("./daily_legacy/base.css") %> <%- `</style>` %> </head><body><h3 class="title"><%= title %></h3><div class="players"> <% players.forEach(p => { %> <% const winRate = Math.round((p.winCount / p.matches.length) * 100); %> <% const imp = getImpInfo(p.avgImp); %> <div class="player"><img src="<%= p.steamAccount.avatar %>" class="avatar"/> <span class="name"><%= p.name %></span><span class="count"><span class="win"><%= $t("dota2tracker.template.report_won") %><%= p.winCount %></span><span class="lose"><%= $t("dota2tracker.template.report_lost") %><%= p.loseCount %></span><span><%= $t("dota2tracker.template.report_winrate") %> <%= winRate %>%</span></span><div class="performance"><div class="<%= imp.barClass %>"><div class="left" <%- `style="${imp.leftStyle}"` %>></div><div class="pipe"></div><div class="right" <%- `style="${imp.rightStyle}"` %>></div></div><span class="score_value"><%= imp.valStr %></span></div><span class="kda"><%= p.avgKills %>/<%= p.avgDeaths %>/<%= p.avgAssists %> (<%= p.avgKDA %>)</span></div> <% }); %> </div><div class="combinations" <%- !showCombi ? `style="display:none;"` : "" %>><span style="grid-column:1/-1"><%= $t("dota2tracker.template.combined_win_loss_summary") %></span> <% combinations.forEach(combi => { %> <% const combiRate = Math.round((combi.winCount / combi.matches.length) * 100); %> <div class="players"> <% combi.players.forEach(p => { %> <img src="<%= p.steamAccount.avatar %>" class="avatar"/> <% }); %> </div><span class="win"><%= $t("dota2tracker.template.report_won") %><%= combi.winCount %></span><span class="lose"><%= $t("dota2tracker.template.report_lost") %><%= combi.matches.length - combi.winCount %></span><span><%= $t("dota2tracker.template.report_winrate") %> <%= combiRate %>%</span> <% }); %> </div></body></html>
|
package/package.json
CHANGED