Aggiorna script backup e bot meteo Telegram.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
3a7b867e83
commit
beb790ed7e
6 files changed
+350
-102
No files matched your search
@@ -18,7 +18,7 @@ from open_meteo_precip import (
|
||||
CASA_LAT,
|
||||
CASA_LON,
|
||||
CASA_TZ,
|
||||
daily_precip_from_hourly,
|
||||
apply_hourly_daily_precip,
|
||||
fetch_icon_italia,
|
||||
hourly_precip_at_index,
|
||||
hourly_precip_series,
|
||||
@@ -560,6 +560,7 @@ def merge_multi_model_forecast(models_data, forecast_days=10):
|
||||
"snowfall": [],
|
||||
"snow_depth": [],
|
||||
"rain": [],
|
||||
"showers": [],
|
||||
"weathercode": [],
|
||||
"windspeed_10m": [],
|
||||
"winddirection_10m": [],
|
||||
@@ -1055,67 +1056,55 @@ def analyze_daily_events(times, codes, probs, precip, winds, temps, dewpoints, s
|
||||
start_ice = i
|
||||
ice_type = current_ice_condition
|
||||
|
||||
# 2. PRECIPITAZIONI
|
||||
# 2. PRECIPITAZIONI — tot_mm è sempre la somma del solo blocco orario (mai il totale giorno)
|
||||
def _precip_type_at(idx):
|
||||
code_val = codes[idx] if idx < len(codes) and codes[idx] is not None else 0
|
||||
t_val = temps[idx] if idx < len(temps) and temps[idx] is not None else None
|
||||
try:
|
||||
code_val = int(code_val) if code_val is not None else 0
|
||||
except (ValueError, TypeError):
|
||||
code_val = 0
|
||||
return get_precip_type(code_val, temp=t_val)
|
||||
|
||||
def _emit_rain(start, end_inclusive, rain_type):
|
||||
if end_inclusive < start:
|
||||
return
|
||||
block_precip = precip[start:end_inclusive + 1]
|
||||
block_precip_clean = [p for p in block_precip if p is not None]
|
||||
tot_mm = sum(float(p) for p in block_precip_clean)
|
||||
if tot_mm <= 0:
|
||||
return
|
||||
hours_str = _format_event_hours(times, start, end_inclusive)
|
||||
avg_intensity = tot_mm / len(block_precip) if block_precip else 0
|
||||
events.append(
|
||||
f"{rain_type} ({get_intensity_label(avg_intensity)}):\n"
|
||||
f" 🕒 {hours_str} | 💧 {tot_mm:.1f}mm"
|
||||
)
|
||||
|
||||
in_rain = False
|
||||
start_idx = 0
|
||||
current_rain_type = ""
|
||||
|
||||
|
||||
for i in range(len(times)):
|
||||
p_val = precip[i] if i < len(precip) and precip[i] is not None else 0
|
||||
is_raining = p_val >= MIN_MM_PER_EVENTO
|
||||
|
||||
is_last = i == len(times) - 1
|
||||
|
||||
if is_raining and not in_rain:
|
||||
in_rain = True
|
||||
start_idx = i
|
||||
code_val = codes[i] if i < len(codes) and codes[i] is not None else 0
|
||||
t_val = temps[i] if i < len(temps) and temps[i] is not None else None
|
||||
try:
|
||||
code_val = int(code_val) if code_val is not None else 0
|
||||
except (ValueError, TypeError):
|
||||
code_val = 0
|
||||
current_rain_type = get_precip_type(code_val, temp=t_val)
|
||||
elif in_rain and is_raining and i < len(codes):
|
||||
code_val = codes[i] if codes[i] is not None else 0
|
||||
t_val = temps[i] if i < len(temps) and temps[i] is not None else None
|
||||
try:
|
||||
code_val = int(code_val) if code_val is not None else 0
|
||||
except (ValueError, TypeError):
|
||||
code_val = 0
|
||||
new_type = get_precip_type(code_val, temp=t_val)
|
||||
current_rain_type = _precip_type_at(i)
|
||||
elif in_rain and is_raining:
|
||||
new_type = _precip_type_at(i)
|
||||
if new_type != current_rain_type:
|
||||
end_inclusive = i - 1
|
||||
block_precip = precip[start_idx:i] if i <= len(precip) else precip[start_idx:]
|
||||
block_precip_clean = [p for p in block_precip if p is not None]
|
||||
tot_mm = sum(block_precip_clean)
|
||||
hours_str = _format_event_hours(times, start_idx, end_inclusive)
|
||||
avg_intensity = tot_mm / len(block_precip) if block_precip else 0
|
||||
|
||||
events.append(
|
||||
f"{current_rain_type} ({get_intensity_label(avg_intensity)}):\n"
|
||||
f" 🕒 {hours_str} | 💧 {tot_mm:.1f}mm"
|
||||
)
|
||||
_emit_rain(start_idx, i - 1, current_rain_type)
|
||||
start_idx = i
|
||||
current_rain_type = new_type
|
||||
elif (not is_raining and in_rain) or (in_rain and i == len(times)-1):
|
||||
|
||||
if in_rain and (not is_raining or is_last):
|
||||
end_inclusive = i if is_raining else i - 1
|
||||
_emit_rain(start_idx, end_inclusive, current_rain_type)
|
||||
in_rain = False
|
||||
if not is_raining:
|
||||
end_inclusive = i - 1
|
||||
end_slice = i
|
||||
else:
|
||||
end_inclusive = i
|
||||
end_slice = i + 1
|
||||
block_precip = precip[start_idx:end_slice] if end_slice <= len(precip) else precip[start_idx:]
|
||||
block_precip_clean = [p for p in block_precip if p is not None]
|
||||
tot_mm = sum(block_precip_clean)
|
||||
|
||||
if tot_mm > 0 and end_inclusive >= start_idx:
|
||||
hours_str = _format_event_hours(times, start_idx, end_inclusive)
|
||||
avg_intensity = tot_mm / len(block_precip) if block_precip else 0
|
||||
|
||||
events.append(
|
||||
f"{current_rain_type} ({get_intensity_label(avg_intensity)}):\n"
|
||||
f" 🕒 {hours_str} | 💧 {tot_mm:.1f}mm"
|
||||
)
|
||||
|
||||
# 3. VENTO
|
||||
if winds:
|
||||
@@ -1249,16 +1238,7 @@ def _apply_unified_precip(hourly: Dict, daily: Dict, casa: bool) -> Tuple[Dict,
|
||||
if icon_d.get("time"):
|
||||
daily = overlay_icon_precip_on_daily(daily, icon_d)
|
||||
hourly["precipitation"] = hourly_precip_series(hourly)
|
||||
totals = daily_precip_from_hourly(hourly)
|
||||
times = daily.get("time") or []
|
||||
psum = list(daily.get("precipitation_sum") or [])
|
||||
while len(psum) < len(times):
|
||||
psum.append(None)
|
||||
for i, t in enumerate(times):
|
||||
d = str(t)[:10]
|
||||
if d in totals:
|
||||
psum[i] = round(totals[d], 2)
|
||||
daily["precipitation_sum"] = psum
|
||||
daily = apply_hourly_daily_precip(daily, hourly)
|
||||
return hourly, daily
|
||||
|
||||
|
||||
@@ -1806,27 +1786,36 @@ def format_weather_context_report(models_data, location_name, country_code, as_j
|
||||
if day_info['precip_sum'] > 0.1:
|
||||
# Caratterizza usando dati daily se disponibili
|
||||
precip_parts = []
|
||||
|
||||
# Neve (solo con aria abbastanza fredda: evita cm spurii in estate)
|
||||
if day_info.get('snowfall_sum', 0) > 0.1 and day_info['t_min'] <= ICE_EVENT_MAX_AIR_TEMP:
|
||||
precip_parts.append(f"❄️ {day_info['snowfall_sum']:.1f}cm")
|
||||
|
||||
# Pioggia
|
||||
if day_info.get('rain_sum', 0) > 0.1:
|
||||
precip_parts.append(f"🌧️ {day_info['rain_sum']:.1f}mm")
|
||||
|
||||
# Temporali (showers)
|
||||
if day_info.get('showers_sum', 0) > 0.1:
|
||||
precip_parts.append(f"⛈️ {day_info['showers_sum']:.1f}mm")
|
||||
|
||||
# Se non abbiamo dati daily dettagliati, usa il tipo generale
|
||||
if not precip_parts:
|
||||
precip_symbol = "❄️" if day_info['precip_type'] == "snow" else "⛈️" if day_info['precip_type'] in ("hail", "thunderstorms") else "🌨️" if day_info['precip_type'] == "mixed" else "🌧️"
|
||||
precip_parts.append(f"{precip_symbol} {day_info['precip_sum']:.1f}mm")
|
||||
elif day_info['precip_sum'] > 0.1 and day_info.get('snowfall_sum', 0) > 0.1 and day_info['t_min'] > ICE_EVENT_MAX_AIR_TEMP:
|
||||
# snowfall spurio a caldo: assicurati che l'accumulo pioggia totale sia visibile
|
||||
if not any("🌧️" in p or "⛈️" in p for p in precip_parts):
|
||||
precip_parts.append(f"🌧️ {day_info['precip_sum']:.1f}mm")
|
||||
snow_sum = day_info.get("snowfall_sum", 0) or 0
|
||||
rain_sum = day_info.get("rain_sum", 0) or 0
|
||||
showers_sum = day_info.get("showers_sum", 0) or 0
|
||||
precip_sum = day_info.get("precip_sum", 0) or 0
|
||||
|
||||
if snow_sum > 0.1 and day_info["t_min"] <= ICE_EVENT_MAX_AIR_TEMP:
|
||||
precip_parts.append(f"❄️ {snow_sum:.1f}cm")
|
||||
|
||||
overlapping = (
|
||||
rain_sum > 0.1 and showers_sum > 0.1 and (
|
||||
abs(rain_sum - precip_sum) < 0.25
|
||||
or abs(showers_sum - precip_sum) < 0.25
|
||||
or (rain_sum + showers_sum) > precip_sum + 0.3
|
||||
)
|
||||
)
|
||||
if overlapping or (rain_sum <= 0.1 and showers_sum <= 0.1):
|
||||
if precip_sum > 0.1:
|
||||
precip_symbol = (
|
||||
"❄️" if day_info["precip_type"] == "snow"
|
||||
else "⛈️" if day_info["precip_type"] in ("hail", "thunderstorms")
|
||||
else "🌨️" if day_info["precip_type"] == "mixed"
|
||||
else "🌧️"
|
||||
)
|
||||
if not (day_info["precip_type"] == "snow" and snow_sum > 0.1 and day_info["t_min"] <= ICE_EVENT_MAX_AIR_TEMP):
|
||||
precip_parts.append(f"{precip_symbol} {precip_sum:.1f}mm")
|
||||
else:
|
||||
if rain_sum > 0.1:
|
||||
precip_parts.append(f"🌧️ {rain_sum:.1f}mm")
|
||||
if showers_sum > 0.1:
|
||||
precip_parts.append(f"⛈️ {showers_sum:.1f}mm")
|
||||
|
||||
line += f" | {' + '.join(precip_parts)}"
|
||||
|
||||
|
||||
Reference in new issue
Block a user