123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- from typing import List
- import million.analyze.message_evaluation as msg_val
- from million.model.message import Message
-
-
- def check_extra_or_missing_letter(word: str, reference: str) -> bool:
- """
- Cette méthode vérifie si la str word contient une et une seule lettre
- de trop ou de moins par rapport à la str reference
- """
- len_word = len(word)
- len_ref = len(reference)
-
- if abs(len_word - len_ref) != 1:
- return False
-
- shortest = word if len_word < len_ref else reference
- longest = word if len_word > len_ref else reference
-
- for i in range(len(shortest)):
- if shortest[i] != longest[i]:
- return shortest[i:] == longest[i + 1 :]
-
- return True
-
-
- def check_single_letter_differ(word: str, reference: str) -> bool:
- """
- Cette méthode vérifie si la str word contient une et une seule
- lettre différente par rapport à la str reference
- """
- return sum(1 for x, y in zip(reference, word) if x != y) == 1
-
-
- def check_letter_swap(word: str, reference: str) -> bool:
- """
- Cette méthode vérifie si la str word contient un et un seul
- échange de lettres consécutives par rapport à la str reference
- """
- if len(word) != len(reference):
- return False
-
- for i in range(len(word) - 1):
- if word[i] != reference[i]:
- return word[i + 1] + word[i] + word[i + 2 :] == reference[i:]
-
- return False
-
-
- def check_typo(word: str, reference: str) -> bool:
- """
- Cette méthode vérifie si la str word contient une typo en se référant à la str reference
- """
- if len(reference) == len(word):
- return check_single_letter_differ(word, reference) or check_letter_swap(
- word, reference
- )
- else:
- return check_extra_or_missing_letter(word, reference)
-
-
- def _check_message_concatenation(messages: List[Message], index: int, expected: int) -> bool:
- """
- Cette méthode détermine si la liste messages contient le compte expected à partir de l'index donné
- en concaténant les valeurs des messages suivants.
- Cette méthode permet de trouver un compte qui a été étalé sur plusieurs messages
- """
- reference = str(expected)
- testing = ""
-
- offset = 0
-
- while len(testing) < len(reference):
- next_message = messages[index + offset]
- offset += 1
- if next_message.sender_name == messages[index].sender_name:
- testing += str(msg_val.get(next_message))
-
- return testing == reference
-
-
- def _heavy_check(messages: List[Message], index: int, expected: int) -> bool:
- """
- Cette méthode détermine si la liste messages contient le compte expected à partir de l'index donné.
- Elle utilise pour cela des méthodes complexes qui ne permettent de trouver un résultat
- seulement si on est sortis du cas nominal
- """
- # TODO
- # - créer une méthode pour gérer le cas où plusieurs comptages sont contenus dans le même corps de message
- # - créer une méthode pour le cas où les chiffres sont représentés par un substitut au sein du corps du message
- # i.e. un nombre écrit en toutes lettres (français ou breton), 🍁 pour 420, @Elias Cheddar pour 69
- m = messages[index]
- word = str(msg_val.get(m))
-
- return _check_message_concatenation(messages, index, expected) or \
- check_typo(word, str(expected)) and msg_val.get(messages[index+1]) == expected+1
-
-
- def _check_value_around(messages, index, expected, amplitude_after, amplitude_before):
- for i in range(1, amplitude_after + 1):
- if index + i < len(messages) and expected == msg_val.get(messages[index + i]):
- return index + i
- for i in range(1, amplitude_before + 1):
- if expected == msg_val.get(messages[index - i]):
- return index - i
-
- return None
-
-
- def search_value_at(messages, index, expected, do_heavy_check=True, amplitude_after=1000, amplitude_before=10):
- """
- Cette méthode détermine si la liste messages contient le compte expected à partir de l'index donné.
- Le paramètre amplitude détermine la plage où effectuer les recherches autour de l'index donné.
- Le paramètre do_heavy_check précise si on doit pousser l'analyse avec des méthodes plus lourdes en cas d'échec
- """
- # Si le message courant contient la valeur, on renvoie
- curr_value = msg_val.get(messages[index])
- if expected == curr_value:
- return index
-
- # Sinon on regarde aux alentours
- jump_index = _check_value_around(messages, index, expected, amplitude_after, amplitude_before)
- if jump_index is not None:
- return jump_index
-
- # Enfin, si on ne trouve pas la valeur à l'index donné et dans l'amplitude donnée
- # On performe une vérification lourde à cet endroit
- if do_heavy_check and _heavy_check(messages, index, expected):
- return index
-
- # Si tout cela n'a rien donné, on renvoie None
- return None
|