// main.js Chart.defaults.color = '#a0aabf'; Chart.defaults.font.family = "'Outfit', sans-serif"; let rawData = []; let voltageChart = null; let currentChart = null; const colors = { app1: 'rgba(0, 240, 255, 1)', // Neon Blue app2: 'rgba(189, 0, 255, 1)', // Purple app3: 'rgba(0, 255, 102, 1)', // Neon Green alert: 'rgba(255, 0, 85, 0.8)' // Red for alert }; document.addEventListener('DOMContentLoaded', () => { loadCSVData(); document.getElementById('apply-btn').addEventListener('click', updateDashboard); document.getElementById('csv-upload').addEventListener('change', handleFileUpload); }); function loadCSVData() { Papa.parse('donnees_appareils (1).csv', { download: true, header: true, dynamicTyping: true, skipEmptyLines: true, complete: function(results) { console.log("CSV Parsed:", results.data); rawData = results.data; // Vérifier si le CSV est valide (s'il contient bien la colonne 'Date') // PapaParse peut parfois lire une page d'erreur 404 comme un CSV if (rawData.length === 0 || !rawData[0] || !rawData[0].hasOwnProperty('Date')) { console.warn("Le fichier CSV est introuvable ou invalide. Affichage de l'upload manuel."); document.getElementById('upload-group').style.display = 'block'; return; } if (rawData.length > 0) { // Initialiser les dates min et max const dates = rawData.map(d => d.Date).filter(d => d); if (dates.length > 0) { const minDate = dates[0]; const maxDate = dates[dates.length - 1]; document.getElementById('start-date').value = minDate; document.getElementById('end-date').value = maxDate; document.getElementById('start-date').min = minDate; document.getElementById('start-date').max = maxDate; document.getElementById('end-date').min = minDate; document.getElementById('end-date').max = maxDate; } } initializeCharts(); updateDashboard(); }, error: function(err) { console.error("Erreur CSV:", err); document.getElementById('upload-group').style.display = 'block'; console.log("Affichage du champ de chargement manuel activé."); } }); } function handleFileUpload(event) { const file = event.target.files[0]; if (!file) return; Papa.parse(file, { header: true, dynamicTyping: true, skipEmptyLines: true, complete: function(results) { console.log("Uploaded CSV Parsed:", results.data); rawData = results.data; if (rawData.length > 0) { const dates = rawData.map(d => d.Date).filter(d => d); if (dates.length > 0) { const minDate = dates[0]; const maxDate = dates[dates.length - 1]; document.getElementById('start-date').value = minDate; document.getElementById('end-date').value = maxDate; document.getElementById('start-date').min = minDate; document.getElementById('start-date').max = maxDate; document.getElementById('end-date').min = minDate; document.getElementById('end-date').max = maxDate; } } if (!voltageChart || !currentChart) { initializeCharts(); } updateDashboard(); document.getElementById('upload-label').innerText = "Fichier chargé avec succès !"; document.getElementById('upload-label').style.color = "#00ff66"; }, error: function(err) { console.error("Erreur lors du parse du fichier uploadé:", err); alert("Erreur lors de la lecture du fichier uploadé."); } }); } function initializeCharts() { const ctxVoltage = document.getElementById('voltageChart').getContext('2d'); const ctxCurrent = document.getElementById('currentChart').getContext('2d'); const commonOptions = { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top', labels: { color: '#fff', usePointStyle: true, boxWidth: 8 } }, tooltip: { mode: 'index', intersect: false, backgroundColor: 'rgba(20, 25, 40, 0.9)', titleColor: '#fff', bodyColor: '#a0aabf', borderColor: 'rgba(255,255,255,0.1)', borderWidth: 1 }, annotation: { annotations: {} } }, scales: { x: { grid: { color: 'rgba(255, 255, 255, 0.05)' }, title: { display: true, text: 'Date / Heure' } }, y: { grid: { color: 'rgba(255, 255, 255, 0.05)' } } }, elements: { line: { tension: 0.4, borderWidth: 2 }, point: { radius: 0, hitRadius: 10, hoverRadius: 6 } }, interaction: { mode: 'nearest', axis: 'x', intersect: false } }; voltageChart = new Chart(ctxVoltage, { type: 'line', data: { labels: [], datasets: [] }, options: { ...commonOptions, scales: { ...commonOptions.scales, y: { ...commonOptions.scales.y, title: { display: true, text: 'Tension (V)' } } } } }); currentChart = new Chart(ctxCurrent, { type: 'line', data: { labels: [], datasets: [] }, options: { ...commonOptions, scales: { ...commonOptions.scales, y: { ...commonOptions.scales.y, title: { display: true, text: 'Intensité (A)' } } } } }); } function updateDashboard() { if (!rawData || rawData.length === 0) return; const startDateStr = document.getElementById('start-date').value; const endDateStr = document.getElementById('end-date').value; const selectedAppareil = document.querySelector('input[name="appareil"]:checked').value; const threshVol = parseFloat(document.getElementById('threshold-voltage').value); const threshCur = parseFloat(document.getElementById('threshold-current').value); // Filtrer par date let filteredData = rawData; if (startDateStr && endDateStr) { filteredData = rawData.filter(d => { if (!d.Date) return false; // On peut comparer directement les strings YYYY-MM-DD return d.Date >= startDateStr && d.Date <= endDateStr; }); } const labels = filteredData.map(d => `${d.Date} ${d.Heure}`); // Calcul des sommes et préparation des datasets let sumVoltage = 0; let sumCurrent = 0; let voltDatasets = []; let currDatasets = []; // Fonction d'aide pour ajouter un dataset et cumuler les sommes const processAppareil = (appNum, color) => { const keyVol = `Tension_Appareil_${appNum}`; const keyCur = `Intensite_Appareil_${appNum}`; const volData = filteredData.map(d => { const val = parseFloat(d[keyVol]) || 0; sumVoltage += val; return val; }); const curData = filteredData.map(d => { const val = parseFloat(d[keyCur]) || 0; sumCurrent += val; return val; }); voltDatasets.push(createDataset(`Tension App ${appNum}`, volData, color)); currDatasets.push(createDataset(`Intensité App ${appNum}`, curData, color)); }; if (selectedAppareil === '1' || selectedAppareil === 'all') processAppareil(1, colors.app1); if (selectedAppareil === '2' || selectedAppareil === 'all') processAppareil(2, colors.app2); if (selectedAppareil === '3' || selectedAppareil === 'all') processAppareil(3, colors.app3); // Mise à jour de l'UI des sommes document.getElementById('sum-voltage').innerText = sumVoltage.toLocaleString('fr-FR', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' V'; document.getElementById('sum-current').innerText = sumCurrent.toLocaleString('fr-FR', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' A'; // Mise à jour des graphiques voltageChart.data.labels = labels; voltageChart.data.datasets = voltDatasets; setAlertAnnotation(voltageChart, threshVol); voltageChart.update(); currentChart.data.labels = labels; currentChart.data.datasets = currDatasets; setAlertAnnotation(currentChart, threshCur); currentChart.update(); } function createDataset(label, data, color) { return { label: label, data: data, borderColor: color, backgroundColor: color.replace('1)', '0.1)'), fill: true, pointBackgroundColor: color, pointBorderColor: '#fff', }; } function setAlertAnnotation(chartInstance, thresholdValue) { if (!isNaN(thresholdValue) && thresholdValue > 0) { chartInstance.options.plugins.annotation.annotations = { line1: { type: 'line', yMin: thresholdValue, yMax: thresholdValue, borderColor: colors.alert, borderWidth: 2, borderDash: [5, 5], label: { display: true, content: 'SEUIL ALERTE', position: 'end', backgroundColor: colors.alert, color: '#fff', font: { size: 10, weight: 'bold' } } } }; } else { chartInstance.options.plugins.annotation.annotations = {}; } }