user.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import abc
  2. import threading
  3. from conf import Config
  4. from tool.type_ import *
  5. from tool.time_ import HGSTime
  6. from .garbage import GarbageBag, GarbageType
  7. class UserNotSupportError(Exception):
  8. pass
  9. class UserType:
  10. UserTypeStrList: List = ["", "NORMAL", "MANAGER"]
  11. normal: enum = 1
  12. manager: enum = 2
  13. class User(metaclass=abc.ABCMeta):
  14. def __init__(self, name: uname_t, uid: uid_t, user_type: enum):
  15. self._name: uname_t = uname_t(name)
  16. self._uid: uid_t = uid_t(uid)
  17. self._type: enum = enum(user_type)
  18. self._lock = threading.RLock()
  19. def is_manager(self):
  20. try:
  21. self._lock.acquire()
  22. _type = self._type
  23. finally:
  24. self._lock.release()
  25. return _type == UserType.manager
  26. def get_uid(self) -> uid_t:
  27. try:
  28. self._lock.acquire()
  29. uid = self._uid
  30. finally:
  31. self._lock.release()
  32. return uid
  33. def get_name(self) -> uname_t:
  34. try:
  35. self._lock.acquire()
  36. name = self._name
  37. finally:
  38. self._lock.release()
  39. return name
  40. def get_user_type(self) -> enum:
  41. try:
  42. self._lock.acquire()
  43. _type = self._type
  44. finally:
  45. self._lock.release()
  46. return _type
  47. def get_info(self) -> Dict[str, str]:
  48. raise UserNotSupportError
  49. def __repr__(self):
  50. try:
  51. self._lock.acquire()
  52. _type = UserType.UserTypeStrList[self._type]
  53. uid = self._uid
  54. name = self._name
  55. finally:
  56. self._lock.release()
  57. return f"User {uid} {name} is {_type}"
  58. def evaluate(self, is_right: bool) -> score_t:
  59. raise UserNotSupportError
  60. def add_score(self, score: score_t) -> score_t:
  61. raise UserNotSupportError
  62. def throw_rubbish(self, garbage: GarbageBag, garbage_type: enum, loc: location_t) -> bool:
  63. raise UserNotSupportError
  64. def check_rubbish(self, garbage: GarbageBag, right: bool, user) -> bool:
  65. raise UserNotSupportError
  66. class NormalUser(User):
  67. def __init__(self, name: uname_t, uid: uid_t, reputation: score_t, rubbish: count_t, score: score_t):
  68. super(NormalUser, self).__init__(name, uid, UserType.normal)
  69. self._reputation = score_t(reputation)
  70. self._rubbish = count_t(rubbish)
  71. self._score = score_t(score)
  72. def __repr__(self):
  73. try:
  74. self._lock.acquire()
  75. info = (f"User {self._uid} {self._name} "
  76. f"reputation {self._reputation} "
  77. f"rubbish {self._rubbish} "
  78. f"score {self._score} "
  79. f"is NORMAL")
  80. finally:
  81. self._lock.release()
  82. return info
  83. def get_info(self) -> Dict[str, str]:
  84. """
  85. 获取当前用户的简单信息
  86. :return: 用户信息字典
  87. """
  88. try:
  89. self._lock.acquire()
  90. info = {
  91. "name": str(self._name),
  92. "uid": str(self._uid),
  93. "manager": '0',
  94. "reputation": str(self._reputation),
  95. "rubbish": str(self._rubbish),
  96. "score": str(self._score)
  97. }
  98. finally:
  99. self._lock.release()
  100. return info
  101. def evaluate(self, is_right: bool) -> score_t:
  102. """
  103. 评估信誉积分
  104. 使用朴素贝叶斯公式为基础
  105. 总分值: 1000分
  106. 实际分: P(A|B) * 1000
  107. A=能正确仍对垃圾的概率
  108. B=本次仍对垃圾的概率
  109. 初始概率:
  110. P(A) = 0.3 (default_reputation = 300)
  111. P(B|A) = 0.6
  112. P(B|^A) = 0.3
  113. P(B) = 0.8 * 0.3 + 0.1 * 0.7 = 0.31
  114. p(^B) = 0.69
  115. P(A|B) = P(A) * (P(B|A) / P(B)) = P(A) * 2.5806
  116. P(A|^B) = P(A) * (P(^B|A) / P(^B)) = P(A) * (0.2/0.96) = P(A) * 0.2083
  117. :return: 信誉积分
  118. """
  119. try:
  120. self._lock.acquire()
  121. if is_right and self._rubbish > Config.max_rubbish_week:
  122. return self._reputation # 执行 finally将释放锁
  123. pa = self._reputation / 1000 # P(A)
  124. if pa < 0.01:
  125. pa = 0.01
  126. p_a = 1 - pa # P(^A)
  127. pba, p_ba, pb_a, p_b_a = 0.6, 0.4, 0.3, 0.7 # P(B|A), P(^B|A), P(B|^A), P(^B|^A)
  128. pb = pba * pa + pb_a * p_a # P(B) = P(B|A) * P(A) + P(B|^A) * P(^A)
  129. p_b = p_ba * pa + p_b_a * p_a # P(^B) = P(^B|A) * P(A) + P(^B|^A) * P(^A)
  130. if is_right:
  131. new_pa = pa * (pba / pb) # P(A|B)
  132. else:
  133. new_pa = pa * (p_ba / p_b) # P(A|^B)
  134. new_pa = new_pa * 1000
  135. if int(new_pa) == 0:
  136. new_pa = 1
  137. if int(new_pa) > 1000:
  138. new_pa = 999
  139. amplitude = new_pa - self._reputation # 分差
  140. amplitude_top = 1000 - self._reputation # 距离总分分差
  141. if is_right:
  142. if amplitude >= 20:
  143. amplitude = amplitude * (amplitude_top / 1000) # 涨分抑制
  144. else:
  145. if amplitude <= -20:
  146. amplitude = amplitude * (self._reputation / 1000) # 总分分差月小扣分越高
  147. self._reputation += int(amplitude)
  148. if self._reputation <= 5:
  149. self._reputation = 5
  150. reputation = self._reputation
  151. finally:
  152. self._lock.release()
  153. return reputation
  154. def add_score(self, score: score_t) -> score_t:
  155. try:
  156. self._lock.acquire()
  157. if self._score + score < 0:
  158. self._score = 0
  159. return 0
  160. self._score += score
  161. score = self._score
  162. finally:
  163. self._lock.release()
  164. return score
  165. def throw_rubbish(self, garbage: GarbageBag, garbage_type: enum, loc: location_t = Config.base_location) -> bool:
  166. try:
  167. self._lock.acquire()
  168. if self._rubbish > Config.max_rubbish_week:
  169. self.add_score(-3)
  170. elif self._rubbish > Config.limit_rubbish_week:
  171. return False
  172. if garbage.is_use() or garbage.is_check()[0]:
  173. return False
  174. garbage.config_use(garbage_type, HGSTime(), self._uid, loc)
  175. self._rubbish += 1
  176. finally:
  177. self._lock.release()
  178. return True
  179. def check_rubbish(self, garbage: GarbageBag, right: bool, user: User) -> bool:
  180. raise UserNotSupportError
  181. class ManagerUser(User):
  182. def __init__(self, name: uname_t, uid: uid_t):
  183. super(ManagerUser, self).__init__(name, uid, UserType.manager)
  184. def check_rubbish(self, garbage: GarbageBag, right: bool, user: User) -> bool:
  185. if (not garbage.is_use()) or garbage.is_check()[0] or user.get_uid() != garbage.get_user(): # 调用时已经有锁
  186. return False
  187. try:
  188. self._lock.acquire()
  189. garbage.config_check(right, self._uid)
  190. user.evaluate(right)
  191. if right:
  192. if garbage.get_type() == GarbageType.recyclable:
  193. user.add_score(3)
  194. elif garbage.get_type() == GarbageType.kitchen or garbage.get_type() == GarbageType.hazardous:
  195. user.add_score(2)
  196. else:
  197. user.add_score(1)
  198. else:
  199. user.add_score(-4)
  200. finally:
  201. self._lock.release()
  202. return True
  203. def get_info(self) -> Dict[str, str]:
  204. try:
  205. self._lock.acquire()
  206. info = {
  207. "name": str(self._name),
  208. "uid": str(self._uid),
  209. "manager": '1'
  210. }
  211. finally:
  212. self._lock.release()
  213. return info