function renderDetectionChart() {
const canvas = document.getElementById('detectionChart');
const ctx = canvas.getContext('2d');
const w = canvas.width, h = canvas.height;
ctx.clearRect(0, 0, w, h);
const dpo = [7,8,9,10,11,12,13,14,15,16,17,18];
const prob = [5,10,25,45,65,80,90,95,98,99,99.5,99.9];
const padding = 40;
const chartW = w - padding * 2;
const chartH = h - padding * 2;
ctx.strokeStyle = '#e8e4df'; ctx.lineWidth = 1;
for (let i = 0; i <= 5; i++) {
const y = padding + (chartH / 5) * i;
ctx.beginPath(); ctx.moveTo(padding, y); ctx.lineTo(w - padding, y); ctx.stroke();
}
ctx.strokeStyle = '#7dd3c0'; ctx.lineWidth = 3; ctx.beginPath();
dpo.forEach((d, i) => {
const x = padding + (chartW / (dpo.length - 1)) * i;
const y = padding + chartH - (prob[i] / 100) * chartH;
if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
});
ctx.stroke();
ctx.fillStyle = '#7dd3c0';
dpo.forEach((d, i) => {
const x = padding + (chartW / (dpo.length - 1)) * i;
const y = padding + chartH - (prob[i] / 100) * chartH;
ctx.beginPath(); ctx.arc(x, y, 5, 0, Math.PI * 2); ctx.fill();
});
ctx.fillStyle = '#8a8a8a'; ctx.font = '12px Segoe UI'; ctx.textAlign = 'center';
dpo.forEach((d, i) => {
const x = padding + (chartW / (dpo.length - 1)) * i;
ctx.fillText(d + 'd', x, h - 15);
});
}
renderDetectionChart();
function renderDetectionChart() {
const canvas = document.getElementById('detectionChart');
const ctx = canvas.getContext('2d');
const w = canvas.width, h = canvas.height;
ctx.clearRect(0, 0, w, h);
const dpo = [7,8,9,10,11,12,13,14,15,16,17,18];
const prob = [5,10,25,45,65,80,90,95,98,99,99.5,99.9];
const padding = 40;
const chartW = w - padding * 2;
const chartH = h - padding * 2;
ctx.strokeStyle = '#e8e4df'; ctx.lineWidth = 1;
for (let i = 0; i <= 5; i++) {
const y = padding + (chartH / 5) * i;
ctx.beginPath(); ctx.moveTo(padding, y); ctx.lineTo(w - padding, y); ctx.stroke();
}
ctx.strokeStyle = '#7dd3c0'; ctx.lineWidth = 3; ctx.beginPath();
dpo.forEach((d, i) => {
const x = padding + (chartW / (dpo.length - 1)) * i;
const y = padding + chartH - (prob[i] / 100) * chartH;
if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
});
ctx.stroke();
ctx.fillStyle = '#7dd3c0';
dpo.forEach((d, i) => {
const x = padding + (chartW / (dpo.length - 1)) * i;
const y = padding + chartH - (prob[i] / 100) * chartH;
ctx.beginPath(); ctx.arc(x, y, 5, 0, Math.PI * 2); ctx.fill();
});
ctx.fillStyle = '#8a8a8a'; ctx.font = '12px Segoe UI'; ctx.textAlign = 'center';
dpo.forEach((d, i) => {
const x = padding + (chartW / (dpo.length - 1)) * i;
ctx.fillText(d + 'd', x, h - 15);
});
}
renderDetectionChart();
All calculations are performed locally. Your data never leaves your browser.