|
@@ -1,41 +1,72 @@
|
|
|
|
+import abc
|
|
|
|
+import conf
|
|
from tool.type_ import *
|
|
from tool.type_ import *
|
|
-from enum import Enum
|
|
|
|
|
|
+from tool.time_ import HGSTime
|
|
|
|
+from .garbage import GarbageBag, GarbageType
|
|
|
|
+from sql.garbage import update_garbage
|
|
|
|
|
|
|
|
|
|
-class UserNotSupportError(Exception):
|
|
|
|
|
|
+class UserException(Exception):
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
|
|
-class UserType(Enum):
|
|
|
|
|
|
+class UserNotSupportError(UserException):
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class UserNotScoreException(UserException):
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class UserRubbishException(UserException):
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class UserType:
|
|
|
|
+ UserTypeStrList: List = ["", "NORMAL", "MANAGER"]
|
|
normal: enum = 1
|
|
normal: enum = 1
|
|
manager: enum = 2
|
|
manager: enum = 2
|
|
|
|
|
|
|
|
|
|
-class User:
|
|
|
|
|
|
+class User(metaclass=abc.ABCMeta):
|
|
def __init__(self, name: uname_t, uid: uid_t, user_type: enum):
|
|
def __init__(self, name: uname_t, uid: uid_t, user_type: enum):
|
|
self._name: uname_t = name
|
|
self._name: uname_t = name
|
|
self._uid: uid_t = uid
|
|
self._uid: uid_t = uid
|
|
self._type: enum = user_type
|
|
self._type: enum = user_type
|
|
|
|
|
|
|
|
+ def is_manager(self):
|
|
|
|
+ return self._type == UserType.manager
|
|
|
|
+
|
|
def get_uid(self) -> uid_t:
|
|
def get_uid(self) -> uid_t:
|
|
return self._uid
|
|
return self._uid
|
|
|
|
|
|
def get_name(self) -> uname_t:
|
|
def get_name(self) -> uname_t:
|
|
return self._name
|
|
return self._name
|
|
|
|
|
|
- def get_info(self) -> Dict[str: uid_t, str: uname_t]:
|
|
|
|
|
|
+ def get_user_type(self) -> enum:
|
|
|
|
+ return self._type
|
|
|
|
+
|
|
|
|
+ def get_info(self) -> Dict[str, str]:
|
|
return {
|
|
return {
|
|
- "name": self._name,
|
|
|
|
- "uid": self._uid,
|
|
|
|
|
|
+ "name": str(self._name),
|
|
|
|
+ "uid": str(self._uid),
|
|
|
|
+ "manager": self._type == UserType.manager if '1' else '0'
|
|
}
|
|
}
|
|
|
|
|
|
- def evaluate(self) -> score_t:
|
|
|
|
|
|
+ def __repr__(self):
|
|
|
|
+ tmp = UserType.UserTypeStrList
|
|
|
|
+ return f"User {self._uid} {self._name} is {tmp[self._type]}"
|
|
|
|
+
|
|
|
|
+ def evaluate(self, is_right: bool) -> score_t:
|
|
raise UserNotSupportError
|
|
raise UserNotSupportError
|
|
|
|
|
|
def add_score(self, score: score_t) -> score_t:
|
|
def add_score(self, score: score_t) -> score_t:
|
|
raise UserNotSupportError
|
|
raise UserNotSupportError
|
|
|
|
|
|
- def throw_rubbish(self) -> count_t:
|
|
|
|
|
|
+ def throw_rubbish(self, garbage: GarbageBag, garbage_type: enum, loc: location_t) -> bool:
|
|
|
|
+ raise UserNotSupportError
|
|
|
|
+
|
|
|
|
+ def check_rubbish(self, garbage: GarbageBag, right: bool, user) -> bool:
|
|
raise UserNotSupportError
|
|
raise UserNotSupportError
|
|
|
|
|
|
|
|
|
|
@@ -46,35 +77,133 @@ class NormalUser(User):
|
|
self._rubbish = rubbish
|
|
self._rubbish = rubbish
|
|
self._score = score
|
|
self._score = score
|
|
|
|
|
|
- def get_info(self) -> Dict[str: uid_t, str: uname_t, str: score_t, str: count_t]:
|
|
|
|
|
|
+ def __repr__(self):
|
|
|
|
+ return (f"User {self._uid} {self._name} "
|
|
|
|
+ f"reputation {self._reputation} "
|
|
|
|
+ f"rubbish {self._rubbish} "
|
|
|
|
+ f"score {self._score} "
|
|
|
|
+ f"is NORMAL")
|
|
|
|
+
|
|
|
|
+ def get_info(self) -> Dict[str, str]:
|
|
"""
|
|
"""
|
|
获取当前用户的简单信息
|
|
获取当前用户的简单信息
|
|
:return: 用户信息字典
|
|
:return: 用户信息字典
|
|
"""
|
|
"""
|
|
return {
|
|
return {
|
|
- "name": self._name,
|
|
|
|
- "uid": self._uid,
|
|
|
|
- "reputation": self._reputation,
|
|
|
|
- "rubbish": self._rubbish,
|
|
|
|
- "score": self._score
|
|
|
|
|
|
+ "name": str(self._name),
|
|
|
|
+ "uid": str(self._uid),
|
|
|
|
+ "manager": self._type == UserType.manager if '1' else '0',
|
|
|
|
+ "reputation": str(self._reputation),
|
|
|
|
+ "rubbish": str(self._rubbish),
|
|
|
|
+ "score": str(self._score)
|
|
}
|
|
}
|
|
|
|
|
|
- def evaluate(self) -> score_t:
|
|
|
|
|
|
+ def evaluate(self, is_right: bool) -> score_t:
|
|
"""
|
|
"""
|
|
评估信誉积分
|
|
评估信誉积分
|
|
|
|
+ 使用朴素贝叶斯公式为基础
|
|
|
|
+ 总分值: 1000分
|
|
|
|
+ 实际分: P(A|B) * 1000
|
|
|
|
+ A=能正确仍对垃圾的概率
|
|
|
|
+ B=本次仍对垃圾的概率
|
|
|
|
+
|
|
|
|
+ 初始概率:
|
|
|
|
+ P(A) = 0.3 (default_reputation = 300)
|
|
|
|
+ P(B|A) = 0.6
|
|
|
|
+ P(B|^A) = 0.3
|
|
|
|
+ P(B) = 0.8 * 0.3 + 0.1 * 0.7 = 0.31
|
|
|
|
+ p(^B) = 0.69
|
|
|
|
+
|
|
|
|
+ P(A|B) = P(A) * (P(B|A) / P(B)) = P(A) * 2.5806
|
|
|
|
+ P(A|^B) = P(A) * (P(^B|A) / P(^B)) = P(A) * (0.2/0.96) = P(A) * 0.2083
|
|
:return: 信誉积分
|
|
:return: 信誉积分
|
|
"""
|
|
"""
|
|
- ...
|
|
|
|
|
|
+
|
|
|
|
+ if is_right and self._rubbish > conf.max_rubbish_week:
|
|
|
|
+ return self._reputation
|
|
|
|
+
|
|
|
|
+ pa = self._reputation / 1000 # P(A)
|
|
|
|
+ if pa < 0.01:
|
|
|
|
+ pa = 0.01
|
|
|
|
+ p_a = 1 - pa # P(^A)
|
|
|
|
+ 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)
|
|
|
|
+ pb = pba * pa + pb_a * p_a # P(B) = P(B|A) * P(A) + P(B|^A) * P(^A)
|
|
|
|
+ p_b = p_ba * pa + p_b_a * p_a # P(^B) = P(^B|A) * P(A) + P(^B|^A) * P(^A)
|
|
|
|
+
|
|
|
|
+ if is_right:
|
|
|
|
+ new_pa = pa * (pba / pb) # P(A|B)
|
|
|
|
+ else:
|
|
|
|
+ new_pa = pa * (p_ba / p_b) # P(A|^B)
|
|
|
|
+ new_pa = new_pa * 1000
|
|
|
|
+ if int(new_pa) == 0:
|
|
|
|
+ new_pa = 1
|
|
|
|
+ if int(new_pa) > 1000:
|
|
|
|
+ new_pa = 999
|
|
|
|
+
|
|
|
|
+ amplitude = new_pa - self._reputation # 分差
|
|
|
|
+ amplitude_top = 1000 - self._reputation # 距离总分分差
|
|
|
|
+
|
|
|
|
+ if is_right:
|
|
|
|
+ if amplitude >= 20:
|
|
|
|
+ amplitude = amplitude * (amplitude_top / 1000) # 涨分抑制
|
|
|
|
+ else:
|
|
|
|
+ if amplitude <= -20:
|
|
|
|
+ amplitude = amplitude * (self._reputation / 1000) # 总分分差月小扣分越高
|
|
|
|
+
|
|
|
|
+ self._reputation += int(amplitude)
|
|
|
|
+ if self._reputation <= 5:
|
|
|
|
+ self._reputation = 5
|
|
|
|
+ return self._reputation
|
|
|
|
|
|
def add_score(self, score: score_t) -> score_t:
|
|
def add_score(self, score: score_t) -> score_t:
|
|
|
|
+ if self._score + score < 0:
|
|
|
|
+ self._score = 0
|
|
|
|
+ raise UserNotScoreException
|
|
|
|
+
|
|
self._score += score
|
|
self._score += score
|
|
return self._score
|
|
return self._score
|
|
|
|
|
|
- def throw_rubbish(self) -> count_t:
|
|
|
|
|
|
+ def throw_rubbish(self, garbage: GarbageBag, garbage_type: enum, loc: location_t = conf.base_location) -> bool:
|
|
|
|
+ if self._rubbish > conf.max_rubbish_week:
|
|
|
|
+ try:
|
|
|
|
+ self.add_score(-3)
|
|
|
|
+ except UserNotScoreException:
|
|
|
|
+ raise UserRubbishException
|
|
|
|
+ elif self._rubbish > conf.limit_rubbish_week:
|
|
|
|
+ raise UserRubbishException
|
|
|
|
+
|
|
|
|
+ if garbage.is_use() or not garbage.is_check():
|
|
|
|
+ return False
|
|
|
|
+ garbage.config_use(garbage_type, HGSTime(), self._uid, loc)
|
|
|
|
+
|
|
self._rubbish += 1
|
|
self._rubbish += 1
|
|
- return self._rubbish
|
|
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+ def check_rubbish(self, garbage: GarbageBag, right: bool, user: User) -> bool:
|
|
|
|
+ raise UserNotSupportError
|
|
|
|
|
|
|
|
|
|
class ManagerUser(User):
|
|
class ManagerUser(User):
|
|
def __init__(self, name: uname_t, uid: uid_t):
|
|
def __init__(self, name: uname_t, uid: uid_t):
|
|
- super(ManagerUser, self).__init__(name, uid, UserType.normal)
|
|
|
|
|
|
+ super(ManagerUser, self).__init__(name, uid, UserType.manager)
|
|
|
|
+
|
|
|
|
+ def check_rubbish(self, garbage: GarbageBag, right: bool, user: User) -> bool:
|
|
|
|
+ if not garbage.is_use() or garbage.is_check() or user.get_uid() != garbage.get_user():
|
|
|
|
+ return False
|
|
|
|
+ garbage.config_check(right, self._uid)
|
|
|
|
+ user.evaluate(right)
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ if right:
|
|
|
|
+ if garbage.get_type() == GarbageType.recyclable:
|
|
|
|
+ user.add_score(3)
|
|
|
|
+ elif garbage.get_type() == GarbageType.kitchen or garbage.get_type() == GarbageType.hazardous:
|
|
|
|
+ user.add_score(2)
|
|
|
|
+ else:
|
|
|
|
+ user.add_score(1)
|
|
|
|
+ else:
|
|
|
|
+ user.add_score(-4)
|
|
|
|
+ except UserNotScoreException:
|
|
|
|
+ ...
|
|
|
|
+
|
|
|
|
+ return True
|