53 lines
1.8 KiB
JavaScript
53 lines
1.8 KiB
JavaScript
const canvas = document.getElementById('drift-canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
let accuracy = Array.from({ length: 44 }, (_, index) => 92 - Math.sin(index / 3) * 2);
|
|
let status = 'Model is healthy.';
|
|
|
|
function draw() {
|
|
const width = canvas.width;
|
|
const height = canvas.height;
|
|
const pad = 28;
|
|
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 = '#805ad5';
|
|
ctx.lineWidth = 3;
|
|
ctx.beginPath();
|
|
accuracy.forEach((value, index) => {
|
|
const x = pad + (index / Math.max(1, accuracy.length - 1)) * (width - pad * 2);
|
|
const y = height - pad - ((value - 40) / 60) * (height - pad * 2);
|
|
if (index === 0) ctx.moveTo(x, y);
|
|
else ctx.lineTo(x, y);
|
|
});
|
|
ctx.stroke();
|
|
document.getElementById('drift-status').textContent = status;
|
|
}
|
|
|
|
document.getElementById('drift-spike').addEventListener('click', () => {
|
|
accuracy = accuracy.map((value, index) => index > 20 ? Math.max(55, value - (index - 18) * 0.9) : value);
|
|
status = 'Black Friday traffic spike: feature distribution shifted, accuracy is sliding.';
|
|
draw();
|
|
});
|
|
|
|
document.getElementById('drift-corrupt').addEventListener('click', () => {
|
|
accuracy = accuracy.map((value, index) => index % 4 === 0 ? Math.max(45, value - 18) : value);
|
|
status = 'Corrupted input data: model confidence is having a very bad afternoon.';
|
|
draw();
|
|
});
|
|
|
|
document.getElementById('drift-retrain').addEventListener('click', () => {
|
|
accuracy = accuracy.map((_, index) => 91 + Math.sin(index / 4) * 3);
|
|
status = 'Retrained model: accuracy recovered and everyone pretends this was planned.';
|
|
draw();
|
|
});
|
|
|
|
draw();
|