diff --git a/results_visualization/js/ui.js b/results_visualization/js/ui.js new file mode 100644 index 0000000..0059a5e --- /dev/null +++ b/results_visualization/js/ui.js @@ -0,0 +1,100 @@ +'use strict'; + +(function() { + let chartInstance = null; + + /** + * Berechnet statistische Kennzahlen aus den Spike-Daten. + * @param {Array<{timestamp:number, type:string, cpu:int, value:number}>} spikeData + * @returns {{median:number, p99:number, deltaTail:number}} + */ + function computeStats(spikeData) { + if (!Array.isArray(spikeData) || spikeData.length === 0) { + return { median: 0, p99: 0, deltaTail: 0 }; + } + const sorted = [...spikeData].sort((a, b) => a.value - b.value); + const n = sorted.length; + const median = sorted[Math.floor(n / 2)].value; + const p99 = sorted[Math.floor(n * 0.99) - 1 >= 0 ? Math.floor(n * 0.99) - 1 : 0].value; + const deltaTail = p99 - median; + return { median, p99, deltaTail }; + } + + /** + * Erstellt oder aktualisiert das Diagramm mit neuen Spikedaten. + * @param {Array<{timestamp:number, type:string, cpu:int, value:number}>} spikeData + */ + function renderSpikeChart(spikeData) { + const container = document.getElementById('chart-container'); + if (!container) return; + + // Falls eine vorhandene Instanz existiert, diese löschen + if (chartInstance && typeof chartInstance.destroy === 'function') { + chartInstance.destroy(); + } + + // Daten für Chart.js vorbereiten + const labels = spikeData.map(d => new Date(d.timestamp).toLocaleTimeString()); + const values = spikeData.map(d => d.value); + + const canvas = document.createElement('canvas'); + container.innerHTML = ''; + container.appendChild(canvas); + + // Chart.js Initialisierung + if (window.Chart) { + chartInstance = new Chart(canvas.getContext('2d'), { + type: 'line', + data: { + labels: labels, + datasets: [{ + label: 'P99 Spike Werte', + data: values, + borderColor: '#007ACC', + backgroundColor: 'rgba(0, 122, 204, 0.2)', + fill: true, + pointRadius: 2 + }] + }, + options: { + responsive: true, + scales: { + x: { title: { display: true, text: 'Zeit' } }, + y: { title: { display: true, text: 'Spike Wert' } } + } + } + }); + } else { + // Fallback: einfache Textanzeige + const info = document.createElement('div'); + info.textContent = 'Chart-Komponente nicht verfügbar. Werteanzeige deaktiviert.'; + container.innerHTML = ''; + container.appendChild(info); + } + + const stats = computeStats(spikeData); + updateStatsPanel(stats); + } + + /** + * Aktualisiert statistische Kennwerte im UI. + * @param {{median:number, p99:number, deltaTail:number}} stats + */ + function updateStatsPanel(stats) { + const panel = document.querySelector('.stats-panel'); + if (!panel) return; + + const medianEl = panel.querySelector('.stat-median'); + const p99El = panel.querySelector('.stat-p99'); + const deltaEl = panel.querySelector('.stat-delta'); + + if (medianEl) medianEl.textContent = stats.median.toFixed(2); + if (p99El) p99El.textContent = stats.p99.toFixed(2); + if (deltaEl) deltaEl.textContent = stats.deltaTail.toFixed(2); + } + + window.ui = { + renderSpikeChart, + updateStatsPanel + }; +})(); \ No newline at end of file