X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=weather_renderer.py;h=23c5a201e6e44f254c39c112a2d6c59451231ba5;hb=6cd5b068127501d2b48e8ac67b7432bffc5fce53;hp=f10f1ceb7d132f0e92965e8368b60d404f63409b;hpb=6b8d4eeb7153617221f822a243a117f0bcab07bf;p=kiosk.git diff --git a/weather_renderer.py b/weather_renderer.py index f10f1ce..23c5a20 100644 --- a/weather_renderer.py +++ b/weather_renderer.py @@ -10,7 +10,6 @@ import urllib.parse import file_writer import renderer import kiosk_secrets as secrets -import random class weather_renderer(renderer.abstaining_renderer): @@ -20,63 +19,9 @@ class weather_renderer(renderer.abstaining_renderer): super().__init__(name_to_timeout_dict) self.file_prefix = file_prefix - def debug_prefix(self) -> str: - return f"weather({self.file_prefix})" - def periodic_render(self, key: str) -> bool: return self.fetch_weather() - def describe_time(self, index: int) -> str: - if index <= 1: - return "overnight" - elif index <= 3: - return "morning" - elif index <= 5: - return "afternoon" - else: - return "evening" - - def describe_wind(self, mph: float) -> str: - if mph <= 0.3: - return "calm" - elif mph <= 5.0: - return "light" - elif mph < 15.0: - return "breezy" - elif mph <= 25.0: - return "gusty" - else: - return "heavy" - - def describe_magnitude(self, mm: float) -> str: - if mm < 2.0: - return "light" - elif mm < 10.0: - return "moderate" - else: - return "heavy" - - def describe_precip(self, rain: float, snow: float) -> str: - if rain == 0.0 and snow == 0.0: - return "no precipitation" - magnitude = rain + snow - if rain > 0 and snow > 0: - return f"a {self.describe_magnitude(magnitude)} mix of rain and snow" - elif rain > 0: - return f"{self.describe_magnitude(magnitude)} rain" - elif snow > 0: - return f"{self.describe_magnitude(magnitude)} snow" - return "rain" - - def fix_caps(self, s: str) -> str: - r = "" - s = s.lower() - for x in s.split("."): - x = x.strip() - r += x.capitalize() + ". " - r = r.replace(". .", ".") - return r - def pick_icon( self, conditions: List[str], rain: List[float], snow: List[float] ) -> str: @@ -135,89 +80,6 @@ class weather_renderer(renderer.abstaining_renderer): return "partlysunny.gif" return "clear.gif" - def describe_weather( - self, - high: float, - low: float, - wind: List[float], - conditions: List[str], - rain: List[float], - snow: List[float], - ) -> str: - # High temp: 65 - # Low temp: 44 - # -onight------ -morning----- -afternoon-- -evening---- - # 12a-3a 3a-6a 6a-9a 9a-12p 12p-3p 3p-6p 6p-9p 9p-12p - # Wind: [12.1 3.06 3.47 4.12 3.69 3.31 2.73 2.1] - # Conditions: [Clouds Clouds Clouds Clouds Clouds Clouds Clear Clear] - # Rain: [0.4 0.2 0 0 0 0 0 0] - # Snow: [0 0 0 0 0 0 0 0] - high = int(high) - low = int(low) - count = min(len(wind), len(conditions), len(rain), len(snow)) - descr = "" - - lcondition = "" - lwind = "" - lprecip = "" - ltime = "" - for x in range(0, count): - time = self.describe_time(x) - current = "" - chunks = 0 - - txt = conditions[x] - if txt == "Clouds": - txt = "cloudy" - elif txt == "Rain": - txt = "rainy" - - if txt != lcondition: - if txt != "Snow" and txt != "Rain": - current += txt - chunks += 1 - lcondition = txt - - txt = self.describe_wind(wind[x]) - if txt != lwind: - if len(current) > 0: - current += " with " - current += txt + " winds" - lwind = txt - chunks += 1 - - txt = self.describe_precip(rain[x], snow[x]) - if txt != lprecip: - if len(current) > 0: - if chunks > 1: - current += " and " - else: - current += " with " - chunks += 1 - current += txt - lprecip = txt - - if len(current): - if ltime != time: - if random.randint(0, 3) == 0: - if time != "overnight": - descr += current + " in the " + time + ". " - descr += current + " overnight. " - else: - if time != "overnight": - descr += "In the " - descr += time + ", " + current + ". " - else: - current = current.replace("cloudy", "clouds") - descr += current + " developing. " - ltime = time - if ltime == "overnight" or ltime == "morning": - descr += "Conditions continuing the rest of the day. " - descr = descr.replace("with breezy winds", "and breezy") - descr = descr.replace("Clear developing", "Skies clearing") - descr = self.fix_caps(descr) - return descr - def fetch_weather(self) -> bool: if self.file_prefix == "stevens": text_location = "Stevens Pass, WA" @@ -254,15 +116,58 @@ class weather_renderer(renderer.abstaining_renderer): # "dt_txt":"2017-01-30 18:00:00" # }, # {"dt":1485810000,.... - with file_writer.file_writer("weather-%s_3_10800.html" % self.file_prefix) as f: - f.write( - f""" -

Weather at {text_location}:

+ + with file_writer.file_writer(f"weather-{self.file_prefix}_3_10800.html") as f: + f.write(f""" +

Upcoming weather at {text_location}:


+""") + f.write(""" +
- - """ - ) +""") count = parsed_json["cnt"] ts = {} @@ -272,31 +177,32 @@ class weather_renderer(renderer.abstaining_renderer): conditions: Dict[str, List[str]] = {} rain: Dict[str, List[float]] = {} snow: Dict[str, List[float]] = {} + precip: Dict[str, List[float]] = {} + for x in range(0, count): data = parsed_json["list"][x] dt = data["dt_txt"] # 2019-10-07 18:00:00 - date = dt.split(" ")[0] - time = dt.split(" ")[1] + (date, time) = dt.split(' ') wind[date] = [] conditions[date] = [] - highs[date] = -99999 - lows[date] = +99999 + highs[date] = None + lows[date] = None rain[date] = [] snow[date] = [] + precip[date] = [] ts[date] = 0 for x in range(0, count): data = parsed_json["list"][x] dt = data["dt_txt"] # 2019-10-07 18:00:00 - date = dt.split(" ")[0] - time = dt.split(" ")[1] + (date, time) = dt.split(' ') _ = data["dt"] if _ > ts[date]: ts[date] = _ temp = data["main"]["temp"] - if highs[date] < temp: + if highs[date] is None or highs[date] < temp: highs[date] = temp - if temp < lows[date]: + if lows[date] is None or temp < lows[date]: lows[date] = temp wind[date].append(data["wind"]["speed"]) conditions[date].append(data["weather"][0]["main"]) @@ -331,101 +237,129 @@ class weather_renderer(renderer.abstaining_renderer): # }, # u'wind': {u'speed': 6.31, u'deg': 10.09}} - # Next 5 half-days - # for x in xrange(0, 5): - # fcast = parsed_json['forecast']['txt_forecast']['forecastday'][x] - # text = fcast['fcttext'] - # text = re.subn(r' ([0-9]+)F', r' \1°F', text)[0] - # f.write('' % text) - # f.write('

%s

') - # f.close() - # return True - - # f.write("\n") - days_seen = {} + days_seen = set() for date in sorted(highs.keys()): - today = datetime.fromtimestamp(ts[date]) - formatted_date = today.strftime("%a %e %b") + day = datetime.fromtimestamp(ts[date]) + formatted_date = day.strftime("%a %e %b") if formatted_date in days_seen: continue - days_seen[formatted_date] = True - num_days = len(list(days_seen.keys())) - - days_seen = {} - for date in sorted(highs.keys()): - precip = 0.0 - for _ in rain[date]: - precip += _ - for _ in snow[date]: - precip += _ - - today = datetime.fromtimestamp(ts[date]) - formatted_date = today.strftime("%a %e %b") + days_seen.add(formatted_date) + total = len(days_seen) + + first_day = True + days_seen = set() + for n, date in enumerate(sorted(highs.keys())): + if n % 3 == 0: + if n > 0: + f.write("") + f.write('
') + remaining = total - n + if remaining >= 3: + width = "33%" + else: + width = f'{100/remaining}%' + + precip[date] = [] + aggregate_precip = 0.0 + for r, s in zip(rain[date], snow[date]): + aggregate = r + s + aggregate_precip += aggregate + precip[date].append(aggregate) + if first_day: + while len(precip[date]) < 8: + precip[date].insert(0, 0) + first_day = False + + day = datetime.fromtimestamp(ts[date]) + formatted_date = day.strftime("%a %e %b") if formatted_date in days_seen: continue - days_seen[formatted_date] = True + days_seen.add(formatted_date) f.write( - '
\n") - f.write("
\n' % (100 / num_days) + f'
\n' ) - f.write("
\n") # Date - f.write( - " \n" - ) - - # Icon - f.write( - ' \n' - % self.pick_icon(conditions[date], rain[date], snow[date]) - ) - - # Low temp + f.write(f''' + + +''') + + # Conditions icon + icon = self.pick_icon(conditions[date], rain[date], snow[date]) + f.write(f''' + + +''') + + # Low temp -- left color = "#000099" if lows[date] <= 32.5: color = "#009999" - f.write( - ' \n' - % (color, int(lows[date])) - ) - - # Total precip - precip *= 0.0393701 - if precip > 0.025: - f.write( - ' \n' - % precip - ) + f.write(f''' + + +''') + + # Total aggregate_precip in inches + aggregate_precip *= 0.0393701 + if aggregate_precip > 0.025: + f.write(f''' + +''') else: f.write(" \n") - # High temp + # High temp + precip chart color = "#800000" if highs[date] >= 80: color = "#AA0000" - f.write( - ' \n' - % (color, int(highs[date])) - ) - - # Text "description" - f.write( - '\n' - % self.describe_weather( - highs[date], - lows[date], - wind[date], - conditions[date], - rain[date], - snow[date], - ) - ) - f.write("
" - + formatted_date - + "
+
+ {formatted_date} +
+
+
+ +
+
%d°F  
%3.1f"
+ + {int(lows[date])}°F   + + +
+ + {aggregate_precip:3.1f}” + +
+
   %d°F
%s
\n
") + f.write(f''' + + +   {int(highs[date])}°F + + +''') + + # Precip graph + f.write(f''' + + + + + + + + +''') + f.write("") return True -# x = weather_renderer({"Stevens": 1000}, "stevens") -# x.periodic_render("Stevens") +#x = weather_renderer({"Stevens": 1000}, "stevens") +#x.periodic_render("Stevens")