Source code for rupo.rhymes.rhymes

# -*- coding: utf-8 -*-
# Автор: Гусев Илья
# Описание: Класс рифм.

from rupo.stress.word import StressedWord
from rupo.util.preprocess import VOWELS


[docs]class RhymeProfile: def __init__(self, syllable_count: int, stressed_syllable_number: int, stressed_syllable_text: str, next_syllable_text: str, next_char: str): self.syllable_count = syllable_count self.stressed_syllable_number = stressed_syllable_number self.stressed_syllable_text = stressed_syllable_text self.next_syllable_text = next_syllable_text self.next_char = next_char def __str__(self): return "Syllable count: {}; Stressed syllable: {}; " \ "Stressed syllable text: {}; Next syllable: {}; " \ "Next char: {}".format(self.syllable_count, self.stressed_syllable_number, self.stressed_syllable_text, self.next_syllable_text, self.next_char) def __repr__(self): return self.__str__()
[docs]class Rhymes(object): """ Поиск рифм. """
[docs] @staticmethod def is_rhyme(word1: StressedWord, word2: StressedWord, score_border: int=4, syllable_number_border: int=4) -> bool: """ Проверка рифмованности 2 слов. :param word1: первое слово для проверки рифмы, уже акцентуированное (Word). :param word2: второе слово для проверки рифмы, уже акцентуированное (Word). :param score_border: граница определния рифмы, чем выше, тем строже совпадение. :param syllable_number_border: ограничение на номер слога с конца, на который падает ударение. :return result: является рифмой или нет. """ profile1 = Rhymes.__get_rhyme_profile(word1) profile2 = Rhymes.__get_rhyme_profile(word2) score = 0 for i, ch1 in enumerate(profile1.stressed_syllable_text): for j, ch2 in enumerate(profile2.stressed_syllable_text[i:]): if ch1 != ch2: continue if ch1 in VOWELS: score += 3 else: score += 1 if profile1.next_syllable_text == profile2.next_syllable_text and profile1.next_syllable_text != '': score += 3 elif profile1.next_char == profile2.next_char and profile1.next_char != '': score += 1 return (profile1.stressed_syllable_number == profile2.stressed_syllable_number and profile1.syllable_count == profile2.syllable_count and profile1.stressed_syllable_number <= syllable_number_border and score >= score_border)
@staticmethod def __get_rhyme_profile(word: StressedWord) -> 'RhymeProfile': """ Получение профиля рифмовки (набора признаков для сопоставления). :param word: уже акцентуированное слово (Word). :return profile: профиль рифмовки. """ # TODO: Переход на фонетическое слово, больше признаков. profile = RhymeProfile(syllable_count=0, stressed_syllable_number=-1, stressed_syllable_text="", next_syllable_text="", next_char="") syllables = list(word.syllables) profile.syllable_count = len(syllables) for i, syllable in enumerate(reversed(syllables)): if syllable.stress == -1: continue profile.stressed_syllable_text = syllable.text profile.stressed_syllable_number = -i-1 if i != 0: profile.next_syllable = syllables[-i].text if syllable.stress + 1 < len(word.text): profile.next_char = word.text[syllable.stress + 1] break return profile