Add results_visualization/js/app.js
This commit is contained in:
parent
c1ae20e8c5
commit
d6b66281b8
1 changed files with 133 additions and 0 deletions
133
results_visualization/js/app.js
Normal file
133
results_visualization/js/app.js
Normal file
|
|
@ -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<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);
|
||||||
Loading…
Reference in a new issue