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 sentence(state: QueryStateDict, result: Result) -> None: """ Called when sentence processing is complete """ q: Query = state["query"] if "qtype" in result and result.qtype == "Unit": # Successfully matched a query type # If no number is mentioned in the query # ('Hvað eru margir metrar í kílómetra?') # we use 1.0 val_from = result.get("number", 1.0) # Convert between units, getting also the base SI unit and quantity valid, val, si_unit, si_quantity = _convert( val_from, result.unit_from, result.unit_to ) if not valid: answer = voice_answer = "Það er ekki hægt að umbreyta {0} í {1}.".format( to_dative(result.unit_from), to_accusative(result.unit_to) ) response = dict(answer=answer) else: answer = iceformat_float(val) if (0.0 < val < 1.0e-3) or (val > 0.0 and answer == "0"): answer = "næstum núll " + result.unit_to_nf val = 0.0 else: answer += " " + result.unit_to_nf verb = "eru" if int(val_from) % 10 == 1 and int(val_from) % 100 != 11: # 'Einn lítri er...', 'Tuttugu og einn lítri er...', # but on the other hand 'Ellefu lítrar eru...' verb = "er" elif "hálf" in result.desc: # Hack to reply 'Hálfur kílómetri er 500 metrar' verb = "er" unit_to = result.unit_to response = dict(answer=answer) voice_answer = "{0} {1} {2}.".format(result.desc, verb, answer).capitalize() # Store the resulting quantity in the query context q.set_context( { "quantity": { "unit": unit_to, "value": val, "si_unit": si_unit, "si_value": si_quantity, } } ) q.set_key(result.unit_to) q.set_answer(response, answer, voice_answer) q.set_qtype(_UNIT_QTYPE) q.lowercase_beautified_query() return q.set_error("E_QUERY_NOT_UNDERSTOOD")
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"
def calc_arithmetic(query: Query, result): """ Calculate the answer to an arithmetic query """ operator = result.operator nums = result.numbers desc = result.desc if "error_context_reference" in result: # Used 'það' or 'því' without context return gen_answer("Ég veit ekki til hvers þú vísar.") # Ensure that we have the right number of # number args for the operation in question assert _OP_NUM_ARGS[operator] == len(nums) # Global namespace for eval # Block access to all builtins eval_globals: Dict[str, Any] = {"__builtins__": None} # Square root calculation if operator == "sqrt": if len(str(nums[0])) > 100: return gen_answer("Þessi tala er of há.") # Allow sqrt function in eval namespace eval_globals["sqrt"] = math.sqrt s = "sqrt({0})".format(nums[0]) # Pow elif operator == "pow": # Cap max pow if nums[1] > 50: return gen_answer("Þetta er of hátt veldi.") # Allow pow function in eval namespace eval_globals["pow"] = pow s = "pow({0},{1})".format(nums[0], nums[1]) # Percent elif operator == "percent": s = "({0} * {1}) / 100.0".format(nums[0], nums[1]) # Fraction elif operator == "fraction": s = "{0} * {1}".format(nums[0], nums[1]) # Add VAT to sum elif operator == "with_vat": s = "{0} * {1}".format(nums[0], _VAT_MULT) # Subtract VAT from sum elif operator == "without_vat": s = "{0} / {1}".format(nums[0], _VAT_MULT) # Addition, subtraction, multiplication, division elif operator in _STD_OPERATORS: math_op = _STD_OPERATORS[operator] # Check for division by zero if math_op == "/" and nums[1] == 0: return gen_answer("Það er ekki hægt að deila með núlli.") s = "{0} {1} {2}".format(nums[0], math_op, nums[1]) else: logging.warning("Unknown operator: {0}".format(operator)) return None # Set arithmetic expression as query key result.qkey = s # Run eval on expression res = eval(s, eval_globals, {}) if isinstance(res, float): # Convert result to Icelandic decimal format answer = iceformat_float(res) else: answer = str(res) response = dict(answer=answer, result=res) voice_answer = "{0} er {1}".format(desc, answer) return response, answer, voice_answer