You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

count_analysis.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. from typing import List
  2. import million.analyze.message_evaluation as msg_val
  3. from million.model.message import Message
  4. def check_extra_or_missing_letter(word: str, reference: str) -> bool:
  5. len_word = len(word)
  6. len_ref = len(reference)
  7. if abs(len_word - len_ref) != 1:
  8. return False
  9. shortest = word if len_word < len_ref else reference
  10. longest = word if len_word > len_ref else reference
  11. for i in range(len(shortest)):
  12. if shortest[i] != longest[i]:
  13. return shortest[i:] == longest[i + 1 :]
  14. return True
  15. def check_single_letter_differ(word: str, reference: str) -> bool:
  16. return sum(1 for x, y in zip(reference, word) if x != y) == 1
  17. def check_letter_swap(word: str, reference: str) -> bool:
  18. if len(word) != len(reference):
  19. return False
  20. for i in range(len(word) - 1):
  21. if word[i] != reference[i]:
  22. return word[i + 1] + word[i] + word[i + 2 :] == reference[i:]
  23. return False
  24. def check_typo(word: str, reference: str) -> bool:
  25. if len(reference) == len(word):
  26. return check_single_letter_differ(word, reference) or check_letter_swap(
  27. word, reference
  28. )
  29. else:
  30. return check_extra_or_missing_letter(word, reference)
  31. def _check_message_concatenation(messages: List[Message], index: int, expected: int) -> bool:
  32. """
  33. Cette méthode détermine si la liste messages contient le compte expected à partir de l'index donné
  34. en concaténant les valeurs des messages suivants.
  35. Cette méthode permet de trouver un compte qui a été étalé sur plusieurs messages
  36. """
  37. reference = str(expected)
  38. testing = ""
  39. offset = 0
  40. while len(testing) < len(reference):
  41. next_message = messages[index + offset]
  42. offset += 1
  43. if next_message.sender_name == messages[index].sender_name:
  44. testing += str(msg_val.get(next_message))
  45. return testing == reference
  46. def _heavy_check(messages: List[Message], index: int, expected: int) -> bool:
  47. """
  48. Cette méthode détermine si la liste messages contient le compte expected à partir de l'index donné.
  49. Elle utilise pour cela des méthodes complexes qui ne permettent de trouver un résultat
  50. seulement si on est sortis du cas nominal
  51. """
  52. # TODO Si on ne trouve pas le chiffre dans la plage, appliquer différentes méthodes "HEAVYCHECK" avant de le déclarer perdu
  53. # - créer une méthode qui concatène des messages consécutifs jusqu'a trouver la bonne valeur si la valeur est plus basse
  54. # - créer une méthode pour les messages ou 2 valeurs sont collées si la valeur est plus haute
  55. # - sub certains caractères par des chiffres selon une table préconcue, les chiffres en toute lettre par leur équivalent
  56. # - virer tout sauf les chiffres
  57. m = messages[index]
  58. word = str(msg_val.get(m))
  59. return _check_message_concatenation(messages, index, expected) or \
  60. check_typo(word, str(expected)) and msg_val.get(messages[index+1]) == expected+1
  61. def _check_value_around(messages, index, expected, amplitude):
  62. for i in range(1, amplitude + 1):
  63. if index + i < len(messages) and expected == msg_val.get(messages[index + i]):
  64. return index + i
  65. if expected == msg_val.get(messages[index - i]):
  66. return index - i
  67. return None
  68. def search_value_at(messages, index, expected, do_heavy_check=True, amplitude=1000):
  69. """
  70. Cette méthode détermine si la liste messages contient le compte expected à partir de l'index donné.
  71. Le paramètre amplitude détermine la plage où effectuer les recherches autour de l'index donné.
  72. Le paramètre do_heavy_check précise si on doit pousser l'analyse avec des méthodes plus lourdes en cas d'échec
  73. """
  74. # Si le message courant contient la valeur, on renvoie
  75. curr_value = msg_val.get(messages[index])
  76. if expected == curr_value:
  77. return index
  78. # Sinon on regarde aux alentours
  79. jump_index = _check_value_around(messages, index, expected, amplitude)
  80. if jump_index is not None:
  81. return jump_index
  82. # Enfin, si on ne trouve pas la valeur à l'index donné et dans l'amplitude donnée
  83. # On performe une vérification lourde à cet endroit
  84. if do_heavy_check and _heavy_check(messages, index, expected):
  85. return index
  86. # Si tout cela n'a rien donné, on renvoie None
  87. return None