speed-tester/js/index.ts

150 lines
4.1 KiB
TypeScript

import Chart, { ChartOptions } from 'chart.js/auto';
import zoomPlugin from 'chartjs-plugin-zoom';
Chart.register(zoomPlugin);
const lastDay = new Date();
lastDay.setDate(lastDay.getDate() - 1);
const lastHours = `${lastDay.getFullYear()}-${lastDay.getMonth() + 1}-${String(lastDay.getDate()).padStart(2, '0')}`;
const options = {
plugins: {
zoom: {
zoom: {
drag: { enabled: true },
mode: 'x',
},
},
},
} satisfies ChartOptions<'line'>;
const speedChart = new Chart(document.querySelector('#speed-chart') as any, {
type: 'line',
data: { datasets: [] },
options,
});
const latencyChart = new Chart(document.querySelector('#latency-chart') as any, {
type: 'line',
data: { datasets: [] },
options,
});
const durationChart = new Chart(document.querySelector('#duration-chart') as any, {
type: 'line',
data: { datasets: [] },
options,
});
document.querySelectorAll('.reset-chart').forEach(el => {
const chartCanvas = getCanvas(el);
if (!chartCanvas) return;
el.addEventListener('click', () => Chart.getChart(chartCanvas)?.resetZoom('none'));
});
document.querySelectorAll('.last-hours').forEach(el => {
const canvasId = getCanvas(el)?.id;
if (!canvasId) return;
el.addEventListener('click', () => {
switch (canvasId) {
case 'speed-chart':
return updateSpeedChart(lastHours);
case 'latency-chart':
return updateLatencyChart(lastHours);
case 'duration-chart':
return updateDurationChart(lastHours);
default:
return console.warn('[WARNING] `canvasId` not recognized', canvasId);
}
});
});
document.querySelectorAll('.complete-data').forEach(el => {
const canvasId = getCanvas(el)?.id;
if (!canvasId) return;
el.addEventListener('click', () => {
switch (canvasId) {
case 'speed-chart':
return updateSpeedChart();
case 'latency-chart':
return updateLatencyChart();
case 'duration-chart':
return updateDurationChart();
default:
return console.warn('[WARNING] `canvasId` not recognized', canvasId);
}
});
});
updateSpeedChart(lastHours);
updateLatencyChart(lastHours);
updateDurationChart(lastHours);
function updateSpeedChart(from?: string, to?: string): void {
fetch('/data/speed' + toUrlQuery(from, to))
.then(res => res.json())
.then(json => {
const downloadData = json.map(j => j.DLSpeed / 125000.0); // Mbps
const uploadData = json.map(j => j.ULSpeed / 125000.0); // Mbps
const time = json.map(j => j.CreationDate);
speedChart.data = {
labels: time,
datasets: [
{ data: downloadData, label: 'Download' },
{ data: uploadData, label: 'Upload' },
],
};
speedChart.update('none');
speedChart.resetZoom('none');
});
}
function updateLatencyChart(from?: string, to?: string): void {
fetch('/data/latency' + toUrlQuery(from, to))
.then(res => res.json())
.then(json => {
const latencyData = json.map(j => j.Latency / 1000000); // ms
const maxLatencyData = json.map(j => j.MaxLatency / 1000000); // ms
const minLatencyData = json.map(j => j.MinLatency / 1000000); // ms
const jitterData = json.map(j => j.Jitter / 1000000); // ms
const time = json.map(j => j.CreationDate);
latencyChart.data = {
labels: time,
datasets: [
{ data: latencyData, label: 'Latency' },
{ data: maxLatencyData, label: 'max Latency' },
{ data: minLatencyData, label: 'min Latency' },
{ data: jitterData, label: 'Jitter' },
],
};
latencyChart.update('none');
latencyChart.resetZoom('none');
});
}
function updateDurationChart(from?: string, to?: string): void {
fetch('/data/duration' + toUrlQuery(from, to))
.then(res => res.json())
.then(json => {
const durationData = json.map(j => j.TestDuration / 1000000000); // sec
const time = json.map(j => j.CreationDate);
durationChart.data = {
labels: time,
datasets: [{ data: durationData, label: 'Duration' }],
};
durationChart.update('none');
durationChart.resetZoom('none');
});
}
function toUrlQuery(from?: string, to?: string): string {
return `?from=${from ?? ''}&to=${to ?? ''}`;
}
function getCanvas(element: Element): HTMLCanvasElement | undefined {
return element.closest('.wrapper')?.querySelector('canvas') ?? undefined;
}