add analytics page
Some checks failed
deploy / deploy (push) Failing after 20s

This commit is contained in:
Lee 2023-10-27 16:26:23 +01:00
parent 1abb78719b
commit c52ba58d2e
5 changed files with 175 additions and 3 deletions

View File

@ -0,0 +1,46 @@
import AnalyticsChart from "@/components/AnalyticsChart";
import Card from "@/components/Card";
import Container from "@/components/Container";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Search",
};
export async function getData() {
const response = await fetch(
"https://bs-tracker.fascinated.cc/analytics?time=30d",
{
next: {
revalidate: 600, // 10 minutes
},
},
);
const json = await response.json();
return json;
}
export default async function Home() {
const playerCountHistory = await getData();
return (
<main>
<Container>
<Card
className="mt-2 w-full rounded-md bg-gray-800"
innerClassName="flex flex-col items-center justify-center"
>
<h1 className="text-center text-3xl font-bold">Analytics</h1>
<p className="text-center text-gray-300">
Scoresaber metrics and statistics over time.
</p>
<div className="mt-3 h-[400px] w-full">
<AnalyticsChart playerCountHistoryData={playerCountHistory} />
</div>
</Card>
</Container>
</main>
);
}

View File

@ -0,0 +1,114 @@
"use client";
import { ScoresaberPlayerCountHistory } from "@/schemas/fascinated/scoresaberPlayerCountHistory";
import { formatTimeAgo } from "@/utils/timeUtils";
import {
CategoryScale,
Chart as ChartJS,
Legend,
LineElement,
LinearScale,
PointElement,
Title,
Tooltip,
} from "chart.js";
import { Line } from "react-chartjs-2";
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
);
type PlayerChartProps = {
className?: string;
playerCountHistoryData: ScoresaberPlayerCountHistory;
};
export const options: any = {
maintainAspectRatio: false,
aspectRatio: 1,
interaction: {
mode: "index",
intersect: false,
},
scales: {
y: {
ticks: {
autoSkip: true,
maxTicksLimit: 8,
stepSize: 1,
},
},
x: {
ticks: {
autoSkip: true,
},
},
},
elements: {
point: {
radius: 0,
},
},
plugins: {
legend: {
position: "top" as const,
labels: {
color: "white",
},
},
title: {
display: false,
},
tooltip: {
callbacks: {
label(context: any) {
switch (
context.dataset.label
// case "Rank": {
// return `Rank #${formatNumber(context.parsed.y.toFixed(0))}`;
// }
) {
}
},
},
},
},
};
export default function AnalyticsChart({
className,
playerCountHistoryData,
}: PlayerChartProps) {
const playerCountHistory = playerCountHistoryData.history;
let labels = [];
for (let i = 0; i < playerCountHistory.length; i++) {
if (i == playerCountHistory.length - 1) {
labels.push("now");
continue;
}
labels.push(formatTimeAgo(playerCountHistory[i].time));
}
const data = {
labels,
datasets: [
{
lineTension: 0.5,
data: playerCountHistory.map((count) => count.value),
label: "Active Players",
borderColor: "#3e95cd",
fill: false,
color: "#fff",
},
],
};
return <Line className={className} options={options} data={data} />;
}

View File

@ -5,6 +5,7 @@ import useStore from "@/utils/useStore";
import {
CogIcon,
MagnifyingGlassIcon,
ServerIcon,
UserIcon,
} from "@heroicons/react/20/solid";
import { GlobeAltIcon } from "@heroicons/react/24/outline";
@ -95,6 +96,11 @@ export default function Navbar() {
icon={<GlobeAltIcon height={20} width={20} />}
href="/ranking/global/1"
/>
<NavbarButton
text="Analytics"
icon={<ServerIcon height={20} width={20} />}
href="/analytics"
/>
<div className="m-auto" />

View File

@ -29,6 +29,7 @@ export default function Score({ score, player, leaderboard }: ScoreProps) {
leaderboard.difficulty.difficulty,
);
const diffColor = songDifficultyToColor(diffName);
const accuracy = ((score.baseScore / leaderboard.maxScore) * 100).toFixed(2);
return (
// <div className="grid grid-cols-1 pb-2 pt-2 first:pt-0 last:pb-0 md:grid-cols-[1fr_6fr_0.4fr_1.3fr]">
@ -125,9 +126,7 @@ export default function Score({ score, player, leaderboard }: ScoreProps) {
value={
!leaderboard.maxScore
? formatNumber(score.baseScore)
: ((score.baseScore / leaderboard.maxScore) * 100).toFixed(
2,
) + "%"
: accuracy + "%"
}
/>
</div>

View File

@ -0,0 +1,7 @@
export type ScoresaberPlayerCountHistory = {
serverTimeTaken: number;
history: {
time: string;
value: number | null;
}[];
};