diff --git a/frontend/index.html b/frontend/index.html index 3f22867..c0a0bd0 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -117,6 +117,19 @@ + +
+
+
+
Rosa de los vientos
+

Frecuencia por dirección — mes seleccionado

+
+ +
+
+
+
+ @@ -127,6 +140,7 @@ - + + diff --git a/frontend/js/estadisticas.js b/frontend/js/estadisticas.js index ababd79..839cebc 100644 --- a/frontend/js/estadisticas.js +++ b/frontend/js/estadisticas.js @@ -50,6 +50,7 @@ async function loadStats(options = {}) { renderMonthStats(data); renderTrend(data); + renderWindRose(data); } catch (err) { console.error(err); @@ -253,6 +254,92 @@ function renderTrend(data) { container.innerHTML = html; } +// ==================== +// Rosa de los vientos +// ==================== +let windRoseChart = null; + +function renderWindRose(data) { + const sectors = [ + { label: "N", min: 337.5, max: 360 }, + { label: "N", min: 0, max: 22.5 }, + { label: "NE", min: 22.5, max: 67.5 }, + { label: "E", min: 67.5, max: 112.5 }, + { label: "SE", min: 112.5, max: 157.5 }, + { label: "S", min: 157.5, max: 202.5 }, + { label: "SO", min: 202.5, max: 247.5 }, + { label: "O", min: 247.5, max: 292.5 }, + { label: "NO", min: 292.5, max: 337.5 } + ]; + + // Filtrar por mes seleccionado y agrupar por día para no contar duplicados horarios + const byDay = {}; + data.forEach(d => { + const date = new Date(d.dia); + if (date.getMonth() === selectedMonth) { + if (!byDay[d.dia]) byDay[d.dia] = []; + byDay[d.dia].push(parseFloat(d.viento_direccion)); + } + }); + + // Por cada día usar la dirección media del día + const direcciones = Object.values(byDay).map(dirs => { + return dirs.reduce((a, b) => a + b, 0) / dirs.length; + }); + + // Contar frecuencia por sector (N agrupa los dos rangos) + const counts = { N: 0, NE: 0, E: 0, SE: 0, S: 0, SO: 0, O: 0, NO: 0 }; + direcciones.forEach(deg => { + for (const s of sectors) { + if (deg >= s.min && deg < s.max) { + counts[s.label]++; + break; + } + } + }); + + const labels = ["N", "NE", "E", "SE", "S", "SO", "O", "NO"]; + const values = labels.map(l => counts[l]); + const accent = "rgba(164, 215, 244, 0.75)"; + const border = "rgba(164, 215, 244, 1)"; + + const canvas = $("wind-rose"); + if (!canvas) return; + + if (windRoseChart) windRoseChart.destroy(); + + windRoseChart = new Chart(canvas, { + type: "polarArea", + data: { + labels, + datasets: [{ + data: values, + backgroundColor: labels.map(() => accent), + borderColor: labels.map(() => border), + borderWidth: 1 + }] + }, + options: { + responsive: true, + plugins: { + legend: { display: false }, + tooltip: { + callbacks: { + label: ctx => ` ${ctx.label}: ${ctx.raw} días` + } + } + }, + scales: { + r: { + ticks: { color: "#888", font: { size: 10 }, backdropColor: "transparent" }, + grid: { color: "rgba(255,255,255,0.1)" }, + pointLabels: { color: "#a4d7f4", font: { size: 12 } } + } + } + } + }); +} + // ==================== // Cargar mes actual según selectedMonth // ====================