def howlong_desc_answ(target): """ Generate answer to a query about length of period to a given date. """ now = datetime.utcnow() days = date_diff(now, target, unit="days") # Diff. strings for singular vs. plural plural = is_plural(days) verb = "eru" if plural else "er" days_desc = "dagar" if plural else "dagur" # Format date fmt = "%-d. %B" if now.year == target.year else "%-d. %B %Y" tfmt = target.strftime(fmt) # Date asked about is current date if days == 0: return gen_answer("Það er {0} í dag.".format(tfmt)) elif days < 0: # It's in the past days = abs(days) passed = "liðinn" if sing else "liðnir" voice = "Það {0} {1} {2} {3} frá {4}.".format(verb, days, days_desc, passed, tfmt) answer = "{0} {1}".format(days, days_desc) else: # It's in the future voice = "Það {0} {1} {2} þar til {3} gengur í garð.".format( verb, days, days_desc, tfmt) answer = "{0} {1}".format(days, days_desc) response = dict(answer=answer) return (response, answer, voice)
def sentence(state: QueryStateDict, result: Result) -> None: """ Called when sentence processing is complete """ q: Query = state["query"] if "qtype" in result and "op" in result: # Successfully matched a query type val = None target_currency = "ISK" suffix = "" verb = "er" if result.op == "index": # target_currency = "GVT" val = _query_exchange_rate("GVT", "") elif result.op == "exchange": # 'Hvert er gengi evru gagnvart dollara?' target_currency = result.currencies[0] val = _query_exchange_rate(result.currencies[0], result.currencies[1]) elif result.op == "general": # 'Hvert er gengi dollarans?' val = _query_exchange_rate(result.currencies[0], "ISK") if val is None: val = 1.0 suffix = "krónur" if is_plural(iceformat_float(val)) else "króna" elif result.op == "convert": # 'Hvað eru 100 evrur margar krónur?' suffix = result.currency # 'krónur' verb = "eru" target_currency = result.currencies[1] val = _query_exchange_rate(result.currencies[0], result.currencies[1]) val = val * result.amount if val else None if target_currency == "ISK" and val is not None: # For ISK, round to whole numbers val = round(val, 0) else: raise Exception("Unknown operator: {0}".format(result.op)) if val: answer = iceformat_float(val) response = dict(answer=answer) voice_answer = "{0} {3} {1}{2}.".format( result.desc, answer, (" " + suffix) if suffix else "", verb ).capitalize() # Clean up voice answer voice_answer = voice_answer.replace("slot í", "slotí") voice_answer = voice_answer.replace(" dollars ", " Bandaríkjadals ") q.set_answer(response, answer, voice_answer) q.set_key(target_currency) # Store the amount in the query context q.set_context({"amount": {"currency": target_currency, "number": val}}) q.set_qtype(_CURRENCY_QTYPE) return q.set_error("E_QUERY_NOT_UNDERSTOOD")
def howlong_answ(q, result): """ Generate answer to a query about number of days since/until a given date. """ now = datetime.utcnow() target = result["target"] q.set_key("HowLongUntilDate" if "until" in result else "HowLongSinceDate") # Check if it's today if target.date() == now.date(): return q.set_answer( *gen_answer("Það er {0} í dag.".format(target.strftime("%-d. %B"))) ) # Check if it's tomorrow # TODO: Maybe return num hours until tomorrow? if target.date() == now.date() + timedelta(days=1): return q.set_answer( *gen_answer("Það er {0} á morgun.".format(target.strftime("%-d. %B"))) ) # Returns num days rounded down, so we increment by one. days = _date_diff(now, target, unit="days") + 1 # Diff. strings for singular vs. plural plural = is_plural(days) verb = "eru" if plural else "er" days_desc = "dagar" if plural else "dagur" # Format date fmt = "%-d. %B" if now.year == target.year else "%-d. %B %Y" tfmt = target.strftime(fmt) # Date asked about is in the past if days < 0: days = abs(days) passed = "liðnir" if plural else "liðinn" voice = "Það {0} {1} {2} {3} frá {4}.".format( verb, days, days_desc, passed, tfmt ) # Convert e.g. '25.' to 'tuttugasta og fimmta' voice = re.sub(r" \d+\. ", " " + _DAY_INDEX_DAT[target.day] + " ", voice) answer = "{0} {1}".format(days, days_desc) # It's in the future else: voice = "Það {0} {1} {2} þar til {3} gengur í garð.".format( verb, days, days_desc, tfmt ) # Convert e.g. '25.' to 'tuttugasti og fimmti' voice = re.sub(r" \d+\. ", " " + _DAY_INDEX_NOM[target.day] + " ", voice) answer = "{0} {1}".format(days, days_desc) response = dict(answer=answer) q.set_answer(response, answer, voice)
def _gen_num_queries_answer(q): """ Answer questions concerning the number of queries handled. """ with SessionContext(read_only=True) as session: qr = (session.query( Query.id).filter(Query.timestamp >= datetime.utcnow() - timedelta(days=_QUERIES_PERIOD)).count()) fs = "fyrirspurnum" if is_plural(qr) else "fyrirspurn" answer = "Á síðustu {0} dögum hef ég svarað {1} {2}.".format( _QUERIES_PERIOD, qr or "engum", fs) voice = answer response = dict(answer=answer) q.set_key("NumQueries") q.set_answer(response, answer, voice) q.set_qtype(_STATS_QTYPE) return True
def _gen_num_people_answer(q) -> bool: """ Answer questions about person database. """ with SessionContext(read_only=True) as session: qr = session.query(Person.name).distinct().count() pl = is_plural(qr) verb = "eru" if pl else "er" indiv = "einstaklingar" if pl else "einstaklingur" answer = "Í gagnagrunni mínum {0} {1} {2}.".format( verb, qr or "engir", indiv) voice = answer response = dict(answer=answer) q.set_expires(datetime.utcnow() + timedelta(hours=1)) q.set_answer(response, answer, voice) q.set_key("NumPeople") q.set_qtype(_STATS_QTYPE) return True
def get_currweather_answer(query, result): """ Handle queries concerning current weather conditions """ res = _curr_observations(query, result) if not res: return gen_answer(_API_ERRMSG) try: temp = int(round(float(res["T"]))) # Round to nearest whole number desc = res["W"].lower() windsp = float(res["F"]) except: logging.warning("Exception parsing weather API result: {0}".format(e)) return gen_answer(_API_ERRMSG) wind_desc = _wind_descr(windsp) wind_ms_str = str(windsp).rstrip("0").rstrip(".") temp_type = "hiti" if temp >= 0 else "frost" mdesc = ", " + desc + "," if desc else "" locdesc = result.get("subject") or "Úti" # Meters per second string for voice. Say nothing if "logn". voice_ms = ", {0} {1} á sekúndu".format( wind_ms_str, "metrar" if is_plural(wind_ms_str) else "metri") if wind_ms_str != "0" else "" # Format voice string voice = "{0} er {1} stiga {2}{3} og {4}{5}".format( locdesc.capitalize(), abs(temp), temp_type, mdesc, wind_desc, voice_ms, ) # Text answer answer = "{0}°{1} og {2} ({3} m/s)".format(temp, mdesc, wind_desc, wind_ms_str) response = dict(answer=answer) return response, answer, voice
def test_query_utility_functions(): """ Tests for various utility functions used by query modules. """ from queries import ( natlang_seq, nom2dat, numbers_to_neutral, is_plural, sing_or_plur, country_desc, cap_first, time_period_desc, distance_desc, krona_desc, strip_trailing_zeros, iceformat_float, icequote, timezone4loc, # parse_num, ) assert natlang_seq(["Jón", "Gunna"]) == "Jón og Gunna" assert natlang_seq(["Jón", "Gunna", "Siggi"]) == "Jón, Gunna og Siggi" assert ( natlang_seq(["Jón", "Gunna", "Siggi"], oxford_comma=True) == "Jón, Gunna, og Siggi" ) assert nom2dat("hestur") == "hesti" assert nom2dat("Hvolsvöllur") == "Hvolsvelli" # assert parse_num("11") == 11 # assert parse_num("17,33") == 17.33 assert numbers_to_neutral("Öldugötu 4") == "Öldugötu fjögur" assert numbers_to_neutral("Fiskislóð 31") == "Fiskislóð þrjátíu og eitt" assert is_plural(22) assert is_plural(11) assert is_plural("76,3") assert is_plural(27.6) assert is_plural("19,11") assert not is_plural("276,1") assert not is_plural(22.1) assert not is_plural(22.41) assert sing_or_plur(21, "maður", "menn") == "21 maður" assert sing_or_plur(11, "köttur", "kettir") == "11 kettir" assert sing_or_plur(2.11, "króna", "krónur") == "2,11 krónur" assert sing_or_plur(172, "einstaklingur", "einstaklingar") == "172 einstaklingar" assert sing_or_plur(72.1, "gráða", "gráður") == "72,1 gráða" assert country_desc("DE") == "í Þýskalandi" assert country_desc("es") == "á Spáni" assert country_desc("IS") == "á Íslandi" assert country_desc("us") == "í Bandaríkjunum" assert cap_first("yolo") == "Yolo" assert cap_first("YOLO") == "YOLO" assert cap_first("Yolo") == "Yolo" assert time_period_desc(3751) == "1 klukkustund og 3 mínútur" assert ( time_period_desc(3751, omit_seconds=False) == "1 klukkustund, 2 mínútur og 31 sekúnda" ) assert time_period_desc(601) == "10 mínútur" assert time_period_desc(610, omit_seconds=False) == "10 mínútur og 10 sekúndur" assert time_period_desc(61, omit_seconds=False) == "1 mínúta og 1 sekúnda" assert ( time_period_desc(121, omit_seconds=False, case="þgf") == "2 mínútum og 1 sekúndu" ) assert distance_desc(1.1) == "1,1 kílómetri" assert distance_desc(1.2) == "1,2 kílómetrar" assert distance_desc(0.7) == "700 metrar" assert distance_desc(0.021) == "20 metrar" assert distance_desc(41, case="þf") == "41 kílómetra" assert distance_desc(0.215, case="þgf") == "220 metrum" assert krona_desc(361) == "361 króna" assert krona_desc(28) == "28 krónur" assert krona_desc(4264.2) == "4.264,2 krónur" assert krona_desc(2443681.1) == "2.443.681,1 króna" assert strip_trailing_zeros("17,0") == "17" assert strip_trailing_zeros("219.117,0000") == "219.117" assert strip_trailing_zeros("170") == "170" assert strip_trailing_zeros("170,0") == "170" assert iceformat_float(666.0) == "666" assert iceformat_float(666, strip_zeros=False) == "666,00" assert iceformat_float(217.296) == "217,3" assert iceformat_float(2528963.9) == "2.528.963,9" assert iceformat_float(123.12341, decimal_places=4) == "123,1234" assert iceformat_float(123.1000, strip_zeros=True) == "123,1" assert iceformat_float(123.0, decimal_places=4, strip_zeros=False) == "123,0000" assert icequote("sæll") == "„sæll“" assert icequote(" Góðan daginn ") == "„Góðan daginn“" assert timezone4loc((64.157202, -21.948536)) == "Atlantic/Reykjavik" assert timezone4loc((40.093368, 57.000067)) == "Asia/Ashgabat"