@sjtdev/koishi-plugin-dota2tracker 2.5.1 → 2.5.3

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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # 更新日志
2
2
 
3
+ ### [2.5.3](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.5.2...v2.5.3) (2026-02-23)
4
+
5
+ ### 🎨 样式
6
+
7
+ * **report/daily:** 缩窄整体宽度 ([ef756e0](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/ef756e0f418715a63b50586653221f92c25afd91))
8
+
9
+ ### 🐛 Bug 修复
10
+
11
+ * 尝试修复在**异常状态群组**中获取群友信息时失败导致流程阻塞的问题 ([f00841d](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/f00841dd82794afd69987926804147a4b49fbfee)), closes [#17](https://github.com/sjtdev/koishi-plugin-dota2tracker/issues/17)
12
+ * **database:** 修改`dt_match_extension`键类型定义排除某些可能的隐患 ([72c0bbe](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/72c0bbebc0faf540aea29c8e2e4ae8210ab13b3e))
13
+
14
+ ### [2.5.2](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.5.1...v2.5.2) (2026-02-20)
15
+
16
+ ### 🐛 Bug 修复
17
+
18
+ * **report/daily:** 修复如果已订阅的玩家中有不公开数据的玩家,获取日报数据失败的问题 ([e293fb6](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/e293fb62b4120d9db2709c8c073b45225d6e466d))
19
+
20
+ ### 📝 文档
21
+
22
+ * **image/daily:** 修正日报展示图 ([25ad31d](https://github.com/sjtdev/koishi-plugin-dota2tracker/commit/25ad31d193a41920aa940c4c4b188fdb627c1d95))
23
+
3
24
  ### [2.5.1](https://github.com/sjtdev/koishi-plugin-dota2tracker/compare/v2.5.0...v2.5.1) (2026-02-19)
4
25
 
5
26
  ### 🎨 样式
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.ctx.dota2tracker.report.recordMatchExtension(match);
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) {
@@ -2312,13 +2327,19 @@ var DatabaseService = class extends import_koishi7.Service {
2312
2327
  },
2313
2328
  { autoInc: true }
2314
2329
  );
2315
- ctx.model.extend("dt_match_extension", { matchId: "unsigned", startTime: "timestamp", data: "json" }, { autoInc: false, primary: ["matchId"] });
2330
+ ctx.model.extend("dt_match_extension", { matchId: "string", startTime: "timestamp", data: "json" }, { autoInc: false, primary: ["matchId"] });
2316
2331
  }
2317
2332
  async insertMatchExtension(matchId, startTime, data) {
2318
- return this.ctx.database.upsert("dt_match_extension", [{ matchId, startTime, data }]);
2333
+ return this.ctx.database.upsert("dt_match_extension", [{ matchId: String(matchId), startTime, data }]);
2319
2334
  }
2320
2335
  async getMatchExtension(matchIds) {
2321
- return this.ctx.database.get("dt_match_extension", { matchId: matchIds });
2336
+ const rows = await this.ctx.database.get("dt_match_extension", {
2337
+ matchId: matchIds.map((id) => String(id))
2338
+ });
2339
+ return rows.map((row) => ({
2340
+ ...row,
2341
+ matchId: Number(row.matchId)
2342
+ }));
2322
2343
  }
2323
2344
  async setPlayerRank(playerId, rank) {
2324
2345
  return this.ctx.database.set("dt_subscribed_players", playerId, { rank });
@@ -2752,7 +2773,6 @@ var ViewRenderer = class extends import_koishi10.Service {
2752
2773
  $t: /* @__PURE__ */ __name((key, params) => this.ctx.dota2tracker.i18n.$t(languageTag, key, params), "$t"),
2753
2774
  languageTag,
2754
2775
  Random: import_koishi10.Random,
2755
- fontFamily: this.config.templateFonts.map((f) => `${f}`).join(", "),
2756
2776
  getImageUrl: this.getImageUrl.bind(this)
2757
2777
  };
2758
2778
  try {
@@ -3359,7 +3379,12 @@ var MatchWatcherTask = class extends import_koishi13.Service {
3359
3379
  const prevRank = ranks["prevRank"];
3360
3380
  const currRank = ranks["currRank"];
3361
3381
  if (prevRank.medal !== currRank.medal || prevRank.star !== currRank.star && this.config.rankBroadStar || prevRank.leader !== currRank.leader && this.config.rankBroadLeader) {
3362
- const guildMember = await this.ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember?.(subPlayer.guildId, subPlayer.userId);
3382
+ let guildMember;
3383
+ try {
3384
+ guildMember = await this.ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember?.(subPlayer.guildId, subPlayer.userId);
3385
+ } catch (error) {
3386
+ this.logger.warn(this.ctx.dota2tracker.i18n.gt("dota2tracker.logger.fetch_guilds_failed") + error);
3387
+ }
3363
3388
  const name2 = subPlayer.nickName ?? guildMember?.nick ?? playersData.find((player) => player.steamAccount.id == subPlayer.steamId)?.steamAccount.name ?? String(subPlayer.steamId);
3364
3389
  const languageTag = await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId: subPlayer.guildId });
3365
3390
  if (this.config.rankBroadFun === true) {
@@ -3529,15 +3554,15 @@ var ParsePollingTask = class extends import_koishi14.Service {
3529
3554
  }
3530
3555
  };
3531
3556
 
3532
- // src/app/tasks/report.task.ts
3557
+ // src/app/tasks/daily-report.task.ts
3533
3558
  var import_koishi15 = require("koishi");
3534
3559
  var import_luxon9 = require("luxon");
3535
- var ReportTask = class extends import_koishi15.Service {
3560
+ var DailyReportTask = class extends import_koishi15.Service {
3536
3561
  static {
3537
- __name(this, "ReportTask");
3562
+ __name(this, "DailyReportTask");
3538
3563
  }
3539
3564
  constructor(ctx) {
3540
- super(ctx, "dota2tracker.report-task", true);
3565
+ super(ctx, "dota2tracker.daily-report-task", true);
3541
3566
  this.config = ctx.config;
3542
3567
  if (this.config.dailyReportSwitch) {
3543
3568
  ctx.cron(`0 ${this.config.dailyReportHours} * * *`, async () => {
@@ -3551,7 +3576,7 @@ var ReportTask = class extends import_koishi15.Service {
3551
3576
  }
3552
3577
  }
3553
3578
  async runDailyJob() {
3554
- const bundles = await this.ctx.dota2tracker.report.generateDailyReportBundles();
3579
+ const bundles = await this.ctx.dota2tracker.dailyReport.generateDailyReportBundles();
3555
3580
  for (const bundle of bundles) {
3556
3581
  const image = await this.ctx.dota2tracker.view.renderToImageByFile(bundle.report, "daily", "report" /* Report */, await this.ctx.dota2tracker.i18n.getLanguageTag({ channelId: bundle.channelId }));
3557
3582
  await this.ctx.broadcast([`${bundle.platform}:${bundle.channelId}`], image);
@@ -4551,32 +4576,17 @@ function convertBuildingEvents(objectives) {
4551
4576
  }
4552
4577
  __name(convertBuildingEvents, "convertBuildingEvents");
4553
4578
 
4554
- // src/app/core/report.service.ts
4579
+ // src/app/core/daily-report.service.ts
4555
4580
  var import_koishi18 = require("koishi");
4556
4581
  var import_luxon11 = require("luxon");
4557
- var ReportService = class _ReportService extends import_koishi18.Service {
4582
+ var DailyReportService = class _DailyReportService extends import_koishi18.Service {
4558
4583
  static {
4559
- __name(this, "ReportService");
4584
+ __name(this, "DailyReportService");
4560
4585
  }
4561
4586
  constructor(ctx) {
4562
- super(ctx, "dota2tracker.report", true);
4587
+ super(ctx, "dota2tracker.daily-report", true);
4563
4588
  this.config = ctx.config;
4564
4589
  }
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
4590
  /**
4581
4591
  * 入口函数,返回报告数据
4582
4592
  */
@@ -4587,10 +4597,10 @@ var ReportService = class _ReportService extends import_koishi18.Service {
4587
4597
  const users = await this.ctx.dota2tracker.database.getActiveSubscribedPlayers();
4588
4598
  const steamIds = [...new Set(users.map((user) => user.steamId))];
4589
4599
  const data = await this.ctx.dota2tracker.stratzAPI.queryPlayersMatchesForDaily(steamIds, Math.floor(dataStartDate.toSeconds()));
4590
- const allMatchIds = [...new Set(data.players.flatMap((p) => p.matches.map((m) => m.id)))].map((id) => Number(id));
4600
+ const allMatchIds = [...new Set(data.players.flatMap((p) => (p.matches || []).map((m) => m.id)))].map((id) => Number(id));
4591
4601
  const extensions = await this.ctx.dota2tracker.database.getMatchExtension(allMatchIds);
4592
4602
  const getImageUrl = this.ctx.dota2tracker.view.getImageUrl.bind(this.ctx.dota2tracker.view);
4593
- return await _ReportService.formatDailyReportBundles(
4603
+ return await _DailyReportService.formatDailyReportBundles(
4594
4604
  data,
4595
4605
  users,
4596
4606
  extensions,
@@ -4626,7 +4636,7 @@ var ReportService = class _ReportService extends import_koishi18.Service {
4626
4636
  const impactData = [];
4627
4637
  for (const user of squadUsers) {
4628
4638
  const playerData = squadPlayerData.find((p) => p.steamAccount.id === user.steamId);
4629
- if (!playerData || playerData.matches.length === 0) continue;
4639
+ if (!playerData || !playerData.matches || playerData.matches.length === 0) continue;
4630
4640
  const processed = this.processPlayer(user, playerData, dotaconstants, targetDate, extensions, getImageUrl);
4631
4641
  if (processed.impact.matchCount === 0) continue;
4632
4642
  playerRows.push(processed.row);
@@ -4684,7 +4694,7 @@ var ReportService = class _ReportService extends import_koishi18.Service {
4684
4694
  const currentMatches = /* @__PURE__ */ new Map();
4685
4695
  const previousMatches = /* @__PURE__ */ new Map();
4686
4696
  for (const player of squadPlayerData) {
4687
- for (const match of player.matches) {
4697
+ for (const match of player.matches || []) {
4688
4698
  if (match.startDateTime >= targetSeconds) {
4689
4699
  currentMatches.set(match.id, match);
4690
4700
  } else {
@@ -4732,7 +4742,7 @@ var ReportService = class _ReportService extends import_koishi18.Service {
4732
4742
  let bestMatchId = 0, worstMatchId = 0;
4733
4743
  const playedHeroes = /* @__PURE__ */ new Map();
4734
4744
  let processedMatchCount = 0;
4735
- for (const m of playerData.matches) {
4745
+ for (const m of playerData.matches || []) {
4736
4746
  if (m.startDateTime < targetSeconds) continue;
4737
4747
  processedMatchCount++;
4738
4748
  const self = m.players.find((p) => p.steamAccount?.id === user.steamId);
@@ -4831,7 +4841,7 @@ var ReportService = class _ReportService extends import_koishi18.Service {
4831
4841
  return `${mins}:${secs.toString().padStart(2, "0")}`;
4832
4842
  }
4833
4843
  static buildSpotlightCard(playerData, type, matchId, extensions, dotaconstants, t, getHeroName, getImageUrl) {
4834
- const match = playerData.matches.find((m) => m.id === matchId);
4844
+ const match = (playerData.matches || []).find((m) => m.id === matchId);
4835
4845
  const self = match.players.find((p) => p.steamAccount?.id === playerData.steamAccount.id);
4836
4846
  const extension = extensions.find((e) => Number(e.matchId) === Number(matchId));
4837
4847
  const playerExtension = extension?.data?.players?.find((p) => p.steamAccountId === playerData.steamAccount.id);
@@ -5001,7 +5011,7 @@ async function apply(ctx, config) {
5001
5011
  if (ctx.cron) {
5002
5012
  ctx.dota2tracker.matchWatcher = new MatchWatcherTask(ctx);
5003
5013
  ctx.dota2tracker.parsePolling = new ParsePollingTask(ctx);
5004
- ctx.dota2tracker.reportTask = new ReportTask(ctx);
5014
+ ctx.dota2tracker.dailyReportTask = new DailyReportTask(ctx);
5005
5015
  ctx.cron("* * * * *", async () => {
5006
5016
  await ctx.dota2tracker.matchWatcher.discovery();
5007
5017
  await ctx.dota2tracker.parsePolling.polling();
@@ -5011,7 +5021,7 @@ async function apply(ctx, config) {
5011
5021
  }
5012
5022
  ctx.dota2tracker.hero = new HeroService(ctx);
5013
5023
  ctx.dota2tracker.item = new ItemService(ctx);
5014
- ctx.dota2tracker.report = new ReportService(ctx);
5024
+ ctx.dota2tracker.dailyReport = new DailyReportService(ctx);
5015
5025
  ctx.dota2tracker.cache = new CacheService(ctx);
5016
5026
  ctx.dota2tracker.database = new DatabaseService(ctx);
5017
5027
  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`) %> <% if (fontFamily) { %><%- `body { font-family: ${fontFamily}; }` %><% } %> <%- `</style>` %> </head><body> <% let hero = data; %> <% if (hero.primary_attr==3) {
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') %> <% if (fontFamily) { %> <%- `body { font-family: ${fontFamily}; }` %> <% } %> <%- `</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 => {
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; } <% if (fontFamily) { %> body { font-family: <%= fontFamily %>; } <% } %> <%- "</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>
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`) %> <% if (fontFamily) { %><%- `body { font-family: ${fontFamily}; }` %><% } %> <%- `</style>` %> </head><body class="bg-black w-[800px] text-white"> <%- include(`./match_1/main.ejs`, { match, partyColor, facetColor, kc, dc, laneSVG }) %> </body></html>
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") %> <% if (fontFamily) { %> <%- `body { font-family: ${fontFamily}; }` %> <% } %> <%- "</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
+ <!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") %> <% if (fontFamily) { %> <%- `body { font-family: ${fontFamily}; }` %> <% } %> <%- "</style>" %> </head><body> <%- include('./match_2/original') %> </body></html>
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`) %> <% if (fontFamily) { %><%- `body { font-family: ${fontFamily}; }` %><% } %> <%- `</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>) &nbsp;&nbsp; <%= $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>&nbsp; <span><%= $t("dota2tracker.template.winrate_") %> <span <%- `style="color:${getWinRateColor(nearWin / nearCount)};"` %>><%= ((nearWin / nearCount) * 100).toFixed(2) %>%</span> </span>&nbsp; <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>&nbsp;&nbsp; <% 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>
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>) &nbsp;&nbsp; <%= $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>&nbsp; <span><%= $t("dota2tracker.template.winrate_") %> <span <%- `style="color:${getWinRateColor(nearWin / nearCount)};"` %>><%= ((nearWin / nearCount) * 100).toFixed(2) %>%</span> </span>&nbsp; <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>&nbsp;&nbsp; <% 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; } <% if (fontFamily) { %><%- `body { font-family: ${fontFamily}; }` %><% } %> <%- `</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
+ <% 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`) %> <% if (fontFamily) { %><%- `body { font-family: ${fontFamily}; }` %><% } %> <%- `</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 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) { %> <%
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") %> <% if (fontFamily) { %><%- `body { font-family: ${fontFamily}; }` %><% } %> <%- `</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>
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjtdev/koishi-plugin-dota2tracker",
3
3
  "description": "koishi插件-追踪群友的DOTA2对局 | A Koishi plugin to track Dota 2 matches",
4
- "version": "2.5.1",
4
+ "version": "2.5.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [