#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/24 11:28
# @Author : Opfer
# @Site :
# @File : truck.py
# @Software: PyCharm

from para_config import *
from equipment.dump import DumpInfo
from equipment.excavator import ExcavatorInfo
from typing import List


# 矿卡设备类
class TruckInfo(WalkManage):
    def __init__(self, dump, excavator):
        # object fileds
        # self.walker = WalkManage()
        # 矿卡数量
        self.dynamic_truck_num = get_value("dynamic_truck_num")
        # 用于动态派车的矿卡集合
        self.dynamic_truck_set = get_value("dynamic_truck_set")
        # 矿卡抵达卸载设备时间
        self.cur_truck_reach_dump = np.zeros(self.dynamic_truck_num)
        # 矿卡抵达挖机时间
        self.cur_truck_reach_excavator = np.zeros(self.dynamic_truck_num)
        # 矿卡最后装载/卸载时间
        self.last_load_time = {}
        self.last_unload_time = {}
        # 相对矿卡最后装载/卸载时间
        self.relative_last_load_time = {}
        self.relative_last_unload_time = {}
        # 矿卡当前任务
        self.truck_current_task = {}
        # 调度开始时间
        self.start_time = datetime.now()
        # 矿卡有效载重
        self.payload = np.zeros(self.dynamic_truck_num)
        # 矿卡时速
        self.empty_speed = {}
        self.heavy_speed = {}
        # 矿卡长宽
        self.geo_length = {}
        self.geo_width = {}
        # 矿卡型号
        self.size = {}
        # 矿卡当前行程(第一列为出发地序号, 第二列为目的地序号)
        self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
        # 矿卡挖机绑定关系
        self.truck_excavator_bind = {}
        # 矿卡卸点绑定关系
        self.truck_dump_bind = {}
        # 矿卡挖机排斥关系
        self.truck_excavator_exclude = {}
        # 矿卡卸点排斥关系
        self.truck_dump_exclude = {}
        # 排斥关系modify
        self.excavator_exclude_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
        # 矿卡优先级
        self.truck_priority = np.ones(self.dynamic_truck_num)
        # 矿卡绑定物料
        self.truck_material_bind = {}
        # 矿卡绑定物料modify
        self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_dump_num")), 0)
        # self.excavator_material_bind_modify =np.zeros(self.dynamic_truck_num)
        self.excavator_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
        # 各卸载区矿卡数量
        self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
        # 各装载区矿卡数量
        self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
        # 驶往各卸载区矿卡集合
        self.dump_hold_truck_list = {item: [] for item in get_value("dynamic_dump_set")}
        # 驶往各装载区矿卡集合
        self.excavator_hold_truck_list = {item: [] for item in get_value("dynamic_excavator_set")}
        # 日志
        self.logger = get_logger("zxt.truck")
        # # 初始化读取参数
        # self.truck_para_period_update(dump, excavator)
        # # 矿卡所属group
        # self.truck_group = {}
        # 矿卡禁用列表
        self.truck_disable_list = []
        # 对象域
        self._dump = dump
        self._excavator = excavator

    def get_truck_current_trip(self):
        return self.truck_current_trip

    def get_truck_current_task(self):
        return self.truck_current_task

    def get_truck_num(self):
        return self.dynamic_truck_num

    def get_truck_reach_dump(self):
        return self.cur_truck_reach_dump

    def get_truck_reach_excavator(self):
        return self.cur_truck_reach_excavator

    def get_dynamic_truck_set(self):
        return self.dynamic_truck_set

    def get_realative_last_load_time(self):
        return self.relative_last_load_time

    def get_realative_last_unload_time(self):
        return self.relative_last_unload_time

    def get_payload(self):
        return self.payload

    def get_width(self):
        return self.geo_width

    def get_length(self):
        return self.geo_length

    def get_dump_hold_truck_num(self):
        return self.dump_hold_truck_num

    def get_excavator_hold_truck_num(self):
        return self.excavator_hold_truck_num

    ################################################ short term update ################################################

    # 更新矿卡当前任务
    def update_truck_current_task(self):
        self.truck_current_task = {}
        device_name_set = redis2.keys()

        truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")

        for item in device_name_set:
            try:
                item = item.decode(encoding="utf-8")
                key_value_dict = redis2.hgetall(item)  # reids str可以自动转为bytes
                device_type = int(key_value_dict[str_to_byte("type")])
                if device_type == 1:
                    bb = self.dynamic_truck_set
                    cc = truck_name_to_uuid_dict
                    if truck_name_to_uuid_dict[item] in self.dynamic_truck_set:
                        currentTask = int(key_value_dict[str_to_byte("currentTask")])
                        self.truck_current_task[
                            truck_name_to_uuid_dict[item]
                        ] = currentTask
            except Exception as es:
                self.logger.error("读取矿卡任务异常-reids读取异常")
                self.logger.error(es)

        self.logger.info("矿卡当前任务：")
        self.logger.info(self.truck_current_task)

        # logger.info("device_name_set，大小")
        # logger.info(len(device_name_set))
        # logger.info("device_name_set")
        # logger.info(device_name_set)

        # self.truck_current_task = {}
        #
        # dynamic_truck_set = get_value("dynamic_truck_set")
        #
        # for item in dynamic_truck_set:
        #     # try:
        #     # item = item.decode(encoding="utf-8")
        #     key_value_dict = redis2.hgetall(item)  # reids str可以自动转为bytes
        #     currentTask = int(key_value_dict[str_to_byte("currentTask")])
        #     self.truck_current_task[item] = currentTask
        #     # except Exception as es:
        #     #     logger.error("读取矿卡任务异常-reids读取异常")
        #     #     logger.error(es)
        #
        # logger.info("矿卡当前任务：")
        # logger.info(self.truck_current_task)

    # 更新矿卡最后装载/卸载时间
    def update_truck_last_leave_time(self):
        self.last_load_time = {}
        self.last_unload_time = {}

        self.relative_last_load_time = {}
        self.relative_last_unload_time = {}

        try:
            truck_uuid_to_name_dict = get_value("truck_uuid_to_name_dict")
            for item in self.dynamic_truck_set:
                key_value_dict = redis2.hgetall(truck_uuid_to_name_dict[item])
                device_type = int(key_value_dict[str_to_byte("type")])
                # 判断是否为矿卡
                if device_type == 1:
                    task = self.truck_current_task[item]
                    if task in [3, 4, 5]:    # 矿卡重载行驶或仍未出场
                        if str_to_byte("lastLoadTime") in key_value_dict.keys():  # 若最后装载时间存在
                            last_load_time_tmp = eval(byte_to_str(key_value_dict[str_to_byte("lastLoadTime")]))
                            tmp_time = datetime.strptime(last_load_time_tmp, "%Y-%m-%d %H:%M:%S")
                            if tmp_time > datetime.strptime("2000-01-01 01:01:01", "%Y-%m-%d %H:%M:%S"):  # 若最后装载时间异常
                                self.last_load_time[item] = tmp_time
                            else:
                                self.last_load_time[item] = datetime.now()
                                # redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastLoadTime"),
                                #               "\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
                                self.logger.info("lastLoadTime is Error")
                        else:
                            self.last_load_time[item] = datetime.now()
                            # redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastLoadTime"),
                            #               "\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
                            self.logger.info("lastLoadTime is None")
                        self.relative_last_load_time[item] = float(
                            (self.last_load_time[item] - self.start_time)
                            / timedelta(hours=0, minutes=1, seconds=0)
                        )
                        # print("相对last_load_time", self.relative_last_load_time[item])
                        self.logger.info("相对last_load_time")
                        self.logger.info(self.relative_last_load_time[item])
                    if task in [0, 1, 2]:    # 矿卡空载行驶或仍未出场
                        if str_to_byte("lastUnloadTime") in key_value_dict.keys():
                            last_unload_time_tmp = eval(key_value_dict[str_to_byte("lastUnloadTime")])
                            tmp_time = datetime.strptime(last_unload_time_tmp, "%Y-%m-%d %H:%M:%S")
                            if tmp_time > datetime.strptime("2000-01-01 01:01:01", "%Y-%m-%d %H:%M:%S"):
                                self.last_unload_time[item] = tmp_time
                            else:
                                self.last_unload_time[item] = datetime.now()
                                # redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
                                #               "\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
                                self.logger.info("lastUnloadTime is Error")
                        else:
                            self.last_unload_time[item] = datetime.now()
                            # key_value_dict[str_to_byte("lastUnloadTime")] = datetime.now().strftime(
                            #     "%b %d, %Y %I:%M:%S %p"
                            # )
                            # redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
                            #               "\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
                            self.logger.info("lastUnloadTime is None")
                        self.relative_last_unload_time[item] = float(
                            (self.last_unload_time[item] - self.start_time)
                            / timedelta(hours=0, minutes=1, seconds=0)
                        )
                        # print("相对last_unload_time", self.relative_last_unload_time[item])
                        self.logger.info("相对last_unload_time")
                        self.logger.info(self.relative_last_unload_time[item])
                    elif task == -2:
                        # print(datetime.now())
                        self.last_unload_time[item] = datetime.now()
                        # key_value_dict["lastUnloadTime"] = datetime.now().strftime(
                        #     "%b %d, %Y %I:%M:%S %p")
                        # if str_to_byte("lastUnloadTime") in key_value_dict.keys():
                        #     # redis2.hset(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
                        #     #           datetime.now().strftime("%b %d, %Y %I:%M:%S %p"))
                        #     redis2.hset(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
                        #                 "\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
                        # else:
                        #     redis2.hsetnx(truck_uuid_to_name_dict[item], str_to_byte("lastUnloadTime"),
                        #                   "\"" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\"")
                        # # redis2.hsetnx(truck_uuid_to_name_dict[item], str(json.dumps(key_value_dict)))
        except Exception as es:
            self.logger.error("读取矿卡可用时间异常-redis读取异常")
            self.logger.error(es)

    def update_truck_trip(self):

        walk_time_to_load_area = WalkManage.walk_time_to_load_area
        walk_time_to_unload_area = WalkManage.walk_time_to_unload_area

        # 初始化矿卡行程, -1代表备停区
        self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
        ab = self.dynamic_truck_num
        for i in range(self.dynamic_truck_num):
            try:
                session_mysql.commit()
                truck_id = self.truck_index_to_uuid_dict[i]
                task = self.truck_current_task[self.truck_index_to_uuid_dict[i]]
                # print("truck_task:", truck_id, task)
                item = (
                    session_mysql.query(EquipmentPair)
                        .filter_by(truck_id=truck_id, isdeleted=0)
                        .first()
                )
                # item = (
                #     session_mysql.query(DispatchSetting)
                #         .filter_by(truck_id=truck_id, isdeleted=0)
                #         .first()
                # )
                point = empty_task_set
                point2 = heavy_task_set
                if task in (empty_task_set + heavy_task_set) and item is None:
                    raise Exception(f"矿卡 {truck_id} 配对关系异常")
            except Exception as es:
                self.logger.error(es)
                session_postgre.rollback()
                session_mysql.rollback()
                continue

            try:
                load_area_uuid_to_index_dict = get_value("load_area_uuid_to_index_dict")
                unload_area_uuid_to_index_dict = get_value("unload_area_uuid_to_index_dict")
                aa = task
                tt = truck_id
                # 若矿卡状态为空运
                if task in [0, 1, 2]:    # 矿卡空载或仍未出装载区
                    # last_unload_time = self.relative_last_unload_time[
                    #     self.truck_index_to_uuid_dict[i]
                    # ]
                    bb = self.relative_last_unload_time
                    last_unload_time = self.relative_last_unload_time[
                        truck_id
                    ]

                    if item.dump_id in DeviceMap.dump_uuid_to_unload_area_uuid_dict:
                        start_area_id = self.dump_uuid_to_unload_area_uuid_dict[item.dump_id]
                        start_area_index = unload_area_uuid_to_index_dict[start_area_id]
                        start_eq_index = self.dump_uuid_to_index_dict[item.dump_id]
                    else:
                        start_area_index = -1
                        start_eq_index = -1

                    if item.exactor_id in DeviceMap.excavator_uuid_to_load_area_uuid_dict:
                        end_area_id = self.excavator_uuid_to_load_area_uuid_dict[item.exactor_id]
                        end_area_index = load_area_uuid_to_index_dict[end_area_id]
                        end_eq_index = self.excavator_uuid_to_index_dict[item.exactor_id]
                    else:
                        end_area_index = -1
                        end_eq_index = -1

                    self.truck_current_trip[i] = [start_eq_index, end_eq_index]

                    self.cur_truck_reach_excavator[i] = (
                            last_unload_time
                            + walk_time_to_load_area[start_area_index][end_area_index]
                    )

                    self.logger.info(f'update_truck_trip-{truck_id}-last_unload_time')
                    self.logger.info(last_unload_time)
                    self.logger.info(f'update_truck_trip-walk_time_to_load_area')
                    self.logger.info(walk_time_to_load_area[start_area_index][end_area_index])

                    # # 目的地矿卡数加一
                    # self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
                # 若矿卡状态为重载
                elif task in [3, 4, 5]:    # 矿卡重载或仍未出卸载区
                    # print("读取重载行程")
                    # print(item.exactor_id, item.dump_id)
                    last_load_time = self.relative_last_load_time[
                        self.truck_index_to_uuid_dict[i]
                    ]

                    if item.exactor_id in DeviceMap.excavator_uuid_to_load_area_uuid_dict:
                        start_area_id = self.excavator_uuid_to_load_area_uuid_dict[item.exactor_id]
                        start_area_index = load_area_uuid_to_index_dict[start_area_id]
                        start_eq_index = self.excavator_uuid_to_index_dict[item.exactor_id]
                    else:
                        start_area_index = -1
                        start_eq_index = -1

                    if item.dump_id in DeviceMap.dump_uuid_to_index_dict:
                        end_area_id = self.dump_uuid_to_unload_area_uuid_dict[item.dump_id]
                        end_area_index = unload_area_uuid_to_index_dict[end_area_id]
                        end_eq_index = self.dump_uuid_to_index_dict[item.dump_id]
                    else:
                        end_area_index = -1
                        end_eq_index = -1

                    # # 结束设备index
                    # end_eqp_index = self.dump_uuid_to_index_dict[item.dump_id]

                    self.truck_current_trip[i] = [start_eq_index, end_eq_index]

                    self.logger.info("walk_time_to_unload_area")
                    self.logger.info(walk_time_to_unload_area)
                    self.logger.info("end_area_index")
                    self.logger.info(end_area_index)
                    self.logger.info("start_area_index")
                    self.logger.info(start_area_index)

                    self.cur_truck_reach_dump[i] = (
                            last_load_time
                            + walk_time_to_unload_area[end_area_index][start_area_index]
                    )

                    self.logger.info(f'update_truck_trip-{truck_id}-last_load_time')
                    self.logger.info(last_load_time)
                    self.logger.info(f'update_truck_trip-walk_time_to_unload_area')
                    self.logger.info(walk_time_to_unload_area[end_area_index][start_area_index])

                    # 目的地矿卡数加一
                    # self.dump_hold_truck_num[end_eqp_index] = self.dump_hold_truck_num[end_eqp_index] + 1
                # 其他状态，矿卡状态为-2，equipment_pair表不存在该矿卡
                else:
                    # end_eqp_index = excavator.excavator_uuid_to_index_dict[item.exactor_id]
                    # self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
                    pass
            except Exception as es:
                self.logger.error("矿卡行程读取异常")
                self.logger.error(es)

        # print("self.dump_hold_truck_num")
        # print(self.dump_hold_truck_num)
        #
        # print("self.excavator_hold_truck_num")
        # print(self.excavator_hold_truck_num)

        self.truck_current_trip.flatten()
        self.logger.info("当前矿卡行程：")
        self.logger.info(self.truck_current_trip)

    def update_eqp_hold_truck(self):

        for i in range(self.dynamic_truck_num):
            try:
                session_mysql.commit()
                truck_id = self.truck_index_to_uuid_dict[i]
                aa = self.truck_index_to_uuid_dict
                bb = self.truck_current_task
                task = self.truck_current_task[self.truck_index_to_uuid_dict[i]]
                # item = (
                #     session_mysql.query(EquipmentPair)
                #         .filter_by(truck_id=truck_id, isdeleted=0)
                #         .first()
                # )
                item = (
                    session_mysql.query(DispatchSetting)
                        .filter_by(truck_id=truck_id, isdeleted=0)
                        .first()
                )

                if task in empty_task_set + heavy_task_set and item is None:    # 矿卡处于正常工作状态, 但查询不到派车计划
                    raise Exception(f"矿卡 {truck_id} 配对关系异常")
            except Exception as es:
                self.logger.error("配对关系异常")
                self.logger.error(es)
                session_postgre.rollback()
                session_mysql.rollback()
                continue

            try:
                # 若矿卡状态为空运(含装载出场)
                if task in [0, 1, 2]:

                    # 结束设备index
                    end_eqp_index = self.excavator_uuid_to_index_dict[item.exactor_id]

                    # 目的地矿卡数加一
                    self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
                    # 目的地矿卡集合增加
                    if item.exactor_id not in self.excavator_hold_truck_list:
                        self.excavator_hold_truck_list[item.exactor_id] = [truck_id]
                    else:
                        self.excavator_hold_truck_list[item.exactor_id].append(truck_id)
                # 若矿卡状态为重载(含卸载出场)
                elif task in [3, 4, 5]:

                    # 结束设备index
                    end_eqp_index = self.dump_uuid_to_index_dict[item.dump_id]

                    # 目的地矿卡数加一
                    self.dump_hold_truck_num[end_eqp_index] = self.dump_hold_truck_num[end_eqp_index] + 1
                    # 目的地矿卡集合增加
                    if item.dump_id not in self.dump_hold_truck_list:
                        self.dump_hold_truck_list[item.dump_id] = [truck_id]
                    else:
                        self.dump_hold_truck_list[item.dump_id].append(truck_id)
                # 其他状态，矿卡状态为-2，equipment_pair表不存在该矿卡
                else:
                    pass
            except Exception as es:
                self.logger.error("驶往设备矿卡数量统计异常")
                self.logger.error(es)

        print("self.dump_hold_truck_num")
        print(self.dump_hold_truck_num)

        print("self.excavator_hold_truck_num")
        print(self.excavator_hold_truck_num)

    ################################################ long term update ################################################

    # 更新矿卡实际容量
    def update_truck_payload(self):
        self.payload = np.full(self.dynamic_truck_num, 220);
        # try:
        #     self.payload = np.zeros(self.dynamic_truck_num)
        #     for truck_id in self.dynamic_truck_set:
        #         trcuk_index = self.truck_uuid_to_index_dict[truck_id]
        #         truck_spec = (
        #             session_mysql.query(Equipment)
        #                 .filter_by(id=truck_id)
        #                 .first()
        #                 .equipment_spec
        #         )
        #         # truck_spec = query.equipment_spec
        #         self.payload[trcuk_index] = (
        #             session_mysql.query(EquipmentSpec)
        #                 .filter_by(id=truck_spec)
        #                 .first()
        #                 .capacity
        #         )
        # except Exception as es:
        #     self.logger.error("读取矿卡有效载重异常-矿卡型号信息缺失")
        #     self.logger.error(es)

    def update_truck_priority(self):
        self.truck_priority = np.full(self.dynamic_truck_num, 0)
        try:
            rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first()
        except Exception as es:
            session_postgre.rollback()
            session_mysql.rollback()

        try:
            if rule6.disabled == 0:
                for truck_id in self.dynamic_truck_set:
                    try:
                        item = session_mysql.query(Equipment).filter_by(id=truck_id).first()
                    except Exception as es:
                        session_postgre.rollback()
                        session_mysql.rollback()
                    truck_index = self.truck_uuid_to_index_dict[truck_id]
                    if item.priority == 0:
                        self.truck_priority[truck_index] = 0
                    elif item.priority == 1:
                        self.truck_priority[truck_index] = 2
                    elif item.priority == 2:
                        self.truck_priority[truck_index] = 5
                    elif item.priority == 3:
                        self.truck_priority[truck_index] = 10
        except Exception as es:
            self.logger.error("车辆优先级更新异常")
            self.logger.error(es)
            session_postgre.rollback()
            session_mysql.rollback()

    def update_truck_dump_area_bind(self):
        truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
        try:
            rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first()
            if rule5.disabled == 0:
                self.truck_dump_bind = {}
                for dump_area in session_postgre.query(DumpArea).all():
                    if dump_area.BindList is not None:
                        for truck_name in dump_area.BindList:
                            self.truck_dump_bind[truck_name_to_uuid_dict[truck_name]] = str(
                                dump_area.Id
                            )
        except Exception as es:
            self.logger.error("矿卡-卸载区域绑定关系读取异常")
            self.logger.error(es)
            session_postgre.rollback()
            session_mysql.rollback()

    def update_truck_excavator_bind(self):
        truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
        try:
            rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first()
            if rule5.disabled == 0:
                self.truck_excavator_bind = {}
                for excavator_id in get_value("dynamic_excavator_set"):
                    item = session_mysql.query(Equipment).filter_by(id=excavator_id).first()
                    if item.bind_list is not None:
                        for truck_name in json.loads(item.bind_list):
                            self.truck_excavator_bind[
                                truck_name_to_uuid_dict[truck_name]
                            ] = excavator_id
        except Exception as es:
            self.logger.error("矿卡-挖机绑定关系读取异常")
            self.logger.error(es)
            session_postgre.rollback()
            session_mysql.rollback()

    def update_truck_excavator_exclude(self):

        self.truck_excavator_exclude = {}

        truck_uuid_to_name_dict = get_value("truck_uuid_to_name_dict")

        self.excavator_exclude_modify = np.full(
            (self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0
        )

        try:
            try:
                rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first()
            except Exception as es:
                session_postgre.rollback()
                session_mysql.rollback()
            if rule5.disabled == 0:
                for excavator_id in get_value("dynamic_excavator_set"):
                    try:
                        item = (
                            session_mysql.query(Equipment)
                                .filter_by(id=excavator_id, only_allowed=1)
                                .first()
                        )
                    except Exception as es:
                        session_postgre.rollback()
                        session_mysql.rollback()
                    if item is not None:
                        for truck_id in self.dynamic_truck_set:
                            if truck_uuid_to_name_dict[truck_id] not in item.bind_list:
                                self.truck_excavator_exclude[truck_id] = excavator_id
                                self.excavator_exclude_modify[
                                    self.truck_uuid_to_index_dict[truck_id]
                                ][
                                    self.excavator_uuid_to_index_dict[excavator_id]
                                ] = 1000000
        except Exception as es:
            self.logger.error("矿卡-挖机禁止关系读取异常")
            self.logger.error(es)

        return self.excavator_exclude_modify

    def update_truck_dump_exclude(self):
        pass

    def update_truck_material(self):

        try:
            self.truck_material_bind = {}
            self.update_truck_excavator_bind()
            self.update_truck_dump_area_bind()

            self.excavator_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
            self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_dump_num")), 0)

            for truck_id in self.dynamic_truck_set:
                if truck_id in self.truck_dump_bind:
                    unload_area_id = self.truck_dump_bind[truck_id]
                    try:
                        dump_material_id = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Materials
                    except Exception as es:
                        session_postgre.rollback()
                        session_mysql.rollback()
                    self.truck_material_bind[truck_id] = dump_material_id

                if truck_id in self.truck_excavator_bind:
                    excavator_id = self.truck_excavator_bind[truck_id]
                    # print(self._excavator.excavator_material)
                    excavator_material_id = self._excavator.excavator_material[excavator_id]
                    self.truck_material_bind[truck_id] = excavator_material_id

            for truck_id in self.dynamic_truck_set:

                truck_index = self.truck_uuid_to_index_dict[truck_id]

                if truck_id in self.truck_material_bind:

                    material = self.truck_material_bind[truck_id]

                    for excavator_id in get_value("dynamic_excavator_set"):
                        excavator_material_id = self._excavator.excavator_material[excavator_id]
                        excavator_index = self.excavator_uuid_to_index_dict[excavator_id]
                        print(truck_index, excavator_index)
                        if excavator_material_id != material:
                            self.excavator_material_bind_modify[truck_index][excavator_index] = 1000000

                    for dump_id in get_value("dynamic_dump_set"):
                        dump_material_id = self._dump.dump_material[dump_id]
                        dump_index = self.dump_uuid_to_index_dict[dump_id]
                        if dump_material_id != material:
                            self.dump_material_bind_modify[truck_index][dump_index] = 1000000
        except Exception as es:
            self.logger.error(es)
            self.logger.error("矿卡物料更新异常")

    def update_truck_spec(self):
        for truck_id in self.dynamic_truck_set:
            try:
                self.size[truck_id] = session_mysql.query(Equipment).filter_by(id=truck_id).first().equipment_spec
            except Exception as es:
                self.logger.error("车辆型号更新异常")
                self.logger.error(es)
                session_postgre.rollback()
                session_mysql.rollback()

    def update_truck_size(self):
        self.update_truck_spec()
        for truck_id in self.dynamic_truck_set:
            truck_spec_id = self.size[truck_id]
            try:
                self.geo_length[truck_id] = session_mysql.query(EquipmentSpec).filter_by(id=truck_spec_id).first().length
                self.geo_width[truck_spec_id] = session_mysql.query(EquipmentSpec).filter_by(id=truck_spec_id).first().width
            except Exception as es:
                self.logger.error("车辆几何尺寸更新异常")
                self.logger.error(es)
                session_postgre.rollback()
                session_mysql.rollback()

    def update_truck_speed(self):
        for truck_id in self.dynamic_truck_set:
            try:
                empty_speed = session_mysql.query(EquipmentSpec). \
                    join(Equipment, EquipmentSpec.id == Equipment.equipment_spec). \
                    filter(Equipment.id == truck_id).first().max_speed

                if (empty_speed <= 1) or (empty_speed >= 50) or (empty_speed is None):
                    self.empty_speed[truck_id] = 20
                else:
                    self.empty_speed[truck_id] = empty_speed

                heavy_speed = session_mysql.query(EquipmentSpec). \
                    join(Equipment, EquipmentSpec.id == Equipment.equipment_spec). \
                    filter(Equipment.id == truck_id).first().max_speed

                if (heavy_speed <= 1) or (heavy_speed >= 50) or (heavy_speed is None):
                    self.heavy_speed[truck_id] = 20
                else:
                    self.heavy_speed[truck_id] = heavy_speed
            except Exception as es:
                self.logger.error("车辆速度更新异常")
                self.logger.error(es)
                session_postgre.rollback()
                session_mysql.rollback()

    def update_truck_disable_list(self) -> List:
        try:
            for item in session_mysql.query(Equipment).filter_by(device_type=1, disabled=1).all():
                self.truck_disable_list.append(item.equipment_id)
        except Exception as es:
            self.logger.error("车辆禁止列表更新异常")
            self.logger.error(es)
            session_postgre.rollback()
            session_mysql.rollback()
        return self.truck_disable_list

    def truck_reset(self, dump, excavator):
        # 更新矿卡数量
        self.dynamic_truck_num = get_value("dynamic_truck_num")
        # 更新矿卡集合
        self.dynamic_truck_set = get_value("dynamic_truck_set")
        # 矿卡抵达卸载设备时间
        self.cur_truck_reach_dump = np.zeros(self.dynamic_truck_num)
        # 矿卡抵达挖机时间
        self.cur_truck_reach_excavator = np.zeros(self.dynamic_truck_num)
        # 矿卡最后装载/卸载时间
        self.last_load_time = {}
        self.last_unload_time = {}
        # 相对矿卡最后装载/卸载时间
        self.relative_last_load_time = {}
        self.relative_last_unload_time = {}
        # 矿卡当前任务
        self.truck_current_task = {}
        # 矿卡当前行程(第一列为出发地序号, 第二列为目的地序号)
        self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
        # 矿卡不可用列表
        self.truck_disable_list = []
        # 矿卡挖机绑定关系
        self.truck_excavator_bind = {}
        # 矿卡卸点绑定关系
        self.truck_dump_bind = {}
        # 矿卡挖机排斥关系
        self.truck_excavator_exclude = {}
        # 矿卡卸点排斥关系
        self.truck_dump_exclude = {}
        # 排斥关系modify
        self.excavator_exclude_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
        # 矿卡优先级
        self.truck_priority = np.ones(self.dynamic_truck_num)
        # 矿卡绑定物料
        self.truck_material_bind = {}
        # 矿卡绑定物料modify
        self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_dump_num")), 0)
        # self.excavator_material_bind_modify =np.zeros(self.dynamic_truck_num)
        self.excavator_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_excavator_num")), 0)
        # # group_id
        # self.truck_group = {}
        # 各卸载区矿卡数量
        self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
        # 各装载区矿卡数量
        self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
        # 驶往各卸载区矿卡集合
        self.dump_hold_truck_list = {item: [] for item in get_value("dynamic_dump_set")}
        # 驶往各装载区矿卡集合
        self.excavator_hold_truck_list = {item: [] for item in get_value("dynamic_excavator_set")}
        # 对象域更新
        self.dump = dump
        self.excavator = excavator

    def truck_para_period_update(self, dump, excavator):

        # 初始化参数
        self.truck_reset(dump, excavator)

        try:

            # 距离成本启动
            rule1 = session_mysql.query(DispatchRule).filter_by(id=1).first().disabled

            # 拥堵成本启用
            rule2 = session_mysql.query(DispatchRule).filter_by(id=2).first().disabled

            # 车流规划启用
            rule3 = session_mysql.query(DispatchRule).filter_by(id=3).first().disabled

            rule4 = session_mysql.query(DispatchRule).filter_by(id=4).first().disabled

            # 锁定禁止启用
            rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first().disabled

            # 设备优先级启用
            rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first().disabled

            # 物料优先级启用
            rule7 = session_mysql.query(DispatchRule).filter_by(id=7).first().disabled

        except Exception as es:
            self.logger.error("规则读取异常")
            self.logger.error(es)
            session_postgre.rollback()
            session_mysql.rollback()

        self.logger.info("Para truck update!")

        # 更新有效载重
        self.update_truck_payload()

        if rule1:
            self.logger.info("距离成本规则未启用")
        else:
            self.logger.info("距离成本规则启用")

        if rule2:
            self.logger.info("拥堵成本规则未启用")
        else:
            self.logger.info("拥堵成本规则启用")

        if rule3 or rule4:
            self.logger.info("车流规划规则未启用")
        else:
            self.logger.info("车流规划规则启用")

        if rule5:
            self.logger.info("生产组织规则未启用")
        else:
            # 更新绑定关系
            self.update_truck_dump_area_bind()
            self.update_truck_excavator_bind()
            # 更新禁止关系
            self.update_truck_excavator_exclude()
            self.logger.info("生产组织规划规则启用")

        if rule6:
            self.logger.info("设备优先级规则未启用")
        else:
            # 更新矿卡调度优先级
            self.update_truck_priority()
            self.logger.info("设备优先级规则启用")

        if rule7:
            self.logger.info("物料优先级规则未启用")
        else:
            self.logger.info("物料优先级规则启用")
        # 更新矿卡物料类型
        self.update_truck_material()



    def state_period_update(self):

        # 更新卡车当前任务
        self.update_truck_current_task()

        # 更新卡车最后一次装载/卸载时间
        self.update_truck_last_leave_time()

        # 更新卡车当前行程
        self.update_truck_trip()

        # 更新各设备hold矿卡数量
        self.update_eqp_hold_truck()

        # 矿卡速度更新
        self.update_truck_speed()
