import copy
from datetime import datetime, timedelta

from evalidate import Expr, base_eval_model

from mower.utils.plan import PlanConfig

from ..data import agent_arrange_order, agent_list, base_room_list
from ..solvers.infra.record import save_action_to_sqlite_decorator
from ..utils.log import logger


class SkillUpgradeSupport:
    support_class = None
    level = 1
    efficiency = 0
    half_off = False
    add_on = False
    match = False
    use_booster = True
    name = ""
    swap_name = ""

    def __init__(self, name, skill_level, efficiency, match, swap_name="艾丽妮"):
        self.name = name
        self.level = skill_level
        self.efficiency = efficiency
        self.match = match
        if self.level > 1:
            self.half_off = True
        self.swap_name = swap_name


class Operators:
    config = None
    operators = None
    exhaust_agent = []
    exhaust_group = []
    groups = None
    dorm = []
    plan = None

    global_plan = None
    plan_condition = []
    shadow_copy = {}
    current_room_changed_callback = None
    first_init = True
    skill_upgrade_supports = []

    def __init__(self, plan):
        self.operators = {}
        self.groups = {}
        self.exhaust_agent = []
        self.exhaust_group = []
        self.dorm = []
        self.workaholic_agent = []
        self.free_blacklist = []
        self.global_plan = plan
        self.backup_plans = plan["backup_plans"]
        # 切换默认排班
        self.swap_plan([False] * (len(self.backup_plans)))
        self.run_order_rooms = {}
        self.clues = []
        self.current_room_changed_callback = None
        self.party_time = None

        self.eval_model = base_eval_model.clone()
        self.eval_model.nodes.extend(["Call", "Attribute"])
        self.eval_model.attributes.extend(
            [
                "operators",
                "party_time",
                "is_working",
                "is_resting",
                "current_mood",
                "current_room",
            ]
        )

    def __repr__(self):
        return f"Operators(operators={self.operators})"

    def calculate_switch_time(self, support: SkillUpgradeSupport):
        hour = 0
        half_off = support.half_off
        level = support.level
        match = support.match
        efficiency = support.efficiency
        same = support.name == support.swap_name
        if level == 1:
            half_off = False
        # if left_minutes > 0 or left_hours > 0:
        #     hour = left_minutes / 60 + left_hours
        # 基本5%
        basic = 5
        if support.add_on:
            # 阿斯卡伦
            basic += 5
        if hour == 0:
            hour = level * 8
        if half_off:
            hour = hour / 2
        left = 0
        if not same:
            left = 5 * (100 + basic + (30 if match else 0)) / 100
            left = hour - left
        else:
            left = hour
        return left * 100 / (100 + efficiency + basic)

    def swap_plan(self, condition, refresh=False):
        self.plan = copy.deepcopy(self.global_plan["default_plan"].plan)
        self.config: PlanConfig = copy.deepcopy(self.global_plan["default_plan"].config)
        for index, success in enumerate(condition):
            if success:
                self.plan, self.config = self.merge_plan(index, self.config, self.plan)
        self.plan_condition = condition
        if refresh:
            self.first_init = True
            error = self.init_and_validate(True)
            self.first_init = False
            if error:
                return error

    def merge_plan(self, idx, ext_config, default_plan=None):
        if default_plan is None:
            default_plan = copy.deepcopy(self.global_plan["default_plan"].plan)
        plan = copy.deepcopy(self.global_plan["backup_plans"][idx])
        # 更新切换排班表
        for key, value in plan.plan.items():
            if key in default_plan:
                for idx, operator in enumerate(value):
                    if operator.agent != "Current":
                        default_plan[key][idx] = operator
        return default_plan, ext_config.merge_config(plan.config)

    def generate_conditions(self, n):
        if n == 1:
            return [[True], [False]]
        else:
            prev_conditions = self.generate_conditions(n - 1)
            conditions = []
            for condition in prev_conditions:
                conditions.append(condition + [True])
                conditions.append(condition + [False])
            return conditions

    def init_and_validate(self, update=False):
        self.groups = {}
        self.exhaust_agent = []
        self.exhaust_group = []
        self.workaholic_agent = []
        self.shadow_copy = copy.deepcopy(self.operators)
        self.operators = {}
        for room in self.plan.keys():
            for idx, data in enumerate(self.plan[room]):
                if data.agent not in list(agent_list.keys()) and data.agent != "Free":
                    return f"干员名输入错误: 房间->{room}, 干员->{data.agent}"
                if data.agent in ["龙舌兰", "但书"]:
                    return f"高效组不可用龙舌兰，但书 房间->{room}, 干员->{data.agent}"
                if data.agent == "菲亚梅塔" and idx == 1:
                    return f"菲亚梅塔不能安排在2号位置 房间->{room}, 干员->{data.agent}"
                if data.agent == "菲亚梅塔" and not room.startswith("dorm"):
                    return "菲亚梅塔必须安排在宿舍"
                if data.agent == "Free" and not room.startswith("dorm"):
                    return f"Free只能安排在宿舍 房间->{room}, 干员->{data.agent}"
                if data.agent in self.operators and data.agent != "Free":
                    return f"高效组干员不可重复 房间->{room},{self.operators[data.agent].room}, 干员->{data.agent}"
                self.add(
                    Operator(
                        data.agent,
                        room,
                        idx,
                        data.group,
                        data.replacement,
                        "high",
                        operator_type="high",
                    )
                )
        missing_replacements = []
        for room in self.plan.keys():
            if room.startswith("dorm") and len(self.plan[room]) != 5:
                return f"宿舍 {room} 人数少于5人"
            for idx, data in enumerate(self.plan[room]):
                # 菲亚梅塔替换组做特例判断
                if "龙舌兰" in data.replacement and "但书" in data.replacement:
                    return f"替换组不可同时安排龙舌兰和但书 房间->{room}, 干员->{data.agent}"
                if "菲亚梅塔" in data.replacement:
                    return f"替换组不可安排菲亚梅塔 房间->{room}, 干员->{data.agent}"
                r_count = len(data.replacement)
                if "龙舌兰" in data.replacement or "但书" in data.replacement:
                    r_count -= 1
                if r_count <= 0 and (
                    (data.agent != "Free" and (not room.startswith("dorm")))
                    or data.agent == "菲亚梅塔"
                ):
                    missing_replacements.append(data.agent)
                for _replacement in data.replacement:
                    if (
                        _replacement not in list(agent_list.keys())
                        and data.agent != "Free"
                    ):
                        return f"干员名输入错误: 房间->{room}, 干员->{_replacement}"
                    if data.agent != "菲亚梅塔":
                        # 普通替换
                        if (
                            _replacement in self.operators
                            and self.operators[_replacement].is_high()
                        ):
                            return f"替换组不可用高效组干员: 房间->{room}, 干员->{_replacement}"
                        self.add(Operator(_replacement, ""))
                    else:
                        if _replacement not in self.operators:
                            return f"菲亚梅塔替换不在高效组列: 房间->{room}, 干员->{_replacement}"
                        if (
                            _replacement in self.operators
                            and not self.operators[_replacement].is_high()
                        ):
                            return f"菲亚梅塔替换只能为高效组干员: 房间->{room}, 干员->{_replacement}"
        # 判定替换缺失
        if "菲亚梅塔" in missing_replacements:
            return "菲亚梅塔替换缺失"
        if len(missing_replacements):
            return f'以下干员替换组缺失：{",".join(missing_replacements)}'
        dorm_names = [k for k in self.plan.keys() if k.startswith("dorm")]
        dorm_names.sort(key=lambda d: d, reverse=False)
        added = []
        # 竖向遍历出效率高到低
        if not update:
            for dorm in dorm_names:
                free_found = False
                for _idx, _dorm in enumerate(self.plan[dorm]):
                    if _dorm.agent == "Free" and _idx <= 1:
                        if "波登可" not in [_agent.agent for _agent in self.plan[dorm]]:
                            return "宿舍必须安排2个宿管"
                    if _dorm.agent != "Free" and free_found:
                        return "Free必须连续且安排在宿管后"
                    if (
                        _dorm.agent == "Free"
                        and not free_found
                        and (dorm + str(_idx)) not in added
                        and len(added) < self.config.max_resting_count
                    ):
                        self.dorm.append(Dormitory((dorm, _idx)))
                        added.append(dorm + str(_idx))
                        free_found = True
                        continue
                if not free_found:
                    return "宿舍必须安排至少一个Free"
            # VIP休息位用完后横向遍历
            for dorm in dorm_names:
                for _idx, _dorm in enumerate(self.plan[dorm]):
                    if _dorm.agent == "Free" and (dorm + str(_idx)) not in added:
                        self.dorm.append(Dormitory((dorm, _idx)))
                        added.append(dorm + str(_idx))
        else:
            for key, value in self.shadow_copy.items():
                if key not in self.operators:
                    self.add(Operator(key, ""))
        if len(self.dorm) < self.config.max_resting_count:
            return f"宿舍Free总数 {len(self.dorm)}小于最大分组数 {self.config.max_resting_count}"
        # 跑单
        for x, y in self.plan.items():
            if not x.startswith("room"):
                continue
            if any(
                ("但书" in obj.replacement or "龙舌兰" in obj.replacement) for obj in y
            ):
                self.run_order_rooms[x] = {}
        # 判定分组排班可能性
        current_high = self.config.max_resting_count
        current_low = len(self.dorm) - self.config.max_resting_count
        for key in self.groups:
            high_count = 0
            low_count = 0
            _replacement = []
            for name in self.groups[key]:
                _candidate = next(
                    (
                        r
                        for r in self.operators[name].replacement
                        if r not in _replacement and r not in ["龙舌兰", "但书"]
                    ),
                    None,
                )
                if _candidate is None:
                    return f"{key} 分组无法排班,替换组数量不够"
                else:
                    _replacement.append(_candidate)
                if self.operators[name].workaholic:
                    continue
                if self.operators[name].resting_priority == "high":
                    high_count += 1
                else:
                    low_count += 1
            if high_count > current_high or low_count > current_low:
                return f"{key} 分组无法排班,宿舍可用高优先{current_high},低优先{current_low}->分组需要高优先{high_count},低优先{low_count}"
        # 设定令夕模式的心情阈值
        self.init_mood_limit()
        for name in self.workaholic_agent:
            if name not in self.config.free_blacklist:
                self.config.free_blacklist.append(name)
        logger.info("宿舍黑名单：" + str(self.config.free_blacklist))

    def set_mood_limit(self, name, upper_limit=24, lower_limit=0):
        if name in self.operators:
            self.operators[name].upper_limit = upper_limit
            self.operators[name].lower_limit = lower_limit
            logger.info(f"自动设置{name}心情下限为{lower_limit},上限为{upper_limit}")

    def init_mood_limit(self):
        # 设置心情阈值 for 夕，令，
        if self.config.ling_xi == 1:
            self.set_mood_limit("令", upper_limit=12)
            self.set_mood_limit("夕", lower_limit=12)
        elif self.config.ling_xi == 2:
            self.set_mood_limit("夕", upper_limit=12)
            self.set_mood_limit("令", lower_limit=12)
        elif self.config.ling_xi == 0:
            self.set_mood_limit("夕")
            self.set_mood_limit("令")
        # 设置同组心情阈值
        finished = []
        for name in ["夕", "令"]:
            if (
                name in self.operators
                and self.operators[name].group != ""
                and self.operators[name].group not in finished
            ):
                for group_name in self.groups[self.operators[name].group]:
                    if group_name not in ["夕", "令"]:
                        if self.config.ling_xi in [1, 2]:
                            self.set_mood_limit(group_name, lower_limit=12)
                        elif self.config.ling_xi == 0:
                            self.set_mood_limit(group_name, lower_limit=0)
                finished.append(self.operators[name].group)

        # 设置铅踝心情阈值
        # 三种情况：
        # 1. 铅踝不是主力：不管
        # 2. 铅踝是红云组主力，设置心情上限 12、下限 8，效率 37%
        # 3. 铅踝是普通主力：设置心情下限 20，效率 30%
        TOTTER = "铅踝"
        VERMEIL = "红云"
        if TOTTER in self.operators and self.operators[TOTTER].operator_type == "high":
            if (
                VERMEIL in self.operators
                and self.operators[VERMEIL].operator_type == "high"
                and self.operators[VERMEIL].room == self.operators[TOTTER].room
            ):
                self.set_mood_limit(TOTTER, upper_limit=12, lower_limit=8)
            else:
                self.set_mood_limit(TOTTER, upper_limit=24, lower_limit=20)

    def evaluate_expression(self, expression):
        try:
            result = Expr(expression, self.eval_model).eval({"op_data": self})
            return result
        except Exception as e:
            logger.exception(f"Error evaluating expression: {e}")
            return None

    def get_current_room(self, room, bypass=False, current_index=None):
        room_data = {
            v.current_index: v
            for k, v in self.operators.items()
            if v.current_room == room
        }
        res = [obj.agent for obj in self.plan[room]]
        not_found = False
        for idx, op in enumerate(res):
            if idx in room_data:
                res[idx] = room_data[idx].name
            else:
                res[idx] = ""
                if current_index is not None and idx not in current_index:
                    continue
                not_found = True
        if not_found and not bypass:
            return None
        else:
            return res

    def predict_fia(self, operators, fia_mood, hours=240):
        recover_hours = (24 - fia_mood) / 2
        for agent in operators:
            agent.mood -= agent.depletion_rate * recover_hours
            if agent.mood < 0.0:
                return False
        if recover_hours >= hours or 0 < recover_hours < 1:
            return True
        operators.sort(
            key=lambda x: (x.mood - x.lower_limit) / (x.upper_limit - x.lower_limit),
            reverse=False,
        )
        fia_mood = operators[0].mood
        operators[0].mood = 24
        return self.predict_fia(operators, fia_mood, hours - recover_hours)

    def reset_dorm_time(self):
        for name in self.operators.keys():
            agent = self.operators[name]
            if agent.room.startswith("dorm"):
                agent.time_stamp = None

    @save_action_to_sqlite_decorator
    def update_detail(self, name, mood, current_room, current_index, update_time=False):
        agent = self.operators[name]
        if update_time:
            if agent.time_stamp is not None and agent.mood > mood:
                agent.depletion_rate = (
                    (agent.mood - mood)
                    * 3600
                    / ((datetime.now() - agent.time_stamp).total_seconds())
                )
            agent.time_stamp = datetime.now()
        # 如果移出宿舍，则清除对应宿舍数据 且重新记录高效组心情（如果有备用班，则跳过高效组判定）
        if (
            agent.current_room.startswith("dorm")
            and not current_room.startswith("dorm")
            and (agent.is_high() or self.backup_plans)
        ):
            self.refresh_dorm_time(
                agent.current_room, agent.current_index, {"agent": ""}
            )
            if update_time:
                self.time_stamp = datetime.now()
            else:
                self.time_stamp = None
            agent.depletion_rate = 0
        if (
            self.get_dorm_by_name(name)[0] is not None
            and not current_room.startswith("dorm")
            and (agent.is_high() or self.backup_plans)
        ):
            _dorm = self.get_dorm_by_name(name)[1]
            _dorm.name = ""
            _dorm.time = None
        agent.current_room = current_room
        agent.current_index = current_index
        agent.mood = mood
        # 如果是高效组且没有记录时间，则返还index
        if agent.current_room.startswith("dorm") and (
            agent.is_high() or self.backup_plans
        ):
            for dorm in self.dorm:
                if (
                    dorm.position[0] == current_room
                    and dorm.position[1] == current_index
                    and dorm.time is None
                ):
                    return current_index
        if agent.name == "菲亚梅塔" and (
            self.operators["菲亚梅塔"].time_stamp is None
            or self.operators["菲亚梅塔"].time_stamp < datetime.now()
        ):
            return current_index

    def refresh_dorm_time(self, room, index, agent):
        for idx, dorm in enumerate(self.dorm):
            # Filter out resting priority low
            # if idx >= self.config.max_resting_count:
            #     break
            if dorm.position[0] == room and dorm.position[1] == index:
                # 如果人为高效组，则记录时间
                _name = agent["agent"]
                if _name in self.operators.keys() and (
                    self.operators[_name].is_high() or self.config.free_room
                ):
                    dorm.name = _name
                    _agent = self.operators[_name]
                    # 如果干员有心情上限，则按比例修改休息时间
                    if _agent.mood != 24:
                        sec_remaining = (
                            (_agent.upper_limit - _agent.mood)
                            * ((agent["time"] - _agent.time_stamp).total_seconds())
                            / (24 - _agent.mood)
                        )
                        dorm.time = _agent.time_stamp + timedelta(seconds=sec_remaining)
                    else:
                        dorm.time = agent["time"]
                elif _name in list(agent_list.keys()):
                    dorm.name = _name
                    dorm.time = agent["time"]
                break

    def correct_dorm(self):
        for idx, dorm in enumerate(self.dorm):
            if dorm.name != "" and dorm.name in self.operators.keys():
                op = self.operators[dorm.name]
                if not (
                    dorm.position[0] == op.current_room
                    and dorm.position[1] == op.current_index
                ):
                    self.dorm[idx].name = ""
                    self.dorm[idx].time = None
                else:
                    if (
                        self.dorm[idx].time is not None
                        and self.dorm[idx].time < datetime.now()
                    ):
                        op.mood = op.upper_limit
                        op.time_stamp = self.dorm[idx].time
                        logger.debug(
                            f"检测到{op.name}心情恢复满，设置心情至{op.upper_limit}"
                        )

    def get_train_support(self):
        for name in self.operators.keys():
            agent = self.operators[name]
            if agent.current_room == "train" and agent.current_index == 0:
                return agent.name
        return None

    def get_refresh_index(self, room, plan):
        ret = []
        if room.startswith("dorm") and self.config.free_room:
            return [i for i, x in enumerate(self.plan[room]) if x == "Free"]
        for idx, dorm in enumerate(self.dorm):
            # Filter out resting priority low
            if idx >= self.config.max_resting_count:
                if not self.config.free_room:
                    break
            if dorm.position[0] == room:
                for i, _name in enumerate(plan):
                    if _name not in self.operators.keys():
                        self.add(Operator(_name, ""))
                    if not self.config.free_room:
                        if self.operators[_name].is_high() and not self.operators[
                            _name
                        ].room.startswith("dorm"):
                            ret.append(i)
                    elif not self.operators[_name].room.startswith("dorm"):
                        ret.append(i)
                break
        return ret

    def get_dorm_by_name(self, name):
        for idx, dorm in enumerate(self.dorm):
            if dorm.name == name:
                return idx, dorm
        return None, None

    def add(self, operator):
        if operator.name not in list(agent_list.keys()):
            return
        if self.config.is_resting_priority(operator.name):
            operator.resting_priority = "low"
        operator.exhaust_require = self.config.is_exhaust_require(operator.name)
        operator.rest_in_full = self.config.is_rest_in_full(operator.name)
        operator.workaholic = self.config.is_workaholic(operator.name)
        operator.refresh_order_room = self.config.is_refresh_trading(operator.name)
        if operator.name in agent_arrange_order:
            operator.arrange_order = agent_arrange_order[operator.name]
        # 复制基建数据
        if operator.name in self.shadow_copy:
            exist = self.shadow_copy[operator.name]
            operator.mood = exist.mood
            operator.time_stamp = exist.time_stamp
            operator.depletion_rate = exist.depletion_rate
            operator.current_room = exist.current_room
            operator.current_index = exist.current_index
        self.operators[operator.name] = operator
        # 需要用尽心情干员逻辑
        if (
            operator.exhaust_require or operator.group in self.exhaust_group
        ) and operator.name not in self.exhaust_agent:
            self.exhaust_agent.append(operator.name)
            if operator.group != "":
                self.exhaust_group.append(operator.group)
        # 干员分组逻辑
        if operator.group != "":
            if operator.group not in self.groups.keys():
                self.groups[operator.group] = [operator.name]
            else:
                self.groups[operator.group].append(operator.name)
        if operator.workaholic and operator.name not in self.workaholic_agent:
            self.workaholic_agent.append(operator.name)

    def available_free(self, free_type="high"):
        ret = 0
        freeName = []
        if free_type == "high":
            idx = 0
            for dorm in self.dorm:
                if dorm.name == "" or (
                    dorm.name in self.operators.keys()
                    and not self.operators[dorm.name].is_high()
                ):
                    ret += 1
                elif dorm.time is not None and dorm.time < datetime.now():
                    logger.info(f"检测到房间休息完毕，释放{dorm.name}宿舍位")
                    freeName.append(dorm.name)
                    ret += 1
                if idx == self.config.max_resting_count - 1:
                    break
                else:
                    idx += 1
        else:
            idx = self.config.max_resting_count
            for i in range(idx, len(self.dorm)):
                dorm = self.dorm[i]
                # 释放满休息位
                # TODO 高效组且低优先可以相互替换
                if dorm.name == "" or (
                    dorm.name in self.operators.keys()
                    and not self.operators[dorm.name].is_high()
                ):
                    ret += 1
                elif dorm.time is not None and dorm.time < datetime.now():
                    logger.info(f"检测到房间休息完毕，释放{dorm.name}宿舍位")
                    freeName.append(dorm.name)
                    ret += 1
        if len(freeName) > 0:
            for name in freeName:
                if name in list(agent_list.keys()):
                    self.operators[name].mood = self.operators[name].upper_limit
                    self.operators[name].depletion_rate = 0
                    self.operators[name].time_stamp = datetime.now()
        return ret

    def assign_dorm(self, name):
        is_high = self.operators[name].resting_priority == "high"
        if is_high:
            _room = next(
                obj
                for obj in self.dorm
                if obj.name not in self.operators.keys()
                or not self.operators[obj.name].is_high()
            )
        else:
            _room = None
            for i in range(self.config.max_resting_count, len(self.dorm)):
                _name = self.dorm[i].name
                if _name == "" or not self.operators[_name].is_high():
                    _room = self.dorm[i]
                    break
        _room.name = name
        return _room

    def get_current_operator(self, room, index):
        for key, value in self.operators.items():
            if value.current_room == room and value.current_index == index:
                return value
        return None

    def print(self):
        ret = "{"
        op = []
        dorm = []
        for k, v in self.operators.items():
            op.append("'" + k + "': " + str(vars(v)))
        ret += "'operators': {" + ",".join(op) + "},"
        for v in self.dorm:
            dorm.append(str(vars(v)))
        ret += "'dorms': [" + ",".join(dorm) + "]}"
        return ret


class Dormitory:
    def __init__(self, position, name="", time=None):
        self.position = position
        self.name = name
        self.time = time

    def __repr__(self):
        return (
            f"Dormitory(position={self.position},name='{self.name}',time='{self.time}')"
        )


class Operator:
    time_stamp = None
    depletion_rate = 0
    workaholic = False
    arrange_order = [2, "false"]

    def __init__(
        self,
        name,
        room,
        index=-1,
        group="",
        replacement=[],
        resting_priority="low",
        current_room="",
        exhaust_require=False,
        mood=24,
        upper_limit=24,
        rest_in_full=False,
        current_index=-1,
        lower_limit=0,
        operator_type="low",
        depletion_rate=0,
        time_stamp=None,
        refresh_order_room=None,
    ):
        if refresh_order_room is not None:
            self.refresh_order_room = refresh_order_room
        self.refresh_order_room = [False, []]
        self.name = name
        self.room = room
        self.operator_type = operator_type
        self.index = index
        self.group = group
        self.replacement = replacement
        self.resting_priority = resting_priority
        self._current_room = None
        self.current_room = current_room
        self.exhaust_require = exhaust_require
        self.upper_limit = upper_limit
        self.rest_in_full = rest_in_full
        self.mood = mood
        self.current_index = current_index
        self.lower_limit = lower_limit
        self.depletion_rate = depletion_rate
        self.time_stamp = time_stamp

    @property
    def current_room(self):
        return self._current_room

    @current_room.setter
    def current_room(self, value):
        if self._current_room != value:
            self._current_room = value
            if Operators.current_room_changed_callback and self.refresh_order_room[0]:
                Operators.current_room_changed_callback(self)

    def is_high(self):
        return self.operator_type == "high"

    def is_resting(self):
        return self.current_room.startswith("dorm")

    def is_working(self):
        return self.current_room in base_room_list and not self.is_resting()

    def need_to_refresh(self, h=2, r=""):
        # 是否需要读取心情
        if (
            self.time_stamp is None
            or (
                self.time_stamp is not None
                and self.time_stamp + timedelta(hours=h) < datetime.now()
            )
            or (r.startswith("dorm") and not self.room.startswith("dorm"))
        ):
            return True

    def not_valid(self):
        if self.room == "train":
            return False
        if self.operator_type == "high":
            if self.workaholic:
                return (
                    self.current_room != self.room or self.index != self.current_index
                )
            if not self.room.startswith("dorm") and self.current_room.startswith(
                "dorm"
            ):
                if self.mood == -1 or self.mood == 24:
                    return True
                else:
                    return False
            return (
                self.need_to_refresh(2.5)
                or self.current_room != self.room
                or self.index != self.current_index
            )
        return False

    def current_mood(self):
        predict = self.mood
        if self.time_stamp is not None:
            predict = (
                self.mood
                - self.depletion_rate
                * (datetime.now() - self.time_stamp).total_seconds()
                / 3600
            )
        if 0 <= predict <= 24:
            return predict
        else:
            return self.mood

    def __repr__(self):
        return f"Operator(name='{self.name}', room='{self.room}', index={self.index}, group='{self.group}', replacement={self.replacement}, resting_priority='{self.resting_priority}', current_room='{self.current_room}',exhaust_require={self.exhaust_require},mood={self.mood}, upper_limit={self.upper_limit}, rest_in_full={self.rest_in_full}, current_index={self.current_index}, lower_limit={self.lower_limit}, operator_type='{self.operator_type}',depletion_rate={self.depletion_rate},time_stamp='{self.time_stamp}',refresh_order_room = {self.refresh_order_room})"
