Пример #1
0
    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
Пример #2
0
 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
Пример #3
0
    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
Пример #4
0
    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
Пример #5
0
 def vowel(self) -> int:
     """
     :return: позиция гласной буквы этого слога в слове (с 0).
     """
     return get_first_vowel_position(self.text) + self.begin