From ab251d7e4ca5ec055f0c0f10e23c527a9bf8bbc8 Mon Sep 17 00:00:00 2001 From: Mika Date: Mon, 26 Jan 2026 12:23:43 +0000 Subject: [PATCH] Add result_visualization/js/ui.js --- result_visualization/js/ui.js | 129 ++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 result_visualization/js/ui.js diff --git a/result_visualization/js/ui.js b/result_visualization/js/ui.js new file mode 100644 index 0000000..8a9b0e8 --- /dev/null +++ b/result_visualization/js/ui.js @@ -0,0 +1,129 @@ +/* eslint-disable no-undef */ +/** + * @module ui + * Präsentationslogik für die Visualisierung der Analyse-Ergebnisse. + * Verantwortlich für DOM-Manipulationen basierend auf geladenen Daten. + */ + +/** + * Rendert eine Übersicht der aggregierten Statistiken zu Runs im Hauptbereich. + * @param {Array} results - Teil der API-Response mit Statistiken. + */ +export function renderOverview(results = []) { + const container = document.getElementById('results-overview'); + if (!container) return; + + // Defensive: Cleanup und Fallback + container.innerHTML = ''; + if (!Array.isArray(results) || results.length === 0) { + container.textContent = 'Keine Ergebnisse verfügbar.'; + return; + } + + // Aggregation - Beispielhafte Kennzahlen + const totalRuns = results.length; + const pinnedRuns = results.filter(r => r.type === 'pinned').length; + const unpinnedRuns = totalRuns - pinnedRuns; + + const avgCorrelations = (results + .map(r => r?.statistics?.correlation ?? 0) + .reduce((a, b) => a + b, 0)) / totalRuns; + + const overviewHTML = ` +
+

Analyseübersicht

+
    +
  • Gesamtanzahl Runs: ${totalRuns}
  • +
  • Pinned Runs: ${pinnedRuns}
  • +
  • Unpinned Runs: ${unpinnedRuns}
  • +
  • Ø Korrelation: ${avgCorrelations.toFixed(3)}
  • +
+
+ `; + + container.innerHTML = overviewHTML; +} + +/** + * Aktualisiert oder rendert Diagramme auf Basis der gegebenen API-Daten. + * Wird bei Initialisierung und Filter-Events aufgerufen. + * @param {Array} runData - Liste der Runs mit chartData-Feldern. + * @param {string} [filterType] - Optionaler Filter (pinned/unpinned) + */ +export function updateCharts(runData = [], filterType) { + const chartPanel = document.getElementById('chart-panel'); + if (!chartPanel) return; + chartPanel.innerHTML = ''; + + // Optionales Filtern + const filteredData = filterType + ? runData.filter(r => r.type === filterType) + : runData; + + if (filteredData.length === 0) { + chartPanel.textContent = 'Keine Diagrammdaten verfügbar.'; + return; + } + + // Dynamisches Rendern pro Run + filteredData.forEach(run => { + const canvas = document.createElement('canvas'); + canvas.setAttribute('aria-label', `Chart für Run ${run.id}`); + canvas.setAttribute('role', 'img'); + chartPanel.appendChild(canvas); + + const ctx = canvas.getContext('2d'); + if (ctx && run.chartData && Chart) { + // Chart.js Standard-Konfiguration + new Chart(ctx, { + type: 'line', + data: { + labels: run.chartData.labels, + datasets: [{ + label: `${run.type} Run ${run.id}`, + data: run.chartData.values, + borderColor: run.type === 'pinned' ? '#007ACC' : '#FF9900', + fill: false, + tension: 0.1 + }] + }, + options: { + responsive: true, + plugins: { + legend: { + display: true, + labels: { + color: '#333' + } + }, + tooltip: { + mode: 'index', + intersect: false + } + }, + interaction: { + mode: 'nearest', + axis: 'x', + intersect: false + }, + scales: { + x: { + title: { + display: true, + text: 'Parameter Index' + } + }, + y: { + title: { + display: true, + text: 'Wert' + } + } + } + } + }); + } + }); +} + +// Hinweis: Wird von app.initApp() und Filter-Events importiert und genutzt. \ No newline at end of file