/* 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);