diff --git a/app.py b/app.py index f061f46..7220aac 100644 --- a/app.py +++ b/app.py @@ -341,12 +341,22 @@ def pick_daily_icon(hours): return "☀️" def feels_like(temp_c, wind_kmh, cloud_pct): + """Apparent temperature. + + * Below 10 °C with wind > 4.8 km/h: Windchill (JAG/TI formula) + * Above 27 °C: Heat index (Rothfusz, assumed RH 60 %) + * Otherwise: actual temp ± sunshine/wind adjustments + - Wind cools by up to ~3 °C even in the mild range + - Sunshine (low clouds, no wind) warms by up to +4 °C + """ if temp_c is None: return None + # ── Cold range: wind chill ──────────────────────────────────────── if temp_c <= 10 and wind_kmh is not None and wind_kmh > 4.8: v = wind_kmh wc = 13.12 + 0.6215*temp_c - 11.37*(v**0.16) + 0.3965*temp_c*(v**0.16) return round(wc, 1) + # ── Hot range: heat index ───────────────────────────────────────── if temp_c >= 27: rh = 60 hi = (-8.78469475556 + 1.61139411*temp_c + 2.33854883889*rh @@ -354,7 +364,19 @@ def feels_like(temp_c, wind_kmh, cloud_pct): - 0.016424828*rh**2 + 0.002211732*temp_c**2*rh + 0.00072546*temp_c*rh**2 - 0.000003582*temp_c**2*rh**2) return round(hi, 1) - return temp_c + # ── Mild range: sunshine bonus + light wind cooling ─────────────── + adjusted = float(temp_c) + # Sunshine bonus: clear sky (cloud_pct < 30) adds up to +4 °C + if cloud_pct is not None and cloud_pct < 30: + sunshine_bonus = (30 - cloud_pct) / 30 * 4.0 + adjusted += sunshine_bonus + # Moderate wind cooling: >10 km/h removes up to 3 °C + if wind_kmh is not None and wind_kmh > 10: + wind_penalty = _clamp((wind_kmh - 10) / 40 * 3.0, 0, 3.0) + adjusted -= wind_penalty + result = round(adjusted, 1) + # Only return a value if it meaningfully differs from actual temp + return result if abs(result - temp_c) >= 0.5 else temp_c def get_sun_times(lat, lon, date=None): try: @@ -647,7 +669,7 @@ def wetter(): lat, lon, display_name, state_hint, location_names = geocode_location(ort) if lat is None: return render_template("index.html", error=f'Ort "{ort}" konnte nicht gefunden werden.') - forecast, mosmix_station = get_mosmix_forecast(lat, lon, hours=72) + forecast, mosmix_station = get_mosmix_forecast(lat, lon, hours=168) if not forecast: return render_template("index.html", error="Keine Wetterdaten verfügbar. Bitte später erneut versuchen.") station_name = mosmix_station.get("name", ort) @@ -702,7 +724,7 @@ def wetter(): "icon": pick_daily_icon(d["hours"]), }) chart_labels, chart_temps, chart_feels, chart_precip, chart_rain_prob = [], [], [], [], [] - for h in forecast[:48]: + for h in forecast[:72]: dt = h["datetime"] label = dt.strftime("%d.%m %H:%M") if hasattr(dt,"strftime") else str(dt)[5:16] chart_labels.append(label) diff --git a/templates/weather.html b/templates/weather.html index 085ae9d..125fa2d 100644 --- a/templates/weather.html +++ b/templates/weather.html @@ -197,7 +197,7 @@

Temperatur, Gefühlt & Niederschlag

- 48 Stunden + 72 Stunden