#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/21 16:45
# @Author : Opfer
# @Site :
# @File : realtime_dispatch.py
# @Software: PyCharm


# 实时调度模块
from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
import sched
import time
from core.dispatcher import Dispatcher
from core.schedule import PreSchedule
from data.dispatchInfo import DispatchInfo


def direct2redis():
    """
    直接读取数据库写入redis
    :return: None
    """
    # 清空数据库缓存
    session_mysql.commit()
    session_mysql.flush()

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

    truck_disp = {}
    for item in session_mysql.query(DispatchSetting).all():
        if item.truck_id not in truck_disp:
            record = {"truckId": item.truck_id}
            record["id"] = item.id
            record["exactorId"] = item.exactor_id
            record["dumpId"] = item.dump_id
            record["loadAreaId"] = item.load_area_id
            record["unloadAreaId"] = item.unload_area_id
            record["groupId"] = item.group_id
            record["isdeleted"] = False
            record["isTemp"] = False
            record["haulFlag"] = -1
            record["groupName"] = item.group_id

            logger.info("调度结果")
            logger.info(record)
            redis5.set(item.truck_id, str(json.dumps(record)))


def process(dispatcher):
    """
    周期调度进程
    :param dispatcher:  (Dispatch Class) 矿卡调度类对象
    :return: None
    """

    # # 直接读取数据库写入redis
    # direct2redis()

    try:
    # 更新周期参数
        logger.info("#####################################周期更新开始#####################################")

        global_period_para_update()

        if get_value("dynamic_dump_num") * get_value("dynamic_excavator_num") == 0:
            raise Exception("无动态派车计划可用")
            return
        if get_value("dynamic_truck_num") == 0:
            raise Exception("无动态派车可用矿卡")
            return

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

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

        global_period_para_update()

        # 更新调度信息
        DispatchInfo.renew_set()

        DispatchInfo.update_device_group_structure()

        DispatchInfo.update_route_distance()

        DispatchInfo.update_group_mode()

        DispatchInfo.update_group_name()

        # logger.info
        #     group_set = set()
        #
        #     # device group structure
        #     load_excavator_dict = {}  # 装载区id-->>电铲编号的映射
        #     excavator_load_dict = {}  # 电铲编号->>装载区id的映射
        #
        #     group_excavator_dict = {}  # team_id -> dict {[excavator_id, excavator_id], ...}
        #     excavator_group_dict = {}  # excavator_id -> team_id   问题：多个key值对应一个value值
        #
        #     group_dump_dict = {}  # team_id -> dict {unload_area_id, unload_area_id, ...}
        #     dump_group_dict = {}  # unload_area_id -> team_id
        #
        #     group_truck_dict = {}  # team_id -> dict # {group_id:[truck_id,truck_id],...}
        #     truck_group_dict = {}  # truck_id -> team_id
        #
        #     # group feature
        #     group_mode = {}  # 数据格式： {team_id:mode_code}
        #
        #     # route_distance（路网距离）
        #     load_distance = {}
        #     unload_distance = {}
        logger.info("Dispatchinfo，更新后信息")
        logger.info("group_set")
        logger.info(DispatchInfo.group_set)
        logger.info("group_excavator_dict")
        logger.info(DispatchInfo.group_excavator_dict)
        logger.info("group_unload_area_dict")
        logger.info(DispatchInfo.group_unload_area_dict)
        logger.info("group_truck_dict")
        logger.info(DispatchInfo.group_truck_dict)
        logger.info("group_mode")
        logger.info(DispatchInfo.group_mode)
        logger.info("load_distance")
        logger.info(DispatchInfo.load_distance)
        logger.info("unload_distance")
        logger.info(DispatchInfo.unload_distance)

        # logger.info("load_excavator_dict")
        # logger.info(DispatchInfo.load_excavator_dict)
        # logger.info("excavator_load_dict")
        # logger.info(DispatchInfo.excavator_load_dict)
        # logger.info(DispatchInfo.excavator_group_dict)
        # logger.info(DispatchInfo.dump_group_dict)
        # logger.info(DispatchInfo.truck_group_dict)


        # 调度生成
        dispatcher.period_update()

        dispatcher.group_generate()

        dispatcher.group_info_update()

        dispatcher.group_dispatch()

        logger.info("#####################################周期更新结束#####################################")

    except Exception as es:
        logger.error("最外层异常捕获")
        logger.error(es)


def perform(inc, dispatcher):
    """
    控制程序循环执行
    :param inc: (int) 循环周期, 单位, 秒
    :param dispatcher:  (Dispatch Class) 矿卡调度类对象
    :return: None
    """
    scheduler.enter(inc, 0, perform, (inc, dispatcher))
    process(dispatcher)


def main(inc, dispatcher):
    """
    程序循环入口函数
    :param inc:  (int) 循环周期, 单位, 秒
    :param dispatcher:  (Dispatch Class) 矿卡调度类对象
    :return: None
    """
    scheduler.enter(0, 0, perform, (inc, dispatcher))
    scheduler.run()


if __name__ == "__main__":

    # 初始化日志
    set_log()
    # 获取日志器
    logger = get_logger("zxt.main")

    # 全局参数更新
    global_period_para_update()

    # 实例化设备对象
    dump = DumpInfo()
    excavator = ExcavatorInfo()
    truck = TruckInfo(dump, excavator)

    # 实例化程序调度器
    scheduler = sched.scheduler(time.time, time.sleep)

    # 实例化调度预测器
    pre_sch = PreSchedule(truck, excavator, dump)

    # 实例化矿卡调度器
    dispatcher = Dispatcher(truck, dump, excavator, pre_sch, False)

    logger.info(" ")
    logger.info("调度系统启动")

    main(30, dispatcher)
