Skip to content

Commit 5cc62e1

Browse files
authored
Merge pull request #55 from jrambold/gamelength_widget
Gamelength widget
2 parents d0a404e + 40807c1 commit 5cc62e1

7 files changed

+159
-4
lines changed

src/components/sources/ToolMeta.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const domain = new URL(data.url).hostname
1414
{
1515
data.metadata?.external ? (
1616
<>
17-
{domain} <span class="*:w-3 *:h-3 *:inline-block ml-1 text-gray-400" set:html={externalIcon} />
17+
{domain} <span class="ml-1 text-gray-400 *:inline-block *:h-3 *:w-3" set:html={externalIcon} />
1818
</>
1919
) : (
2020
"Made by Stormgate World"
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// @ts-nocheck
2+
3+
import { onMount } from "solid-js"
4+
import {
5+
Chart,
6+
Title,
7+
Tooltip,
8+
Legend,
9+
Colors,
10+
type ChartOptions,
11+
type ChartData,
12+
type ScriptableContext,
13+
type ChartArea,
14+
} from "chart.js"
15+
import { DefaultChart } from "solid-chartjs"
16+
17+
type GameLengthProps = {
18+
data: Array[]
19+
}
20+
21+
const prettyLabels = {
22+
"0-120": "<2m",
23+
"121-240": "2-4m",
24+
"241-360": "4-8m",
25+
"361-480": "8-10m",
26+
"481-600": "10-12m",
27+
"601-720": "12-14m",
28+
"721-840": "14-16m",
29+
"841-960": "16-18m",
30+
"961-1080": "18-20m",
31+
"1081-1200": "20-22m",
32+
"1320+": "22m+",
33+
}
34+
35+
export function GameLengthChart(props: GameLengthChartProps) {
36+
var labels = []
37+
var wins = []
38+
var losses = []
39+
var games = []
40+
props.data.map((period) => labels.push(prettyLabels[period.match_length_range]))
41+
props.data.map((period) => wins.push(period.wins_count))
42+
props.data.map((period) => losses.push(period.losses_count))
43+
props.data.map((period) => games.push(period.matches_count))
44+
let canvas: HTMLCanvasElement
45+
onMount(() => {
46+
Chart.register(Title, Tooltip, Colors)
47+
})
48+
49+
const min = 0
50+
const max = Math.max(...games)
51+
52+
const chartData: ChartData = {
53+
labels: labels,
54+
datasets: [
55+
{
56+
label: "Wins",
57+
data: wins,
58+
backgroundColor: "green",
59+
},
60+
{
61+
label: "Losses",
62+
data: losses,
63+
backgroundColor: "red",
64+
},
65+
],
66+
}
67+
68+
const chartOptions: ChartOptions = {
69+
responsive: true,
70+
maintainAspectRatio: true,
71+
interaction: {
72+
intersect: false,
73+
mode: "index",
74+
},
75+
plugins: {
76+
title: {
77+
display: false,
78+
},
79+
},
80+
scales: {
81+
x: {
82+
stacked: true,
83+
},
84+
y: {
85+
stacked: true,
86+
},
87+
},
88+
}
89+
90+
return (
91+
<div class="relative w-full overflow-hidden">
92+
<DefaultChart
93+
type="bar"
94+
data={chartData}
95+
options={chartOptions}
96+
height={100}
97+
width={300}
98+
ref={(c) => (canvas = c)}
99+
/>
100+
</div>
101+
)
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
import { Race, type PlayerMatchupsStats } from "../../lib/api"
3+
import Widget from "../Widget.astro"
4+
import { classes, styles } from "../../lib/theme"
5+
import { Image } from "astro:assets"
6+
import infernals from "../../assets/game/factions/infernals-small.png"
7+
import vanguard from "../../assets/game/factions/vanguard-small.png"
8+
import { GameLengthChart } from "./GameLengthChart"
9+
10+
type Theme = keyof typeof styles.badges
11+
interface Props {
12+
playerMatchupStats: PlayerMatchupsStats
13+
}
14+
15+
const { playerMatchupStats } = Astro.props
16+
const matchupsSortedByRace = playerMatchupStats.matchups.sort((a, b) => a.race.localeCompare(b.race))
17+
---
18+
19+
<Widget title="Game Length">
20+
<table class="mx-auto w-full table-auto whitespace-nowrap text-left text-sm transition-opacity">
21+
<tbody>
22+
{
23+
matchupsSortedByRace.map((matchup) => (
24+
<>
25+
<tr class="border-b border-gray-700/50 last:border-b-0">
26+
<td class="flex w-full gap-2 truncate p-2 font-semibold text-gray-50">
27+
<Image src={matchup.race === "infernals" ? infernals : vanguard} alt={matchup.race} class="size-6" />
28+
vs
29+
<Image
30+
src={matchup.opponent_race === "infernals" ? infernals : vanguard}
31+
alt={matchup.opponent_race}
32+
class="size-6"
33+
/>
34+
</td>
35+
</tr>
36+
<tr>
37+
<td class="pr-2 text-right text-sm text-gray-100">
38+
<GameLengthChart data={matchup.match_length} client:idle />
39+
</td>
40+
</tr>
41+
</>
42+
))
43+
}
44+
</tbody>
45+
</table>
46+
</Widget>

src/components/widgets/PlayerMatchupStats.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const { playerMatchupStats } = Astro.props
1515
const matchupsSortedByRace = playerMatchupStats.matchups.sort((a, b) => a.race.localeCompare(b.race))
1616
---
1717

18-
<Widget title="Winrates by matchup">
18+
<Widget title="Winrates By Matchup">
1919
<table class="mx-auto w-full table-auto whitespace-nowrap text-left text-sm transition-opacity">
2020
<tbody>
2121
{

src/components/widgets/PlayerOpponents.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface Props {
1111
const { opponents } = Astro.props
1212
---
1313

14-
<Widget title="Top opponents">
14+
<Widget title="Top Opponents">
1515
<table class={classes("mx-auto w-full table-auto whitespace-nowrap text-left transition-opacity")}>
1616
<tbody>
1717
{

src/lib/content.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export type RedditData = {
104104
}
105105

106106
export type ToolData = {
107-
tags: string[],
107+
tags: string[]
108108
external: boolean
109109
}
110110

src/pages/players/[id]-[username].astro

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { PlayersApi } from "../../lib/api"
1010
import { RankedBadge } from "../../components/ui/RankedBadge"
1111
import PlayerActivity from "../../components/widgets/PlayerActivity.astro"
1212
import PlayerMatchupStats from "../../components/widgets/PlayerMatchupStats.astro"
13+
import PlayerGameLengthStats from "../../components/widgets/PlayerGameLengthStats.astro"
1314
import PlayerOpponents from "../../components/widgets/PlayerOpponents.astro"
1415
import { styles } from "../../lib/theme"
1516
@@ -102,6 +103,9 @@ const highestLeague = player?.leaderboard_entries?.reduce(
102103
<div class="hidden lg:block">
103104
{playerMatchupStats.matchups.length > 0 && <PlayerMatchupStats playerMatchupStats={playerMatchupStats} />}
104105
</div>
106+
<div class="hidden lg:block">
107+
{playerMatchupStats.matchups.length > 0 && <PlayerGameLengthStats playerMatchupStats={playerMatchupStats} />}
108+
</div>
105109
<div class="hidden lg:block">
106110
{playerOpponents.opponents.length > 0 && <PlayerOpponents opponents={playerOpponents} />}
107111
</div>
@@ -112,6 +116,9 @@ const highestLeague = player?.leaderboard_entries?.reduce(
112116
<div class="lg:hidden">
113117
{playerMatchupStats.matchups.length > 0 && <PlayerMatchupStats playerMatchupStats={playerMatchupStats} />}
114118
</div>
119+
<div class="lg:hidden">
120+
{playerMatchupStats.matchups.length > 0 && <PlayerGameLengthStats playerMatchupStats={playerMatchupStats} />}
121+
</div>
115122
<div class="lg:hidden">
116123
{playerOpponents.opponents.length > 0 && <PlayerOpponents opponents={playerOpponents} />}
117124
</div>

0 commit comments

Comments
 (0)