missing.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # THIS SOFTWARE IS A PART OF FREE COMPETITOR PROJECT
  2. # THE FOLLOWING SOURCE CODE I UNDER THE GNU
  3. # AGPL LICENSE V3 OR ANY LATER VERSION.
  4. # This project is not for simple users, but for
  5. # web-masters and a like, so we are counting on
  6. # your ability to set it up and running.
  7. ##################################################
  8. # This file is importart, since it's important to
  9. # keep track of software that the users are
  10. # searching, but not getting any answers to.
  11. # The idea is very simple. If the score of any
  12. # search is below 60%, we add the search term into
  13. # a list. But instead of it being a dumb list, it's
  14. # a smart list.
  15. # Using the similar() function we can group very
  16. # similar terms together. So the users could misspel
  17. # certain names. For example we might group '3D Max'
  18. # '3DSMax' into the same data-structure. Using the
  19. # simple count of how much users spell this or that
  20. # name more often, we will make a suggestion for the
  21. # maintainer. So the maintainer could add the missing
  22. # names into the data. Or at least report them to us.
  23. ##################################################
  24. import os
  25. import json
  26. from difflib import SequenceMatcher # checks how similar are two strings
  27. def similar(a, b):
  28. # I guess it simpifies the syntax for SequenceMatcher
  29. # In the previous version we use Lavenshtain but it made
  30. # it an issue for some people to install.
  31. return SequenceMatcher(None, a, b).ratio()
  32. def add(name):
  33. # This function will add a datapoint into the missing
  34. # This shows up way too often. And will show up. Untill we
  35. # will desing a logo.
  36. if name == "favicon.ico":
  37. return
  38. # first we need to make sure that the file exists
  39. try:
  40. with open("data/missing.json") as json_file:
  41. missing = json.load(json_file)
  42. # Reverse the old file
  43. if type(missing) == dict:
  44. missing = []
  45. except:
  46. missing = []
  47. # There could be a problem with writing so we look into it
  48. # for a very close match. Up to about 60%. No more.
  49. match_missing = 0
  50. closest_missing = 0
  51. found = False
  52. for ind, n in enumerate(missing):
  53. for i in n:
  54. sim = similar(name, i)
  55. if sim > 0.6: # At least 60% match
  56. found = True
  57. if match_missing < sim:
  58. match_missing = sim
  59. closest_missing = ind
  60. if not found:
  61. missing.append({name:1})
  62. else:
  63. if not name in missing[closest_missing]:
  64. missing[closest_missing][name] = 1
  65. else:
  66. missing[closest_missing][name] += 1
  67. # Now we save the file
  68. with open("data/missing.json", 'w') as f:
  69. json.dump(missing, f, indent=4, sort_keys=True)
  70. def remove(name):
  71. # This function will remove a datapoint from the missing
  72. try:
  73. with open("data/missing.json") as json_file:
  74. missing = json.load(json_file)
  75. # Reverse the old file
  76. if type(missing) == dict:
  77. missing = []
  78. except:
  79. missing = []
  80. # There could be a problem with writing so we look into it
  81. # for a very close match. Up to about 60%. No more.
  82. match_missing = 0
  83. closest_missing = 0
  84. found = False
  85. for ind, n in enumerate(missing):
  86. for i in n:
  87. sim = similar(name, i)
  88. if sim > 0.6: # At least 60% match
  89. found = True
  90. if match_missing < sim:
  91. match_missing = sim
  92. closest_missing = ind
  93. if found:
  94. del missing[closest_missing]
  95. # Now we save the file
  96. with open("data/missing.json", 'w') as f:
  97. json.dump(missing, f, indent=4, sort_keys=True)
  98. def List():
  99. # This function will list missing in markdown format
  100. try:
  101. with open("data/missing.json") as json_file:
  102. missing = json.load(json_file)
  103. # Reverse the old file
  104. if type(missing) == dict:
  105. missing = []
  106. except:
  107. missing = []
  108. print("| Done | Best Name | Other Names |")
  109. print("| --- | --- | --- |")
  110. for i in missing:
  111. i = sorted(i.items(), key=lambda x:x[1])
  112. i = dict(i)
  113. s = "| | **"+list(i.keys())[0]+"**"
  114. if len(i) > 1:
  115. s = s + " | "
  116. for b in i:
  117. if b == list(i.keys())[0]:
  118. continue
  119. comma = ", "
  120. if b == list(i.keys())[-1]:
  121. comma = ""
  122. s = s + b + comma
  123. s = s + " |"
  124. else:
  125. s = s + " | |"
  126. print(s)
  127. def List_html():
  128. # This function will list missing in html format
  129. try:
  130. with open("data/missing.json") as json_file:
  131. missing = json.load(json_file)
  132. # Reverse the old file
  133. if type(missing) == dict:
  134. missing = []
  135. except:
  136. missing = []
  137. page = """
  138. <h1>Known Missing Software</h1>
  139. <p>This list is auto-generated by the server software when the software
  140. cannot find a '.json' for for the searched query. It may or may not
  141. be know to the developers, or even to the server operators. So please report
  142. the software into <a href="https://notabug.org/jyamihud/FreeCompetitors/issues/25">
  143. the Missing Software Page</a> in our source code repository.</p>
  144. """
  145. for i in missing:
  146. i = sorted(i.items(), key=lambda x:x[1])
  147. i = dict(i)
  148. if len(i) > 1:
  149. page = page + "<details><summary>"+list(i.keys())[0]+"</summary>"
  150. for b in i:
  151. if b == list(i.keys())[0]:
  152. continue
  153. if b == list(i.keys())[-1]:
  154. comma = ""
  155. page = page + "<span>&nbsp;&nbsp;&nbsp;&nbsp;" + b + "</span><br>"
  156. page = page + "</details>"
  157. else:
  158. page = page + list(i.keys())[0]+"<br>"
  159. page = page + "\n\n"
  160. return page