diff --git a/resources/addresses/en.yaml b/resources/addresses/en.yaml index 94cc99df..81b2d067 100644 --- a/resources/addresses/en.yaml +++ b/resources/addresses/en.yaml @@ -719,8 +719,8 @@ directions: affix: r direction: right whitespace_probability: 0.05 - numeric_probability: 0.2 - numeric_affix_probability: 0.8 + numeric_probability: 0.05 + numeric_affix_probability: 0.95 left: &left canonical: left abbreviated: l @@ -732,8 +732,8 @@ directions: affix: l direction: right whitespace_probability: 0.05 - numeric_probability: 0.2 - numeric_affix_probability: 0.8 + numeric_probability: 0.05 + numeric_affix_probability: 0.95 rear: &rear canonical: rear abbreviated: r @@ -745,8 +745,8 @@ directions: affix: r direction: right whitespace_probability: 0.05 - numeric_probability: 0.2 - numeric_affix_probability: 0.8 + numeric_probability: 0.05 + numeric_affix_probability: 0.95 front: &front canonical: front abbreviated: frnt @@ -758,8 +758,8 @@ directions: affix: f direction: right whitespace_probability: 0.05 - numeric_probability: 0.2 - numeric_affix_probability: 0.8 + numeric_probability: 0.05 + numeric_affix_probability: 0.95 alternatives: - alternative: *right probability: 0.45 @@ -770,6 +770,22 @@ directions: - alternative: *rear probability: 0.05 + anteroposterior: + alternatives: + - alternative: *front + probability: 0.5 + - alternative: *rear + probability: 0.5 + + lateral: + alternatives: + - alternative: *left + probability: 0.5 + - alternative: *right + probability: 0.5 + + + cardinal_directions: east: &east canonical: east @@ -1184,10 +1200,19 @@ units: # Separate random probability for adding directions like 2L, 2R, etc. add_direction: true add_direction_probability: 0.1 - # Add directions only for plain numbers + + # Add directions for plain numbers add_direction_numeric: true + # Add direction only e.g. Unit Left add_direction_standalone: true + # Separate random probability for adding quadrant units like 2RF 2RR 2LF 2LR + add_quadrant: true + add_quadrant_probability: 0.001 + add_quadrant_first_direction: lateral + + add_quadrant_numeric: true + # If there are 10 floors, create unit numbers like #301 or #1032 use_floor_probability: 0.35 @@ -1232,17 +1257,6 @@ units: lot_plus_parcel_probability: 0.02 parcel_plus_lot_probability: 0.02 - directional: - modifier: - direction: right # e.g. 1 - numeric_probability: 0.1 - numeric_affix_probability: 0.9 - alternatives: - - alternative: *right - - alternative: *left - - alternative: *rear - - alternative: *front - standalone: sample: false default: *penthouse diff --git a/resources/addresses/es.yaml b/resources/addresses/es.yaml index c45f50a8..9535ba41 100644 --- a/resources/addresses/es.yaml +++ b/resources/addresses/es.yaml @@ -442,8 +442,8 @@ directions: affix: d direction: right whitespace_probability: 0.1 - numeric_probability: 0.7 - numeric_affix_probability: 0.3 + numeric_probability: 0.4 + numeric_affix_probability: 0.6 left: &izquierda canonical: izquierda abbreviated: izq @@ -457,8 +457,8 @@ directions: affix: i direction: right whitespace_probability: 0.1 - numeric_probability: 0.7 - numeric_affix_probability: 0.3 + numeric_probability: 0.4 + numeric_affix_probability: 0.6 rear: &trasera canonical: trasera abbreviated: tras @@ -487,6 +487,20 @@ directions: - alternative: *frente probability: 0.05 + anteroposterior: + alternatives: + - alternative: *frente + probability: 0.5 + - alternative: *trasera + probability: 0.5 + + lateral: + alternatives: + - alternative: *derecha + probability: 0.5 + - alternative: *izquierda + probability: 0.5 + cardinal_directions: east: &este canonical: este diff --git a/scripts/geodata/addresses/directions.py b/scripts/geodata/addresses/directions.py index bf24b41d..50a64be8 100644 --- a/scripts/geodata/addresses/directions.py +++ b/scripts/geodata/addresses/directions.py @@ -8,6 +8,14 @@ class RelativeDirection(NumericPhrase): dictionaries = ['unit_directions'] +class AnteroposteriorDirection(RelativeDirection): + key = 'directions.anteroposterior' + + +class LateralDirection(RelativeDirection): + key = 'directions.lateral' + + class CardinalDirection(NumericPhrase): key = 'cardinal_directions' dictionaries = ['cardinal_directions'] diff --git a/scripts/geodata/addresses/numbering.py b/scripts/geodata/addresses/numbering.py index 6aba95fb..120ce1a1 100644 --- a/scripts/geodata/addresses/numbering.py +++ b/scripts/geodata/addresses/numbering.py @@ -41,8 +41,11 @@ latin_alphabet = [chr(i) for i in range(ord('A'), ord('Z') + 1)] class NumericPhrase(object): key = None + NUMERIC = 'numeric' + NUMERIC_AFFIX = 'numeric_affix' + @classmethod - def phrase(cls, number, language, country=None): + def pick_phrase_and_type(cls, number, language, country=None): values, probs = address_config.alternative_probabilities(cls.key, language, dictionaries=cls.dictionaries, country=country) if not values: return safe_decode(number) if number is not None else None @@ -52,7 +55,7 @@ class NumericPhrase(object): values = [] probs = [] - for num_type in ('numeric', 'numeric_affix'): + for num_type in (cls.NUMERIC, cls.NUMERIC_AFFIX): key = '{}_probability'.format(num_type) prob = phrase_props.get(key, None) if prob is not None: @@ -62,19 +65,16 @@ class NumericPhrase(object): probs = cdf(probs) if len(values) < 2: - num_type = 'numeric' + num_type = cls.NUMERIC else: num_type = weighted_choice(values, probs) - props = phrase_props[num_type] + return num_type, phrase, phrase_props[num_type] - if num_type == 'numeric': - # Numeric phrase the default is with whitespace e.g. "No 1" - whitespace_default = True - elif num_type == 'numeric_affix': + @classmethod + def combine_with_number(cls, number, phrase, num_type, props, whitespace_default=False): + if num_type == cls.NUMERIC_AFFIX: phrase = props['affix'] - # Numeric affix default is no whitespace e.g. "#1" - whitespace_default = False direction = props['direction'] whitespace = props.get('whitespace', whitespace_default) @@ -96,6 +96,12 @@ class NumericPhrase(object): else: return safe_decode(number) + @classmethod + def phrase(cls, number, language, country=None): + num_type, phrase, props = cls.pick_phrase_and_type(number, language, country=country) + whitespace_default = num_type == cls.NUMERIC + return cls.combine_with_number(number, phrase, num_type, props, whitespace_default=whitespace_default) + class Number(NumericPhrase): key = 'numbers' diff --git a/scripts/geodata/addresses/units.py b/scripts/geodata/addresses/units.py index c5af2fed..2c760350 100644 --- a/scripts/geodata/addresses/units.py +++ b/scripts/geodata/addresses/units.py @@ -2,7 +2,7 @@ import random import six from geodata.addresses.config import address_config -from geodata.addresses.directions import RelativeDirection +from geodata.addresses.directions import RelativeDirection, LateralDirection, AnteroposteriorDirection from geodata.addresses.floors import Floor from geodata.addresses.numbering import NumberedComponent, sample_alphabet, latin_alphabet from geodata.configs.utils import nested_get @@ -101,14 +101,63 @@ class Unit(NumberedComponent): if add_direction_standalone: return RelativeDirection.phrase(None, language, country=country) + @classmethod + def add_quadrant(cls, key, unit, language, country=None): + add_quadrant_probability = address_config.get_property('{}.add_quadrant_probability'.format(key), + language, country=country, default=0.0) + if not random.random() < add_quadrant_probability: + return unit + add_quadrant_numeric = address_config.get_property('{}.add_quadrant_numeric'.format(key), + language, country=country) + try: + unit = int(unit) + integer_unit = True + except (ValueError, TypeError): + integer_unit = False + + first_direction = address_config.get_property('{}.add_quadrant_first_direction'.format(key), + language, country=country) + + if first_direction == 'lateral': + ordering = (LateralDirection, AnteroposteriorDirection) + elif first_direction == 'anteroposterior': + ordering = (AnteroposteriorDirection, LateralDirection) + else: + return unit + + if not integer_unit: + add_quadrant_standalone = address_config.get_property('{}.add_quadrant_standalone'.format(key), + language, country=country) + if add_quadrant_standalone: + unit = None + else: + return None + + last_num_type = None + for i, c in enumerate(ordering): + num_type, phrase, props = c.pick_phrase_and_type(unit, language, country=country) + whitespace_default = num_type == c.NUMERIC or last_num_type == c.NUMERIC + unit = c.combine_with_number(unit, phrase, num_type, props, whitespace_default=whitespace_default) + last_num_type = num_type + + return unit + @classmethod def phrase(cls, unit, language, country=None, zone=None): if unit is not None: key = 'units.alphanumeric' if zone is None else 'units.zones.{}'.format(zone) + direction_unit = None add_direction = address_config.get_property('{}.add_direction'.format(key), language, country=country) if add_direction: - unit = cls.add_direction(key, unit, language, country=country) + direction_unit = cls.add_direction(key, unit, language, country=country) + + if direction_unit and direction_unit != unit: + unit = direction_unit + else: + add_quadrant = address_config.get_property('{}.add_quadrant'.format(key), language, country=country) + if add_quadrant: + unit = cls.add_quadrant(key, unit, language, country=country) return cls.numeric_phrase(key, safe_decode(unit), language, dictionaries=['unit_types_numbered'], country=country)