Ahora
+Fecha: --
+Temperatura: --
+Humedad: --
+Lluvia: --
+Viento: --
+Amanecer: --
+Anochecer: --
+diff --git a/eltiempo/bullet-journal.html b/eltiempo/bullet-journal.html new file mode 100644 index 0000000..069f5b5 --- /dev/null +++ b/eltiempo/bullet-journal.html @@ -0,0 +1,54 @@ + + +
+ + +Fecha: --
+Temperatura: --
+Humedad: --
+Lluvia: --
+Viento: --
+Amanecer: --
+Anochecer: --
+Días registrados: --
+Máxima absoluta: --
+Mínima absoluta: --
+Lluvia total: --
+Humedad media: --
+Cargando tendencia…
+Amanecer: --:--
+Anochecer: --:--
+Duración del día: --:--
+Tiempo hasta anochecer: --:--:--
+☀️
+Fase lunar actual: Calculando...
+🌑
+ ++ + + --°C +
+ +Condición: --
+Humedad: --%
+Viento: -- km/h
+ Ver estadísticas ++ Rosario: ${dayData.rosario ? '✔' : '☐'} | Pasos: ${dayData.caminar || 0} + | Vitaminas: ${dayData.vitaminas ? '✔' : '☐'} | Agua: ${dayData.agua || 0}ml +
+ ++ ${year} → + Máx ${maxAvg}°C · + Mín ${minAvg}°C · + Lluvia ${rainTotal} mm +
+ `; + }); +} + +/* ---------- INIT ---------- */ + +document.addEventListener("DOMContentLoaded", () => { + $("year").textContent = new Date().getFullYear(); + loadStats(); +}); + diff --git a/eltiempo/js/estadisticas20260131.js b/eltiempo/js/estadisticas20260131.js new file mode 100644 index 0000000..459c772 --- /dev/null +++ b/eltiempo/js/estadisticas20260131.js @@ -0,0 +1,148 @@ +const API_URL = "http://aplicacionesdevanguardia.es/eltiempo/apis/api-weather-reverse.php?ciudad=madrid"; + +/* ---------- UTILIDADES ---------- */ + +function $(id) { + return document.getElementById(id); +} + +function monthName(monthIndex) { + return new Date(2026, monthIndex, 1) + .toLocaleDateString("es-ES", { month: "long" }); +} + +/* ---------- CARGA PRINCIPAL ---------- */ + +async function loadStats() { + try { + const res = await fetch(API_URL); + const data = await res.json(); + + if (!data || !data.length) throw "Sin datos"; + + renderLastDay(data[0]); + renderMonthStats(data); + renderTrend(data); + + $("stats-location").textContent = "Madrid (datos históricos)"; + } catch (e) { + $("stats-location").textContent = "Error cargando estadísticas"; + console.error(e); + } +} + +/* ---------- ÚLTIMO DÍA ---------- */ + +function renderLastDay(day) { + + $("last-date").textContent = day.dia; + $("last-temp").textContent = `${day.temp_min}°C / ${day.temp_max}°C`; + $("last-humidity").textContent = `${Math.round(day.humedad)} %`; + $("last-rain").textContent = `${day.lluvia} mm`; + $("last-wind").textContent = `${Math.round(day.viento_velocidad)} km/h`; + $("last-sunrise").textContent = day.amanecer; + $("last-sunset").textContent = day.anochecer; + +} + +/* ---------- RESUMEN DEL MES ---------- */ + +function renderMonthStats(data) { + + const now = new Date(); + const month = now.getMonth(); + const year = now.getFullYear(); + + + const monthData = data.filter(d => { + const date = new Date(d.dia); + return date.getMonth() === month && date.getFullYear() === year; + }); + + if (!monthData.length) return; + + const maxTemps = monthData.map(d => d.temp_max); + const minTemps = monthData.map(d => d.temp_min); + + const lluvia = monthData.reduce( + (sum, d) => sum + parseFloat(d.lluvia), 0 + ); + + const humedad = ( + monthData.reduce((sum, d) => sum + parseFloat(d.humedad), 0) + / monthData.length + ).toFixed(1); + + $("month-days").textContent = monthData.length; + $("month-max").textContent = Math.max(...maxTemps) + "°C"; + $("month-min").textContent = Math.min(...minTemps) + "°C"; + $("month-rain").textContent = lluvia.toFixed(1) + " mm"; + $("month-humidity").textContent = humedad + " %"; + + +} + +/* ---------- TENDENCIA HISTÓRICA ---------- */ + +function renderTrend(data) { + + const now = new Date(); + const month = now.getMonth(); + + const byYear = {}; + + data.forEach(d => { + const date = new Date(d.dia); + + if (date.getMonth() === month) { + const year = date.getFullYear(); + + if (!byYear[year]) { + byYear[year] = { max: [], min: [], rain: [] }; + } + + byYear[year].max.push(d.temp_max); + byYear[year].min.push(d.temp_min); + byYear[year].rain.push(parseFloat(d.lluvia)); + } + }); + + const container = $("trend-container"); + container.innerHTML = ""; + + Object.keys(byYear) + .sort() + .forEach(year => { + + const maxAvg = ( + byYear[year].max.reduce((a,b)=>a+b,0) / + byYear[year].max.length + ).toFixed(1); + + const minAvg = ( + byYear[year].min.reduce((a,b)=>a+b,0) / + byYear[year].min.length + ).toFixed(1); + + const rainTotal = ( + byYear[year].rain.reduce((a,b)=>a+b,0) + ).toFixed(1); + + container.innerHTML += ` ++ ${year} → + Máx ${maxAvg}°C · + Mín ${minAvg}°C · + Lluvia ${rainTotal} mm +
+ `; + }); +} + + +/* ---------- INIT ---------- */ + +document.addEventListener("DOMContentLoaded", () => { + $("year").textContent = new Date().getFullYear(); + loadStats(); +}); diff --git a/eltiempo/servidor/api-weather-reverse.php b/eltiempo/servidor/api-weather-reverse.php new file mode 100755 index 0000000..8ab4795 --- /dev/null +++ b/eltiempo/servidor/api-weather-reverse.php @@ -0,0 +1,87 @@ + "Parámetro 'ciudad' es requerido."]); + exit(); // Stop script execution +} + +// Optional: Further sanitize/validate the city name if needed (e.g., alphanumeric only) +// if (!preg_match('/^[a-zA-Z\s]+$/', $ciudad)) { +// http_response_code(400); +// echo json_encode(["error" => "El nombre de la ciudad contiene caracteres inválidos."]); +// exit(); +// } + +// --- 3. Database Connection --- +$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); + +if ($conn->connect_error) { + http_response_code(500); // Internal Server Error + echo json_encode(["error" => "Error de conexión a la base de datos: " . $conn->connect_error]); + exit(); +} + +// --- 4. Prepare and Execute Query --- +$stmt = $conn->prepare(" + SELECT DATE(fecha) AS dia, + MIN(fecha) AS primera_fecha_del_dia, + MIN(amanecer) AS amanecer, + MAX(anochecer) AS anochecer, + MAX(temp_max) AS temp_max, + MIN(temp_min) AS temp_min, + AVG(humedad) AS humedad, + AVG(lluvia) AS lluvia, + AVG(nubes) AS nubes, + AVG(viento_velocidad) AS viento_velocidad, + AVG(viento_direccion) AS viento_direccion + FROM weather + WHERE DATE(fecha) >= '2024-10-01' + AND ciudad LIKE CONCAT('%', ?, '%') + GROUP BY DATE(fecha) + ORDER BY DATE(fecha) DESC +"); + +if (!$stmt) { + http_response_code(500); // Internal Server Error + echo json_encode(["error" => "Error al preparar la consulta: " . $conn->error]); + $conn->close(); + exit(); +} + +$stmt->bind_param("s", $ciudad); +$stmt->execute(); +$result = $stmt->get_result(); + +$datos = []; +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + $datos[] = $row; + } + http_response_code(200); // OK + echo json_encode($datos); +} else { + // It's usually fine to return 200 OK with an empty array or a specific message + // if no data is found, rather than a 404, unless it signifies a resource that + // *should* exist but doesn't. For a query, 200 OK is typical. + http_response_code(200); // OK + echo json_encode(["message" => "No hay datos para la ciudad especificada"]); +} + +// --- 5. Close Resources --- +$stmt->close(); +$conn->close(); +?> diff --git a/info.php b/info.php new file mode 100644 index 0000000..d50a07a --- /dev/null +++ b/info.php @@ -0,0 +1,3 @@ +