@sjtdev/koishi-plugin-dota2tracker 1.5.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjtdev/koishi-plugin-dota2tracker",
3
3
  "description": "koishi插件-追踪群友的DOTA2对局",
4
- "version": "1.5.5",
4
+ "version": "2.0.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -29,10 +29,11 @@
29
29
  "dependencies": {
30
30
  "dotaconstants": "^9.5.0",
31
31
  "ejs": "^3.1.10",
32
- "moment": "^2.30.1"
32
+ "luxon": "^3.8.0-alpha.1",
33
+ "p-queue": "^8.1.1"
33
34
  },
34
35
  "peerDependencies": {
35
- "koishi": "^4.18.8"
36
+ "koishi": "^4.18.9"
36
37
  },
37
38
  "koishi": {
38
39
  "description": {
@@ -50,5 +51,8 @@
50
51
  "zh-CN",
51
52
  "en-US"
52
53
  ]
54
+ },
55
+ "devDependencies": {
56
+ "@types/html-minifier-terser": "^7"
53
57
  }
54
58
  }
@@ -0,0 +1,29 @@
1
+ query GetWeeklyMetaByPosition($bracketIds: [RankBracket]!) {
2
+ heroStats {
3
+ pos1: winWeek(take: 1, bracketIds: $bracketIds, positionIds: [POSITION_1]) {
4
+ heroId
5
+ winCount
6
+ matchCount
7
+ }
8
+ pos2: winWeek(take: 1, bracketIds: $bracketIds, positionIds: [POSITION_2]) {
9
+ heroId
10
+ winCount
11
+ matchCount
12
+ }
13
+ pos3: winWeek(take: 1, bracketIds: $bracketIds, positionIds: [POSITION_3]) {
14
+ heroId
15
+ winCount
16
+ matchCount
17
+ }
18
+ pos4: winWeek(take: 1, bracketIds: $bracketIds, positionIds: [POSITION_4]) {
19
+ heroId
20
+ winCount
21
+ matchCount
22
+ }
23
+ pos5: winWeek(take: 1, bracketIds: $bracketIds, positionIds: [POSITION_5]) {
24
+ heroId
25
+ winCount
26
+ matchCount
27
+ }
28
+ }
29
+ }
@@ -1,6 +1,6 @@
1
- query PlayerExtraInfo($steamAccountId: Long!, $totalHeroCount: Int!, $matchCount: Int!, $heroIds: [Short]) {
1
+ query PlayerExtraInfo($steamAccountId: Long!, $matchCount: Int!, $heroIds: [Short]) {
2
2
  player(steamAccountId: $steamAccountId) {
3
- heroesPerformance(take: $totalHeroCount, request: { matchGroupOrderBy: MATCH_COUNT, take: $matchCount, heroIds: $heroIds }) {
3
+ heroesPerformance(take: 200, request: { matchGroupOrderBy: MATCH_COUNT, take: $matchCount, heroIds: $heroIds }) {
4
4
  hero {
5
5
  id
6
6
  shortName
@@ -0,0 +1,23 @@
1
+ query PlayerPerformanceForHeroRecommendation($steamAccountId: Long!, $recentDateTime: Long!) {
2
+ player(steamAccountId: $steamAccountId) {
3
+ steamAccount {
4
+ seasonRank
5
+ }
6
+ matches(request: { take: 25 }) {
7
+ rank
8
+ }
9
+ lifetimePerformance: heroesPerformance(request: { take: 100000 }, take: 200) {
10
+ heroId
11
+ matchCount
12
+ winCount
13
+ lastPlayedDateTime
14
+ }
15
+ recentPerformance: heroesPerformance(request: { startDateTime: $recentDateTime, take: 10000 }, take: 200) {
16
+ heroId
17
+ matchCount
18
+ winCount
19
+ lastPlayedDateTime
20
+ imp
21
+ }
22
+ }
23
+ }
@@ -102,15 +102,15 @@
102
102
  }
103
103
 
104
104
  .hero .info .attrs > span.str::before {
105
- background-image: url("<%= utils.getImageUrl('hero_strength', ImageType.Icons) %>");
105
+ background-image: url("<%= getImageUrl('hero_strength', ImageType.Icons) %>");
106
106
  }
107
107
 
108
108
  .hero .info .attrs > span.agi::before {
109
- background-image: url("<%= utils.getImageUrl('hero_agility', ImageType.Icons) %>");
109
+ background-image: url("<%= getImageUrl('hero_agility', ImageType.Icons) %>");
110
110
  }
111
111
 
112
112
  .hero .info .attrs > span.int::before {
113
- background-image: url("<%= utils.getImageUrl('hero_intelligence', ImageType.Icons) %>");
113
+ background-image: url("<%= getImageUrl('hero_intelligence', ImageType.Icons) %>");
114
114
  }
115
115
 
116
116
  .details {
@@ -625,7 +625,7 @@
625
625
  <body>
626
626
  <% let hero = data; %>
627
627
  <% if (hero.primary_attr==3) {
628
- const base_damage = Math.floor((hero.str_base+hero.agi_base+hero.int_base)*0.7);
628
+ const base_damage = Math.floor((hero.str_base+hero.agi_base+hero.int_base)*0.45);
629
629
  hero.damage_max+=base_damage;
630
630
  hero.damage_min+=base_damage;
631
631
  } %>
@@ -634,8 +634,8 @@
634
634
  <div class="wrapper">
635
635
  <%- `
636
636
  <div class="hero" id="${hero.id}">
637
- <img src="${utils.getImageUrl(hero["name"].match(/^npc_dota_hero_(.+)$/)[1], ImageType.Heroes)}"/>
638
- <img class="pri_attr" src="${utils.getImageUrl(primary_attrs[hero.primary_attr], ImageType.Icons)}"/>
637
+ <img src="${getImageUrl(hero["name"].match(/^npc_dota_hero_(.+)$/)[1], ImageType.Heroes)}"/>
638
+ <img class="pri_attr" src="${getImageUrl(primary_attrs[hero.primary_attr], ImageType.Icons)}"/>
639
639
  <div class="info">
640
640
  <p class="name">${hero.name_loc}</p>
641
641
  <p class="roles">
@@ -684,45 +684,45 @@
684
684
  <div class="column">
685
685
  <p>${$t("dota2tracker.template.attack")}</p>
686
686
  <div class="stat">
687
- <img src="${utils.getImageUrl("icon_damage", ImageType.HeroStats)}"/>
687
+ <img src="${getImageUrl("icon_damage", ImageType.HeroStats)}"/>
688
688
  <span>${hero.damage_min}~${hero.damage_max}</span>
689
689
  </div>
690
690
  <div class="stat">
691
- <img src="${utils.getImageUrl("icon_attack_time", ImageType.HeroStats)}"/>
691
+ <img src="${getImageUrl("icon_attack_time", ImageType.HeroStats)}"/>
692
692
  <span>${hero.attack_rate.toFixed(1)}</span>
693
693
  </div>
694
694
  <div class="stat">
695
- <img src="${utils.getImageUrl("icon_attack_range", ImageType.HeroStats)}"/>
695
+ <img src="${getImageUrl("icon_attack_range", ImageType.HeroStats)}"/>
696
696
  <span>${hero.attack_range}</span>
697
697
  </div>
698
698
  <div class="stat${hero_dc.attack_type=="Melee"?" hide":""}">
699
- <img src="${utils.getImageUrl("icon_projectile_speed", ImageType.HeroStats)}"/>
699
+ <img src="${getImageUrl("icon_projectile_speed", ImageType.HeroStats)}"/>
700
700
  <span>${hero.projectile_speed}</span>
701
701
  </div>
702
702
  </div>
703
703
  <div class="column">
704
704
  <p>${$t("dota2tracker.template.defense")}</p>
705
705
  <div class="stat">
706
- <img src="${utils.getImageUrl("icon_armor", ImageType.HeroStats)}"/>
706
+ <img src="${getImageUrl("icon_armor", ImageType.HeroStats)}"/>
707
707
  <span>${hero.armor.toFixed(1)}</span>
708
708
  </div>
709
709
  <div class="stat">
710
- <img src="${utils.getImageUrl("icon_magic_resist", ImageType.HeroStats)}"/>
710
+ <img src="${getImageUrl("icon_magic_resist", ImageType.HeroStats)}"/>
711
711
  <span>${hero.magic_resistance}%</span>
712
712
  </div>
713
713
  </div>
714
714
  <div class="column">
715
715
  <p>${$t("dota2tracker.template.mobility")}</p>
716
716
  <div class="stat">
717
- <img src="${utils.getImageUrl("icon_movement_speed", ImageType.HeroStats)}"/>
717
+ <img src="${getImageUrl("icon_movement_speed", ImageType.HeroStats)}"/>
718
718
  <span>${hero.movement_speed}</span>
719
719
  </div>
720
720
  <div class="stat">
721
- <img src="${utils.getImageUrl("icon_turn_rate", ImageType.HeroStats)}"/>
721
+ <img src="${getImageUrl("icon_turn_rate", ImageType.HeroStats)}"/>
722
722
  <span>${hero.turn_rate.toFixed(1)}</span>
723
723
  </div>
724
724
  <div class="stat">
725
- <img src="${utils.getImageUrl("icon_vision", ImageType.HeroStats)}"/>
725
+ <img src="${getImageUrl("icon_vision", ImageType.HeroStats)}"/>
726
726
  <span>${hero.sight_range_day} / ${hero.sight_range_night}</span>
727
727
  </div>
728
728
  </div>
@@ -735,7 +735,7 @@
735
735
  <div class="name_back type_${facet.color}"></div>
736
736
  <div class="name_line type_${facet.color}"></div>
737
737
  <p class="name">
738
- <img src="${utils.getImageUrl(facet.icon, ImageType.IconsFacets)}"/>
738
+ <img src="${getImageUrl(facet.icon, ImageType.IconsFacets)}"/>
739
739
  <span>${facet.title_loc}</span>
740
740
  </p>
741
741
  <div class="content">
@@ -743,7 +743,7 @@
743
743
  ${facet.abilities?facet.abilities.map(ability=>
744
744
  `<div class="ability">
745
745
  <div class="name">
746
- <img src="${utils.getImageUrl(ability.name, ImageType.Abilities)}" onerror="this.onerror=null; this.src='${utils.getImageUrl(`innate_icon`,ImageType.Icons)}';"/>
746
+ <img src="${getImageUrl(ability.name, ImageType.Abilities)}" onerror="this.onerror=null; this.src='${getImageUrl(`innate_icon`,ImageType.Icons)}';"/>
747
747
  <span>${ability.name_loc}</span>
748
748
  </div>
749
749
  ${ability.description_ability_loc?`<div class="description">${ability.description_ability_loc}</div>`:""}
@@ -762,14 +762,14 @@
762
762
  .map((item) => {const ability_dc = dotaconstants.abilities[item.name]; return `
763
763
  <div class="skill${item.facet?' facet':''}" data-innate="${item.ability_is_innate&&!item.ability_is_facet}">
764
764
  <p class="title${item.facet?(' name_back type_' + item.facet?.color):''}">
765
- ${item.facet?`<img src="${utils.getImageUrl(item.facet?.icon, ImageType.IconsFacets)}">`:""}
765
+ ${item.facet?`<img src="${getImageUrl(item.facet?.icon, ImageType.IconsFacets)}">`:""}
766
766
  <span class="name">${item.name_loc}</span>
767
767
  ${item.ability_is_innate&&!item.ability_is_facet?`<span class="is_innate">${$t("dota2tracker.template.innate")}</span>`:""}
768
- ${item.ability_is_granted_by_scepter ?`<img src="${utils.getImageUrl("scepter")}" class="scepter">`:""}
769
- ${item.ability_is_granted_by_shard ?`<img src="${utils.getImageUrl("shard")}" class="shard">`:""}
768
+ ${item.ability_is_granted_by_scepter ?`<img src="${getImageUrl("scepter")}" class="scepter">`:""}
769
+ ${item.ability_is_granted_by_shard ?`<img src="${getImageUrl("shard")}" class="shard">`:""}
770
770
  </p>
771
771
  <div class="img_stats">
772
- <img src="${utils.getImageUrl(item.name, ImageType.Abilities)}" onerror="this.onerror=null; this.src='${utils.getImageUrl(`innate_icon`,ImageType.Icons)}';"/>
772
+ <img src="${getImageUrl(item.name, ImageType.Abilities)}" onerror="this.onerror=null; this.src='${getImageUrl(`innate_icon`,ImageType.Icons)}';"/>
773
773
  <div class="stats">
774
774
  <p class="behavior">${$t("dota2tracker.template.ability")}${[].concat(ability_dc?.behavior)
775
775
  .filter((beh) => beh !== "Hidden" || !(item.ability_is_granted_by_shard || item.ability_is_granted_by_scepter))
@@ -798,7 +798,7 @@
798
798
  <div class="name_back type_${hero.facets[index].color}"></div>
799
799
  <div class="name_line type_${hero.facets[index].color}"></div>
800
800
  <p class="name">
801
- <img src="${utils.getImageUrl(hero.facets[index].icon, ImageType.IconsFacets)}" />
801
+ <img src="${getImageUrl(hero.facets[index].icon, ImageType.IconsFacets)}" />
802
802
  <span>${hero.facets[index].title_loc}</span>
803
803
  </p>
804
804
  <div class="content">
@@ -810,12 +810,12 @@
810
810
  `:"")).join("")}
811
811
  ${item.ability_has_scepter&&!item.ability_is_granted_by_scepter&&item.scepter_loc
812
812
  ? `<p class="aghanim_description">
813
- <span class="title"><img src="${utils.getImageUrl("scepter")}"class="scepter">${$t("dota2tracker.template.scepter")}</span>
813
+ <span class="title"><img src="${getImageUrl("scepter")}"class="scepter">${$t("dota2tracker.template.scepter")}</span>
814
814
  <span class="desc">${item.scepter_loc}</span>
815
815
  </p>` : ""}
816
816
  ${item.ability_has_shard&&!item.ability_is_granted_by_shard&&item.shard_loc
817
817
  ? `<p class="aghanim_description">
818
- <span class="title"><img src="${utils.getImageUrl("shard")}"class="shard">${$t("dota2tracker.template.shard")}</span>
818
+ <span class="title"><img src="${getImageUrl("shard")}"class="shard">${$t("dota2tracker.template.shard")}</span>
819
819
  <span class="desc">${item.shard_loc}</span>
820
820
  </p>` : ""}
821
821
  <div class="notes"${!item.notes_loc.length ? ` style="display:none;"` : ""}>
@@ -835,19 +835,19 @@
835
835
  </span>` : "" }
836
836
  ${sv.values_scepter && sv.values_scepter.length ?
837
837
  `<span class="alternative scepter">
838
- <img src="${utils.getImageUrl("scepter")}"/>${sv.values_scepter.map(value => (value > 0 ? '<span class="plus">+</span>' : "") + value + (sv.is_percentage ? "%" : "")).join(" / ")}
838
+ <img src="${getImageUrl("scepter")}"/>${sv.values_scepter.map(value => (value > 0 ? '<span class="plus">+</span>' : "") + value + (sv.is_percentage ? "%" : "")).join(" / ")}
839
839
  </span>` : "" }
840
840
  ${sv.values_shard && sv.values_shard.length ?
841
841
  `<span class="alternative shard">
842
- <img src="${utils.getImageUrl("shard")}"/>${sv.values_shard.map(value => (value > 0 ? '<span class="plus">+</span>' : "") + value + (sv.is_percentage ? "%" : "")).join(" / ")}
842
+ <img src="${getImageUrl("shard")}"/>${sv.values_shard.map(value => (value > 0 ? '<span class="plus">+</span>' : "") + value + (sv.is_percentage ? "%" : "")).join(" / ")}
843
843
  </span>` : "" }
844
844
  ${sv.facet_bonus.name && hero.facets.some(facet=>facet.name==sv.facet_bonus.name) ?
845
845
  `<span class="alternative facet">
846
- <span class="facet"><span class="name_back type_${hero.facets.find(facet=>facet.name==sv.facet_bonus.name).color}"><img src="${utils.getImageUrl(hero.facets.find(facet=>facet.name==sv.facet_bonus.name).icon, ImageType.IconsFacets)}" />${sv.facet_bonus.values.map(value => value + (sv.is_percentage ? "%" : "")).join(" / ")}</span></span>
846
+ <span class="facet"><span class="name_back type_${hero.facets.find(facet=>facet.name==sv.facet_bonus.name).color}"><img src="${getImageUrl(hero.facets.find(facet=>facet.name==sv.facet_bonus.name).icon, ImageType.IconsFacets)}" />${sv.facet_bonus.values.map(value => value + (sv.is_percentage ? "%" : "")).join(" / ")}</span></span>
847
847
  </span>` : "" }
848
848
  ${sv.bonuses.length ?
849
849
  `<span class="alternative talent">
850
- ${sv.bonuses.map(bonus=>` <img src="${utils.getImageUrl("talents","icons","svg")}"/>${(bonus.value>0?'<span class="plus">+</span>':"")+bonus.value+(sv.is_percentage?"%":"")}`).join(" ")}
850
+ ${sv.bonuses.map(bonus=>` <img src="${getImageUrl("talents","icons","svg")}"/>${(bonus.value>0?'<span class="plus">+</span>':"")+bonus.value+(sv.is_percentage?"%":"")}`).join(" ")}
851
851
  </span>` : "" }
852
852
  </span>
853
853
  </p>`)
@@ -889,7 +889,7 @@
889
889
  if (abilityIsInnate) {
890
890
  item.style.order = -1;
891
891
  item.style.flexBasis = "100%";
892
- img.src = '<%- utils.getImageUrl("innate_icon",ImageType.Icons) %>'; // Set backup image URL
892
+ img.src = '<%- getImageUrl("innate_icon",ImageType.Icons) %>'; // Set backup image URL
893
893
  // item.querySelector(".cooldown").style.display = "none";
894
894
  // item.querySelector(".mana_cost").style.display = "none";
895
895
  }
@@ -6,7 +6,7 @@
6
6
  <div class="upper<%= multiple %>">
7
7
  <% item.builds_into.forEach(item => { %>
8
8
  <div class="item">
9
- <img src="<%= utils.getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
9
+ <img src="<%= getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
10
10
  <p><%= item.name_loc %></p>
11
11
  </div>
12
12
  <% }) %>
@@ -22,7 +22,7 @@
22
22
  <% } %>
23
23
  <div class="middle">
24
24
  <div class="item">
25
- <img src="<%= utils.getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
25
+ <img src="<%= getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
26
26
  <p><%= item.name_loc %></p>
27
27
  </div>
28
28
  </div>
@@ -41,7 +41,7 @@
41
41
  <div class="lower<%= multiple %>">
42
42
  <% recipe.items.forEach(item => { %>
43
43
  <div class="item">
44
- <img src="<%= utils.getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
44
+ <img src="<%= getImageUrl(item.name.startsWith("recipe_") ? "recipe" : item.name, ImageType.Items) %>">
45
45
  <p><%= item.name_loc %></p>
46
46
  </div>
47
47
  <% }) %>
@@ -43,11 +43,11 @@ const valueMap = item.special_values.reduce((map, val) => {
43
43
  <body>
44
44
  <div class="container">
45
45
  <div class="header">
46
- <img src="<%= utils.getImageUrl(item.name, ImageType.Items) %>">
46
+ <img src="<%= getImageUrl(item.name, ImageType.Items) %>">
47
47
  <div>
48
48
  <p class="name"><%= item.name_loc %> <span class="item_id"><%= item.name %></span></p>
49
49
  <% if (item.item_cost) { %>
50
- <p class="cost"><img style="height: 20px; width: auto; margin-right: 4px;" src="<%= utils.getImageUrl("gold", ImageType.Icons) %>"> <%= item.item_cost %></p>
50
+ <p class="cost"><img style="height: 20px; width: auto; margin-right: 4px;" src="<%= getImageUrl("gold", ImageType.Icons) %>"> <%= item.item_cost %></p>
51
51
  <% } %>
52
52
  </div>
53
53
  </div>
@@ -107,7 +107,7 @@ const valueMap = item.special_values.reduce((map, val) => {
107
107
  <% } %>
108
108
  <% if (item.cooldowns && item.cooldowns[0]) { %>
109
109
  <div class="attr">
110
- <img class="icon" src="<%= utils.getImageUrl("cooldown", ImageType.Icons) %>">
110
+ <img class="icon" src="<%= getImageUrl("cooldown", ImageType.Icons) %>">
111
111
  <span class="value"><%= item.cooldowns.join("/") %></span>
112
112
  </div>
113
113
  <% } %>
@@ -88,7 +88,7 @@ function calculateFontSize(text) {
88
88
  <div class="container">
89
89
  <% items.forEach(function(item) { %>
90
90
  <div class="item">
91
- <img src="<%= utils.getImageUrl(item.name, ImageType.Items) %>" />
91
+ <img src="<%= getImageUrl(item.name, ImageType.Items) %>" />
92
92
  <div class="name" <%- `style="font-size: ${calculateFontSize(item.name_loc)}px"` %>>
93
93
  <%= item.name_loc %>
94
94
  </div>
@@ -1,11 +1,11 @@
1
- <% const isRecipe = item?.isRecipe ? ` style="background-image: url('${utils.getImageUrl("recipe", ImageType.Items)}');"` : ''; %>
1
+ <% const isRecipe = item?.isRecipe ? ` style="background-image: url('${getImageUrl("recipe", ImageType.Items)}');"` : ''; %>
2
2
  <div class="relative <%= style %>"<%- isRecipe %>>
3
3
  <% if (item) { %>
4
4
  <% if (!isNeutral) { %>
5
- <img class="w-full h-full object-cover aspect-[11/8] <%= item.isRecipe ? "opacity-75 scale-[0.6] origin-top-right" : '' %>" src="<%= utils.getImageUrl(item.name, ImageType.Items) %>">
6
- <p class="absolute w-full text-[#ccc] text-center bottom-0 leading-[1] text-xs bg-stone-700/50"><%= utils.sec2time(item.time) %></p>
5
+ <img class="w-full h-full object-cover aspect-[11/8] <%= item.isRecipe ? "opacity-75 scale-[0.6] origin-top-right" : '' %>" src="<%= getImageUrl(item.name, ImageType.Items) %>">
6
+ <p class="absolute w-full text-[#ccc] text-center bottom-0 leading-[1] text-xs bg-stone-700/50"><%= item.time %></p>
7
7
  <% } else { %>
8
- <img class="w-full h-full object-contain" src="<%= utils.getImageUrl(dotaconstants.item_ids[player.neutral0Id], ImageType.Items) %>">
8
+ <img class="w-full h-full object-contain" src="<%= getImageUrl(dotaconstants.item_ids[player.neutral0Id], ImageType.Items) %>">
9
9
  <% } %>
10
10
  <% } %>
11
11
  </div>
@@ -1,5 +1,5 @@
1
1
  <div class="w-[790px] h-[100px] flex justify-between box m-[5px]">
2
- <div class="flag w-[100px] h-full flex justify-center items-end bg-cover <%= !match.didRadiantWin ? 'grayscale' : "" %>" style="background-image: url('<%= utils.getImageUrl("flag_radiant") %>')"><%= match.didRadiantWin ? $t("dota2tracker.template.won") : "" %></div>
2
+ <div class="flag w-[100px] h-full flex justify-center items-end bg-cover <%= !match.didRadiantWin ? 'grayscale' : "" %>" style="background-image: url('<%= getImageUrl("flag_radiant") %>')"><%= match.didRadiantWin ? $t("dota2tracker.template.won") : "" %></div>
3
3
  <div class="details grow relative flex-col flex">
4
4
  <p class="w-full flex justify-around">
5
5
  <span><%= $t("dota2tracker.template.match_id_") %><%= match.id %></span>
@@ -7,18 +7,18 @@
7
7
  <span><%= $t("dota2tracker.template.region_") %><%= $t("dota2tracker.template.regions." + match.regionId) %></span>
8
8
  </p>
9
9
  <p class="w-full flex justify-around">
10
- <span><%= $t("dota2tracker.template.start_time_") %><%= moment(new Date(match.startDateTime * 1000)).format("YYYY-MM-DD HH:mm:ss").slice(2) %></span>
11
- <span><%= $t("dota2tracker.template.end_time_") %><%= moment(new Date(match.endDateTime * 1000)).format("YYYY-MM-DD HH:mm:ss").slice(2) %></span>
10
+ <span><%= $t("dota2tracker.template.start_time_") %><%= DateTime.fromSeconds(match.startDateTime).toFormat("yyyy-MM-dd HH:mm:ss").slice(2) %></span>
11
+ <span><%= $t("dota2tracker.template.end_time_") %><%= DateTime.fromSeconds(match.endDateTime).toFormat("yyyy-MM-dd HH:mm:ss").slice(2) %></span>
12
12
  </p>
13
13
  <p class="w-full grow score flex justify-evenly items-end">
14
14
  <span class="score radiant text-3xl"><%= match.radiant.killsCount %></span>
15
- <span class="time text-sm"><%= utils.sec2time(match.durationSeconds) %></span>
15
+ <span class="time text-sm"><%= match.durationTime %></span>
16
16
  <span class="score dire text-3xl"><%= match.dire.killsCount %></span>
17
17
  </p>
18
- <img class="star absolute w-[64px] bottom-[10px] left-1/2 -translate-x-1/2" src="<%= utils.getImageUrl('star_' + (match.rank ? match.rank.toString().split('')[1] : '')) %>">
19
- <img class="medal absolute w-[64px] bottom-[10px] left-1/2 -translate-x-1/2" src="<%= utils.getImageUrl('medal_' + (match.rank ? match.rank.toString().split('')[0] : '')) %>">
18
+ <img class="star absolute w-[64px] bottom-[10px] left-1/2 -translate-x-1/2" src="<%= getImageUrl('star_' + (match.rank ? match.rank.toString().split('')[1] : '')) %>">
19
+ <img class="medal absolute w-[64px] bottom-[10px] left-1/2 -translate-x-1/2" src="<%= getImageUrl('medal_' + (match.rank ? match.rank.toString().split('')[0] : '')) %>">
20
20
  </div>
21
- <div class="flag w-[100px] h-full flex justify-center items-end bg-cover <%= match.didRadiantWin ? 'grayscale' : "" %>" style="background-image: url('<%= utils.getImageUrl("flag_dire") %>')"><%= !match.didRadiantWin ? $t("dota2tracker.template.won") : "" %></div>
21
+ <div class="flag w-[100px] h-full flex justify-center items-end bg-cover <%= match.didRadiantWin ? 'grayscale' : "" %>" style="background-image: url('<%= getImageUrl("flag_dire") %>')"><%= !match.didRadiantWin ? $t("dota2tracker.template.won") : "" %></div>
22
22
  </div>
23
23
  <div class="w-[790px] grid grid-cols-2 gap-[5px] mx-[5px]">
24
24
  <% for( let index = 0; index < match.players.length; index++ ) { %>
@@ -29,7 +29,7 @@
29
29
  <% for (const hero of (match.pickBans ?? []).filter(x => !x.isPick)) { %>
30
30
  <div class="ban_hero relative w-[10%]">
31
31
  <i class="absolute w-full h-full z-1" style="background-image: linear-gradient(to bottom left, transparent calc(50% - 1px), red calc(50% - 1px), black calc(50% + 1px), transparent calc(50% + 1px));"></i>
32
- <img class="grayscale" src="<%= utils.getImageUrl(/^npc_dota_hero_(?<name>.+)$/.exec(dotaconstants.heroes[hero.bannedHeroId].name)[1], ImageType.Heroes) %>" alt="" />
32
+ <img class="grayscale" src="<%= getImageUrl(/^npc_dota_hero_(?<name>.+)$/.exec(dotaconstants.heroes[hero.bannedHeroId].name)[1], ImageType.Heroes) %>" alt="" />
33
33
  </div>
34
34
  <% } %>
35
35
  </div>
@@ -2,7 +2,7 @@
2
2
  <section class="grid grid-cols-[112px_1fr_100px] grid-rows-[63px_24px]">
3
3
  <div class="avatar relative h-full relative row-1 col-1 text-[10px] text-shadow-[-1px_1px_2px_#000,1px_-1px_2px_#000,-1px_1px_2px_#000,1px_1px_2px_#000]">
4
4
  <% if (player.leaverStatus != "NONE" && player.leaverStatus != "DISCONNECTED") { %>
5
- <img class="leaver absolute w-full h-full object-contain" src="<%= utils.getImageUrl("disconnected") %>" />
5
+ <img class="leaver absolute w-full h-full object-contain" src="<%= getImageUrl("disconnected") %>" />
6
6
  <% } %>
7
7
  <div class="party contents">
8
8
  <i class="party_line absolute w-full h-[2px]" <%- `style="background-color:${partyColor[player.partyId]};"` %>></i>
@@ -13,7 +13,7 @@
13
13
  <p class="position"><%= $t("dota2tracker.template.position_" + player.position?.slice(-1))??'' %></p>
14
14
  </div>
15
15
  <p class="level absolute bottom-0 right-0 text-xs px-[2px]"><%= player.level %></p>
16
- <img class="h-full" src="<%= utils.getImageUrl(player.hero.shortName, ImageType.Heroes) %>" />
16
+ <img class="h-full" src="<%= getImageUrl(player.hero.shortName, ImageType.Heroes) %>" />
17
17
  </div>
18
18
  <div class="player_profile mx-[10px] row-1 col-2 w-auto h-full overflow-hidden text-center flex flex-col justify-around leading-[1]">
19
19
  <p class="player_name truncate max-w-full"><%= player.steamAccount.name %></p>
@@ -34,13 +34,13 @@
34
34
  </div>
35
35
  <div class="rank_plus w-[36px] h-full relative text-[10px] leading-[1.15] text-shadow-[-1px_1px_0_#000,1px_-1px_0_#000,-1px_1px_0_#000,1px_1px_0_#000]">
36
36
  <div class="rank absolute top-0 size-[36px] z-2">
37
- <img class="medal absolute inset-0" src="<%= utils.getImageUrl('medal_' + (player.rank.inTop100 ?? player.rank.medal)) %>"/>
38
- <img class="stars absolute inset-0" src="<%= utils.getImageUrl('star_' + player.rank.star) %>" />
37
+ <img class="medal absolute inset-0" src="<%= getImageUrl('medal_' + (player.rank.inTop100 ?? player.rank.medal)) %>"/>
38
+ <img class="stars absolute inset-0" src="<%= getImageUrl('star_' + player.rank.star) %>" />
39
39
  <p class="leader absolute bottom-0 text-center w-full"><%= player.steamAccount?.seasonLeaderboardRank ?? "" %></p>
40
40
  </div>
41
41
  <% if (player.dotaPlus) { %>
42
42
  <div class="plus absolute bottom-0 size-[36px] z-1">
43
- <img class="" src="<%= utils.getImageUrl("hero_badge_" + (player.dotaPlus ? Math.ceil((player.dotaPlus?.level + 1) / 6) : 1)) %>">
43
+ <img class="" src="<%= getImageUrl("hero_badge_" + (player.dotaPlus ? Math.ceil((player.dotaPlus?.level + 1) / 6) : 1)) %>">
44
44
  <p class="level absolute bottom-0 text-center w-full"><%= player.dotaPlus?.level %></p>
45
45
  </div>
46
46
  <% } %>
@@ -50,10 +50,10 @@
50
50
  <%- facetColor[player.facet?.color ?? 'Black'] %>">
51
51
  <% if (player.facet) { %>
52
52
  <div class="w-[24px] h-[24px] flex items-center justify-center bg-[#4444]">
53
- <img class="h-[18px]" src="<%= utils.getImageUrl(player.facet?.icon, ImageType.IconsFacets) %>" />
53
+ <img class="h-[18px]" src="<%= getImageUrl(player.facet?.icon, ImageType.IconsFacets) %>" />
54
54
  </div>
55
55
  <% } %>
56
- <div class="facet_name w-full truncate grow px-[4px] text-sm flex justify-center items-center"><span class="w-full truncate text-center"><%= player.facet?.name ?? "?" %></span></div>
56
+ <div class="facet_name w-full truncate grow px-[4px] text-sm flex justify-center items-center"><span class="w-full truncate text-center"><%= player.facet?.displayName ?? "?" %></span></div>
57
57
  </div>
58
58
  <div class="titles row-2 col-start-2 col-end-3 w-full flex items-center pl-[12px] gap-[6px]">
59
59
  <% for (let item of player.titles) { %>
@@ -114,7 +114,7 @@
114
114
  <div class="buffs flex h-[24px]">
115
115
  <% for (const buff of player.buffs) { %>
116
116
  <div class="relative">
117
- <img class="w-[33px] h-[24px]" src="<%= utils.getImageUrl(dotaconstants[`${buff.type}_ids`][buff.id], ImageType[buff.type === "ability" ? "Abilities" : "Items"]) %>" />
117
+ <img class="w-[33px] h-[24px]" src="<%= getImageUrl(dotaconstants[`${buff.type}_ids`][buff.id], ImageType[buff.type === "ability" ? "Abilities" : "Items"]) %>" />
118
118
  <p class="count absolute w-full bottom-0 leading-[1] text-center bg-stone-700/50 text-[10px]"><%= buff.stackCount || "" %></p>
119
119
  </div>
120
120
  <% } %>
@@ -122,7 +122,7 @@
122
122
  <div class="supports flex h-[24px]">
123
123
  <% for (const supportItem of player.supportItemsCount){ %>
124
124
  <div class="relative">
125
- <img class="w-[33px] h-[24px]" src="<%= utils.getImageUrl(supportItem.name, ImageType.Items) %>" />
125
+ <img class="w-[33px] h-[24px]" src="<%= getImageUrl(supportItem.name, ImageType.Items) %>" />
126
126
  <p class="count absolute w-full bottom-0 leading-[1] text-center bg-stone-700/50 text-[10px]"><%= supportItem.count || "" %></p>
127
127
  </div>
128
128
  <% } %>
@@ -42,12 +42,12 @@
42
42
  };
43
43
  // 对线结果的图标(来自免费SVG素材网)
44
44
  const laneSVG = {
45
- stomp: utils.getImageUrl("lane_stomp", undefined, ImageFormat.svg),
46
- advantage: utils.getImageUrl("lane_victory", undefined, ImageFormat.svg),
47
- disadvantage: utils.getImageUrl("lane_fail", undefined, ImageFormat.svg),
48
- stomped: utils.getImageUrl("lane_stomped", undefined, ImageFormat.svg),
49
- tie: utils.getImageUrl("lane_tie", undefined, ImageFormat.svg),
50
- jungle: utils.getImageUrl("lane_jungle", undefined, ImageFormat.svg),
45
+ stomp: getImageUrl("lane_stomp", undefined, ImageFormat.svg),
46
+ advantage: getImageUrl("lane_victory", undefined, ImageFormat.svg),
47
+ disadvantage: getImageUrl("lane_fail", undefined, ImageFormat.svg),
48
+ stomped: getImageUrl("lane_stomped", undefined, ImageFormat.svg),
49
+ tie: getImageUrl("lane_tie", undefined, ImageFormat.svg),
50
+ jungle: getImageUrl("lane_jungle", undefined, ImageFormat.svg),
51
51
  };
52
52
  %>
53
53
  <body class="bg-black w-[800px] text-white">