diff --git a/src/base/LibTimeSelector.py b/src/base/LibTimeSelector.py index 27234c5..b8df859 100644 --- a/src/base/LibTimeSelector.py +++ b/src/base/LibTimeSelector.py @@ -9,6 +9,8 @@ See the LICENSE file for details. """ import queue +from datetime import datetime + from base.LibOperator import LibOperator @@ -29,25 +31,33 @@ class LibTimeSelector(LibOperator): super().__init__(input_queue, output_queue) @staticmethod - def _timeToMins( + def _timeStrToMins( time_str: str ) -> int: """ Convert time string "HH:MM" to minutes since midnight. + + Example: + "10:00" -> 600 + "13:30" -> 810 """ hour, minute = map(int, time_str.split(":")) return hour*60 + minute @staticmethod - def _minsToTime( + def _minsToTimeStr( mins: int ) -> str: """ Convert minutes since midnight to time string "HH:MM". + + Example: + 600 -> "10:00" + 810 -> "13:30" """ - hour, minute = divmod(mins, 60) + hour, minute = divmod(int(mins), 60) return f"{hour:02d}:{minute:02d}" @@ -99,11 +109,11 @@ class LibTimeSelector(LibOperator): for time_opt in time_options: # Parse time value based on context if is_reserve: + # Reservation context: parse 'time' attribute time_attr = time_opt.get_attribute("time") if time_attr == "now": - from datetime import datetime now = datetime.now() - time_val = now.hour * 60 + now.minute + time_val = now.hour*60 + now.minute elif time_attr and time_attr.isdigit(): time_val = int(time_attr) else: @@ -114,9 +124,7 @@ class LibTimeSelector(LibOperator): if not (time_attr and time_attr.isdigit()): continue time_val = int(time_attr) - - free_times.append(time_opt.text.strip() if not is_reserve else self._minsToTime(time_val)) - + free_times.append(time_opt.text.strip() if not is_reserve else self._minsToTimeStr(time_val)) actual_diff = time_val - target_time abs_diff = abs(actual_diff) @@ -125,11 +133,9 @@ class LibTimeSelector(LibOperator): (abs_diff == best_time_diff and ((prefer_earlier and actual_diff <= 0) or (not prefer_earlier and actual_diff >= 0)))): - best_time_diff = abs_diff best_actual_diff = actual_diff best_time_opt = time_opt - if best_time_opt is not None: return (best_time_opt, best_time_opt.text.strip(), best_actual_diff, free_times) return (None, None, None, free_times) diff --git a/src/operators/LibRenew.py b/src/operators/LibRenew.py index cea784c..f6cf153 100644 --- a/src/operators/LibRenew.py +++ b/src/operators/LibRenew.py @@ -91,7 +91,7 @@ class LibRenew(LibTimeSelector): renew_info = reserve_info["renew_time"] max_diff = renew_info["max_diff"] prefer_earlier = renew_info["prefer_early"] - target_renew_mins = self._timeToMins(end_time) + renew_info["expect_duration"]*60 + target_renew_mins = self._timeStrToMins(end_time) + renew_info["expect_duration"]*60 # Validate and adjust target renew time to library closing time if not self.__validateAndAdjustRenewTime(end_time, target_renew_mins): @@ -127,12 +127,12 @@ class LibRenew(LibTimeSelector): """ LIBRARY_CLOSE_TIME = 1410 # 23:30 in minutes if target_renew_mins > LIBRARY_CLOSE_TIME: - actual_renew_duration = LIBRARY_CLOSE_TIME - self._timeToMins(end_time) + actual_renew_duration = LIBRARY_CLOSE_TIME - self._timeStrToMins(end_time) if actual_renew_duration <= 0: self._showTrace(f"当前结束时间 {end_time} 已接近闭馆时间,无法续约 !") return False self._showTrace( - f"续约时间已调整至闭馆时间 {self._minsToTime(LIBRARY_CLOSE_TIME)}," + f"续约时间已调整至闭馆时间 {self._minsToTimeStr(LIBRARY_CLOSE_TIME)}," f"实际续约时长为 {actual_renew_duration//60} 小时 {actual_renew_duration%60} 分钟" ) return True diff --git a/src/operators/LibReserve.py b/src/operators/LibReserve.py index 224eeee..adac708 100644 --- a/src/operators/LibReserve.py +++ b/src/operators/LibReserve.py @@ -190,10 +190,10 @@ class LibReserve(LibTimeSelector): if reserve_info.get("end_time") is None: reserve_info["end_time"] = {} if "time" not in reserve_info["end_time"]: - end_mins = self._timeToMins(reserve_info["begin_time"]["time"]) + end_mins = self._timeStrToMins(reserve_info["begin_time"]["time"]) end_mins = end_mins + int(reserve_info["expect_duration"]*60) reserve_info["end_time"] = { - "time": self._minsToTime(end_mins), + "time": self._minsToTimeStr(end_mins), "max_diff": 30, "prefer_early": False } @@ -215,8 +215,8 @@ class LibReserve(LibTimeSelector): ): begin_time, end_time = reserve_info["begin_time"], reserve_info["end_time"] - begin_mins = self._timeToMins(begin_time["time"]) - end_mins = self._timeToMins(end_time["time"]) + begin_mins = self._timeStrToMins(begin_time["time"]) + end_mins = self._timeStrToMins(end_time["time"]) # if end time is earlier than begin_time, exchange them if end_mins < begin_mins: self._showTrace( @@ -225,15 +225,15 @@ class LibReserve(LibTimeSelector): reserve_info["end_time"] = begin_time reserve_info["begin_time"] = end_time begin_time, end_time = reserve_info["begin_time"], reserve_info["end_time"] - begin_mins = self._timeToMins(begin_time["time"]) - end_mins = self._timeToMins(end_time["time"]) + begin_mins = self._timeStrToMins(begin_time["time"]) + end_mins = self._timeStrToMins(end_time["time"]) # ensure the end time is not later than 23:30 - if end_mins > self._timeToMins("23:30"): + if end_mins > self._timeStrToMins("23:30"): self._showTrace( f"结束时间 {end_time['time']} 晚于 23:30, 自动设置为 23:30" ) reserve_info["end_time"]["time"] = "23:30" - end_mins = self._timeToMins("23:30") + end_mins = self._timeStrToMins("23:30") # ensure the duration is not longer than 8 hours if reserve_info["satisfy_duration"]: if reserve_info["expect_duration"] > 8: @@ -250,7 +250,7 @@ class LibReserve(LibTimeSelector): f"{float((end_mins - begin_mins)/60)} 小时 " f"超出最大时长 8 小时, 自动设置为 8 小时" ) - reserve_info["end_time"]["time"] = self._minsToTime(begin_mins + 8*60) + reserve_info["end_time"]["time"] = self._minsToTimeStr(begin_mins + 8*60) return True @@ -481,6 +481,9 @@ class LibReserve(LibTimeSelector): """ Select the nearest available time option. + + Returns: + int: The actual selected time value in minutes. """ # Wait for time options to load try: @@ -515,7 +518,7 @@ class LibReserve(LibTimeSelector): ) return target_time self._showTrace( - f"无法选择最近的 {time_type} {self._minsToTime(target_time)}, " + f"无法选择最近的 {time_type} {self._minsToTimeStr(target_time)}, " f"所有可选时间与目标时间相差都超过 {max_time_diff} 分钟" ) self._showTrace(f"当前可供预约的 {time_type} 有: {free_times}") @@ -530,47 +533,49 @@ class LibReserve(LibTimeSelector): satisfy_duration: bool = True ) -> bool: - """Select seat begin and end time.""" - expect_begin_time = actual_begin_time = begin_time["time"] - expect_end_time = actual_end_time = end_time["time"] - expect_begin_mins = self._timeToMins(expect_begin_time) - actual_begin_mins = expect_begin_mins - expect_end_mins = self._timeToMins(expect_end_time) + """ + Select seat begin and end time. + """ + exp_beg_tm_str = act_beg_tm_str = begin_time["time"] + exp_end_tm_str = act_end_tm_str = end_time["time"] + exp_beg_mins = self._timeStrToMins(exp_beg_tm_str) + act_beg_mins = exp_beg_mins + exp_end_mins = self._timeStrToMins(exp_end_tm_str) + act_end_mins = exp_end_mins # Select begin time - if self.__selectNearestTime( + if act_beg_mins := self.__selectNearestTime( time_id="startTime", time_type="开始时间", - target_time=expect_begin_mins, + target_time=exp_beg_mins, max_time_diff=begin_time["max_diff"], prefer_earlier=begin_time["prefer_early"] - ) == -1: + ) and act_beg_mins == -1: return False - actual_begin_time = self._minsToTime(expect_begin_mins) - actual_begin_mins = self._timeToMins(actual_begin_time) + act_beg_tm_str = self._minsToTimeStr(act_beg_mins) # If 'satisfy_duration' is True, select end time based on actual begin time if satisfy_duration: - expect_end_mins = self.validateAndAdjustEndTime(actual_begin_mins, expct_duration) - expect_end_time = self._minsToTime(expect_end_mins) + exp_end_mins = int(self.validateAndAdjustEndTime(act_beg_mins, expct_duration)) + exp_end_tm_str = self._minsToTimeStr(exp_end_mins) self._showTrace( f"需要满足期望预约持续时间: {expct_duration} 小时, " - f"根据开始时间 {actual_begin_time} 计算结束时间: {expect_end_time}" + f"根据开始时间 {act_beg_tm_str} 计算结束时间: {exp_end_tm_str}" ) # Select end time - if self.__selectNearestTime( + if act_end_mins := self.__selectNearestTime( time_id="endTime", time_type="结束时间", - target_time=expect_end_mins, + target_time=exp_end_mins, max_time_diff=end_time["max_diff"], prefer_earlier=end_time["prefer_early"] - ) == -1: + ) and act_end_mins == -1: return False - actual_end_time = self._minsToTime(expect_end_mins) + act_end_tm_str = self._minsToTimeStr(act_end_mins) self._showTrace( - f"期望预约时间段: {expect_begin_time} - {expect_end_time}, " - f"实际预约时间段: {actual_begin_time} - {actual_end_time}" + f"期望预约时间段: {exp_beg_tm_str} - {exp_end_tm_str}, " + f"实际预约时间段: {act_beg_tm_str} - {act_end_tm_str}" ) return True @@ -584,8 +589,8 @@ class LibReserve(LibTimeSelector): """ Validate and adjust reserve end time to library closing time if needed. """ - LIBRARY_CLOSE_TIME = self._timeToMins("23:30") - expect_end_mins = begin_mins + duration * 60 + LIBRARY_CLOSE_TIME = self._timeStrToMins("23:30") + expect_end_mins = int(begin_mins + duration*60) if expect_end_mins > LIBRARY_CLOSE_TIME: expect_end_mins = LIBRARY_CLOSE_TIME self._showTrace(