Migra dal codice salvato in locale al codice condiviso

This commit is contained in:
Giuseppe Raffa
2026-01-06 17:36:58 +01:00
parent 8a88c31c75
commit ff1566d36b
30 changed files with 8985 additions and 0 deletions

View File

@@ -0,0 +1,350 @@
const fs = require('fs');
const path = require('path');
const ARCHIVE_FILE = path.join(__dirname, 'hourly_archive.json');
// Cache dati OpenMeteo condivisi (evita chiamate duplicate)
let sharedWeatherData = {
forecast: null,
waves: null,
units: null, // Unità di misura globali
lastUpdate: null,
updateInterval: 2 * 60 * 1000 // 2 minuti
};
// Archivio dati orari
let hourlyArchive = {
temperature: [],
windSpeed: [],
windDirection: [],
waveHeight: [],
wavePeriod: [],
waveDirection: [],
humidity: [],
pressure: []
};
/**
* Carica l'archivio da file
*/
function loadArchive() {
try {
if (fs.existsSync(ARCHIVE_FILE)) {
const data = fs.readFileSync(ARCHIVE_FILE, 'utf8');
const parsed = JSON.parse(data);
// Valida struttura archivio
if (parsed && typeof parsed === 'object') {
hourlyArchive = {
temperature: Array.isArray(parsed.temperature) ? parsed.temperature : [],
windSpeed: Array.isArray(parsed.windSpeed) ? parsed.windSpeed : [],
windDirection: Array.isArray(parsed.windDirection) ? parsed.windDirection : [],
waveHeight: Array.isArray(parsed.waveHeight) ? parsed.waveHeight : [],
wavePeriod: Array.isArray(parsed.wavePeriod) ? parsed.wavePeriod : [],
waveDirection: Array.isArray(parsed.waveDirection) ? parsed.waveDirection : [],
humidity: Array.isArray(parsed.humidity) ? parsed.humidity : [],
pressure: Array.isArray(parsed.pressure) ? parsed.pressure : []
};
console.log('[GraphsCore] Archivio caricato');
}
}
} catch (error) {
console.error('[GraphsCore] Errore caricamento archivio:', error.message);
// Resetta archivio se corrotto
hourlyArchive = {
temperature: [], windSpeed: [], windDirection: [],
waveHeight: [], wavePeriod: [], waveDirection: [],
humidity: [], pressure: []
};
}
}
/**
* Salva l'archivio su file
*/
function saveArchive() {
try {
fs.writeFileSync(ARCHIVE_FILE, JSON.stringify(hourlyArchive, null, 2));
} catch (error) {
console.error('[GraphsCore] Errore salvataggio archivio:', error.message);
}
}
/**
* Aggiorna i dati meteo condivisi
* @param {object} forecastData - Dati forecast da OpenMeteo
* @param {object} wavesData - Dati onde da OpenMeteo
*/
function updateSharedWeatherData(forecastData, wavesData) {
if (forecastData) {
sharedWeatherData.forecast = forecastData;
}
if (wavesData) {
sharedWeatherData.waves = wavesData;
}
// Aggiorna unità se disponibili
if (forecastData?.units || wavesData?.units) {
sharedWeatherData.units = {
forecast: forecastData?.units || sharedWeatherData.units?.forecast || {},
waves: wavesData?.units || sharedWeatherData.units?.waves || {}
};
}
sharedWeatherData.lastUpdate = Date.now();
}
/**
* Ottiene i dati meteo condivisi
* @returns {object} Dati meteo attuali
*/
function getSharedWeatherData() {
return {
forecast: sharedWeatherData.forecast,
waves: sharedWeatherData.waves,
units: sharedWeatherData.units,
lastUpdate: sharedWeatherData.lastUpdate,
isValid: sharedWeatherData.lastUpdate &&
(Date.now() - sharedWeatherData.lastUpdate) < sharedWeatherData.updateInterval * 2
};
}
/**
* Ottiene le unità di misura globali
*/
function getUnits() {
return sharedWeatherData.units || {
forecast: {
temperature: '°C',
humidity: '%',
pressure: 'hPa',
windSpeed: 'km/h',
windDirection: '°'
},
waves: {
waveHeight: 'm',
wavePeriod: 's',
waveDirection: '°'
}
};
}
/**
* Formatta un valore con la sua unità
*/
function formatValue(value, unitKey, category = 'forecast') {
if (value === null || value === undefined) return 'n/d';
const units = getUnits();
const unit = units[category]?.[unitKey] || '';
return `${value}${unit}`;
}
/**
* Verifica se i dati condivisi sono ancora validi
*/
function isWeatherDataValid() {
if (!sharedWeatherData.lastUpdate) return false;
return (Date.now() - sharedWeatherData.lastUpdate) < sharedWeatherData.updateInterval;
}
/**
* Archivia un punto dati orario
*/
function archiveHourlyData(data) {
if (!data || typeof data !== 'object') {
console.warn('[GraphsCore] archiveHourlyData: dati non validi');
return;
}
const timestamp = new Date().toISOString();
const maxPoints = 168; // 7 giorni di dati orari
const addPoint = (arr, value) => {
if (value === null || value === undefined || Number.isNaN(value)) return;
arr.push({ timestamp, value });
if (arr.length > maxPoints) arr.shift();
};
addPoint(hourlyArchive.temperature, data.temperature);
addPoint(hourlyArchive.windSpeed, data.windSpeed);
addPoint(hourlyArchive.windDirection, data.windDirection);
addPoint(hourlyArchive.waveHeight, data.waveHeight);
addPoint(hourlyArchive.wavePeriod, data.wavePeriod);
addPoint(hourlyArchive.waveDirection, data.waveDirection);
addPoint(hourlyArchive.humidity, data.humidity);
addPoint(hourlyArchive.pressure, data.pressure);
saveArchive();
console.log('[GraphsCore] Dati orari archiviati');
}
/**
* Ottiene i dati per un grafico specifico
* @param {string} parameter - temperatura, vento, onde, etc.
* @param {number} hours - ultimi N ore (default 24)
*/
function getGraphData(parameter, hours = 24) {
const paramMap = {
'temperature': hourlyArchive.temperature,
'windSpeed': hourlyArchive.windSpeed,
'windDirection': hourlyArchive.windDirection,
'waveHeight': hourlyArchive.waveHeight,
'wavePeriod': hourlyArchive.wavePeriod,
'waveDirection': hourlyArchive.waveDirection,
'humidity': hourlyArchive.humidity,
'pressure': hourlyArchive.pressure
};
const data = paramMap[parameter] || [];
const cutoff = Date.now() - (hours * 60 * 60 * 1000);
return data.filter(point => new Date(point.timestamp).getTime() > cutoff);
}
/**
* Genera dati formattati per Chart.js
*/
function formatForChart(parameter, hours = 24) {
const data = getGraphData(parameter, hours);
return {
labels: data.map(p => {
const d = new Date(p.timestamp);
return `${d.getHours()}:${String(d.getMinutes()).padStart(2, '0')}`;
}),
datasets: [{
label: getParameterLabel(parameter),
data: data.map(p => p.value),
borderColor: getParameterColor(parameter),
backgroundColor: getParameterColor(parameter, 0.2),
tension: 0.3,
fill: true
}]
};
}
/**
* Label leggibili per i parametri
*/
function getParameterLabel(param) {
const labels = {
'temperature': 'Temperatura (°C)',
'windSpeed': 'Velocità Vento (km/h)',
'windDirection': 'Direzione Vento (°)',
'waveHeight': 'Altezza Onde (m)',
'wavePeriod': 'Periodo Onde (s)',
'waveDirection': 'Direzione Onde (°)',
'humidity': 'Umidità (%)',
'pressure': 'Pressione (hPa)'
};
return labels[param] || param;
}
/**
* Colori per i grafici
*/
function getParameterColor(param, alpha = 1) {
const colors = {
'temperature': `rgba(255, 99, 132, ${alpha})`,
'windSpeed': `rgba(54, 162, 235, ${alpha})`,
'windDirection': `rgba(75, 192, 192, ${alpha})`,
'waveHeight': `rgba(153, 102, 255, ${alpha})`,
'wavePeriod': `rgba(255, 159, 64, ${alpha})`,
'waveDirection': `rgba(255, 205, 86, ${alpha})`,
'humidity': `rgba(201, 203, 207, ${alpha})`,
'pressure': `rgba(100, 149, 237, ${alpha})`
};
return colors[param] || `rgba(128, 128, 128, ${alpha})`;
}
/**
* Ottiene tutti i dati disponibili per dashboard
*/
function getAllGraphsData(hours = 24) {
return {
temperature: formatForChart('temperature', hours),
windSpeed: formatForChart('windSpeed', hours),
waveHeight: formatForChart('waveHeight', hours),
humidity: formatForChart('humidity', hours)
};
}
/**
* Statistiche sull'archivio
*/
function getArchiveStats() {
return {
temperature: hourlyArchive.temperature.length,
windSpeed: hourlyArchive.windSpeed.length,
waveHeight: hourlyArchive.waveHeight.length,
oldestData: getOldestTimestamp(),
newestData: getNewestTimestamp()
};
}
function getOldestTimestamp() {
const all = [
...hourlyArchive.temperature,
...hourlyArchive.windSpeed,
...hourlyArchive.waveHeight
];
if (all.length === 0) return null;
return all.reduce((oldest, p) =>
new Date(p.timestamp) < new Date(oldest.timestamp) ? p : oldest
).timestamp;
}
function getNewestTimestamp() {
const all = [
...hourlyArchive.temperature,
...hourlyArchive.windSpeed,
...hourlyArchive.waveHeight
];
if (all.length === 0) return null;
return all.reduce((newest, p) =>
new Date(p.timestamp) > new Date(newest.timestamp) ? p : newest
).timestamp;
}
/**
* Pulisce l'archivio
*/
function clearArchive() {
hourlyArchive = {
temperature: [],
windSpeed: [],
windDirection: [],
waveHeight: [],
wavePeriod: [],
waveDirection: [],
humidity: [],
pressure: []
};
saveArchive();
console.log('[GraphsCore] Archivio pulito');
}
// Carica archivio all'avvio
loadArchive();
module.exports = {
// Gestione dati condivisi
updateSharedWeatherData,
getSharedWeatherData,
isWeatherDataValid,
// Unità di misura
getUnits,
formatValue,
// Archivio orario
archiveHourlyData,
getGraphData,
formatForChart,
getAllGraphsData,
getArchiveStats,
clearArchive,
// Utility
getParameterLabel,
getParameterColor
};