From 8dddf4fcf478a61daf31d6f255af472d477d4d24 Mon Sep 17 00:00:00 2001 From: Mika Date: Tue, 24 Feb 2026 13:33:04 +0000 Subject: [PATCH] Add visualization_tool/js/charts.js --- visualization_tool/js/charts.js | 123 ++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 visualization_tool/js/charts.js diff --git a/visualization_tool/js/charts.js b/visualization_tool/js/charts.js new file mode 100644 index 0000000..7490f49 --- /dev/null +++ b/visualization_tool/js/charts.js @@ -0,0 +1,123 @@ +/** + * js/charts.js + * Visualisierung der Laufdaten in Matrix- und Zeitdiagrammen. + * Enthält Funktionen zur DOM-Aktualisierung von #delta-matrix und #timeline-chart. + * @module charts + */ + +/** + * Rendert eine 2×2-Matrix aus den gegebenen aggregierten Daten. + * Die Matrix zeigt pinned/unpinned (x) vs. Δt≥0/<0 (y). + * @param {Object} data - Aggregierte Daten in der Form: + * { + * pinned_pos: number, + * pinned_neg: number, + * unpinned_pos: number, + * unpinned_neg: number + * } + */ +export function renderDeltaMatrix(data) { + const container = document.getElementById('delta-matrix'); + if (!container) return; + + container.innerHTML = ''; + + const matrixData = [ + { label: 'Pinned Δt≥0', value: data?.pinned_pos ?? 0 }, + { label: 'Pinned Δt<0', value: data?.pinned_neg ?? 0 }, + { label: 'Unpinned Δt≥0', value: data?.unpinned_pos ?? 0 }, + { label: 'Unpinned Δt<0', value: data?.unpinned_neg ?? 0 } + ]; + + const matrixGrid = document.createElement('div'); + matrixGrid.className = 'delta-matrix__grid'; + matrixGrid.style.display = 'grid'; + matrixGrid.style.gridTemplateColumns = 'repeat(2, 1fr)'; + matrixGrid.style.gap = '1rem'; + + matrixData.forEach(cell => { + const cellDiv = document.createElement('div'); + cellDiv.className = 'delta-matrix__cell'; + cellDiv.setAttribute('role', 'region'); + cellDiv.setAttribute('aria-label', cell.label); + + const label = document.createElement('div'); + label.className = 'delta-matrix__label'; + label.textContent = cell.label; + + const value = document.createElement('div'); + value.className = 'delta-matrix__value'; + value.textContent = cell.value.toFixed(2); + + cellDiv.appendChild(label); + cellDiv.appendChild(value); + matrixGrid.appendChild(cellDiv); + }); + + container.appendChild(matrixGrid); +} + +/** + * Rendert den zeitlichen Verlauf der Δt-Werte als Liniendiagramm. + * Nutzt Canvas API (ohne externes Chart-Framework). + * @param {Array<{timestamp: string|number, delta_t: number}>} timeData - Zeitreihen-Daten. + */ +export function renderTimelineChart(timeData) { + const container = document.getElementById('timeline-chart'); + if (!container) return; + + container.innerHTML = ''; + + const canvas = document.createElement('canvas'); + canvas.width = container.clientWidth || 600; + canvas.height = 300; + container.appendChild(canvas); + + const ctx = canvas.getContext('2d'); + if (!ctx || !Array.isArray(timeData) || timeData.length === 0) { + ctx.fillStyle = '#666'; + ctx.fillText('Keine Daten verfügbar', 20, 40); + return; + } + + const maxVal = Math.max(...timeData.map(d => d.delta_t)); + const minVal = Math.min(...timeData.map(d => d.delta_t)); + + const normalize = v => (v - minVal) / (maxVal - minVal || 1); + + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.strokeStyle = '#0077cc'; + + timeData.forEach((point, i) => { + const x = (i / (timeData.length - 1)) * (canvas.width - 40) + 20; + const y = canvas.height - (normalize(point.delta_t) * (canvas.height - 40) + 20); + if (i === 0) ctx.moveTo(x, y); + else ctx.lineTo(x, y); + }); + + ctx.stroke(); + + // Achsen zeichnen + ctx.strokeStyle = '#333'; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(20, 10); + ctx.lineTo(20, canvas.height - 20); + ctx.lineTo(canvas.width - 20, canvas.height - 20); + ctx.stroke(); + + // Beschriftungen + ctx.fillStyle = '#222'; + ctx.font = '12px sans-serif'; + ctx.fillText('Zeit', canvas.width / 2 - 20, canvas.height - 5); + ctx.save(); + ctx.rotate(-Math.PI / 2); + ctx.fillText('Δt', -canvas.height / 2 - 10, 10); + ctx.restore(); + + // Accessibility-Hinweis + canvas.setAttribute('role', 'img'); + canvas.setAttribute('aria-label', 'Liniendiagramm der Δt-Zeitverteilung'); +}