瀏覽代碼

feat: 排行榜

SongZihuan 3 年之前
父節點
當前提交
29410c6656
共有 6 個文件被更改,包括 268 次插入48 次删除
  1. 4 0
      conf/__init__.py
  2. 49 1
      control/__init__.py
  3. 206 39
      control/tk.py
  4. 4 3
      equipment/scan_user.py
  5. 4 4
      sql/user.py
  6. 1 1
      tool/type_.py

+ 4 - 0
conf/__init__.py

@@ -37,3 +37,7 @@ capture_num = 0  # 摄像头号
 capture_arg = []
 capture_arg = []
 
 
 tk_refresh_delay = 50  # 延时任务的时间
 tk_refresh_delay = 50  # 延时任务的时间
+
+qr_show_uid_len = 12  # qr 码上展示uid的长度
+tk_show_uid_len = qr_show_uid_len  # tk 界面上展示uid的长度
+ranking_tk_show_uid_len = tk_show_uid_len  # tk ranking 界面上展示uid的长度

+ 49 - 1
control/__init__.py

@@ -5,7 +5,7 @@ from sql.db import DB, mysql_db
 from sql.user import update_user, find_user_by_id, creat_new_user
 from sql.user import update_user, find_user_by_id, creat_new_user
 from sql.garbage import update_garbage, creat_new_garbage
 from sql.garbage import update_garbage, creat_new_garbage
 from equipment.scan import HGSCapture, HGSQRCoder, QRCode, capture, qr_capture
 from equipment.scan import HGSCapture, HGSQRCoder, QRCode, capture, qr_capture
-from equipment.scan_user import scan_user
+from equipment.scan_user import scan_user, write_uid_qr, write_all_uid_qr
 from equipment.scan_garbage import scan_garbage, write_gid_qr
 from equipment.scan_garbage import scan_garbage, write_gid_qr
 from core.user import User, UserNotSupportError
 from core.user import User, UserNotSupportError
 from core.garbage import GarbageBag, GarbageType, GarbageBagNotUse
 from core.garbage import GarbageBag, GarbageType, GarbageBagNotUse
@@ -35,6 +35,10 @@ class CreatUserError(ControlError):
     ...
     ...
 
 
 
 
+class RankingUserError(ControlError):
+    ...
+
+
 class ControlScanType:
 class ControlScanType:
     switch_user = 1
     switch_user = 1
     throw_garbage = 2
     throw_garbage = 2
@@ -62,6 +66,10 @@ class Control:
         self._user: Optional[User] = None  # 操作者
         self._user: Optional[User] = None  # 操作者
         self._user_last_time: time_t = 0
         self._user_last_time: time_t = 0
 
 
+    def update_user_time(self):
+        if self.check_user():
+            self._user_last_time = time.time()
+
     def is_manager(self):
     def is_manager(self):
         if not self.check_user():
         if not self.check_user():
             return False
             return False
@@ -94,6 +102,11 @@ class Control:
         self.__check_user()
         self.__check_user()
         return self._user.get_info()
         return self._user.get_info()
 
 
+    def get_uid_no_update(self):
+        if not self.check_user():
+            return ""
+        return self._user.get_uid()
+
     def get_user_info_no_update(self) -> Dict[str, str]:
     def get_user_info_no_update(self) -> Dict[str, str]:
         if not self.check_user():
         if not self.check_user():
             return {}
             return {}
@@ -188,5 +201,40 @@ class Control:
             re.append(user)
             re.append(user)
         return re
         return re
 
 
+    def get_uid_qrcode(self, uid: uid_t, path: str) -> Tuple[str, Optional[User]]:
+        return write_uid_qr(uid, path, self._db)
+
+    def get_uid_qrcode_from_list(self, uid_list: List[uid_t], path: str) -> List[Tuple[str, Optional[User]]]:
+        re = []
+        for uid in uid_list:
+            res = write_uid_qr(uid, path, self._db)
+            re.append(res)
+        return re
+
+    def get_all_uid_qrcode(self, path: str, where: str = "") -> List[str]:
+        return write_all_uid_qr(path, self._db, where=where)
+
+    def ranking(self, limit: int = 0, order_by: str = 'DESC') -> list[Tuple[uid_t, uname_t, score_t, score_t]]:
+        """
+        获取排行榜的功能
+        :return:
+        """
+        if limit > 0:
+            limit = f"LIMIT {int(limit)}"
+        else:
+            limit = ""
+
+        if order_by != 'ASC' and order_by != 'DESC':
+            order_by = 'DESC'
+
+        cur = self._db.search((f"SELECT uid, name, score, reputation "
+                               f"FROM user "
+                               f"WHERE manager = 0 "
+                               f"ORDER BY reputation {order_by}, score {order_by} "
+                               f"{limit}"))
+        if cur is None:
+            raise RankingUserError
+        return list(cur.fetchall())
+
 
 
 global_control = Control()
 global_control = Control()

+ 206 - 39
control/tk.py

@@ -29,6 +29,8 @@ class GarbageStationStatus:
         self._garbage: Optional[GarbageBag] = None
         self._garbage: Optional[GarbageBag] = None
         self._flat = GarbageStationStatus.status_normal
         self._flat = GarbageStationStatus.status_normal
         self._have_easter_eggs = False
         self._have_easter_eggs = False
+        self.rank = None
+        self.rank_index = 0
 
 
     def to_get_garbage_type(self, garbage: GarbageBag):
     def to_get_garbage_type(self, garbage: GarbageBag):
         self._flat = GarbageStationStatus.status_get_garbage_type
         self._flat = GarbageStationStatus.status_get_garbage_type
@@ -59,6 +61,7 @@ class GarbageStationStatus:
         return self._ctrl.switch_user(user)
         return self._ctrl.switch_user(user)
 
 
     def throw_garbage(self, garbage_type: enum):
     def throw_garbage(self, garbage_type: enum):
+        self.update_user_time()
         if self._flat != GarbageStationStatus.status_get_garbage_type or self._garbage is None:
         if self._flat != GarbageStationStatus.status_get_garbage_type or self._garbage is None:
             self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             return
             return
@@ -73,6 +76,7 @@ class GarbageStationStatus:
             self._garbage = None
             self._garbage = None
 
 
     def check_garbage(self, check: bool):
     def check_garbage(self, check: bool):
+        self.update_user_time()
         if self._flat != GarbageStationStatus.status_get_garbage_check or self._garbage is None:
         if self._flat != GarbageStationStatus.status_get_garbage_check or self._garbage is None:
             self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             return
             return
@@ -86,6 +90,7 @@ class GarbageStationStatus:
             self._garbage = None
             self._garbage = None
 
 
     def show_garbage_info(self):
     def show_garbage_info(self):
+        self.update_user_time()
         if self._flat != GarbageStationStatus.status_get_garbage_check or self._garbage is None:
         if self._flat != GarbageStationStatus.status_get_garbage_check or self._garbage is None:
             self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             return
             return
@@ -102,6 +107,7 @@ class GarbageStationStatus:
                                             f"Date:\n  {time_str}"))
                                             f"Date:\n  {time_str}"))
 
 
     def show_user_info(self):
     def show_user_info(self):
+        self.update_user_time()
         if not self._ctrl.check_user():
         if not self._ctrl.check_user():
             self._win.show_warning("Operation Fail", "You should login first")
             self._win.show_warning("Operation Fail", "You should login first")
             return
             return
@@ -120,6 +126,7 @@ class GarbageStationStatus:
                                               f"Rubbish: {info['rubbish']}"))
                                               f"Rubbish: {info['rubbish']}"))
 
 
     def show_help_info(self):
     def show_help_info(self):
+        self.update_user_time()
         self._win.show_msg("Help", f'''
         self._win.show_msg("Help", f'''
 HGSSystem:
 HGSSystem:
   1) Scan User QR code
   1) Scan User QR code
@@ -131,6 +138,7 @@ HGSSystem:
         '''.strip())
         '''.strip())
 
 
     def show_about_info(self):
     def show_about_info(self):
+        self.update_user_time()
         self._win.show_msg("About", f'''
         self._win.show_msg("About", f'''
 HGSSystem (c) SuperHuan
 HGSSystem (c) SuperHuan
 From github
 From github
@@ -140,6 +148,7 @@ Run on python {sys.version}
                 '''.strip())
                 '''.strip())
 
 
     def show_exit(self):
     def show_exit(self):
+        self.update_user_time()
         if self._ctrl.is_manager():
         if self._ctrl.is_manager():
             self._win.exit_win()
             self._win.exit_win()
             return
             return
@@ -149,6 +158,7 @@ Run on python {sys.version}
         return self._ctrl.is_manager()
         return self._ctrl.is_manager()
 
 
     def easter_eggs(self):
     def easter_eggs(self):
+        self.update_user_time()
         if (not self._have_easter_eggs) and random.randint(0, 10) != 1:  # 10% 概率触发
         if (not self._have_easter_eggs) and random.randint(0, 10) != 1:  # 10% 概率触发
             return
             return
         self._have_easter_eggs = True
         self._have_easter_eggs = True
@@ -161,11 +171,52 @@ Run on python {sys.version}
                 '''.strip())
                 '''.strip())
 
 
     def show_search_info(self):
     def show_search_info(self):
+        self.update_user_time()
         self._win.show_msg("Search", f'''
         self._win.show_msg("Search", f'''
 He will get the camera content and feedback the garbage type.
 He will get the camera content and feedback the garbage type.
 The function has not yet been implemented.
 The function has not yet been implemented.
                 '''.strip())
                 '''.strip())
 
 
+    def get_show_rank(self):
+        self.update_user_time()
+        rank_list = self._ctrl.ranking(limit=20)
+        self.rank = [[]]
+        for i, r in enumerate(rank_list):
+            if len(self.rank[-1]) == 5:
+                self.rank.append([])
+            color = None
+            if i == 0:
+                color = "#eaff56"
+            elif i == 1:
+                color = "#ffa631"
+            elif i == 2:
+                color = "#ff7500"
+            elif r[0] == self._ctrl.get_uid_no_update():
+                color = "#b0a4e3"
+            self.rank[-1].append((i + 1, r[1], r[0], r[2], r[3], color))
+        if len(self.rank[0]) == 0:
+            self.rank = None
+            self._win.show_warning("RankError", f'Unable to get leaderboard data')
+            return
+        self.rank_index = 0
+        self.show_rank(0)
+
+    def show_rank(self, n: int):
+        self.update_user_time()
+        self.rank_index += n
+
+        if self.rank_index < 0 or self.rank_index >= len(self.rank):
+            self._win.show_msg("RankError", f'Unable to get leaderboard data')
+            return
+
+        self._win.show_rank(self.rank_index + 1, len(self.rank),
+                            lambda: self.show_rank(-1),
+                            lambda: self.show_rank(+1),
+                            self.rank[self.rank_index])
+
+    def update_user_time(self):
+        self._ctrl.update_user_time()
+
 
 
 class GarbageStation:
 class GarbageStation:
     def __init__(self, ctrl: Control = global_control, refresh_delay: int = conf.tk_refresh_delay):
     def __init__(self, ctrl: Control = global_control, refresh_delay: int = conf.tk_refresh_delay):
@@ -212,7 +263,7 @@ class GarbageStation:
         self._user_rubbish: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
         self._user_rubbish: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
                                              tk.StringVar(), "Garbage")
                                              tk.StringVar(), "Garbage")
         self._user_eval: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
         self._user_eval: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
-                                          tk.StringVar(), "Evaluation")
+                                          tk.StringVar(), "Reputation")
         self._user_img = tk.Label(self._user_frame)
         self._user_img = tk.Label(self._user_frame)
 
 
         self._throw_ctrl_frame = tk.Frame(self._window)
         self._throw_ctrl_frame = tk.Frame(self._window)
@@ -235,18 +286,35 @@ class GarbageStation:
                                            tk.Button(self._user_btn_frame)]
                                            tk.Button(self._user_btn_frame)]
 
 
         self._msg_frame = tk.Frame(self._window)
         self._msg_frame = tk.Frame(self._window)
-        self._msg_table = tk.Label(self._msg_frame), tk.Label(self._msg_frame), tk.StringVar(), tk.StringVar()
+        self._msg_label = tk.Label(self._msg_frame), tk.Label(self._msg_frame), tk.StringVar(), tk.StringVar()
         self._msg_hide = tk.Button(self._msg_frame)
         self._msg_hide = tk.Button(self._msg_frame)
 
 
+        self._rank_frame = tk.Frame(self._window)
+        self._rank_label = [tk.Label(self._rank_frame),
+                            tk.Label(self._rank_frame),
+                            tk.Label(self._rank_frame),
+                            tk.Label(self._rank_frame),
+                            tk.Label(self._rank_frame),
+                            tk.Label(self._rank_frame)]
+        self._rank_var = [tk.StringVar(),
+                          tk.StringVar(),
+                          tk.StringVar(),
+                          tk.StringVar(),
+                          tk.StringVar(),
+                          tk.StringVar()]
+        self._rank_btn = [tk.Button(self._rank_frame), tk.Button(self._rank_frame), tk.Button(self._rank_frame)]
+
     def __conf_font_size(self, n: Union[int, float] = 1):
     def __conf_font_size(self, n: Union[int, float] = 1):
-        self._title_font_size = int(25 * n)
+        self._title_font_size = int(27 * n)
         self._win_ctrl_font_size = int(15 * n)
         self._win_ctrl_font_size = int(15 * n)
         self._win_info_font_size = int(18 * n)
         self._win_info_font_size = int(18 * n)
         self._throw_ctrl_btn_font_size = int(20 * n)
         self._throw_ctrl_btn_font_size = int(20 * n)
-        self.__check_ctrl_btn_font_size = int(20 * n)
+        self._check_ctrl_btn_font_size = int(20 * n)
         self._sys_info_font_size = int(18 * n)
         self._sys_info_font_size = int(18 * n)
         self._user_btn_font_size = int(20 * n)
         self._user_btn_font_size = int(20 * n)
-        self.__msg_font_size = int(20 * n)
+        self._msg_font_size = int(20 * n)
+        self._rank_font_title_size = int(24 * n)
+        self._rank_font_size = int(16 * n)
 
 
     def __conf_tk(self):
     def __conf_tk(self):
         self.__conf_title_label()
         self.__conf_title_label()
@@ -258,7 +326,8 @@ class GarbageStation:
         self.__conf_cap_label()
         self.__conf_cap_label()
         self.__conf_user_btn()
         self.__conf_user_btn()
         self.__conf_msg()
         self.__conf_msg()
-        self.hide_msg()  # 隐藏消息
+        self.__conf_rank()
+        self.hide_msg_rank()  # 隐藏消息
 
 
     def __conf_windows(self):
     def __conf_windows(self):
         self._window.title('HGSSystem: Garbage Station')
         self._window.title('HGSSystem: Garbage Station')
@@ -320,16 +389,19 @@ class GarbageStation:
 
 
         bt_help: tk.Button = self._win_ctrl_button[0]
         bt_help: tk.Button = self._win_ctrl_button[0]
         bt_help['text'] = 'Help'
         bt_help['text'] = 'Help'
+        bt_help['bg'] = '#A9A9A9'
         bt_help['command'] = lambda: self._status.show_help_info()
         bt_help['command'] = lambda: self._status.show_help_info()
         bt_help.place(relx=0.81, rely=0.01, relwidth=0.05, relheight=0.05)
         bt_help.place(relx=0.81, rely=0.01, relwidth=0.05, relheight=0.05)
 
 
         bt_about: tk.Button = self._win_ctrl_button[1]
         bt_about: tk.Button = self._win_ctrl_button[1]
         bt_about['text'] = 'About'
         bt_about['text'] = 'About'
+        bt_about['bg'] = '#A9A9A9'
         bt_about['command'] = lambda: self._status.show_about_info()
         bt_about['command'] = lambda: self._status.show_about_info()
         bt_about.place(relx=0.87, rely=0.01, relwidth=0.05, relheight=0.05)
         bt_about.place(relx=0.87, rely=0.01, relwidth=0.05, relheight=0.05)
 
 
         bt_exit: tk.Button = self._win_ctrl_button[2]
         bt_exit: tk.Button = self._win_ctrl_button[2]
         bt_exit['text'] = 'Exit'
         bt_exit['text'] = 'Exit'
+        bt_exit['bg'] = '#A9A9A9'
         bt_exit['command'] = lambda: self._status.show_exit()
         bt_exit['command'] = lambda: self._status.show_exit()
         bt_exit.place(relx=0.93, rely=0.01, relwidth=0.05, relheight=0.05)
         bt_exit.place(relx=0.93, rely=0.01, relwidth=0.05, relheight=0.05)
 
 
@@ -395,7 +467,7 @@ class GarbageStation:
                                            ("Hazardous", "#DC143C"),
                                            ("Hazardous", "#DC143C"),
                                            ("Kitchen", "#32CD32")]
                                            ("Kitchen", "#32CD32")]
 
 
-        self._throw_ctrl_frame.place(relx=0.45, rely=0.1, relwidth=0.53, relheight=0.70)
+        self.__show_throw_frame()
 
 
         for btn, info in zip(self._throw_ctrl_btn, btn_info):
         for btn, info in zip(self._throw_ctrl_btn, btn_info):
             btn['font'] = btn_font
             btn['font'] = btn_font
@@ -413,11 +485,11 @@ class GarbageStation:
         self._throw_ctrl_btn[3].place(relx=0.505, rely=0.505, relwidth=0.495, relheight=0.495)
         self._throw_ctrl_btn[3].place(relx=0.505, rely=0.505, relwidth=0.495, relheight=0.495)
 
 
     def __conf_check_btn(self):
     def __conf_check_btn(self):
-        btn_font = self.__make_font(size=self.__check_ctrl_btn_font_size, weight="bold")
+        btn_font = self.__make_font(size=self._check_ctrl_btn_font_size, weight="bold")
         btn_info: List[Tuple[str, str]] = [("Fail", "#ef7a82"),
         btn_info: List[Tuple[str, str]] = [("Fail", "#ef7a82"),
                                            ("Pass", "#70f3ff")]
                                            ("Pass", "#70f3ff")]
 
 
-        self._check_ctrl_frame.place(relx=0.45, rely=0.82, relwidth=0.53, relheight=0.16)
+        self.__show_check_frame()
 
 
         for btn, info in zip(self._check_ctrl_btn, btn_info):
         for btn, info in zip(self._check_ctrl_btn, btn_info):
             btn['font'] = btn_font
             btn['font'] = btn_font
@@ -487,6 +559,7 @@ class GarbageStation:
             height += height_label + h_label_s / height_count
             height += height_label + h_label_s / height_count
 
 
         self._user_btn[0]['state'] = 'disable'
         self._user_btn[0]['state'] = 'disable'
+        self._user_btn[1]['command'] = lambda: self._status.get_show_rank()
         self._user_btn[2]['command'] = lambda: self._status.show_search_info()
         self._user_btn[2]['command'] = lambda: self._status.show_search_info()
 
 
     def __conf_cap_label(self):
     def __conf_cap_label(self):
@@ -494,53 +567,146 @@ class GarbageStation:
         self._cap_label.place(relx=0.22, rely=0.66, relwidth=0.2, relheight=0.32)
         self._cap_label.place(relx=0.22, rely=0.66, relwidth=0.2, relheight=0.32)
 
 
     def __conf_msg(self):
     def __conf_msg(self):
-        title_font = self.__make_font(size=self.__msg_font_size + 1, weight="bold")
-        info_font = self.__make_font(size=self.__msg_font_size - 1)
+        title_font = self.__make_font(size=self._msg_font_size + 1, weight="bold")
+        info_font = self.__make_font(size=self._msg_font_size - 1)
 
 
         self._msg_frame['bg'] = "#F5FFFA"
         self._msg_frame['bg'] = "#F5FFFA"
         self._msg_frame['bd'] = 5
         self._msg_frame['bd'] = 5
         self._msg_frame['relief'] = "ridge"
         self._msg_frame['relief'] = "ridge"
         # frame 不会立即显示
         # frame 不会立即显示
 
 
-        self._msg_table[0]['font'] = title_font
-        self._msg_table[0]['bg'] = "#F5FFFA"
-        self._msg_table[0]['anchor'] = 'w'
-        self._msg_table[0]['textvariable'] = self._msg_table[2]
+        self._msg_label[0]['font'] = title_font
+        self._msg_label[0]['bg'] = "#F5FFFA"
+        self._msg_label[0]['anchor'] = 'w'
+        self._msg_label[0]['textvariable'] = self._msg_label[2]
 
 
-        self._msg_table[1]['font'] = info_font
-        self._msg_table[1]['bg'] = "#F5FFFA"
-        self._msg_table[1]['anchor'] = 'nw'
-        self._msg_table[1]['justify'] = 'left'
-        self._msg_table[1]['textvariable'] = self._msg_table[3]
+        self._msg_label[1]['font'] = info_font
+        self._msg_label[1]['bg'] = "#F5FFFA"
+        self._msg_label[1]['anchor'] = 'nw'
+        self._msg_label[1]['justify'] = 'left'
+        self._msg_label[1]['textvariable'] = self._msg_label[3]
 
 
-        self._msg_table[0].place(relx=0.05, rely=0.05, relwidth=0.9, relheight=0.1)
-        self._msg_table[1].place(relx=0.075, rely=0.2, relwidth=0.85, relheight=0.64)
+        self._msg_label[0].place(relx=0.05, rely=0.05, relwidth=0.9, relheight=0.1)
+        self._msg_label[1].place(relx=0.075, rely=0.2, relwidth=0.85, relheight=0.64)
 
 
         self._msg_hide['font'] = info_font
         self._msg_hide['font'] = info_font
         self._msg_hide['bg'] = "#00CED1"
         self._msg_hide['bg'] = "#00CED1"
-        self._msg_hide['text'] = 'Hide-Msg'
-        self._msg_hide['command'] = lambda: self.hide_msg()
+        self._msg_hide['text'] = 'close'
+        self._msg_hide['command'] = lambda: self.hide_msg_rank(True)
         self._msg_hide.place(relx=0.375, rely=0.85, relwidth=0.25, relheight=0.1)
         self._msg_hide.place(relx=0.375, rely=0.85, relwidth=0.25, relheight=0.1)
 
 
     def show_msg(self, title, info, msg_type='info'):
     def show_msg(self, title, info, msg_type='info'):
-        self._msg_table[2].set(f'{msg_type}: {title}')
-        self._msg_table[3].set(f'{info}')
+        self._msg_label[2].set(f'{msg_type}: {title}')
+        self._msg_label[3].set(f'{info}')
+
+        self.__show_check_frame()
         self._msg_frame.place(relx=0.45, rely=0.20, relwidth=0.53, relheight=0.50)
         self._msg_frame.place(relx=0.45, rely=0.20, relwidth=0.53, relheight=0.50)
         frame_width = self._win_width * 0.53
         frame_width = self._win_width * 0.53
-        self._msg_table[1]['wraplength'] = frame_width * 0.85 - 5  # 设定自动换行的像素
+        self._msg_label[1]['wraplength'] = frame_width * 0.85 - 5  # 设定自动换行的像素
+
         self._throw_ctrl_frame.place_forget()
         self._throw_ctrl_frame.place_forget()
+        self._rank_frame.place_forget()
+
         self._msg_time = time.time()
         self._msg_time = time.time()
 
 
     def show_warning(self, title, info):
     def show_warning(self, title, info):
         self.show_msg(title, info, msg_type='Warning')
         self.show_msg(title, info, msg_type='Warning')
 
 
-    def hide_msg(self):
-        self._msg_table[2].set('')
-        self._msg_table[3].set('')
-        self._throw_ctrl_frame.place(relx=0.45, rely=0.1, relwidth=0.53, relheight=0.70)
+    def __conf_rank(self):
+        title_font = self.__make_font(size=self._rank_font_title_size, weight="bold")
+        info_font = self.__make_font(size=self._rank_font_size)
+        btn_font = self.__make_font(size=self._msg_font_size - 1)
+
+        self._rank_frame['bg'] = "#F5F5DC"
+        self._rank_frame['relief'] = "ridge"
+        self._rank_frame['bd'] = 5
+        # frame 不会立即显示
+
+        self._rank_label[0]['font'] = title_font
+        self._rank_label[0]['bg'] = "#F5F5DC"
+        self._rank_label[0]['textvariable'] = self._rank_var[0]
+        self._rank_label[0].place(relx=0.02, rely=0.00, relwidth=0.96, relheight=0.1)
+
+        for lb, v in zip(self._rank_label[1:], self._rank_var[1:]):
+            lb['font'] = info_font
+            lb['bg'] = "#F5FFFA"
+            lb['textvariable'] = v
+            lb['relief'] = "ridge"
+            lb['bd'] = 2
+
+        # 标签结束的高度为 0.12 + 0.15 * 5 = 0.87
+        for btn, text in zip(self._rank_btn, ("prev", "close", "next")):
+            btn['font'] = btn_font
+            btn['bg'] = "#00CED1"
+            btn['text'] = text
+
+        self._rank_btn[0].place(relx=0.050, rely=0.88, relwidth=0.25, relheight=0.1)
+        self._rank_btn[1].place(relx=0.375, rely=0.88, relwidth=0.25, relheight=0.1)
+        self._rank_btn[2].place(relx=0.700, rely=0.88, relwidth=0.25, relheight=0.1)
+
+    def set_rank_info(self, page, page_c, prev_func: Callable, next_func: Callable,
+                      rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]]):
+        if len(rank_info) > 5:
+            rank_info = rank_info[:5]
+
+        for lb in self._rank_label[1:]:  # 隐藏全部标签
+            lb.place_forget()
+
+        height = 0.12
+        for i, info in enumerate(rank_info):
+            no, name, uid, score, eval_, color = info
+            self._rank_var[i + 1].set(f"NO.{no}  {name}\nUID: {uid[0:conf.ranking_tk_show_uid_len]}\n"
+                                      f"Score: {score} Reputation: {eval_}")
+            if color is None:
+                self._rank_label[i + 1]['bg'] = "#F5FFFA"
+            else:
+                self._rank_label[i + 1]['bg'] = color
+
+            self._rank_label[i + 1].place(relx=0.04, rely=height, relwidth=0.92, relheight=0.13)
+            height += 0.15
+
+        self._rank_btn[0]['command'] = prev_func
+        self._rank_btn[0]['state'] = 'normal'
+        self._rank_btn[1]['command'] = lambda: self.hide_msg_rank(True)
+        self._rank_btn[2]['command'] = next_func
+        self._rank_btn[2]['state'] = 'normal'
+
+        if page == 1:
+            self._rank_btn[0]['state'] = 'disable'
+        if page == page_c:
+            self._rank_btn[2]['state'] = 'disable'
+
+    def show_rank(self, page: int, page_c: int, prev_func: Callable, next_func: Callable,
+                  rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]],
+                  title: str = 'Ranking'):
+        self._rank_var[0].set(f'{title} ({page}/{page_c})')
+        self._rank_frame.place(relx=0.47, rely=0.15, relwidth=0.47, relheight=0.80)
+        frame_width = self._win_width * 0.53
+
+        for lb in self._rank_label[1:]:
+            lb['wraplength'] = frame_width * 0.85 - 5  # 设定自动换行的像素
+
+        self.set_rank_info(page, page_c, prev_func, next_func, rank_info)
+        self._throw_ctrl_frame.place_forget()
+        self._check_ctrl_frame.place_forget()
         self._msg_frame.place_forget()
         self._msg_frame.place_forget()
         self._msg_time = None
         self._msg_time = None
 
 
+    def hide_msg_rank(self, update: bool = False):
+        self.__show_check_frame()  # rank会令此消失
+        self.__show_throw_frame()  # rank和msg令此消失
+        self._msg_frame.place_forget()
+        self._rank_frame.place_forget()
+        self._msg_time = None
+        if update:
+            self._status.update_user_time()
+
+    def __show_check_frame(self):
+        self._check_ctrl_frame.place(relx=0.45, rely=0.82, relwidth=0.53, relheight=0.16)
+
+    def __show_throw_frame(self):
+        self._throw_ctrl_frame.place(relx=0.45, rely=0.1, relwidth=0.53, relheight=0.70)
+
     def __define_after(self, ms, func, *args):
     def __define_after(self, ms, func, *args):
         self._window.after(ms, self.__after_func_maker(func), *args)
         self._window.after(ms, self.__after_func_maker(func), *args)
 
 
@@ -589,9 +755,9 @@ class GarbageStation:
                 uid.set('error')
                 uid.set('error')
             else:
             else:
                 uid.set(uid_get[0:21])
                 uid.set(uid_get[0:21])
-            eval_.set('Manager-User')
-            rubbish.set('Manager-User')
-            score.set('Manager-User')
+            eval_.set('Manager')
+            rubbish.set('Manager')
+            score.set('Manager')
             self.__switch_to_manager_user()
             self.__switch_to_manager_user()
         else:
         else:
             name.set(user_info.get('name'))
             name.set(user_info.get('name'))
@@ -599,7 +765,7 @@ class GarbageStation:
             if uid_get is None or len(uid_get) < 32:
             if uid_get is None or len(uid_get) < 32:
                 uid.set('error')
                 uid.set('error')
             else:
             else:
-                uid.set(uid_get[0:21])
+                uid.set(uid_get[0:conf.tk_show_uid_len])
             eval_.set(user_info.get('reputation'))
             eval_.set(user_info.get('reputation'))
             rubbish.set(user_info.get('rubbish'))
             rubbish.set(user_info.get('rubbish'))
             score.set(user_info.get('score'))
             score.set(user_info.get('score'))
@@ -632,7 +798,7 @@ class GarbageStation:
             self.update_control()
             self.update_control()
         elif res[0] == ControlScanType.throw_garbage:
         elif res[0] == ControlScanType.throw_garbage:
             self._status.to_get_garbage_type(res[1])
             self._status.to_get_garbage_type(res[1])
-            self.hide_msg()  # 如果有msg也马上隐藏
+            self.hide_msg_rank()  # 如果有msg也马上隐藏
             self.update_control()
             self.update_control()
         elif res[0] == ControlScanType.check_garbage:
         elif res[0] == ControlScanType.check_garbage:
             self._status.to_get_garbage_check(res[1])
             self._status.to_get_garbage_check(res[1])
@@ -644,7 +810,7 @@ class GarbageStation:
             return
             return
 
 
         if time.time() - self._msg_time > 10:  # 10s 自动关闭消息
         if time.time() - self._msg_time > 10:  # 10s 自动关闭消息
-            self.hide_msg()
+            self.hide_msg_rank()
 
 
     def __switch_to_normal_user(self):
     def __switch_to_normal_user(self):
         self.normal_user_disable()
         self.normal_user_disable()
@@ -690,5 +856,6 @@ class GarbageStation:
         self._window.destroy()
         self._window.destroy()
 
 
 
 
-station = GarbageStation()
-station.mainloop()
+if __name__ == '__main__':
+    station = GarbageStation()
+    station.mainloop()

+ 4 - 3
equipment/scan_user.py

@@ -1,3 +1,4 @@
+import conf
 from core.user import User
 from core.user import User
 from sql.db import DB, mysql_db
 from sql.db import DB, mysql_db
 from sql.user import find_user_by_id
 from sql.user import find_user_by_id
@@ -46,7 +47,7 @@ def make_uid_image(uid: uid_t, name: uname_t, path: str):
     res = qr.make_img(path)
     res = qr.make_img(path)
     if not res:
     if not res:
         return False
         return False
-    write_text((60, 5), "noto", f"User: {name} {uid[0: 12]}", path)
+    write_text((60, 5), "noto", f"User: {name} {uid[0: conf.qr_show_uid_len]}", path)
     return True
     return True
 
 
 
 
@@ -62,7 +63,7 @@ def write_uid_qr(uid: uid_t, path: str, db: DB, name="nu") -> Tuple[str, Optiona
     return "", None
     return "", None
 
 
 
 
-def write_all_uid_qr(path: str, db: DB, name="nu", where: str = "") -> List[Tuple[str,]]:
+def write_all_uid_qr(path: str, db: DB, name="nu", where: str = "") -> List[str]:
     if len(where) > 0:
     if len(where) > 0:
         where = f"WHERE {where}"
         where = f"WHERE {where}"
 
 
@@ -76,7 +77,7 @@ def write_all_uid_qr(path: str, db: DB, name="nu", where: str = "") -> List[Tupl
         assert len(res) == 2
         assert len(res) == 2
         path_ = __get_uid_qr_file_name(res[0], res[1], path, name)
         path_ = __get_uid_qr_file_name(res[0], res[1], path, name)
         if make_uid_image(res[0], res[1], path_):
         if make_uid_image(res[0], res[1], path_):
-            re_list.append((path_,))
+            re_list.append(path_)
     return re_list
     return re_list
 
 
 
 

+ 4 - 4
sql/user.py

@@ -3,7 +3,7 @@ from tool.type_ import *
 from tool.login import creat_uid, randomPassword
 from tool.login import creat_uid, randomPassword
 from core.user import NormalUser, ManagerUser, User
 from core.user import NormalUser, ManagerUser, User
 import conf
 import conf
-from .garbage import countGarbageByTime
+from garbage import countGarbageByTime
 
 
 
 
 def find_user_by_id(uid: uid_t, db: DB) -> Optional[User]:
 def find_user_by_id(uid: uid_t, db: DB) -> Optional[User]:
@@ -84,17 +84,17 @@ def creat_new_user(name: Optional[uname_t], passwd: Optional[passwd_t], phone: p
 
 
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
-    name_ = 'Huan8'
+    name_ = 'Huan12'
     usr = find_user_by_name(name_, "123", mysql_db)
     usr = find_user_by_name(name_, "123", mysql_db)
     if usr is None:
     if usr is None:
         usr = creat_new_user(name_, "123", "12345678900", False, mysql_db)
         usr = creat_new_user(name_, "123", "12345678900", False, mysql_db)
     print(usr)
     print(usr)
 
 
-    for i in range(90):
+    for i in range(9):
         usr.evaluate(False)
         usr.evaluate(False)
         print(usr)
         print(usr)
 
 
-    for i in range(90):
+    for i in range(1):
         usr.evaluate(True)
         usr.evaluate(True)
         print(usr)
         print(usr)
 
 

+ 1 - 1
tool/type_.py

@@ -1,4 +1,4 @@
-from typing import Dict, List, Tuple, Union, Optional
+from typing import Dict, List, Tuple, Union, Optional, Callable
 
 
 gid_t = str  # garbage bag id 类型
 gid_t = str  # garbage bag id 类型
 uid_t = str  # user id 类型
 uid_t = str  # user id 类型