Example #1
0
def _capital_query(country, q):
    """ Generate answer to question concerning a country capital. """

    # Get country code
    cc = isocode_for_country_name(country)
    if not cc:
        logging.warning("No CC for country {0}".format(country))
        return False

    # Find capital city, given the country code
    capital = capital_for_cc(cc)
    if not capital:
        return False

    # Use the Icelandic name for the city
    ice_cname = icelandic_city_name(capital["name_ascii"])

    # Look up genitive country name for voice description
    bres = BIN_Db().lookup_genitive(country, cat="no")
    country_gen = bres[0].ordmynd if bres else country

    answer = ice_cname
    response = dict(answer=answer)
    voice = "Höfuðborg {0} er {1}".format(country_gen, answer)

    q.set_answer(response, answer, voice)
    q.set_key("Höfuðborg {0}".format(country_gen))
    q.set_context(dict(subject=ice_cname))

    return True
Example #2
0
def test_geo():
    """ Test geography and location-related functions in geo.py """
    from geo import (
        icelandic_city_name,
        continent_for_country,
        coords_for_country,
        coords_for_street_name,
        country_name_for_isocode,
        isocode_for_country_name,
        icelandic_addr_info,
        lookup_city_info,
        parse_address_string,
        iceprep_for_street,
        iceprep_for_placename,
        iceprep_for_country,
        iceprep_for_cc,
        capitalize_placename,
        distance,
        in_iceland,
        code_for_us_state,
        coords_for_us_state_code,
        location_info,
    )

    assert icelandic_city_name("London") == "Lundúnir"
    assert icelandic_city_name("Rome") == "Róm"

    assert continent_for_country("IS") == "EU"
    assert continent_for_country("no") == "EU"
    assert continent_for_country("MX") == "NA"

    assert coords_for_country("DE") is not None
    assert coords_for_country("it") is not None

    assert coords_for_street_name("Austurstræti") is not None
    assert coords_for_street_name("Háaleitisbraut") is not None

    assert country_name_for_isocode("DE", lang="is") == "Þýskaland"
    assert country_name_for_isocode("DE") == "Þýskaland"

    assert isocode_for_country_name("Danmörk", lang="is") == "DK"
    assert isocode_for_country_name("Danmörk", lang="IS") == "DK"
    assert isocode_for_country_name("Noregur") == "NO"

    addr_info = icelandic_addr_info("Fiskislóð 31")
    assert addr_info and addr_info["stadur_tgf"] == "Reykjavík"

    # Test city info lookup
    city_info = lookup_city_info("Kænugarður")
    assert city_info and len(
        city_info) == 1 and city_info[0]["country"] == "UA"

    city_info = lookup_city_info("Kaupmannahöfn")
    assert city_info and len(
        city_info) == 1 and city_info[0]["country"] == "DK"

    city_info = lookup_city_info("Pjongjang")
    assert city_info and len(
        city_info) == 1 and city_info[0]["country"] == "KP"

    city_info = lookup_city_info("Pyongyang")
    assert city_info and len(
        city_info) == 1 and city_info[0]["country"] == "KP"

    # Test address string parsing
    assert parse_address_string("   Fiskislóð  31") == {
        "street": "Fiskislóð",
        "number": 31,
        "letter": "",
    }
    assert parse_address_string("Öldugata 19c ") == {
        "street": "Öldugata",
        "number": 19,
        "letter": "c",
    }
    assert parse_address_string("    Dúfnahólar   10   ") == {
        "street": "Dúfnahólar",
        "number": 10,
        "letter": "",
    }

    # Test prepositions for street names
    assert iceprep_for_street("Öldugata") == "á"
    assert iceprep_for_street("Fiskislóð") == "á"
    assert iceprep_for_street("Austurstræti") == "í"
    assert iceprep_for_street("Hamrahlíð") == "í"

    # Test prepositions for placenames
    assert iceprep_for_placename("Dalvík") == "á"
    assert iceprep_for_placename("Akureyri") == "á"
    assert iceprep_for_placename("Ísafjörður") == "á"
    assert iceprep_for_placename("Reykjavík") == "í"
    assert iceprep_for_placename("Hafnarfjörður") == "í"
    assert iceprep_for_placename("London") == "í"
    assert iceprep_for_placename("Dyflinni") == "í"

    # Test prepositions for countries
    assert iceprep_for_country("Ítalía") == "á"
    assert iceprep_for_country("Ísland") == "á"
    assert iceprep_for_country("Þýskaland") == "í"
    assert iceprep_for_country("Japan") == "í"
    assert iceprep_for_country("spánn") == "á"

    # Test prepositions for countries, queried by CC
    assert iceprep_for_cc("IS") == "á"
    assert iceprep_for_cc("US") == "í"
    assert iceprep_for_cc("ES") == "á"
    assert iceprep_for_cc("es") == "á"

    # Test placename capitalization
    assert capitalize_placename("ríó de janeiro") == "Ríó de Janeiro"
    assert capitalize_placename("vík í mýrdal") == "Vík í Mýrdal"
    assert capitalize_placename("Vík í mýrdal") == "Vík í Mýrdal"
    assert capitalize_placename("frankfúrt am main") == "Frankfúrt am Main"
    assert capitalize_placename("mið-afríkulýðveldið") == "Mið-Afríkulýðveldið"
    assert capitalize_placename("Norður-kórea") == "Norður-Kórea"
    assert capitalize_placename("norður-Kórea") == "Norður-Kórea"
    assert capitalize_placename(
        "bosnía og hersegóvína") == "Bosnía og Hersegóvína"
    assert capitalize_placename("Norður-Makedónía") == "Norður-Makedónía"

    # Distance
    assert int(distance((64.141439, -21.943944),
                        (65.688131, -18.102528))) == 249
    assert in_iceland((66.462205, -15.968417))
    assert not in_iceland((62.010846, -6.776709))
    assert not in_iceland((62.031342, -18.539553))

    # US States
    assert code_for_us_state("Flórída") == "FL"
    assert code_for_us_state("Norður-Karólína") == "NC"
    assert code_for_us_state("Kalifornía") == "CA"
    assert coords_for_us_state_code("CA") == [36.778261, -119.417932]

    # Generic location info lookup functions
    assert "country" in location_info("Reykjavík", "placename")
    assert "continent" in location_info("Minsk", "placename")
    assert location_info("Japan", "country")["continent"] == "AS"
    assert location_info("Danmörk", "country")["continent"] == "EU"
    assert location_info("Mexíkó", "country")["continent"] == "NA"
    assert location_info("ísafjörður", "placename")["continent"] == "EU"
    assert location_info("Meðalfellsvatn", "placename")["country"] == "IS"
    assert location_info("Georgía", "country")["country"] != "US"
    assert location_info("Virginía", "placename")["country"] == "US"
    assert location_info("Norður-Dakóta", "country")["country"] == "US"
    assert location_info("Kænugarður", "placename")["continent"] == "EU"
    assert location_info("Fiskislóð 31", "address")["country"] == "IS"
Example #3
0
def _process_result(result: Result) -> Dict[str, str]:
    """
    Return formatted description of arrival/departure
    time of flights to or from an Icelandic airport,
    based on info in result dict.
    """
    airport: str  # Icelandic or foreign airport/country
    api_airport: str  # Always an Icelandic airport, as the ISAVIA API only covers them

    departing: bool = result["departure"]
    if departing:
        # Departures (from Keflavík by default)
        api_airport = result.get("from_loc", "keflavík").lower()
        # Wildcard matches any flight (if airport wasn't specified)
        airport = result.get("to_loc", "*").lower()
    else:
        # Arrivals (to Keflavík by default)
        api_airport = result.get("to_loc", "keflavík").lower()
        airport = result.get("from_loc", "*").lower()

    from_date: datetime
    to_date: datetime
    days: int = result.get("day_count", 5)  # Check 5 days into future by default
    from_date = result.get("from_date", datetime.now(timezone.utc))
    to_date = result.get("to_date", datetime.now(timezone.utc) + timedelta(days=days))

    # Normalize airport/city names
    airport = _LOCATION_ABBREV_MAP.get(airport, airport)
    airport = NounPhrase(airport).nominative or airport

    api_airport = _LOCATION_ABBREV_MAP.get(api_airport, api_airport)
    api_airport = NounPhrase(api_airport).nominative or api_airport

    # Translate Icelandic airport to its IATA code
    iata_code: str = _AIRPORT_TO_IATA_MAP.get(api_airport, api_airport)

    # TODO: Currently module only fetches one flight,
    # modifications to the grammar could allow fetching of more flights at once
    flight_count: int = result.get("flight_count", 1)

    flight_data: FlightList
    # Check first if function result in cache, else fetch data from API
    if departing in _FLIGHT_CACHE:
        flight_data = _FLIGHT_CACHE[departing]
    else:
        flight_data = _fetch_flight_data(from_date, to_date, iata_code, departing)

    flight_data = _filter_flight_data(flight_data, airport, api_airport, flight_count)

    answ: Dict[str, str] = dict()
    if len(flight_data) > 0:
        # (Format month names in Icelandic)
        with changedlocale(category="LC_TIME"):
            answ = _format_flight_answer(flight_data)
    else:
        to_airp: str
        from_airp: str
        if departing:
            to_airp, from_airp = airport, api_airport
        else:
            from_airp, to_airp = airport, api_airport

        to_airp = icelandic_city_name(capitalize_placename(to_airp))
        from_airp = icelandic_city_name(capitalize_placename(from_airp))

        from_airp = NounPhrase(from_airp).dative or from_airp
        to_airp = NounPhrase(to_airp).genitive or to_airp

        if from_airp == "*":
            answ["answer"] = f"Ekkert flug fannst til {to_airp} næstu {days} daga."
        elif to_airp == "*":
            answ["answer"] = f"Ekkert flug fannst frá {from_airp} næstu {days} daga."
        else:
            answ["answer"] = (
                f"Ekkert flug fannst "
                f"frá {from_airp} "
                f"til {to_airp} "
                f"næstu {days} daga."
            )
        answ["voice"] = answ["answer"]

    return answ
Example #4
0
def _format_flight_answer(flights: FlightList) -> Dict[str, str]:
    """
    Takes in a list of flights and returns a dict
    containing a formatted answer and text for a voice line.

    Each flight should contain the attributes:
        'No':           Flight number
        'DisplayName':  Name of airport/city
        'api_airport':  Name of Icelandic airport/city
        'flight_time':  Time of departure/arrival
        'Departure':    True if departing from api_airport, else False
        'Status':       Info on flight status (e.g. whether it's cancelled)
    """
    airport: str
    api_airport: str
    flight_dt: Optional[datetime]
    answers: List[str] = []
    voice_lines: List[str] = []

    for flight in flights:
        airport = icelandic_city_name(capitalize_placename(flight.get("DisplayName", "")))
        api_airport = icelandic_city_name(capitalize_placename(flight.get("api_airport", "")))

        flight_dt = flight.get("flight_time")
        if flight_dt is None or airport == "" or api_airport == "":
            continue
        flight_date_str = flight_dt.strftime("%-d. %B")
        flight_time_str = flight_dt.strftime("%H:%M")

        if flight.get("Departure"):
            airport = NounPhrase(airport).genitive or airport
            api_airport = NounPhrase(api_airport).dative or api_airport

            # Catch cancelled flights
            if (
                isinstance(flight.get("Status"), str)
                and "aflýst" in str(flight["Status"]).lower()
            ):
                line = f"Flugi {flight.get('No')} frá {api_airport} til {airport} er aflýst."
            else:
                line = (
                    f"Flug {flight.get('No')} til {airport} "
                    f"flýgur frá {api_airport} {flight_date_str} "
                    f"klukkan {flight_time_str} að staðartíma."
                )
        else:
            airport = NounPhrase(airport).dative or airport
            prep = iceprep_for_placename(api_airport)
            api_airport = NounPhrase(api_airport).dative or api_airport

            if (
                isinstance(flight.get("Status"), str)
                and "aflýst" in str(flight["Status"]).lower()
            ):
                line = f"Flugi {flight.get('No')} frá {airport} til {api_airport} er aflýst."
            else:
                line = (
                    f"Flug {flight.get('No')} frá {airport} "
                    f"lendir {prep} {api_airport} {flight_date_str} "
                    f"klukkan {flight_time_str} að staðartíma."
                )

        voice_line = re.sub(r" \d+\. ", " " + _DAY_INDEX_ACC[flight_dt.day] + " ", line)

        answers.append(line)
        voice_lines.append(voice_line)

    return {
        "answer": "<br/>".join(answers).strip(),
        "voice": _BREAK_SSML.join(voice_lines).strip(),
    }