From d6b66281b806dd3bda3efc7900f582c145df5bad Mon Sep 17 00:00:00 2001 From: Mika Date: Mon, 19 Jan 2026 12:48:34 +0000 Subject: [PATCH] Add results_visualization/js/app.js --- results_visualization/js/app.js | 133 ++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 results_visualization/js/app.js diff --git a/results_visualization/js/app.js b/results_visualization/js/app.js new file mode 100644 index 0000000..52ddf1c --- /dev/null +++ b/results_visualization/js/app.js @@ -0,0 +1,133 @@ +/* global Chart */ + +/** + * @file js/app.js + * @description Main controller: Initialisiert die Anwendung, lädt Daten, bindet Filter-Events und aktualisiert Diagramme. + */ + +// Selektoren und Zustand +const state = { + rawData: [], + filteredData: [], + charts: {}, + filters: { + pinnedOnly: false + } +}; + +/** + * Lädt Ergebnisse von der API. + * @returns {Promise} Analyseergebnisse + */ +async function loadResults() { + try { + const response = await fetch('/api/results'); + if (!response.ok) throw new Error('API-Fehler: ' + response.status); + const data = await response.json(); + return Array.isArray(data) ? data : []; + } catch (err) { + console.error('Fehler beim Laden der Ergebnisse:', err); + return []; + } +} + +/** + * Rendert die Diagramme mit Chart.js. + * @param {Array} dataset Datenarray + */ +function renderCharts(dataset) { + const ctxStability = document.getElementById('chart-stability'); + const ctxCorrelation = document.getElementById('chart-correlation'); + + const labels = dataset.map(d => d.run_id); + const stabilityData = dataset.map(d => d.step_stability_score); + const correlationData = dataset.map(d => d.correlation_coefficient); + + if (state.charts.stability) state.charts.stability.destroy(); + if (state.charts.correlation) state.charts.correlation.destroy(); + + state.charts.stability = new Chart(ctxStability, { + type: 'bar', + data: { + labels, + datasets: [{ + label: 'Stabilität', + data: stabilityData, + backgroundColor: stabilityData.map(v => v > 0.8 ? '#4caf50' : '#f44336') + }] + }, + options: { + responsive: true, + scales: { + y: { beginAtZero: true, title: { display: true, text: 'Stabilität' } } + }, + plugins: { + tooltip: { callbacks: { label: ctx => `Score: ${ctx.parsed.y}` } } + } + } + }); + + state.charts.correlation = new Chart(ctxCorrelation, { + type: 'line', + data: { + labels, + datasets: [{ + label: 'Korrelation', + data: correlationData, + borderColor: '#2196f3', + fill: false + }] + }, + options: { + responsive: true, + tension: 0.3, + scales: { + y: { beginAtZero: true, title: { display: true, text: 'Korrelation' } } + }, + plugins: { + tooltip: { callbacks: { label: ctx => `Coeff: ${ctx.parsed.y}` } } + } + } + }); +} + +/** + * Filtert Daten basierend auf aktuellen Filtern. + * @param {Array} data Ursprungsdaten + * @returns {Array} Gefilterte Daten + */ +function applyFilters(data) { + if (state.filters.pinnedOnly) { + return data.filter(d => d.is_pinned); + } + return data; +} + +/** + * Aktualisiert Diagramme und Statistiken bei Filteränderungen. + * @param {Object} newFilters Neue Filterwerte + */ +function handleFilterChange(newFilters) { + state.filters = { ...state.filters, ...newFilters }; + state.filteredData = applyFilters(state.rawData); + renderCharts(state.filteredData); +} + +/** + * Initialisiert die Anwendung, bindet Events und lädt Daten. + */ +async function initApp() { + const pinnedCheckbox = document.getElementById('filter-pinned'); + if (pinnedCheckbox) { + pinnedCheckbox.addEventListener('change', e => { + handleFilterChange({ pinnedOnly: e.target.checked }); + }); + } + + const data = await loadResults(); + state.rawData = data; + state.filteredData = applyFilters(data); + renderCharts(state.filteredData); +} + +window.addEventListener('load', initApp); \ No newline at end of file