Skip to content

Commit

Permalink
add tracking.html
Browse files Browse the repository at this point in the history
  • Loading branch information
salvoilmiosi committed Sep 23, 2024
1 parent 5e2d2d0 commit e9e26c4
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 0 deletions.
47 changes: 47 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
"@types/node": "^16.18.32",
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"chartjs-adapter-moment": "^1.0.1",
"moment": "^2.30.1",
"node-fetch": "^3.3.1",
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0",
"react-use-event-hook": "^0.9.6",
"ts-curry": "^1.0.4",
Expand Down
120 changes: 120 additions & 0 deletions src/Scenes/Tracking/Tracking.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Chart as ChartJS, registerables } from 'chart.js';
import 'chartjs-adapter-moment';
import { useEffect, useMemo, useState } from "react";
import { Line } from "react-chartjs-2";
import Env from "../../Model/Env";

ChartJS.register(...registerables);

function useFetch<T>(url: string): T | undefined {
const [result, setResult] = useState<T>();

useEffect(() => {
let fetching = true;
(async () => {
const response = await fetch(url);
const json = await response.json();
if (fetching) {
setResult(json);
}
})();
return () => { fetching = false; };
}, [url]);

return result;
}

type Timestamp = number;
type TimestampCount = [Timestamp, number];

interface TrackingData {
client_count: TimestampCount[];
user_count: TimestampCount[];
lobby_count: TimestampCount[];
}

function timestampToDate(timestamp: Timestamp) {
return new Date(timestamp * 1000);
}

function timestampLabels(...minmax: TimestampCount[][]): Date[] {
let min: Timestamp | undefined;
let max: Timestamp | undefined;

for (const count of minmax) {
if (count.length > 2) {
const minTimestamp = count[0][0];
if (min !== undefined && min > minTimestamp) {
min = minTimestamp;
}
const maxTimestamp = count[count.length - 1][0];
if (max !== undefined && max < maxTimestamp) {
max = maxTimestamp;
}
}
}

if (min !== undefined && max !== undefined) {
return [timestampToDate(min), timestampToDate(max)];
} else {
return [];
}
}

function TrackingDataChart({ data }: { data: TrackingData }) {
return <Line
data={{
labels: timestampLabels(data.client_count, data.user_count, data.lobby_count),
datasets: [
{
label: 'Client Count',
data: data.client_count.map(row => ({ x: timestampToDate(row[0]), y: row[1] })),
stepped: true,
borderColor: '#0000ff',
backgroundColor: '#ffffff',
},
{
label: 'User Count',
data: data.user_count.map(row => ({ x: timestampToDate(row[0]), y: row[1] })),
stepped: true,
borderColor: '#0080ff',
backgroundColor: '#ffffff',
},
{
label: 'Lobby Count',
data: data.lobby_count.map(row => ({ x: timestampToDate(row[0]), y: row[1] })),
stepped: true,
borderColor: '#ff8000',
backgroundColor: '#ffffff',
},
]
}}

options={{
scales: { x: { type: 'time' }, },
elements: { point: { radius: 0 }}
}}
/>;
}

export default function TrackingScene() {
const bangServerUrl = useMemo(() => {
if (!Env.bangServerUrl) {
throw new Error('missing BANG_SERVER_URL environment variable');
}
let url = Env.bangServerUrl.replace('wss://', 'https://').replace('ws://', 'http://');
if (!url.endsWith('/')) {
url += '/';
}
url += 'tracking';
return url;
}, []);

const sinceDate = ''; // TODO add state

const trackingData = useFetch<TrackingData>(bangServerUrl + '?since_date=' + sinceDate);

return <div className="flex flex-col items-center">
{trackingData && <TrackingDataChart data={trackingData} /> }
</div>;
}
14 changes: 14 additions & 0 deletions src/tracking.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import { getSystemLanguage } from './Locale/Registry';
import './index.css';
import TrackingScene from './Scenes/Tracking/Tracking';

document.documentElement.lang = getSystemLanguage();

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<StrictMode>
<TrackingScene />
</StrictMode>
);
17 changes: 17 additions & 0 deletions tracking.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>Bang! salvoserver - User tracking</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/tracking.tsx"></script>
</body>
</html>

0 comments on commit e9e26c4

Please sign in to comment.