Beispiel #1
0
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")
Beispiel #2
0
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")
Beispiel #3
0
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"
Beispiel #4
0
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