You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
5.4 KiB

from datetime import datetime
import pytz
from typing import List, Dict
from .models import LocationInfo, CurrentConditions, WeatherForecast, WeatherAlert
class Narrator:
STRINGS = {
'en': {
'wind_fmt': ", with winds from the {dir} at {kph} kilometers per hour, or {mph} miles per hour",
'current_intro': "Current conditions for {city}, {region}.",
'temp_fmt': "The temperature is {temp_c} degrees celsius, {temp_f} degrees fahrenheit.",
'conditions_fmt': "Conditions are {desc}{wind}.",
'forecast_intro': "Here is the forecast. ",
'high_fmt': " with a high of {c} celsius, {f} fahrenheit",
'low_fmt': " with a low of {c} celsius, {f} fahrenheit",
'period_fmt': "{period}: {summary}{temp}. ",
'no_alerts': "There are no active weather alerts.",
'alerts_intro': "There are {count} active weather alerts. ",
'alert_item': "A {title} is in effect until {expires}. ",
'greeting': "Good day. The time is {time}.",
'intro_city': "This is the automated weather report for {city}.",
'alert_advise': "Please be advised: ",
'time_fmt': "%I %M %p"
},
'fr': {
'wind_fmt': ", avec des vents du {dir} à {kph} kilomètres à l'heure",
'current_intro': "Conditions actuelles pour {city}, {region}.",
'temp_fmt': "La température est de {temp_c} degrés Celsius, {temp_f} degrés Fahrenheit.",
'conditions_fmt': "Les conditions sont {desc}{wind}.",
'forecast_intro': "Voici les prévisions. ",
'high_fmt': " avec un maximum de {c} Celsius, {f} Fahrenheit",
'low_fmt': " avec un minimum de {c} Celsius, {f} Fahrenheit",
'period_fmt': "{period}: {summary}{temp}. ",
'no_alerts': "Il n'y a aucune alerte météo en vigueur.",
'alerts_intro': "Il y a {count} alertes météo en vigueur. ",
'alert_item': "Un {title} est en vigueur jusqu'à {expires}. ",
'greeting': "Bonjour. Il est {time}.",
'intro_city': "Ceci est le bulletin météo automatisé pour {city}.",
'alert_advise': "Veuillez noter : ",
'time_fmt': "%H heures %M"
}
}
def __init__(self, config: Dict):
self.lang = config.get('language', 'en')
self.s = self.STRINGS.get(self.lang, self.STRINGS['en'])
def _c_to_f(self, temp_c: float) -> int:
return int((temp_c * 9/5) + 32)
def _t(self, key, **kwargs):
tpl = self.s.get(key, "")
return tpl.format(**kwargs)
def announce_conditions(self, loc: LocationInfo, current: CurrentConditions) -> str:
wind = ""
if current.wind_speed and current.wind_speed > 5:
mph = int(current.wind_speed * 0.621371)
wind = self._t('wind_fmt', dir=current.wind_direction, kph=int(current.wind_speed), mph=mph)
intro = self._t('current_intro', city=loc.city, region=loc.region)
temp_str = self._t('temp_fmt', temp_c=int(current.temperature), temp_f=self._c_to_f(current.temperature))
cond_str = self._t('conditions_fmt', desc=current.description, wind=wind)
return f"{intro} {temp_str} {cond_str}"
def announce_forecast(self, forecasts: List[WeatherForecast]) -> str:
if not forecasts:
return ""
text = self._t('forecast_intro')
for f in forecasts[:3]:
temp = ""
if f.high_temp is not None:
temp = self._t('high_fmt', c=int(f.high_temp), f=self._c_to_f(f.high_temp))
elif f.low_temp is not None:
temp = self._t('low_fmt', c=int(f.low_temp), f=self._c_to_f(f.low_temp))
text += self._t('period_fmt', period=f.period_name, summary=f.summary, temp=temp)
return text
def announce_alerts(self, alerts: List[WeatherAlert]) -> str:
if not alerts:
return self._t('no_alerts')
text = self._t('alerts_intro', count=len(alerts))
for a in alerts:
# Need locale specific time format?
# Alerts usually have specific expiration.
expires_str = a.expires.strftime(self.s.get('time_fmt', "%I %M %p"))
text += self._t('alert_item', title=a.title, expires=expires_str)
return text
def build_full_report(self, loc: LocationInfo, current: CurrentConditions, forecast: List[WeatherForecast], alerts: List[WeatherAlert], sun_info: str = "") -> str:
parts = []
try:
tz = pytz.timezone(loc.timezone)
now = datetime.now(tz)
except Exception:
now = datetime.now()
time_fmt = self.s.get('time_fmt', "%I %M %p")
now_str = now.strftime(time_fmt)
if self.lang == 'en' and now_str.startswith("0"):
now_str = now_str[1:]
parts.append(self._t('greeting', time=now_str))
parts.append(self._t('intro_city', city=loc.city))
if alerts:
parts.append(self._t('alert_advise') + self.announce_alerts(alerts))
parts.append(self.announce_conditions(loc, current))
parts.append(self.announce_forecast(forecast))
if sun_info:
parts.append(sun_info)
return " ".join(parts)

Powered by TurnKey Linux.