#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/9/3 14:44
# @Author : Opfer
# @Site :
# @File : priority_control.py
# @Software: PyCharm

from equipment.truck import *
from equipment.dump import *
from equipment.excavator import *
from para_config import *


class PriorityController:

    def __init__(self, dump, excavator, truck):
        # 设备类
        self.dump = dump
        self.excavator = excavator
        self.truck = truck

        # 获取日志器
        self.logger = get_logger("zxt.prio")
        

    def weighted_walk_calc(self):
        """
        计算运输路线权重, 权重影响因素：设备优先级, 物料优先级,
        :return:
            walk_weight: 卸载-装载区 路网权重
            park_walk_weight: 备停区-装载区 路网权重
        """
        park_num = get_value("park_num")
        dynamic_dump_num = get_value("dynamic_dump_num")
        dynamic_excavator_num = get_value("dynamic_excavator_num")
        dynamic_dump_set = get_value("dynamic_dump_set")
        dynamic_excavator_set = get_value("dynamic_excavator_set")
        walk_to_excavator_weight = np.ones((dynamic_dump_num, dynamic_excavator_num))
        walk_to_dump_weight = np.ones((dynamic_excavator_num, dynamic_dump_num))
        excavator_priority = self.excavator.excavator_priority_coefficient
        excavator_material_priority = self.excavator.excavator_material_priority
        dump_priority = self.dump.dump_priority_coefficient
        dump_material_priority = np.ones(dynamic_dump_num)
        park_walk_weight = np.ones((park_num, dynamic_excavator_num))

        try:
            rule6 = session_mysql.query(DispatchRule).filter_by(id=6).first()
        except Exception as es:
            session_postgre.rollback()
            session_mysql.rollback()

        if not rule6.disabled:
            for dump_id in dynamic_dump_set:
                for excavator_id in dynamic_excavator_set:
                    dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
                    excavator_inedx = self.excavator.excavator_uuid_to_index_dict[excavator_id]
                    walk_to_excavator_weight[dump_index][excavator_inedx] += excavator_priority[excavator_inedx]
                    walk_to_dump_weight[excavator_inedx][dump_index] += dump_priority[dump_index]
            park_walk_weight = park_walk_weight * self.excavator.excavator_priority_coefficient

        try:
            rule7 = session_mysql.query(DispatchRule).filter_by(id=7).first()
        except Exception as es:
            session_postgre.rollback()
            session_mysql.rollback()

        if not rule7.disabled:
            for dump_id in dynamic_dump_set:
                for excavator_id in dynamic_excavator_set:
                    dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
                    excavator_inedx = self.excavator.excavator_uuid_to_index_dict[excavator_id]
                    walk_to_excavator_weight[dump_index][excavator_inedx] += excavator_material_priority[excavator_inedx]
                    walk_to_dump_weight[excavator_inedx][dump_index] += dump_material_priority[dump_index]
            park_walk_weight = park_walk_weight * self.excavator.excavator_material_priority

        try:
            walk_to_excavator_weight = walk_to_excavator_weight - (walk_to_excavator_weight.min() - 1)

            walk_to_dump_weight = walk_to_dump_weight - (walk_to_dump_weight.min() - 1)

            park_walk_weight = park_walk_weight - (park_walk_weight.min() - 1)
        except Exception as es:
            self.logger.error(es)
            self.logger.error("优先级归一化异常")

        return walk_to_excavator_weight, walk_to_dump_weight, park_walk_weight

    def walk_available_calc(self):
        """
        计算路网可通行性(物料, 地图, 分组三者综合)
        :return:
            walk_available: 路网可通行性(dump_num, excavator_num)
        """

        map_walk_available = self.update_map_walk_available()
        group_walk_available = self.update_group_walk_available()
        material_walk_available = self.update_material_walk_available()

        walk_available = map_walk_available * group_walk_available * material_walk_available

        return walk_available

    def update_group_walk_available(self):
        """
        计算调度分组间的路网可通行性, 不同分组间路网不可通行
        :return:
            group_walk_available: 调度分组路网可通行性矩阵(dump_num, excavator_num)
        """
        group_walk_available = np.zeros((get_value("dynamic_dump_num"), get_value("dynamic_excavator_num")))

        for dump_id in get_value("dynamic_dump_set"):
            for excavator_id in get_value("dynamic_excavator_set"):
                try:
                    item = session_mysql.query(Dispatch).filter_by(dump_id=dump_id, exactor_id=excavator_id, isauto=1,
                                                               isdeleted=0).first()
                except Exception as es:
                    session_postgre.rollback()
                    session_mysql.rollback()
                if item is not None:
                    dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
                    excavator_index = self.excavator.excavator_uuid_to_index_dict[excavator_id]
                    group_walk_available[dump_index][excavator_index] = 1

        return group_walk_available

    def update_material_walk_available(self):
        """
        更新物料兼容性下路网可通行性
        :return:
            walk_available: 物料兼容路网可通行性矩阵(dump_num, excavator_num)
        """
        dynamic_dump_num = get_value("dynamic_dump_num")
        dynamic_excavator_num = get_value("dynamic_excavator_num")
        dynamic_dump_set = get_value("dynamic_dump_set")
        dynamic_excavator_set = get_value("dynamic_excavator_set")
        walk_available = np.ones((dynamic_dump_num, dynamic_excavator_num))

        try:

            for dump_id in dynamic_dump_set:
                for excavator_id in dynamic_excavator_set:
                    dump_index = self.dump.dump_uuid_to_index_dict[dump_id]
                    excavator_inedx = self.excavator.excavator_uuid_to_index_dict[excavator_id]
                    # 两设备处理物料不同, 相关路网不可通行
                    if self.excavator.excavator_material[excavator_id] != self.dump.dump_material[dump_id]:
                        walk_available[dump_index][excavator_inedx] = 0
        except Exception as es:
            self.logger.info(es)
            self.logger.info("error-12")

        return walk_available

    def update_map_walk_available(self):
        """
        更新物理路网可通行性
        :return:
            walk_available: 物理路网可通行性矩阵(dump_num, excavator_num)
        """
        dynamic_dump_num = get_value("dynamic_dump_num")
        dynamic_excavator_num = get_value("dynamic_excavator_num")
        walk_available = np.ones((dynamic_dump_num, dynamic_excavator_num))

        for dump_index in range(dynamic_dump_num):
            for excavator_index in range(dynamic_excavator_num):
                if WalkManage.distance_to_excavator[dump_index][excavator_index] > M / 2:
                    walk_available[dump_index][excavator_index] = 0

        return walk_available
