my-homelab-configs/apps/demos-static/public/network-quality/network-quality.js

60 lines
2.1 KiB
JavaScript

const canvas = document.getElementById('network-canvas');
const ctx = canvas.getContext('2d');
const samples = [];
let timer = null;
function draw(values) {
const width = canvas.width;
const height = canvas.height;
const pad = 28;
const max = Math.max(120, ...values);
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = '#f8fafc';
ctx.fillRect(0, 0, width, height);
ctx.strokeStyle = '#d9e2ec';
for (let i = 0; i < 5; i += 1) {
const y = pad + ((height - pad * 2) / 4) * i;
ctx.beginPath();
ctx.moveTo(pad, y);
ctx.lineTo(width - pad, y);
ctx.stroke();
}
ctx.strokeStyle = '#2563eb';
ctx.lineWidth = 3;
ctx.beginPath();
values.forEach((value, index) => {
const x = pad + (index / Math.max(1, values.length - 1)) * (width - pad * 2);
const y = height - pad - (value / max) * (height - pad * 2);
if (index === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
}
async function measure() {
const start = performance.now();
await fetch(`../shared.css?probe=${Date.now()}`, { cache: 'no-store' });
const latency = Math.round(performance.now() - start);
samples.push(latency);
while (samples.length > 60) samples.shift();
const deltas = samples.slice(1).map((value, index) => Math.abs(value - samples[index]));
const jitter = deltas.length ? Math.round(deltas.reduce((sum, value) => sum + value, 0) / deltas.length) : 0;
const average = Math.round(samples.reduce((sum, value) => sum + value, 0) / samples.length);
const stability = Math.max(0, Math.min(100, Math.round(100 - (jitter / Math.max(average, 1)) * 100)));
document.getElementById('latency-stat').textContent = `${latency} ms`;
document.getElementById('jitter-stat').textContent = `${jitter} ms`;
document.getElementById('stability-stat').textContent = `${stability}%`;
draw(samples);
}
document.getElementById('network-start').addEventListener('click', () => {
if (timer) return;
measure().catch(() => {});
timer = window.setInterval(() => measure().catch(() => {}), 1400);
});
document.getElementById('network-stop').addEventListener('click', () => {
window.clearInterval(timer);
timer = null;
});
draw([0, 0]);