user.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import abc
  2. import conf
  3. from tool.type_ import *
  4. from tool.time_ import HGSTime
  5. from .garbage import GarbageBag, GarbageType
  6. from sql.garbage import update_garbage
  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. def is_manager(self):
  25. return self._type == UserType.manager
  26. def get_uid(self) -> uid_t:
  27. return self._uid
  28. def get_name(self) -> uname_t:
  29. return self._name
  30. def get_user_type(self) -> enum:
  31. return self._type
  32. def get_info(self) -> Dict[str, str]:
  33. return {
  34. "name": str(self._name),
  35. "uid": str(self._uid),
  36. "manager": self._type == UserType.manager if '1' else '0'
  37. }
  38. def __repr__(self):
  39. tmp = UserType.UserTypeStrList
  40. return f"User {self._uid} {self._name} is {tmp[self._type]}"
  41. def evaluate(self, is_right: bool) -> score_t:
  42. raise UserNotSupportError
  43. def add_score(self, score: score_t) -> score_t:
  44. raise UserNotSupportError
  45. def throw_rubbish(self, garbage: GarbageBag, garbage_type: enum, loc: location_t) -> bool:
  46. raise UserNotSupportError
  47. def check_rubbish(self, garbage: GarbageBag, right: bool, user) -> bool:
  48. raise UserNotSupportError
  49. class NormalUser(User):
  50. def __init__(self, name: uname_t, uid: uid_t, reputation: score_t, rubbish: count_t, score: score_t):
  51. super(NormalUser, self).__init__(name, uid, UserType.normal)
  52. self._reputation = reputation
  53. self._rubbish = rubbish
  54. self._score = score
  55. def __repr__(self):
  56. return (f"User {self._uid} {self._name} "
  57. f"reputation {self._reputation} "
  58. f"rubbish {self._rubbish} "
  59. f"score {self._score} "
  60. f"is NORMAL")
  61. def get_info(self) -> Dict[str, str]:
  62. """
  63. 获取当前用户的简单信息
  64. :return: 用户信息字典
  65. """
  66. return {
  67. "name": str(self._name),
  68. "uid": str(self._uid),
  69. "manager": self._type == UserType.manager if '1' else '0',
  70. "reputation": str(self._reputation),
  71. "rubbish": str(self._rubbish),
  72. "score": str(self._score)
  73. }
  74. def evaluate(self, is_right: bool) -> score_t:
  75. """
  76. 评估信誉积分
  77. 使用朴素贝叶斯公式为基础
  78. 总分值: 1000分
  79. 实际分: P(A|B) * 1000
  80. A=能正确仍对垃圾的概率
  81. B=本次仍对垃圾的概率
  82. 初始概率:
  83. P(A) = 0.3 (default_reputation = 300)
  84. P(B|A) = 0.6
  85. P(B|^A) = 0.3
  86. P(B) = 0.8 * 0.3 + 0.1 * 0.7 = 0.31
  87. p(^B) = 0.69
  88. P(A|B) = P(A) * (P(B|A) / P(B)) = P(A) * 2.5806
  89. P(A|^B) = P(A) * (P(^B|A) / P(^B)) = P(A) * (0.2/0.96) = P(A) * 0.2083
  90. :return: 信誉积分
  91. """
  92. if is_right and self._rubbish > conf.max_rubbish_week:
  93. return self._reputation
  94. pa = self._reputation / 1000 # P(A)
  95. if pa < 0.01:
  96. pa = 0.01
  97. p_a = 1 - pa # P(^A)
  98. 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)
  99. pb = pba * pa + pb_a * p_a # P(B) = P(B|A) * P(A) + P(B|^A) * P(^A)
  100. p_b = p_ba * pa + p_b_a * p_a # P(^B) = P(^B|A) * P(A) + P(^B|^A) * P(^A)
  101. if is_right:
  102. new_pa = pa * (pba / pb) # P(A|B)
  103. else:
  104. new_pa = pa * (p_ba / p_b) # P(A|^B)
  105. new_pa = new_pa * 1000
  106. if int(new_pa) == 0:
  107. new_pa = 1
  108. if int(new_pa) > 1000:
  109. new_pa = 999
  110. amplitude = new_pa - self._reputation # 分差
  111. amplitude_top = 1000 - self._reputation # 距离总分分差
  112. if is_right:
  113. if amplitude >= 20:
  114. amplitude = amplitude * (amplitude_top / 1000) # 涨分抑制
  115. else:
  116. if amplitude <= -20:
  117. amplitude = amplitude * (self._reputation / 1000) # 总分分差月小扣分越高
  118. self._reputation += int(amplitude)
  119. if self._reputation <= 5:
  120. self._reputation = 5
  121. return self._reputation
  122. def add_score(self, score: score_t) -> score_t:
  123. if self._score + score < 0:
  124. self._score = 0
  125. raise UserNotScoreException
  126. self._score += score
  127. return self._score
  128. def throw_rubbish(self, garbage: GarbageBag, garbage_type: enum, loc: location_t = conf.base_location) -> bool:
  129. if self._rubbish > conf.max_rubbish_week:
  130. try:
  131. self.add_score(-3)
  132. except UserNotScoreException:
  133. raise UserRubbishException
  134. elif self._rubbish > conf.limit_rubbish_week:
  135. raise UserRubbishException
  136. if garbage.is_use() or not garbage.is_check():
  137. return False
  138. garbage.config_use(garbage_type, HGSTime(), self._uid, loc)
  139. self._rubbish += 1
  140. return True
  141. def check_rubbish(self, garbage: GarbageBag, right: bool, user: User) -> bool:
  142. raise UserNotSupportError
  143. class ManagerUser(User):
  144. def __init__(self, name: uname_t, uid: uid_t):
  145. super(ManagerUser, self).__init__(name, uid, UserType.manager)
  146. def check_rubbish(self, garbage: GarbageBag, right: bool, user: User) -> bool:
  147. if not garbage.is_use() or garbage.is_check() or user.get_uid() != garbage.get_user():
  148. return False
  149. garbage.config_check(right, self._uid)
  150. user.evaluate(right)
  151. try:
  152. if right:
  153. if garbage.get_type() == GarbageType.recyclable:
  154. user.add_score(3)
  155. elif garbage.get_type() == GarbageType.kitchen or garbage.get_type() == GarbageType.hazardous:
  156. user.add_score(2)
  157. else:
  158. user.add_score(1)
  159. else:
  160. user.add_score(-4)
  161. except UserNotScoreException:
  162. ...
  163. return True