#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/4 15:50
# @Author : Opfer
# @Site :
# @File : para_config.py
# @Software: PyCharm

from static_data_process import *
from settings import *
import numpy as np

# 全局参数设定

# 空载任务集合
empty_task_set = [0, 1, 5]

# 重载任务集合
heavy_task_set = [2, 3, 4]

# 任务集合
task_set = [-2, 0, 1, 2, 3, 4, 5]

# Big integer
M = 100000000

logger = get_logger("zxt.para")

# 装载区、卸载区、备停区在调度算法运行器件默认不发生改变，提前计算部分参量
# (uuid,index(id)映射关系, 装载区数量, 卸载区数量, 备停区数量, 以及初次统计动态调度矿卡)
(
    load_area_uuid_to_index_dict,
    unload_area_uuid_to_index_dict,
    load_area_index_to_uuid_dict,
    unload_area_index_to_uuid_dict,
) = build_work_area_uuid_index_map()

load_area_num, unload_area_num = len(load_area_uuid_to_index_dict), len(
    unload_area_uuid_to_index_dict
)

park_uuid_to_index_dict, park_index_to_uuid_dict = build_park_uuid_index_map()

park_num = len(park_uuid_to_index_dict)

truck_uuid_to_name_dict, truck_name_to_uuid_dict = build_truck_uuid_name_map()

excavator_uuid_to_name_dict, dump_uuid_to_name_dict = build_equipment_uuid_name_map()

# 矿卡集合
truck_set = set(update_total_truck())

# 固定派车矿卡集合
fixed_truck_set = set(update_fixdisp_truck())

# 动态派车矿卡集合
# dynamic_truck_set = truck_set.difference(fixed_truck_set)
dynamic_truck_set = update_dynamic_truck()

dynamic_truck_num = len(dynamic_truck_set)

logger.info("可用于动态派车的矿卡：")
logger.info(dynamic_truck_set)

# 用于动态调度的挖机及卸载设备
dynamic_excavator_set = set(update_autodisp_excavator())
dynamic_excavator_num = len(dynamic_excavator_set)

dynamic_dump_set = set(update_autodisp_dump())
dynamic_dump_num = len(dynamic_dump_set)

global global_dict

global_dict = {}

global_dict["dynamic_truck_set"] = dynamic_truck_set
global_dict["dynamic_truck_num"] = dynamic_truck_num
global_dict["dynamic_excavator_set"] = dynamic_excavator_set
global_dict["dynamic_excavator_num"] = dynamic_excavator_num
global_dict["dynamic_dump_set"] = dynamic_dump_set
global_dict["dynamic_dump_num"] = dynamic_dump_num
global_dict["park_num"] = park_num


def get_value(name):
    return global_dict[name]


# 设备映射类, 存储除工作区以外的映射关系
# 其余设备类继承该类
class DeviceMap:
    excavator_uuid_to_index_dict = {}
    dump_uuid_to_index_dict = {}
    excavator_index_to_uuid_dict = {}
    dump_index_to_uuid_dict = {}

    dump_uuid_to_unload_area_uuid_dict = {}
    excavator_uuid_to_load_area_uuid_dict = {}
    excavator_index_to_load_area_index_dict = {}
    dump_index_to_unload_area_index_dict = {}

    truck_uuid_to_index_dict = {}
    truck_index_to_uuid_dict = {}

    # def __init__(cls):
    #     cls.excavator_uuid_to_index_dict = {}
    #     cls.dump_uuid_to_index_dict = {}
    #     cls.excavator_index_to_uuid_dict = {}
    #     cls.dump_index_to_uuid_dict = {}
    #
    #     cls.dump_uuid_to_unload_area_uuid_dict = {}
    #     cls.excavator_uuid_to_load_area_uuid_dict = {}
    #     cls.excavator_index_to_load_area_index_dict = {}
    #     cls.dump_index_to_unload_area_index_dict = {}
    #
    #     cls.truck_uuid_to_index_dict = {}
    #     cls.truck_index_to_uuid_dict = {}

    # def get_excavator_uuid_to_index_dict(cls):
    #     return cls.excavator_uuid_to_index_dict
    #
    # def get_dump_uuid_to_index_dict(cls):
    #     return cls.dump_uuid_to_index_dict
    #
    # def get_excavator_index_to_uuid_dict(cls):
    #     return cls.excavator_index_to_uuid_dict
    #
    # def get_dump_index_to_uuid_dict(cls):
    #     return cls.dump_index_to_uuid_dict
    #
    # def get_dump_uuid_to_unload_area_uuid_dict(cls):
    #     return cls.dump_uuid_to_unload_area_uuid_dict
    #
    # def get_excavator_uuid_to_load_area_uuid_dict(cls):
    #     return cls.excavator_uuid_to_load_area_uuid_dict
    #
    # def get_excavator_index_to_load_area_index_dict(cls):
    #     return cls.excavator_index_to_load_area_index_dict
    #
    # def get_dump_index_to_unload_area_index_dict(cls):
    #     return cls.dump_index_to_unload_area_index_dict
    #
    # def get_truck_uuid_to_index_dict(cls):
    #     return cls.truck_uuid_to_index_dict
    #
    # def get_truck_index_to_uuid_dict(cls):
    #     return cls.truck_index_to_uuid_dict

    @classmethod
    def reset(cls):
        cls.excavator_uuid_to_index_dict = {}
        cls.dump_uuid_to_index_dict = {}
        cls.excavator_index_to_uuid_dict = {}
        cls.dump_index_to_uuid_dict = {}

        cls.dump_uuid_to_unload_area_uuid_dict = {}
        cls.excavator_uuid_to_load_area_uuid_dict = {}
        cls.excavator_index_to_load_area_index_dict = {}
        cls.dump_index_to_unload_area_index_dict = {}

        cls.truck_uuid_to_index_dict = {}
        cls.truck_index_to_uuid_dict = {}

    @classmethod
    def period_map_para_update(cls):
        cls.reset()

        device_map_dict = update_deveices_map(
            unload_area_uuid_to_index_dict, load_area_uuid_to_index_dict
        )

        cls.excavator_uuid_to_index_dict = device_map_dict[
            "excavator_uuid_to_index_dict"
        ]

        cls.dump_uuid_to_index_dict = device_map_dict["dump_uuid_to_index_dict"]
        cls.excavator_index_to_uuid_dict = device_map_dict[
            "excavator_index_to_uuid_dict"
        ]
        cls.dump_index_to_uuid_dict = device_map_dict["dump_index_to_uuid_dict"]

        cls.dump_uuid_to_unload_area_uuid_dict = device_map_dict[
            "dump_uuid_to_unload_area_uuid_dict"
        ]
        cls.excavator_uuid_to_load_area_uuid_dict = device_map_dict[
            "excavator_uuid_to_load_area_uuid_dict"
        ]
        cls.excavator_index_to_load_area_index_dict = device_map_dict[
            "excavator_index_to_load_area_index_dict"
        ]
        cls.dump_index_to_unload_area_index_dict = device_map_dict[
            "dump_index_to_unload_area_index_dict"
        ]

        truck_map_dict = update_truck_uuid_index_map(get_value("dynamic_truck_set"))

        cls.truck_uuid_to_index_dict = truck_map_dict["truck_uuid_to_index_dict"]

        cls.truck_index_to_uuid_dict = truck_map_dict["truck_index_to_uuid_dict"]

    # def period_map_para_load(cls):
    #     # 装载关系映射
    #     cls.excavator_uuid_to_index_dict = device_map.excavator_uuid_to_index_dict
    #     cls.dump_uuid_to_index_dict = device_map.dump_uuid_to_index_dict
    #     cls.excavator_index_to_uuid_dict = device_map.excavator_index_to_uuid_dict
    #     cls.dump_index_to_uuid_dict = device_map.dump_index_to_uuid_dict
    #
    #     cls.dump_uuid_to_unload_area_uuid_dict = (
    #         device_map.dump_uuid_to_unload_area_uuid_dict
    #     )
    #     cls.excavator_uuid_to_load_area_uuid_dict = (
    #         device_map.excavator_uuid_to_load_area_uuid_dict
    #     )
    #     cls.excavator_index_to_load_area_index_dict = (
    #         device_map.excavator_index_to_load_area_index_dict
    #     )
    #     cls.dump_index_to_unload_area_index_dict = (
    #         device_map.dump_index_to_unload_area_index_dict
    #     )
    #
    #     cls.truck_uuid_to_index_dict = device_map.truck_uuid_to_index_dict
    #     cls.truck_index_to_uuid_dict = device_map.truck_index_to_uuid_dict


# 路网信息类
class WalkManage(DeviceMap):
    # def __init__(cls):
    #     # # 工作区和设备不具备一一对应关系, 为方便就计算, 算法维护两套路网: 面向路网和面向设备
    #
    #     # 路网真实距离
    #     cls.walk_time_to_excavator = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    #     cls.walk_time_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    #     cls.walk_time_park_to_excavator = np.full((park_num, dynamic_excavator_num), M, dtype=float)
    #     cls.walk_time_park_to_load_area = np.full((park_num, load_area_num), M, dtype=float)
    #     cls.walk_time_to_load_area = np.full((unload_area_num, load_area_num), M, dtype=float)
    #     cls.walk_time_to_unload_area = np.full((unload_area_num, load_area_num), M, dtype=float)
    #
    #     # 路网行驶时间
    #     cls.distance_to_excavator = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    #     cls.distance_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    #     cls.distance_park_to_excavator = np.full((park_num, dynamic_excavator_num), M, dtype=float)
    #     cls.distance_park_to_load_area = np.full((park_num, load_area_num), M, dtype=float)
    #     cls.distance_to_load_area = np.full((unload_area_num, load_area_num), M, dtype=float)
    #     cls.distance_to_unload_area = np.full((unload_area_num, load_area_num), M, dtype=float)

    # # 工作区和设备不具备一一对应关系, 为方便就计算, 算法维护两套路网: 面向路网和面向设备

    # 路网真实距离
    walk_time_to_excavator = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    walk_time_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    walk_time_park_to_excavator = np.full((park_num, dynamic_excavator_num), M, dtype=float)
    walk_time_park_to_load_area = np.full((park_num, load_area_num), M, dtype=float)
    walk_time_to_load_area = np.full((unload_area_num, load_area_num), M, dtype=float)
    walk_time_to_unload_area = np.full((unload_area_num, load_area_num), M, dtype=float)

    # 路网行驶时间
    distance_to_excavator = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    distance_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M, dtype=float)
    distance_park_to_excavator = np.full((park_num, dynamic_excavator_num), M, dtype=float)
    distance_park_to_load_area = np.full((park_num, load_area_num), M, dtype=float)
    distance_to_load_area = np.full((unload_area_num, load_area_num), M, dtype=float)
    distance_to_unload_area = np.full((unload_area_num, load_area_num), M, dtype=float)

    # def get_walk_time_to_load_area(cls):
    #     return cls.walk_time_to_load_area
    #
    # def get_walk_time_to_unload_area(cls):
    #     return cls.walk_time_to_unload_area
    #
    # def get_walk_time_to_excavator(cls):
    #     return cls.walk_time_to_excavator
    #
    # def get_walk_time_to_dump(cls):
    #     return cls.walk_time_to_dump
    #
    # def get_walk_time_park_to_load_area(cls):
    #     return cls.walk_time_park_to_load_area
    #
    # def get_walk_time_park_to_excavator(cls):
    #     return cls.walk_time_park_to_excavator
    #
    # def get_distance_to_load_area(cls):
    #     return cls.distance_to_load_area
    #
    # def get_distance_to_unload_area(cls):
    #     return cls.distance_to_unload_area
    #
    # def get_distance_to_excavator(cls):
    #     return cls.distance_to_excavator
    #
    # def get_distance_to_dump(cls):
    #     return cls.distance_to_dump
    #
    # def get_distance_park_to_load_area(cls):
    #     return cls.distance_park_to_load_area
    #
    # def get_distance_park_to_excavator(cls):
    #     return cls.distance_park_to_excavator

    @classmethod
    def reset(cls):

        # dynamic_excavator_num
        # dynamic_dump_num
        # park_num

        # 路网真实距离
        cls.walk_time_to_excavator = np.full(
            (dynamic_dump_num, dynamic_excavator_num), M
        )
        cls.walk_time_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M)
        cls.walk_time_park_to_excavator = np.full((park_num, dynamic_excavator_num), M)
        cls.walk_time_park_to_load_area = np.full((park_num, load_area_num), M)
        cls.walk_time_to_load_area = np.full((unload_area_num, load_area_num), M)
        cls.walk_time_to_unload_area = np.full((unload_area_num, load_area_num), M)

        # 路网行驶时间
        cls.distance_to_excavator = np.full((dynamic_dump_num, dynamic_excavator_num), M)
        cls.distance_to_dump = np.full((dynamic_dump_num, dynamic_excavator_num), M)
        cls.distance_park_to_excavator = np.full((park_num, dynamic_excavator_num), M)
        cls.distance_park_to_load_area = np.full((park_num, load_area_num), M)
        cls.distance_to_load_area = np.full((unload_area_num, load_area_num), M)
        cls.distance_to_unload_area = np.full((unload_area_num, load_area_num), M)

    @classmethod
    def period_walk_para_update(cls):

        cls.reset()

        cls.period_map_para_update()

        # 计算路网距离及行走时间
        try:
            # 处理距离
            for item in session_postgre.query(WalkTime).all():
                load_area = str(item.load_area_id)
                unload_area = str(item.unload_area_id)
                load_area_index = load_area_uuid_to_index_dict[load_area]
                unload_area_index = unload_area_uuid_to_index_dict[unload_area]
                cls.distance_to_load_area[unload_area_index][load_area_index] = float(
                    item.to_load_distance
                )
                cls.walk_time_to_load_area[unload_area_index][load_area_index] = float(
                    60 / 1000 * item.to_load_distance / empty_speed
                )
                cls.distance_to_unload_area[unload_area_index][
                    load_area_index
                ] = float(item.to_unload_distance)
                cls.walk_time_to_unload_area[unload_area_index][
                    load_area_index
                ] = float(60 / 1000 * item.to_unload_distance / heavy_speed)
        except Exception as es:
            logger.error("路网信息异常")
            logger.error(es)

        # 计算设备路网距离及行走时间
        try:
            for i in range(dynamic_dump_num):
                for j in range(dynamic_excavator_num):
                    cls.distance_to_excavator[i][j] = cls.distance_to_load_area[
                        cls.dump_index_to_unload_area_index_dict[i]
                    ][cls.excavator_index_to_load_area_index_dict[j]]
                    cls.walk_time_to_excavator[i][j] = cls.walk_time_to_load_area[
                        cls.dump_index_to_unload_area_index_dict[i]
                    ][cls.excavator_index_to_load_area_index_dict[j]]
                    cls.distance_to_dump[i][j] = cls.distance_to_unload_area[
                        cls.dump_index_to_unload_area_index_dict[i]
                    ][cls.excavator_index_to_load_area_index_dict[j]]
                    cls.walk_time_to_dump[i][j] = cls.walk_time_to_unload_area[
                        cls.dump_index_to_unload_area_index_dict[i]
                    ][cls.excavator_index_to_load_area_index_dict[j]]
        except Exception as es:
            logger.error("设备路网信息异常异常")
            logger.error(es)

        try:
            for item in session_postgre.query(WalkTimePark).all():
                load_area = str(item.load_area_id)
                park_area = str(item.park_area_id)
                load_area_index = load_area_uuid_to_index_dict[load_area]
                park_index = park_uuid_to_index_dict[park_area]
                cls.distance_park_to_load_area[park_index][load_area_index] = float(
                    item.park_load_distance
                )
                cls.walk_time_park_to_load_area[park_index][load_area_index] = float(
                    60 / 1000 * item.park_load_distance / empty_speed
                )
        except Exception as es:
            logger.error("备停区路网信息异常")
            logger.error(es)
        try:
            for i in range(park_num):
                for j in range(dynamic_excavator_num):
                    cls.distance_park_to_excavator[i][j] = cls.distance_park_to_load_area[
                        i
                    ][cls.excavator_index_to_load_area_index_dict[j]]
                    cls.walk_time_park_to_excavator[i][
                        j
                    ] = cls.walk_time_park_to_load_area[i][
                        cls.excavator_index_to_load_area_index_dict[j]
                    ]
        except Exception as es:
            logger.error("备停区设备路网信息异常")
            logger.error(es)

        logger.info("distance_park_to_excavator")
        logger.info(cls.distance_park_to_excavator)


def global_period_para_update():
    global load_area_uuid_to_index_dict, load_area_index_to_uuid_dict
    global unload_area_uuid_to_index_dict, unload_area_index_to_uuid_dict
    global load_area_num, unload_area_num, park_num
    global park_uuid_to_index_dict, park_index_to_uuid_dict
    global truck_uuid_to_name_dict, truck_name_to_uuid_dict
    global dynamic_truck_num, dynamic_excavator_num, dynamic_dump_num
    global excavator_uuid_to_name_dict, dump_uuid_to_name_dict

    # 清空数据库缓存
    session_mysql.commit()
    session_mysql.flush()

    # 装载区、卸载区、备停区在调度算法运行器件默认不发生改变，提前计算部分参量
    # (uuid,index(id)映射关系, 装载区数量, 卸载区数量, 备停区数量, 以及初次统计动态调度矿卡)
    (
        load_area_uuid_to_index_dict,
        unload_area_uuid_to_index_dict,
        load_area_index_to_uuid_dict,
        unload_area_index_to_uuid_dict,
    ) = build_work_area_uuid_index_map()

    load_area_num, unload_area_num = len(load_area_uuid_to_index_dict), len(
        unload_area_uuid_to_index_dict
    )

    park_uuid_to_index_dict, park_index_to_uuid_dict = build_park_uuid_index_map()

    park_num = len(park_uuid_to_index_dict)

    truck_uuid_to_name_dict, truck_name_to_uuid_dict = build_truck_uuid_name_map()

    excavator_uuid_to_name_dict, dump_uuid_to_name_dict = build_equipment_uuid_name_map()

    # 矿卡集合
    truck_set = set(update_total_truck())

    logger.info("truck_set")
    logger.info(truck_set)

    # 固定派车矿卡集合
    fixed_truck_set = set(update_fixdisp_truck())

    logger.info("fixed_truck_set")
    logger.info(fixed_truck_set)

    # 动态派车矿卡集合
    # dynamic_truck_set = truck_set.difference(fixed_truck_set)
    dynamic_truck_set = update_dynamic_truck()

    dynamic_truck_num = len(dynamic_truck_set)

    logger.info("可用于动态派车的矿卡：")
    logger.info(dynamic_truck_num)
    logger.info(dynamic_truck_set)

    # 用于动态调度的挖机及卸载设备
    dynamic_excavator_set = set(update_autodisp_excavator())
    dynamic_excavator_num = len(dynamic_excavator_set)

    dynamic_dump_set = set(update_autodisp_dump())
    dynamic_dump_num = len(dynamic_dump_set)

    DeviceMap.reset()

    DeviceMap.period_map_para_update()

    WalkManage.reset()

    WalkManage.period_walk_para_update()

    global_dict["dynamic_truck_set"] = dynamic_truck_set
    global_dict["dynamic_truck_num"] = dynamic_truck_num
    global_dict["dynamic_excavator_set"] = dynamic_excavator_set
    global_dict["dynamic_excavator_num"] = dynamic_excavator_num
    global_dict["dynamic_dump_set"] = dynamic_dump_set
    global_dict["dynamic_dump_num"] = dynamic_dump_num
    global_dict["park_num"] = park_num
    global_dict["load_area_num"] = load_area_num
    global_dict["unload_area_num"] = unload_area_num

    global_dict["truck_uuid_to_name_dict"] = truck_uuid_to_name_dict
    global_dict["excavator_uuid_to_name_dict"] = excavator_uuid_to_name_dict
    global_dict["dump_uuid_to_name_dict"] = dump_uuid_to_name_dict
    global_dict["unload_area_uuid_to_index_dict"] = unload_area_uuid_to_index_dict
    global_dict["unload_area_index_to_uuid_dict"] = unload_area_index_to_uuid_dict
    global_dict["park_uuid_to_index_dict"] = park_uuid_to_index_dict
    global_dict["park_index_to_uuid_dict"] = park_index_to_uuid_dict

    global_dict["distance_to_excavator"] = WalkManage.distance_to_excavator
    global_dict["distance_park_to_excavator"] = WalkManage.distance_park_to_excavator
    global_dict["distance_to_dump"] = WalkManage.distance_to_dump

    # logger.info("walk_manage_para")
    # logger.info("distance_to_excavator")
    # logger.info(walk_manage.distance_to_excavator)
    # logger.info("distance_park_to_excavator")
    # logger.info(walk_manage.distance_park_to_excavator)
    # logger.info("distance_to_dump")
    # logger.info(walk_manage.distance_to_dump)
    # logger.info("excavator_uuid_to_index_dict")
    # logger.info(walk_manage.excavator_uuid_to_index_dict)
    # logger.info("dump_uuid_to_index_dict")
    # logger.info(walk_manage.dump_uuid_to_index_dict)
    # logger.info("walk_manage.distance_park_to_excavator")
    # logger.info(walk_manage.distance_park_to_excavator)
    #
    # logger.info("walk_manage.truck_index_to_uuid_dict")
    # logger.info(walk_manage.truck_index_to_uuid_dict)
    # logger.info("walk_manage.dynamic_truck_set")
    # logger.info(dynamic_truck_set)
