def get_improved_markup(markup: Markup, result: ClassificationResult) -> Markup: """ Улучшаем разметку после классификации метра. :param markup: начальная разметка. :param result: результат классификации. :return: улучшенная разметка. """ for pos in result.corrections[result.metre] + result.resolutions[ result.metre]: syllables = markup.lines[pos.line_number].words[ pos.word_number].syllables for i, syllable in enumerate(syllables): syllable.stress = -1 if syllable.number == pos.syllable_number: syllable.stress = syllable.begin + get_first_vowel_position( syllable.text) for pos in result.additions[result.metre]: syllable = markup.lines[pos.line_number].words[ pos.word_number].syllables[pos.syllable_number] syllable.stress = syllable.begin + get_first_vowel_position( syllable.text) return markup
def count_vowels(self): num_vowels = 0 for word in self.words: for syllable in word.syllables: if get_first_vowel_position(syllable.text) != -1: num_vowels += 1 return num_vowels
def get_syllables(word: str) -> List[Syllable]: """ Разделение слова на слоги. :param word: слово для разбивки на слоги. :return syllables: массив слогов слова. """ syllables = [] begin = 0 number = 0 # В случае наличия дефиса разбиваем слова на подслова, находим слоги в них, объединяем. if "-" in word: word_parts = word.split("-") word_syllables = [] last_part_end = 0 for part in word_parts: part_syllables = Graphemes.get_syllables(part) if len(part_syllables) == 0: continue for i in range(len(part_syllables)): part_syllables[i].begin += last_part_end part_syllables[i].end += last_part_end part_syllables[i].number += len(word_syllables) word_syllables += part_syllables last_part_end = part_syllables[-1].end + 1 return word_syllables # Для слов или подслов, в которых нет дефиса. for i, ch in enumerate(word): if ch not in VOWELS: continue if i + 1 < len(word) - 1 and word[i + 1] in CLOSED_SYLLABLE_CHARS: if i + 2 < len(word) - 1 and word[i + 2] in "ьЬ": # Если после сонорного согласного идёт мягкий знак, заканчиваем на нём. ("бань-ка") end = i + 3 elif i + 2 < len(word) - 1 and word[i + 2] not in VOWELS and \ (word[i + 2] not in CLOSED_SYLLABLE_CHARS or word[i + 1] == "й"): # Если после сонорного согласного не идёт гласная или другой сонорный согласный, # слог закрывается на этом согласном. ("май-ка") end = i + 2 else: # Несмотря на наличие закрывающего согласного, заканчиваем на гласной. # ("со-ло", "да-нный", "пол-ный") end = i + 1 else: # Если после гласной идёт не закрывающая согласная, заканчиваем на гласной. ("ко-гда") end = i + 1 syllables.append(Syllable(begin, end, number, word[begin:end])) number += 1 begin = end if get_first_vowel_position(word) != -1: # Добиваем последний слог до конца слова. syllables[-1] = Syllable(syllables[-1].begin, len(word), syllables[-1].number, word[syllables[-1].begin:len(word)]) return syllables
def predict(self, word: str) -> List[int]: """ Определение ударения в слове по словарю. Возможно несколько вариантов ударения. :param word: слово для простановки ударений. :return stresses: позиции букв, на которые падает ударение. """ stresses = [] if count_vowels(word) == 0: # Если гласных нет, то и ударений нет. pass elif count_vowels(word) == 1: # Если одна гласная, то на неё и падает ударение. stresses.append(get_first_vowel_position(word)) elif word.find("ё") != -1: # Если есть буква "ё", то только на неё может падать ударение. stresses.append(word.find("ё")) else: # Проверяем словарь на наличие форм с ударениями. stresses = self.stress_dict.get_stresses(word, Stress.Type.PRIMARY) +\ self.stress_dict.get_stresses(word, Stress.Type.SECONDARY) if 'е' not in word: return stresses # Находим все возможные варинаты преобразований 'е' в 'ё'. positions = [i for i in range(len(word)) if word[i] == 'е'] beam = [word[:positions[0]]] for i in range(len(positions)): new_beam = [] for prefix in beam: n = positions[i + 1] if i + 1 < len(positions) else len(word) new_beam.append(prefix + 'ё' + word[positions[i] + 1:n]) new_beam.append(prefix + 'е' + word[positions[i] + 1:n]) beam = new_beam # И проверяем их по словарю. for permutation in beam: if len(self.stress_dict.get_stresses(permutation)) != 0: yo_pos = permutation.find("ё") if yo_pos != -1: stresses.append(yo_pos) return stresses
def vowel(self) -> int: """ :return: позиция гласной буквы этого слога в слове (с 0). """ return get_first_vowel_position(self.text) + self.begin