Пример #1
0
def street_desc(street_nom: str, street_num: int, locality_nom: str) -> str:
    """ Generate description of being on a particular (Icelandic) street with
        correct preposition and case + locality e.g. 'á Fiskislóð 31 í Reykjavík'. """
    street_dat = None
    locality_dat = None

    # Start by looking up address in staðfangaskrá to get
    # the dative case of street name and locality.
    # This works better than BÍN lookup since not all street
    # names are present in BÍN.
    addrinfo = iceaddr_lookup(street_nom, placename=locality_nom, limit=1)
    if len(addrinfo):
        street_dat = addrinfo[0]["heiti_tgf"]
        if locality_nom and locality_nom == addrinfo[0]["stadur_nf"]:
            locality_dat = addrinfo[0]["stadur_tgf"]

    # OK, if staðfangaskrá can't help us, try to use BÍN to
    # get dative version of name. Some names given by Google's
    # API are generic terms such as "Göngustígur" and the like.
    if not street_dat:
        street_dat = nom2dat(street_nom)
    if not locality_dat:
        locality_dat = nom2dat(locality_nom)

    # Create street descr. ("á Fiskislóð 31")
    street_comp = iceprep_for_street(street_nom) + " " + street_dat
    if street_num:
        street_comp += " " + str(street_num)

    # Append locality if available ("í Reykjavík")
    if locality_dat:
        ldesc = iceprep_for_placename(locality_nom) + " " + locality_dat
        street_comp += " " + ldesc

    return street_comp
Пример #2
0
def _answer_phonenum4name_query(q: Query, result: Result) -> AnswerTuple:
    """ Answer query of the form "hvað er síminn hjá [íslenskt mannsnafn]?" """
    res = query_ja_api(result.qkey)

    nþgf = NounPhrase(result.qkey).dative or result.qkey

    # Verify that we have a sane response with at least 1 result
    if not res or not res.get("people") or not res["people"].get("items"):
        return gen_answer("Ekki tókst að fletta upp {0}.".format(nþgf))

    # Check if we have a single canonical match from API
    allp = res["people"]["items"]
    single = len(allp) == 1
    first = allp[0]
    fname = first["name"]
    if not single:
        # Many found with that name, generate smart message asking for disambiguation
        name_components = result.qkey.split()
        one_name_only = len(name_components) == 1
        with GreynirBin.get_db() as bdb:
            fn = name_components[0].title()
            gender = bdb.lookup_name_gender(fn)
        msg = (
            "Það fundust {0} með það nafn. Prófaðu að tilgreina {1}heimilisfang"
            .format(
                "margar" if gender == "kvk" else "margir",
                "fullt nafn og " if one_name_only else "",
            ))
        # Try to generate example, e.g. "Jón Jónssón á Smáragötu"
        for i in allp:
            try:
                street_nf = i["address_nominative"].split()[0]
                street_þgf = i["address"].split()[0]
                msg = msg + " t.d. {0} {1} {2}".format(
                    fname, iceprep_for_street(street_nf), street_þgf)
                break
            except (KeyError, ValueError) as e:
                logging.warning("Exception: " + str(e))
                continue
        return gen_answer(msg)

    # Scan API call result, try to find the best phone nuber to provide
    phone_number = _best_number(first)
    if not phone_number:
        return gen_answer("Ég finn ekki símanúmerið hjá {0}".format(nþgf))

    # Sanitize number and generate answer
    phone_number = phone_number.replace("-", "").replace(" ", "")
    answ = phone_number
    fn = NounPhrase(fname).dative or fname
    voice = "Síminn hjá {0} er {1}".format(fn, " ".join(list(phone_number)))

    q.set_context(dict(phone_number=phone_number, name=fname))
    q.set_source(_JA_SOURCE)

    return dict(answer=answ), answ, voice
Пример #3
0
def _whatsmyaddr_handler(q: Query, ql: str) -> bool:
    """ Handle queries of the form "Hvar á ég heima?" """
    if ql not in _WHATS_MY_ADDR:
        return False
    answ = None
    ad = q.client_data("address")
    if not ad:
        answ = _DUNNO_ADDRESS
    else:
        addr = cast(Dict[str, str], ad)
        street = addr["street"]
        prep = iceprep_for_street(street)
        answ = "Þú átt heima {0} {1}".format(prep, _addr2str(addr, case="þgf"))
    q.set_answer(*gen_answer(answ))
    return True
Пример #4
0
def answ_address(placename: str, loc: LatLonTuple, qtype: str) -> AnswerTuple:
    """ Generate answer to a question concerning the address of a place. """
    # Look up placename in places API
    res = query_places_api(placename,
                           userloc=loc,
                           fields="formatted_address,name,geometry")

    if (not res or res["status"] != "OK" or "candidates" not in res
            or not res["candidates"]):
        return gen_answer(_PLACES_API_ERRMSG)

    # Use top result in Iceland
    place = _top_candidate(res["candidates"])
    if not place:
        return gen_answer(_NOT_IN_ICELAND_ERRMSG)

    # Remove superfluous "Ísland" in addr string
    addr = re.sub(r", Ísland$", "", place["formatted_address"])
    # Get street name without number to get preposition
    street_name = addr.split()[0].rstrip(",")
    maybe_postcode = re.search(r"^\d\d\d", street_name) is not None
    prep = "í" if maybe_postcode else iceprep_for_street(street_name)
    # Split addr into street name w. number, and remainder
    street_addr = addr.split(",")[0]
    remaining = re.sub(r"^{0}".format(street_addr), "", addr)
    # Get street name in dative case
    addr_þgf = NounPhrase(street_addr).dative or street_addr
    # Assemble final address
    final_addr = "{0}{1}".format(addr_þgf, remaining)

    # Create answer
    answer = final_addr
    voice = "{0} er {1} {2}".format(placename, prep,
                                    numbers_to_neutral(final_addr))
    response = dict(answer=answer)

    return response, answer, voice
Пример #5
0
def answ_openhours(placename: str, loc: LatLonTuple,
                   qtype: str) -> AnswerTuple:
    """ Generate answer to a question concerning the opening hours of a place. """
    # Look up placename in places API
    res = query_places_api(
        placename,
        userloc=loc,
        fields="opening_hours,place_id,formatted_address,geometry",
    )
    if (res is None or res["status"] != "OK" or "candidates" not in res
            or not res["candidates"]):
        return gen_answer(_PLACES_API_ERRMSG)

    # Use top result
    place = _top_candidate(res["candidates"])
    if place is None:
        return gen_answer(_NOT_IN_ICELAND_ERRMSG)

    if "opening_hours" not in place:
        return gen_answer("Ekki tókst að sækja opnunartíma fyrir " +
                          icequote(placename))

    place_id = place["place_id"]
    is_open = place["opening_hours"]["open_now"]
    # needs_disambig = len(res["candidates"]) > 1
    fmt_addr = place["formatted_address"]

    # Look up place ID in Place Details API to get more information
    res = query_place_details(place_id, fields="opening_hours,name")
    if not res or res.get("status") != "OK" or "result" not in res:
        return gen_answer(_PLACES_API_ERRMSG)

    now = datetime.utcnow()
    wday = now.weekday()
    answer = voice = ""

    try:
        name = res["result"]["name"]
        name_gender = NounPhrase(name).gender or "hk"

        # Generate placename w. street, e.g. "Forréttabarinn á Nýlendugötu"
        street = fmt_addr.split()[0].rstrip(",")
        street_þgf = NounPhrase(street).dative or street

        name = "{0} {1} {2}".format(name, iceprep_for_street(street),
                                    street_þgf)

        # Get correct "open" adjective for place name
        open_adj_map = {"kk": "opinn", "kvk": "opin", "hk": "opið"}
        open_adj = open_adj_map.get(name_gender) or "opið"

        # Get opening hours for current weekday
        # TODO: Handle when place is closed (no entry in periods)
        periods = res["result"]["opening_hours"]["periods"]
        if len(periods) == 1 or wday >= len(periods):
            # Open 24 hours a day
            today_desc = p_desc = "{0} er {1} allan sólarhringinn".format(
                name, open_adj)
        else:
            # Get period
            p = periods[wday]
            opens = p["open"]["time"]
            closes = p["close"]["time"]

            # Format correctly, e.g. "12:00 - 19:00"
            openstr = opens[:2] + ":" + opens[2:]
            closestr = closes[:2] + ":" + opens[2:]
            p_desc = "{0} - {1}".format(openstr, closestr)
            p_voice = p_desc.replace("-", "til")

            today_desc = "Í dag er {0} {1} frá {2}".format(
                name, open_adj, p_voice)
    except Exception as e:
        logging.warning(
            "Exception generating answer for opening hours: {0}".format(e))
        return gen_answer(_PLACES_API_ERRMSG)

    # Generate answer
    if qtype == "OpeningHours":
        answer = p_desc
        voice = today_desc
    # Is X open? Is X closed?
    elif qtype == "IsOpen" or qtype == "IsClosed":
        yes_no = ("Já" if ((is_open and qtype == "IsOpen") or
                           (not is_open and qtype == "IsClosed")) else "Nei")
        answer = "{0}. {1}.".format(yes_no, today_desc)
        voice = answer

    response = dict(answer=answer)

    return response, answer, voice
Пример #6
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"