diff --git a/app/core/cleaner.py b/app/core/cleaner.py index 5c0877f..58fb2e7 100644 --- a/app/core/cleaner.py +++ b/app/core/cleaner.py @@ -94,6 +94,35 @@ MONTHS_GENITIVE = [ # Леммы единиц времени (для корректного падежа числительных) TIME_UNIT_LEMMAS = {"час", "минута", "секунда"} +# Суффиксы порядковых числительных для формата "1968-й", "1968-го", "1968-му", "1968-м" и т.п. +_ORDINAL_SUFFIX_MAP = { + # Masculine + "ого": ("genitive", "m"), + "его": ("genitive", "m"), + "ому": ("dative", "m"), + "ему": ("dative", "m"), + "ым": ("instrumental", "m"), + "им": ("instrumental", "m"), + "ом": ("prepositional", "m"), + "ем": ("prepositional", "m"), + "ый": ("nominative", "m"), + "ий": ("nominative", "m"), + "й": ("nominative", "m"), + "го": ("genitive", "m"), + "му": ("dative", "m"), + "м": ("prepositional", "m"), + # Feminine + "ая": ("nominative", "f"), + "яя": ("nominative", "f"), + "ую": ("accusative", "f"), + "юю": ("accusative", "f"), + "ой": ("genitive", "f"), + "ей": ("genitive", "f"), + # Neuter + "ое": ("nominative", "n"), + "ее": ("nominative", "n"), +} + def get_case_from_preposition(prep_token): """Определяет падеж по предлогу.""" @@ -128,16 +157,40 @@ def numbers_to_words(text: str) -> str: if not text: return "" - # 0. Обработка короткой записи годов с суффиксом: "1968-м", "в 1968-м году" + preps_list = "|".join(map(re.escape, PREPOSITION_CASES.keys())) + + # 0. Обработка короткой записи годов с суффиксом: "1968-й", "1968-го", "1968-му", "1968-м", "в 1968-м году" def replace_year_suffix_match(match): prep = match.group(1) # Предлог (в, во, о...) year_str = match.group(2) # Само число - year_word = match.group(3) # Слово "год", "году" и т.д. (опционально) + suffix = match.group(3) # Суффикс порядкового числительного + year_word = match.group(4) # Слово "год", "году" и т.д. (опционально) - # Суффикс "-м/-ом" обычно соответствует предложному падежу - words = convert_number( - year_str, context_type="ordinal", case="prepositional", gender="m" - ) + case = None + gender = None + + if prep: + morph_case = get_case_from_preposition(prep.strip().lower()) + if morph_case: + case = PYMORPHY_TO_NUM2WORDS.get(morph_case) + + suffix_key = suffix.lower() + suffix_case, suffix_gender = _ORDINAL_SUFFIX_MAP.get(suffix_key, (None, None)) + + if not case and suffix_case: + case = suffix_case + + if year_word: + gender = "m" + elif suffix_gender: + gender = suffix_gender + + if not case: + case = "nominative" + if not gender: + gender = "m" + + words = convert_number(year_str, context_type="ordinal", case=case, gender=gender) prefix = f"{prep} " if prep else "" if year_word: @@ -145,7 +198,9 @@ def numbers_to_words(text: str) -> str: return f"{prefix}{words}" text = re.sub( - r"(?i)\b((?:в|во|о|об|обо|при)\s+)?(\d{3,4})[-‑–—](?:м|ом)\b(?:\s+(год[а-я]*))?", + rf"(?i)\b((?:{preps_list})\s+)?(\d{{3,4}})[-‑–—]" + r"(ого|его|ому|ему|ым|им|ом|ем|ый|ий|ая|яя|ую|юю|ой|ей|ое|ее|й|го|му|м)\b" + r"(?:\s+(год[а-я]*))?", replace_year_suffix_match, text, ) @@ -270,7 +325,6 @@ def numbers_to_words(text: str) -> str: # Регулярка теперь захватывает (опционально) следующее слово для определения рода - preps_list = "|".join(map(re.escape, PREPOSITION_CASES.keys())) text = re.sub( rf"(?i)(?