import logging from typing import TypeVar, Dict from datetime import datetime, timedelta logger = logging.getLogger("desktopenv.getters.misc") R = TypeVar("Rule") day_of_week_mapping = { 0: 'Mon', 1: 'Tue', 2: 'Wed', 3: 'Thu', 4: 'Fri', 5: 'Sat', 6: 'Sun' } month_mapping = { 1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec' } Month_Mapping_Full = { 1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December" } month_mapping_full = { 1: 'january', 2: 'february', 3:'march', 4: 'april', 5:'may', 6: 'june', 7: 'july', 8: 'august', 9:'september', 10: 'october', 11: 'november', 12: 'december' } relativeTime_to_IntDay = { "tomorrow": 1, "5th next month": "special", "10th next month": "special", "11th next month": "special", "this month": "special", "this Saturday": "special", "this Sunday": "special", "next Monday": "special", "next Friday": "special", "first monday four months later": "special" } def get_rule(env, config: Dict[str, R]) -> R: """ Returns the rule as-is. """ return config["rules"] def get_rule_relativeTime(env, config: Dict[str, R]) -> R: """ According to the rule definded in funciton "apply_rules_to_timeFormat", convert the relative time to absolute time. config: 'relativeTime': { "from": must exist; indicates the relativeTime. "to": optional; indicates the relativeTime. } If relativeTime only has key "from", then the key of time in "expected" dict must be "time". If relativeTime has key "to", then the key of time in "expected" dict must be "from" and "to". """ relativeRules = config["rules"] relativeTime = relativeRules["relativeTime"] # int, "+" means future, "-" means past # get the date now now = datetime.now() # calculate the relative time if "to" not in relativeTime.keys(): start_relative_time = relativeTime["from"] if relativeTime_to_IntDay[start_relative_time] != "special": # relativeTime can be represented by actual int days start_relative_time_IntDat = relativeTime_to_IntDay[start_relative_time] timediff = timedelta(days=start_relative_time_IntDat) absoluteDay = now + timediff else: # special case, you can add more special cases here if start_relative_time == "5th next month": next_year = now.year + 1 if now.month == 12 else now.year next_month = now.month + 1 if now.month < 12 else 1 next_day = 5 absoluteDay = datetime(next_year, next_month, next_day) elif start_relative_time == "10th next month": next_year = now.year + 1 if now.month == 12 else now.year next_month = now.month + 1 if now.month < 12 else 1 next_day = 10 absoluteDay = datetime(next_year, next_month, next_day) elif start_relative_time == "this month": absoluteDay = now elif start_relative_time == "next Monday": absoluteDay = now + timedelta(days=((6-now.weekday())+1)) elif start_relative_time == "first monday four months later": next_year = now.year + 1 if now.month >=9 else now.year next_month = (now.month + 4)%12 # get the first monday of the next_month temp_date = datetime(next_year, next_month, 1) absoluteDay = temp_date + timedelta(days=((6-temp_date.weekday())+1)%7) regular_time = apply_rules_to_timeFormat(relativeRules["expected"]["time"], absoluteDay) config["rules"]["expected"]["time"] = regular_time else: from_time = relativeTime["from"] to_time = relativeTime["to"] # deal with from_time first if relativeTime_to_IntDay[from_time] != "special": from_time_IntDat = relativeTime_to_IntDay[from_time] from_timediff = timedelta(days=from_time_IntDat) from_absoluteDay = now + from_timediff else: if from_time == "this Saturday": from_absoluteDay = now + timedelta(days=(5-now.weekday())) elif from_time == "10th next month": next_year = now.year + 1 if now.month == 12 else now.year next_month = now.month + 1 if now.month < 12 else 1 next_day = 10 from_absoluteDay = datetime(next_year, next_month, next_day) elif from_time == "next Monday": from_absoluteDay = now + timedelta(days=((6-now.weekday())+1)) else: pass # more rules here regular_from_time = apply_rules_to_timeFormat(relativeRules["expected"]["from"], from_absoluteDay) config["rules"]["expected"]["from"] = regular_from_time # deal with to_time if relativeTime_to_IntDay[to_time] != "special": to_time_IntDat = relativeTime_to_IntDay[to_time] to_timediff = timedelta(days=to_time_IntDat) to_absoluteDay = now + to_timediff else: if to_time == "this Sunday": to_absoluteDay = now + timedelta(days=(6-now.weekday())) elif to_time == "11th next month": next_year = now.year + 1 if now.month == 12 else now.year next_month = now.month + 1 if now.month < 12 else 1 next_day = 11 to_absoluteDay = datetime(next_year, next_month, next_day) elif to_time == "next Friday": if now.weekday() < 4 and from_time in ["next Monday"]: to_absoluteDay = now + timedelta(days=((4-now.weekday())+7)) else: to_absoluteDay = now + timedelta(days=((4-now.weekday()) if now.weekday() < 4 else (6-now.weekday()) + 5)) else: pass # more rules here regular_to_time = apply_rules_to_timeFormat(relativeRules["expected"]["to"], to_absoluteDay) config["rules"]["expected"]["to"] = regular_to_time return config["rules"] def apply_rules_to_timeFormat(timeFormat: str, absoluteDay: datetime): timeFormat = timeFormat.replace("{DoW}", day_of_week_mapping[absoluteDay.weekday()], 1) timeFormat = timeFormat.replace("{Month}", month_mapping[absoluteDay.month], 1) timeFormat = timeFormat.replace("{DayD}", str(absoluteDay.day), 1) timeFormat = timeFormat.replace("{Year}", str(absoluteDay.year), 1) timeFormat = timeFormat.replace("{Month0D}", "0"+str(absoluteDay.month) if absoluteDay.month < 10 else str(absoluteDay.month), 1) timeFormat = timeFormat.replace("{month}", month_mapping_full[absoluteDay.month], 1) timeFormat = timeFormat.replace("{MonthFull}", Month_Mapping_Full[absoluteDay.month], 1) timeFormat = timeFormat.replace("{Day0D}", "0"+str(absoluteDay.day) if absoluteDay.day < 10 else str(absoluteDay.day), 1) # you can add other replace rules here return timeFormat def get_accessibility_tree(env, *args) -> str: accessibility_tree: str = env.controller.get_accessibility_tree() logger.debug("AT@eval: %s", accessibility_tree) return accessibility_tree def get_time_diff_range(env, config) -> str: try: return config["diff_range_in_minutes"] except: logger.error("diff_range_in_minutes not found in config.") return None