60 lines
2.1 KiB
JavaScript
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]);
|