user.py 8.1 KB

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