run_set_analysis_n40/results_visualization/js/app.js

133 lines
No EOL
3.4 KiB
JavaScript

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