package com.njcn.gather.detection.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.njcn.gather.detection.lock.DetectionLockManager;
import com.njcn.gather.detection.pojo.dto.DevXiNumData;
import com.njcn.gather.detection.pojo.enums.DetectionCodeEnum;
import com.njcn.gather.detection.pojo.enums.SourceOperateCodeEnum;
import com.njcn.gather.detection.pojo.enums.SourceResponseCodeEnum;
import com.njcn.gather.detection.pojo.param.PreDetectionParam;
import com.njcn.gather.detection.pojo.po.DevData;
import com.njcn.gather.detection.pojo.po.IcdCheckData;
import com.njcn.gather.detection.pojo.po.SourceCompareDev;
import com.njcn.gather.detection.pojo.vo.*;
import com.njcn.gather.detection.service.impl.DetectionServiceImpl;
import com.njcn.gather.detection.util.DetectionUtil;
import com.njcn.gather.detection.util.socket.*;
import com.njcn.gather.detection.util.socket.websocket.WebServiceManager;
import com.njcn.gather.device.pojo.enums.CommonEnum;
import com.njcn.gather.device.pojo.enums.PatternEnum;
import com.njcn.gather.device.pojo.po.PqDevSub;
import com.njcn.gather.device.pojo.vo.PreDetection;
import com.njcn.gather.device.service.IPqDevService;
import com.njcn.gather.device.service.IPqDevSubService;
import com.njcn.gather.plan.pojo.po.AdPlan;
import com.njcn.gather.plan.service.IAdPlanService;
import com.njcn.gather.report.pojo.enums.PowerIndexEnum;
import com.njcn.gather.result.service.IResultService;
import com.njcn.gather.script.pojo.param.PqScriptCheckDataParam;
import com.njcn.gather.script.pojo.param.PqScriptIssueParam;
import com.njcn.gather.script.pojo.po.SourceIssue;
import com.njcn.gather.script.service.IPqScriptCheckDataService;
import com.njcn.gather.script.service.IPqScriptDtlsService;
import com.njcn.gather.source.pojo.po.PqSource;
import com.njcn.gather.source.service.IPqSourceService;
import com.njcn.gather.storage.pojo.param.StorageParam;
import com.njcn.gather.storage.pojo.po.SimAndDigHarmonicResult;
import com.njcn.gather.storage.pojo.po.SimAndDigNonHarmonicResult;
import com.njcn.gather.storage.service.DetectionDataDealService;
import com.njcn.gather.storage.service.SimAndDigHarmonicService;
import com.njcn.gather.storage.service.TableGenService;
import com.njcn.gather.system.dictionary.pojo.enums.DictDataEnum;
import com.njcn.gather.system.dictionary.pojo.po.DictData;
import com.njcn.gather.system.dictionary.service.IDictDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Service
@RequiredArgsConstructor
public class SocketDevResponseService {

    private Set<String> dataTypeList;

    private List<String> icdTypeList;

    private final List<String> nonHarmonicList = Stream.of(PowerIndexEnum.FREQ.getKey(), PowerIndexEnum.V.getKey(), PowerIndexEnum.I.getKey(), PowerIndexEnum.IMBV.getKey(), PowerIndexEnum.IMBA.getKey(), PowerIndexEnum.VOLTAGE.getKey(), PowerIndexEnum.F.getKey(), PowerIndexEnum.LF.getKey()).collect(Collectors.toList());

    private final IPqDevService iPqDevService;
    private final IPqDevSubService iPqDevSubService;
    private final IPqScriptDtlsService scriptDtlsService;
    private final IPqScriptDtlsService pqScriptDtlsService;
    private final DetectionServiceImpl detectionServiceImpl;
    private final DetectionDataDealService detectionDataDealService;
    private final IPqScriptCheckDataService iPqScriptCheckDataService;
    private final SimAndDigHarmonicService adHarmonicService;
    private final IAdPlanService adPlanService;
    private final IDictDataService dictDataService;
    private final IPqSourceService pqSourceService;
    private final IResultService resultService;
    private final TableGenService tableGenService;

    @Value("${dataCheck.enable}")
    private Boolean dataCheck;

    /**
     * 存储的装置相序数据
     */
    List<DevData> devInfo = new ArrayList<>();

    /**
     * 成功结束的测点
     */
    Set<String> successComm = new HashSet<>();

    /**
     * 失败的测点
     */
    Set<String> failComm = new HashSet<>();

    /**
     * 存放从装置收到的icd校验数据。key为icdType，value为IcdCheckData
     */
    Map<String, IcdCheckData> icdCheckDataMap = new HashMap<>();

    /**
     * 保存成功的协议
     */
    DictDataEnum dataRule;


    //标识当前检测小项是否结束
    public void deal(PreDetectionParam param, String msg) throws Exception {
        SocketDataMsg socketDataMsg = MsgUtil.socketDataMsg(msg);
        String[] tem = socketDataMsg.getRequestId().split(CnSocketUtil.STEP_TAG);
        SourceOperateCodeEnum sourceOperateCodeEnum = SourceOperateCodeEnum.getDictDataEnumByCode(tem[0]);

        switch (Objects.requireNonNull(sourceOperateCodeEnum)) {
            //设备通讯校验
            case YJC_SBTXJY:
                devComm(socketDataMsg, param);
                break;
            //协议校验
            case YJC_XYJY:
                protocolDeal(socketDataMsg, param, msg);
                break;
            //相序校验
            case YJC_XUJY:
                devXu(param, socketDataMsg);
                break;
            //正式检测
            case FORMAL_REAL:
                formalDeal(param, socketDataMsg);
                break;
            //系数校验
            case Coefficient_Check:
                coefficient(param, socketDataMsg);
                break;
            //报告处理
            case REPORT_CAT:
                SourceOperateCodeEnum temOp = SourceOperateCodeEnum.getDictDataEnumByCode(socketDataMsg.getOperateCode());
                SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
                switch (Objects.requireNonNull(dictDataEnumByCode)) {
                    case SUCCESS:
                        SocketManager.removeUser(param.getUserPageId() + CnSocketUtil.DEV_TAG);
                        break;
                    case UNPROCESSED_BUSINESS:
                        break;
                    default:
                        SocketManager.removeUser(param.getUserPageId() + CnSocketUtil.DEV_TAG);
                        System.out.println(socketDataMsg);
                }
                break;
            //退出关闭
            case QUITE:
                quitDeal(socketDataMsg, param, msg);
                break;
            case YXT:
                break;
            default:
                // todo... 要日志记录或者websocket送到前端友好提示用户
                break;
        }
    }

    /**
     * 系数校验
     */
    private void coefficient(PreDetectionParam param, SocketDataMsg socketDataMsg) {
        SourceOperateCodeEnum sourceOperateCodeEnum = SourceOperateCodeEnum.getDictDataEnumByCode(socketDataMsg.getOperateCode());
        SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
        SocketMsg<String> xiSocket = new SocketMsg<>();
        xiSocket.setRequestId(SourceOperateCodeEnum.Coefficient_Check.getValue());

        switch (Objects.requireNonNull(sourceOperateCodeEnum)) {
            case DATA_CHNFACTOR$01:
                //获取系数
                switch (Objects.requireNonNull(dictDataEnumByCode)) {
                    case SUCCESS:
                        if (CollUtil.isNotEmpty(XiNumberManager.xiDevList)) {
                            List<DevXiNumData.GF> gfList = JSON.parseArray(socketDataMsg.getData(), DevXiNumData.GF.class);
                            DevXiNumData devXiNumData = new DevXiNumData();
                            devXiNumData.setDevIP(XiNumberManager.xiDevList.get(0).getDevIP());
                            devXiNumData.setGf(gfList);
                            XiNumberManager.devXiNumDataMap.put(XiNumberManager.xiDevList.get(0).getDevIP(), devXiNumData);
                            XiNumberManager.xiDevList.remove(0);
                            if (CollUtil.isEmpty(XiNumberManager.xiDevList)) {
                                xiSocket.setRequestId(SourceOperateCodeEnum.Coefficient_Check.getValue());
                                xiSocket.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
                                xiSocket.setData(JSON.toJSONString(XiNumberManager.xiSourceIssueList.get(0)));
                                SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xiSocket));
                            }
                        }
                        break;
                    case UNPROCESSED_BUSINESS:
                        break;
                    case NORMAL_RESPONSE:
                        break;
                    case DATA_RESOLVE:
                        break;
                    case COMMUNICATION_ERR:
                        break;
                    default:
                        break;
                }

                break;
            case DATA_CHNFACTOR$02:
                //系数下发后的响应
                switch (Objects.requireNonNull(dictDataEnumByCode)) {
                    case SUCCESS:
                        if (CollUtil.isNotEmpty(XiNumberManager.devXiList)) {
                            //单台装置系数下发后，需要删除集合中存在的当前装置
                            String devIp = XiNumberManager.devXiList.get(0);
                            XiNumberManager.devXiList.removeIf(it -> it.equals(devIp));

                            //继续下发每台装置系数，只到集合为空
                            if (CollUtil.isNotEmpty(XiNumberManager.devXiList)) {
                                xiSocket.setOperateCode(SourceOperateCodeEnum.DATA_CHNFACTOR$02.getValue());
                                xiSocket.setData(JSON.toJSONString(XiNumberManager.devXiNumDataMap.get(XiNumberManager.devXiList.get(0))));
                                SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.DEV_TAG, JSON.toJSONString(xiSocket));
                            } else {
                                if (XiNumberManager.stepNumber == 0) {
                                    //为空则认为所有装置都已经下发,开始进行小电压的申请,步骤进行+1
                                    XiNumberManager.stepNumber = 1;
                                    sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.big_end.getValue(), XiNumberManager.devParameterList.get(0));
                                    sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.small_start.getValue(), XiNumberManager.devParameterList.get(1));

                                    System.out.println("第一步结束开始配置小电压电流参数下发给源----------------------");
                                    xiSocket.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
                                    xiSocket.setData(JSON.toJSONString(XiNumberManager.xiSourceIssueList.get(1)));
                                    SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xiSocket));
                                } else if (XiNumberManager.stepNumber == 1) {
                                    //小电流系数下发完毕;开始重新测试一次大电压
                                    sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.small_end.getValue(), XiNumberManager.devParameterList.get(0));
                                    sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.big_comp_start.getValue(), XiNumberManager.devParameterList.get(0));

                                    xiSocket.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
                                    xiSocket.setData(JSON.toJSONString(XiNumberManager.xiSourceIssueList.get(0)));
                                    SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xiSocket));
                                    XiNumberManager.stepNumber = 2;
                                }
                                FormalTestManager.realDataXiList.clear();
                                successComm.clear();
                                XiNumberManager.devXiList.clear();
                            }
                        } else {
                            System.out.println("应该不会出现的--------------------------------");
                        }

                        break;
                    case UNPROCESSED_BUSINESS:
                        break;
                    case NORMAL_RESPONSE:
                        break;
                    case DATA_RESOLVE:
                        //quitSend(param);
                        break;
                    case COMMUNICATION_ERR:
                        break;
                    default:
                        break;
                }
                break;
            case DEV_DATA_REQUEST_02:
                //实时采集申请
                String data = socketDataMsg.getData();
                DevData devData = JSON.parseObject(data, DevData.class);
                if (ObjectUtil.isNotNull(dictDataEnumByCode)) {
                    switch (dictDataEnumByCode) {
                        case SUCCESS:
                            if (devData.getResult()) {
                                FormalTestManager.realDataXiList.add(devData);
                                successComm.add(devData.getId());
                                System.out.println(successComm.size() + " ==" + FormalTestManager.monitorIdListComm.size() + "FormalTestManager.realDataXiList:" + FormalTestManager.realDataXiList.size() + "当前步骤" + XiNumberManager.stepNumber);
                                if (successComm.size() == FormalTestManager.monitorIdListComm.size()) {
                                    processData(param, xiSocket);
                                }
                            } else {
                                System.out.println("系数校准抛除数据" + devData);
                            }
                            break;
                        case UNPROCESSED_BUSINESS:
                            WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
                            break;
                        case NORMAL_RESPONSE:
                            if (devData.getResult()) {
                                FormalTestManager.realDataXiList.add(devData);
                            } else {
                                System.out.println("系数校准抛除数据" + devData);
                            }
                            break;
                        default:
                            xiSocket.setRequestId(socketDataMsg.getRequestId());
                            xiSocket.setOperateCode(socketDataMsg.getOperateCode());
                            xiSocket.setData(dictDataEnumByCode.getMessage());
                            WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(xiSocket));
                            break;
                    }
                }
                break;
            default:
                WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
                break;
        }


    }


    private void processData(PreDetectionParam param, SocketMsg<String> xiSocket) {
        System.out.println(XiNumberManager.stepNumber + "从装置中已经完成获取测试数据，准备开始计算----------------------");
        Map<String, List<DevData>> realDataXiMap = FormalTestManager.realDataXiList.stream().collect(Collectors.groupingBy(it -> it.getId().split(CnSocketUtil.SPLIT_TAG)[0]));
        realDataXiMap.forEach((devIp, dataList) -> processDeviceData(devIp, dataList, param));

        handleStep(XiNumberManager.stepNumber, param, xiSocket);
    }


    private void handleStep(int stepNumber, PreDetectionParam param, SocketMsg<String> xiSocket) {
        switch (stepNumber) {
            case 0:
                sendModifyCoefficientCommand(param, xiSocket);
                break;
            case 1:
                handleSmallVoltageStep(param, xiSocket);
                break;
            case 2:
                handleBigVoltageStep(param, xiSocket);
                break;
            case 3:
                handleFinalStep(param);
                break;
        }
    }

    /**
     * 修改系数命令下发
     */
    private void sendModifyCoefficientCommand(PreDetectionParam param, SocketMsg<String> xiSocket) {
        xiSocket.setRequestId(SourceOperateCodeEnum.Coefficient_Check.getValue());
        xiSocket.setOperateCode(SourceOperateCodeEnum.DATA_CHNFACTOR$02.getValue());
        xiSocket.setData(JSON.toJSONString(XiNumberManager.devXiNumDataMap.get(XiNumberManager.devXiList.get(0))));
        SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.DEV_TAG, JSON.toJSONString(xiSocket));
    }

    private void handleSmallVoltageStep(PreDetectionParam param, SocketMsg<String> xiSocket) {
        System.out.println("进入小电压步骤》》》》》》》》》》》》》》》》》》》》》》》》");
        double limit = 0.1;
        XiNumberManager.smallDevXiNumDataMap.forEach((devIp, devXiNumDataSmall) -> {
            boolean flag = checkCoefficientDifference(devIp, devXiNumDataSmall, limit);
            if (flag) {
                XiNumberManager.devXiList.removeIf(it -> it.equals(devIp));
            }
        });

        //如果差距超过10%则再次下发系数
        if (CollUtil.isNotEmpty(XiNumberManager.devXiList)) {
            xiSocket.setOperateCode(SourceOperateCodeEnum.DATA_CHNFACTOR$02.getValue());
            xiSocket.setData(JSON.toJSONString(XiNumberManager.devXiNumDataMap.get(XiNumberManager.devXiList.get(0))));
            SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.DEV_TAG, JSON.toJSONString(xiSocket));
        } else {
            //存在小电压系数在误差范围内情况,直接结束。
            sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.small_end.getValue(), XiNumberManager.devParameterList.get(1));
            sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.big_comp_start.getValue(), XiNumberManager.devParameterList.get(0));
            //小电流系数下发完毕;开始重新测试一次大电压
            xiSocket.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
            xiSocket.setData(JSON.toJSONString(XiNumberManager.xiSourceIssueList.get(0)));
            SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xiSocket));
            XiNumberManager.stepNumber = 2;
            FormalTestManager.realDataXiList.clear();
            successComm.clear();
        }
    }


    private void handleBigVoltageStep(PreDetectionParam param, SocketMsg<String> xiSocket) {
        //大电压处理
        sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.big_comp_end.getValue(), XiNumberManager.devParameterList.get(0));
        sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.small_comp_start.getValue(), XiNumberManager.devParameterList.get(1));

        xiSocket.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
        xiSocket.setData(JSON.toJSONString(XiNumberManager.xiSourceIssueList.get(1)));
        SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xiSocket));
        XiNumberManager.stepNumber = 3;
        FormalTestManager.realDataXiList.clear();
        successComm.clear();
    }

    private void handleFinalStep(PreDetectionParam param) {
        FormalTestManager.realDataXiList.clear();
        successComm.clear();
        XiNumberManager.devXiList.clear();
        sendWebSocket(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.small_comp_end.getValue(), XiNumberManager.devParameterList.get(1));
        System.out.println("-------------------------已经全部结束----------------------");

        if (param.isFormalTestSelected()) {
            startFormalScripts(param, null, param.isResumeFormal());
        } else {
            //后续什么都不做
            CnSocketUtil.quitSend(param);
            //修改设备表Factor_Check_Result字段
            XiNumberManager.devXiNumDataMap.forEach((key, val) -> {
                DevXiNumData small = XiNumberManager.smallDevXiNumDataMap.get(key);
                LambdaUpdateWrapper<PqDevSub> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(PqDevSub::getDevId, FormalTestManager.devIdMapComm.get(key));
                if (val.getResultFlag() == 0 || small.getResultFlag() == 0) {
                    updateWrapper.set(PqDevSub::getFactorCheckResult, 0);
                } else {
                    updateWrapper.set(PqDevSub::getFactorCheckResult, 1);
                }
                iPqDevSubService.update(updateWrapper);
                updateWrapper.clear();
            });
        }
    }


    private boolean checkCoefficientDifference(String devIp, DevXiNumData devXiNumDataSmall, double limit) {
        boolean flag = true;
        DevXiNumData devXiNumDataBig = XiNumberManager.devXiNumDataMap.get(devIp);
        Map<Integer, DevXiNumData.GF> gfMapSmall = devXiNumDataSmall.getGf().stream().collect(Collectors.toMap(DevXiNumData.GF::getUMonitorPoint, Function.identity()));

        for (DevXiNumData.GF bigGf : devXiNumDataBig.getGf()) {
            DevXiNumData.F smallF = gfMapSmall.get(bigGf.getUMonitorPoint()).getF();
            DevXiNumData.F bigF = bigGf.getF();

            boolean ia = isWithinTenPercent(smallF.getIa_gain(), bigF.getIa_gain(), limit);
            boolean ib = isWithinTenPercent(smallF.getIb_gain(), bigF.getIb_gain(), limit);
            boolean ic = isWithinTenPercent(smallF.getIc_gain(), bigF.getIc_gain(), limit);
            boolean va = isWithinTenPercent(smallF.getUa_gain(), bigF.getUa_gain(), limit);
            boolean vb = isWithinTenPercent(smallF.getUb_gain(), bigF.getUb_gain(), limit);
            boolean vc = isWithinTenPercent(smallF.getUc_gain(), bigF.getUc_gain(), limit);
            if (!(ia && ib && ic && va && vb && vc)) {
                flag = false;
                adjustCoefficients(smallF, bigF);
            }
        }
        return flag;
    }

    /**
     * 当小电压系数和大电压系数的差距超过 10% 时，对大电压系数进行调整，调整的方式是取小电压系数和大电压系数的平均值。
     */
    private void adjustCoefficients(DevXiNumData.F smallF, DevXiNumData.F bigF) {
        if (!isWithinTenPercent(smallF.getIa_gain(), bigF.getIa_gain(), 0.1)) {
            bigF.setIa_gain((smallF.getIa_gain() + bigF.getIa_gain()) / 2);
        }
        if (!isWithinTenPercent(smallF.getIb_gain(), bigF.getIb_gain(), 0.1)) {
            bigF.setIb_gain((smallF.getIb_gain() + bigF.getIb_gain()) / 2);
        }
        if (!isWithinTenPercent(smallF.getIc_gain(), bigF.getIc_gain(), 0.1)) {
            bigF.setIc_gain((smallF.getIc_gain() + bigF.getIc_gain()) / 2);
        }
        if (!isWithinTenPercent(smallF.getUa_gain(), bigF.getUa_gain(), 0.1)) {
            bigF.setUa_gain((smallF.getUa_gain() + bigF.getUa_gain()) / 2);
        }
        if (!isWithinTenPercent(smallF.getUb_gain(), bigF.getUb_gain(), 0.1)) {
            bigF.setUb_gain((smallF.getUb_gain() + bigF.getUb_gain()) / 2);
        }
        if (!isWithinTenPercent(smallF.getUc_gain(), bigF.getUc_gain(), 0.1)) {
            bigF.setUc_gain((smallF.getUc_gain() + bigF.getUc_gain()) / 2);
        }
    }


    private void processDeviceData(String devIp, List<DevData> dataList, PreDetectionParam param) {
        AtomicBoolean xiFlag = new AtomicBoolean(true);
        XiNumberManager.devXiList.add(devIp);

        DevXiNumData startXiData = XiNumberManager.devXiNumDataMap.get(devIp);
        Map<Integer, DevXiNumData.GF> gfMap = startXiData.getGf().stream().collect(Collectors.toMap(DevXiNumData.GF::getUMonitorPoint, Function.identity()));
        Map<String, List<DevData>> monitorMap = dataList.stream().collect(Collectors.groupingBy(DevData::getId));

        List<DevXiNumData.GF> gf = new ArrayList<>();
        monitorMap.forEach((monitorId, list) -> {
            CoefficientVO coefficientVO = createCoefficientVO(monitorId);
            DevXiNumData.F F = new DevXiNumData.F();
            CoefficientVO.DevParameter devParameter = getDevParameter();

            assemblyEntity(list, F, gfMap.get(Integer.parseInt(monitorId.split(CnSocketUtil.SPLIT_TAG)[1]) - 1), coefficientVO, devParameter);
            if (Objects.nonNull(coefficientVO.getResultFlag()) && coefficientVO.getResultFlag() == 0) {
                xiFlag.set(false);
            }

            DevXiNumData.GF gfItem = createGFItem(monitorId, F);
            gf.add(gfItem);
            //表格数据
            WebServiceManager.sendDetectionMessage(param.getUserPageId(), SourceOperateCodeEnum.Coefficient_Check.getValue(), SourceOperateCodeEnum.DATA_CHNFACTOR$02.getValue(), coefficientVO, null);
        });
        DevXiNumData devXiNumData = createDevXiNumData(devIp, gf, xiFlag.get());
        saveDevXiNumData(devIp, devXiNumData);
    }

    private CoefficientVO createCoefficientVO(String monitorId) {
        CoefficientVO coefficientVO = new CoefficientVO();
        String[] splitStr = monitorId.split(CnSocketUtil.SPLIT_TAG);
        if (XiNumberManager.stepNumber == 0 || XiNumberManager.stepNumber == 2) {
            coefficientVO.setType("big");
        } else {
            coefficientVO.setType("small");
        }
        coefficientVO.setMonitorNum(splitStr[1]);
        coefficientVO.setDevName(FormalTestManager.devNameMapComm.get(splitStr[0]));
        coefficientVO.setDesc((XiNumberManager.stepNumber == 0 || XiNumberManager.stepNumber == 1) ? "系数下装" : "系数校准");
        return coefficientVO;
    }

    private CoefficientVO.DevParameter getDevParameter() {
        return (XiNumberManager.stepNumber == 0 || XiNumberManager.stepNumber == 2) ? XiNumberManager.devParameterList.get(0) : XiNumberManager.devParameterList.get(1);
    }

    private DevXiNumData.GF createGFItem(String monitorId, DevXiNumData.F F) {
        DevXiNumData.GF gfItem = new DevXiNumData.GF();
        gfItem.setUMonitorPoint(Integer.parseInt(monitorId.split(CnSocketUtil.SPLIT_TAG)[1]) - 1);
        gfItem.setF(F);
        return gfItem;
    }

    private DevXiNumData createDevXiNumData(String devIp, List<DevXiNumData.GF> gf, boolean xiFlag) {
        DevXiNumData devXiNumData = new DevXiNumData();
        devXiNumData.setChnNum(0);
        devXiNumData.setDevIP(devIp);
        devXiNumData.setGf(gf);
        devXiNumData.setResultFlag(xiFlag ? 1 : 0);
        return devXiNumData;
    }

    private void saveDevXiNumData(String devIp, DevXiNumData devXiNumData) {
        if (XiNumberManager.stepNumber == 0 || XiNumberManager.stepNumber == 2) {
            XiNumberManager.devXiNumDataMap.put(devIp, devXiNumData);
        } else if (XiNumberManager.stepNumber == 1 || XiNumberManager.stepNumber == 3) {
            XiNumberManager.smallDevXiNumDataMap.put(devIp, devXiNumData);
        }
    }

    /**
     * 比较两个数的差值,是否再limit范围内
     */
    private boolean isWithinTenPercent(double num1, double num2, double limit) {
        double diff = Math.abs(num1 - num2);
        double larger = Math.max(num1, num2);
        double percentage = diff / larger;
        return percentage <= limit;
    }

    private BigDecimal rangeNum(double num1, double num2, String type) {
        double diff = Math.abs(num1 - num2);
        double larger = Math.max(num1, num2);
        if (PowerIndexEnum.V.getKey().equals(type)) {
            return BigDecimal.valueOf(num1 - num2).setScale(4, RoundingMode.HALF_UP);
        } else {
            return BigDecimal.valueOf(diff / larger).multiply(BigDecimal.valueOf(100)).setScale(4, RoundingMode.HALF_UP);
        }
    }

    private void assemblyEntity(List<DevData> deList, DevXiNumData.F F, DevXiNumData.GF startF, CoefficientVO coefficientVO, CoefficientVO.DevParameter devParameter) {
        //表示接收完成,必须保证3个数
        if (deList.size() >= 7) {
            List<Double> aList = deList.stream().map(it -> it.getSqlData().get(0).getList().getA()).collect(Collectors.toList());
            List<Double> bList = deList.stream().map(it -> it.getSqlData().get(0).getList().getB()).collect(Collectors.toList());
            List<Double> cList = deList.stream().map(it -> it.getSqlData().get(0).getList().getC()).collect(Collectors.toList());

            Double optionalA = reduceList(aList);
            Double optionalB = reduceList(bList);
            Double optionalC = reduceList(cList);

            List<Double> aIList = deList.stream().map(it -> it.getSqlData().get(1).getList().getA()).collect(Collectors.toList());
            List<Double> bIList = deList.stream().map(it -> it.getSqlData().get(1).getList().getB()).collect(Collectors.toList());
            List<Double> cIList = deList.stream().map(it -> it.getSqlData().get(1).getList().getC()).collect(Collectors.toList());

            Double optionalIA = reduceList(aIList);
            Double optionalIB = reduceList(bIList);
            Double optionalIC = reduceList(cIList);

            coefficientVO.setAVuData(String.valueOf(optionalA));
            coefficientVO.setBVuData(String.valueOf(optionalB));
            coefficientVO.setCVuData(String.valueOf(optionalC));
            coefficientVO.setAIeData(String.valueOf(optionalIA));
            coefficientVO.setBIeData(String.valueOf(optionalIB));
            coefficientVO.setCIeData(String.valueOf(optionalIC));
            if (XiNumberManager.stepNumber == 0 || XiNumberManager.stepNumber == 1) {
                Integer aXi = BigDecimal.valueOf(devParameter.getDevVolt() * startF.getF().getUa_gain() / optionalA).setScale(0, RoundingMode.HALF_UP).intValue();
                Integer bXi = BigDecimal.valueOf(devParameter.getDevVolt() * startF.getF().getUb_gain() / optionalB).setScale(0, RoundingMode.HALF_UP).intValue();
                Integer cXi = BigDecimal.valueOf(devParameter.getDevVolt() * startF.getF().getUc_gain() / optionalC).setScale(0, RoundingMode.HALF_UP).intValue();
                Integer aIXi = BigDecimal.valueOf(devParameter.getDevCurr() * startF.getF().getIa_gain() / optionalIA).setScale(0, RoundingMode.HALF_UP).intValue();
                Integer bIXi = BigDecimal.valueOf(devParameter.getDevCurr() * startF.getF().getIb_gain() / optionalIB).setScale(0, RoundingMode.HALF_UP).intValue();
                Integer cIXi = BigDecimal.valueOf(devParameter.getDevCurr() * startF.getF().getIc_gain() / optionalIC).setScale(0, RoundingMode.HALF_UP).intValue();

                coefficientVO.setAVuXi(aXi.toString());
                coefficientVO.setBVuXi(bXi.toString());
                coefficientVO.setCVuXi(cXi.toString());
                coefficientVO.setAIeXi(aIXi.toString());
                coefficientVO.setBIeXi(bIXi.toString());
                coefficientVO.setCIeXi(cIXi.toString());

                F.setUa_gain(aXi);
                F.setUb_gain(bXi);
                F.setUc_gain(cXi);
                F.setIa_gain(aIXi);
                F.setIb_gain(bIXi);
                F.setIc_gain(cIXi);
            } else {
                double vLimit = 0.1 / 100 * devParameter.getDevVolt();
                double iLimit = 0.005;
                coefficientVO.setAVuXi(isWithinTenPercent(optionalA, devParameter.getDevVolt(), vLimit) ? "合格" : "不合格");
                coefficientVO.setBVuXi(isWithinTenPercent(optionalB, devParameter.getDevVolt(), vLimit) ? "合格" : "不合格");
                coefficientVO.setCVuXi(isWithinTenPercent(optionalC, devParameter.getDevVolt(), vLimit) ? "合格" : "不合格");
                coefficientVO.setAIeXi(isWithinTenPercent(optionalIA, devParameter.getDevCurr(), iLimit) ? "合格" : "不合格");
                coefficientVO.setBIeXi(isWithinTenPercent(optionalIB, devParameter.getDevCurr(), iLimit) ? "合格" : "不合格");
                coefficientVO.setCIeXi(isWithinTenPercent(optionalIC, devParameter.getDevCurr(), iLimit) ? "合格" : "不合格");

                coefficientVO.setAV(rangeNum(optionalA, devParameter.getDevVolt(), PowerIndexEnum.V.getKey()).toString());
                coefficientVO.setBV(rangeNum(optionalB, devParameter.getDevVolt(), PowerIndexEnum.V.getKey()).toString());
                coefficientVO.setCV(rangeNum(optionalC, devParameter.getDevVolt(), PowerIndexEnum.V.getKey()).toString());
                coefficientVO.setAI(rangeNum(optionalIA, devParameter.getDevCurr(), PowerIndexEnum.I.getKey()).toString());
                coefficientVO.setBI(rangeNum(optionalIB, devParameter.getDevCurr(), PowerIndexEnum.I.getKey()).toString());
                coefficientVO.setCI(rangeNum(optionalIC, devParameter.getDevCurr(), PowerIndexEnum.I.getKey()).toString());

                if ("不合格".equals(coefficientVO.getAVuXi()) || "不合格".equals(coefficientVO.getBVuXi()) || "不合格".equals(coefficientVO.getCVuXi()) || "不合格".equals(coefficientVO.getAIeXi()) || "不合格".equals(coefficientVO.getBIeXi()) || "不合格".equals(coefficientVO.getCIeXi())) {
                    coefficientVO.setResultFlag(0);
                } else {
                    coefficientVO.setResultFlag(1);
                }
            }
        }
    }

    /**
     * 删除集合中前五个数以及最后两个数
     */
    private Double reduceList(List<Double> valList) {
        // valList.subList(0, 5).clear();
        valList.subList(valList.size() - 2, valList.size()).clear();
        return valList.stream().mapToDouble(Double::doubleValue).average().getAsDouble();
    }


    /**
     * 装置通讯检测
     */
    private void devComm(SocketDataMsg socketDataMsg, PreDetectionParam param) {
        SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
        String s = param.getUserPageId() + CnSocketUtil.DEV_TAG;
        SocketMsg<String> socketMsg = new SocketMsg<>();
        switch (Objects.requireNonNull(dictDataEnumByCode)) {
            case SUCCESS:
                String result = socketDataMsg.getData();
                successComm.add(result);
                //单个测点通讯成功
                WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 1));
                System.out.println("设备通讯校验！" + successComm.size() + "=====" + FormalTestManager.monitorIdListComm.size());
                if (successComm.size() == FormalTestManager.monitorIdListComm.size()) {
                    // 通知前端整个装置通讯检测过程成功
                    SocketDataMsg temMsg = new SocketDataMsg();
                    temMsg.setCode(SourceResponseCodeEnum.ALL_SUCCESS.getCode());
                    temMsg.setOperateCode(SourceOperateCodeEnum.DEV_INIT_GATHER_01.getValue());
                    temMsg.setRequestId(SourceOperateCodeEnum.YJC_SBTXJY.getValue());
                    WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(temMsg));

                    //开始进行协议校验
                    successComm.clear();
                    failComm.clear();
                    Map<String, List<PreDetection>> map = new HashMap<>(1);
                    map.put("deviceList", FormalTestManager.devList);
                    String jsonString = JSON.toJSONString(map);
                    socketMsg.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                    socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_INIT_GATHER_02.getValue());
                    socketMsg.setData(jsonString);
                    String json = JSON.toJSONString(socketMsg);

                    System.out.println("开始协议校验》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");
                    SocketManager.sendMsg(s, json);
                }
                completeJudgment(param);
                break;
            case UNPROCESSED_BUSINESS:
                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
                break;
            case DEV_ERROR:
                failComm.addAll(FormalTestManager.devMapMonitorNum.get(socketDataMsg.getData()));
                WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 0));
                completeJudgment(param);
                break;
            case DEV_TARGET:
                failComm.add(socketDataMsg.getData());
                WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 1));
                completeJudgment(param);
                break;
            case RE_OPERATE:
                //出现已经初始化情况，发送用户用户确认是否继续检测
                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
                break;
            case NO_INIT_DEV:
                //发起关闭操作
                break;
            default:
                WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
                break;
        }
    }


    //检测结束判断
    private void completeJudgment(PreDetectionParam param) {
        System.out.println("成功失败测点数量" + successComm.size() + ":" + failComm.size() + "监测点总数" + FormalTestManager.monitorIdListComm.size());

        if (successComm.size() + failComm.size() == FormalTestManager.monitorIdListComm.size()) {
            //全部装置返回
            if (!failComm.isEmpty()) {
                CnSocketUtil.quitSend(param);
                WebSocketVO<String> webSocketVO = new WebSocketVO<>();
                webSocketVO.setRequestId(SourceOperateCodeEnum.ERROR_FLOW_END.getValue());
                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
            }
            successComm.clear();
            failComm.clear();
        }
    }

    /**
     * 装置协议检测
     */
    private void protocolDeal(SocketDataMsg socketDataMsg, PreDetectionParam param, String msg) {
        SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
        SocketMsg<String> socketMsg = new SocketMsg<>();
        String s = param.getUserPageId() + CnSocketUtil.DEV_TAG;
        switch (Objects.requireNonNull(dictDataEnumByCode)) {
            case SUCCESS:
                if (socketDataMsg.getOperateCode().equals(SourceOperateCodeEnum.DEV_INIT_GATHER_02.getValue())) {
                    successComm.add(socketDataMsg.getData());
                    WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 1));
                    if (successComm.size() == FormalTestManager.monitorIdListComm.size()) {
                        for (String string : successComm) {
                            //模拟统计协议校验，通讯校验已经校验过，模拟直接推送
                            SocketDataMsg webSend = new SocketDataMsg();
                            webSend.setOperateCode(SourceOperateCodeEnum.DEV_INIT_GATHER_01.getValue());
                            webSend.setCode(SourceResponseCodeEnum.SUCCESS.getCode());
                            webSend.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                            webSend.setData(string);
                            WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(webSend, FormalTestManager.devNameMapComm, 1));
                        }
                        successComm.clear();
                        failComm.clear();
                        Map<String, List<PreDetection>> map = new HashMap<>(1);
                        map.put("deviceList", FormalTestManager.devList);
                        String jsonString = JSON.toJSONString(map);
                        socketMsg.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                        socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_INIT_GATHER_03.getValue());
                        socketMsg.setData(jsonString);
                        System.out.println("开始暂态协议校验++++++++++");
                        SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                    }
                    completeJudgment(param);
                } else if (socketDataMsg.getOperateCode().equals(SourceOperateCodeEnum.DEV_INIT_GATHER_03.getValue())) {
                    successComm.add(socketDataMsg.getData());
                    WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 1));
                    System.out.println(successComm.size() + "=====" + FormalTestManager.monitorIdListComm.size());

                    if (successComm.size() == FormalTestManager.monitorIdListComm.size()) {
                        successComm.clear();
                        failComm.clear();
                        icdCheckDataMap.clear();

                        dataTypeList = pqScriptDtlsService.getScriptToIcdCheckInfo(param);
                        icdTypeList = FormalTestManager.devList.stream().map(PreDetection::getIcdType).collect(Collectors.toList());
                        PreDetection preDetection = FormalTestManager.devList.stream().filter(obj -> obj.getIcdType().equals(icdTypeList.get(0))).findFirst().orElse(null);
                        boolean angleCheck = false;
                        if (ObjectUtil.isNotNull(preDetection)) {
                            angleCheck = preDetection.getAngle() == 1 ? true : false;
                        }
                        if (angleCheck) {
                            dataTypeList.add(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.VA.getCode());
                            dataTypeList.add(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.IA.getCode());
                        } else {
                            dataTypeList.remove(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.VA.getCode());
                            dataTypeList.remove(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.IA.getCode());
                        }

                        socketMsg.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                        socketMsg.setOperateCode(SourceOperateCodeEnum.VERIFY_MAPPING$01.getValue());
                        Map<String, Object> map = new HashMap<>(2);
                        map.put("dataType", new ArrayList<>(dataTypeList));
                        map.put("icdType", icdTypeList.get(0));
                        socketMsg.setData(JSON.toJSONString(map));
                        System.out.println("开始脚本与icd校验:++++++++++");
                        SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                    }
                    completeJudgment(param);
                } else if (socketDataMsg.getOperateCode().equals(SourceOperateCodeEnum.VERIFY_MAPPING$01.getValue())) {
                    String data = socketDataMsg.getData();
                    IcdCheckData icdCheckData = JSON.parseObject(data, IcdCheckData.class);
                    boolean isContinue = true;
                    List<String> descList = icdCheckData.getResultData().stream().map(
                            obj -> {
                                if (DetectionCodeEnum.MAG.getCode().equals(obj.getDesc()) || DetectionCodeEnum.DUR.getCode().equals(obj.getDesc()) || DetectionCodeEnum.PST.getCode().equals(obj.getDesc()) || DetectionCodeEnum.PLT.getCode().equals(obj.getDesc())) {
                                    return DetectionCodeEnum.AVG_PREFIX.getCode() + obj.getDesc();
                                } else {
                                    return DetectionCodeEnum.REAL_PREFIX.getCode() + obj.getDesc();
                                }
                            }
                    ).collect(Collectors.toList());
                    if (descList.containsAll(dataTypeList)) {
                        for (int i = 0; i < icdCheckData.getResultData().size(); i++) {
                            IcdCheckData.ResultData item = icdCheckData.getResultData().get(i);
                            Integer errorType = getErrorType(item.getDesc(), item.getPhaseResult());
                            // 校验脚本与icd校验失败
                            if (errorType.equals(0)) {
                                isContinue = false;
                                Map<String, Object> map = new HashMap<>(2);
                                map.put("icdType", icdCheckData.getIcdType());
                                DetectionCodeEnum anEnum = DetectionCodeEnum.getDetectionCodeByCode(item.getDesc());
                                map.put("dataType", anEnum.getMessage());
                                WebSocketVO<String> webSocketVO = new WebSocketVO<>();
                                webSocketVO.setData(JSON.toJSONString(map));
                                webSocketVO.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                                webSocketVO.setOperateCode(SourceOperateCodeEnum.VERIFY_MAPPING$01.getValue());
                                webSocketVO.setCode(SourceResponseCodeEnum.FAIL.getCode());
                                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
                            } else {
                                icdCheckDataMap.put(icdCheckData.getIcdType(), icdCheckData);
                            }
                        }
                    } else {
                        isContinue = false;
                    }

                    if (isContinue) {
                        //System.out.println("icdCheckDataMap.size()="+icdCheckDataMap.size()+",icdTypeList.size()="+icdTypeList.size());
                        if (icdCheckDataMap.size() == icdTypeList.size()) {
                            SocketDataMsg temMsg = new SocketDataMsg();
                            temMsg.setCode(SourceResponseCodeEnum.ALL_SUCCESS.getCode());
                            temMsg.setOperateCode(SourceOperateCodeEnum.VERIFY_MAPPING$01.getValue());
                            temMsg.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                            WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(temMsg));

                            //开始下源控制脚本
                            PqScriptIssueParam issueParam = new PqScriptIssueParam();
                            issueParam.setPlanId(param.getPlanId());
                            issueParam.setSourceId(param.getSourceName());
                            issueParam.setDevIds(param.getDevIds());
                            issueParam.setScriptId(param.getScriptId());

                            socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
                            List<SourceIssue> sourceIssues;
                            // 做预检测、后续做系数校准
//                            if (param.isPreTestSelected() || param.isCoefficientSelected() || param.isFormalTestSelected()) {
                            issueParam.setIsPhaseSequence(CommonEnum.PHASE_TEST.getValue());
                            sourceIssues = pqScriptDtlsService.listSourceIssue(issueParam);
                            socketMsg.setRequestId(SourceOperateCodeEnum.YJC_XUJY.getValue());
                            socketMsg.setData(JSON.toJSONString(sourceIssues.get(0)));
                            SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(socketMsg));
//                            }
//                            else if (param.isFormalTestSelected()) {
//                                // 后续做正式检测
//                                if (param.getReCheckType().equals(SourceOperateCodeEnum.RE_ERROR_TEST.getValue())) {
//                                    //不合格项复检
//                                    Set<Integer> indexes = new HashSet<>();
//                                    StorageParam storageParam = new StorageParam();
//                                    storageParam.setCode(param.getCode());
//                                    storageParam.setScriptId(param.getScriptId());
//                                    param.getDevIds().forEach(devId -> {
//                                        storageParam.setDevId(devId);
//                                        indexes.addAll(adHarmonicService.getIndex(storageParam));
//                                    });
//                                    issueParam.setIndexList(indexes.stream().collect(Collectors.toList()));
//                                    issueParam.setIsPhaseSequence(SourceOperateCodeEnum.RE_ERROR_TEST.getValue());
//                                } else {
//                                    issueParam.setIsPhaseSequence(CommonEnum.FORMAL_TEST.getValue());
//                                }
//                                //正式检测
//                                sourceIssues = pqScriptDtlsService.listSourceIssue(issueParam);
//                                sourceIssues = sourceIssues.stream().sorted(Comparator.comparing(SourceIssue::getIndex)).collect(Collectors.toList());
//                                // 使用 LinkedHashMap 保持分组顺序
//                                Map<String, List<SourceIssue>> groupedIssues = sourceIssues.stream()
//                                        .collect(Collectors.groupingBy(
//                                                SourceIssue::getType,
//                                                LinkedHashMap::new,
//                                                Collectors.toList()
//                                        ));
//
//                                // 将分组后的元素合并成一个新的集合，保持原有顺序
//                                sourceIssues = groupedIssues.values().stream()
//                                        .flatMap(List::stream)
//                                        .collect(Collectors.toList());
//                                // 存放所有检测小项
//                                SocketManager.addSourceList(sourceIssues);
//                                // 按照大项分组。key为大项code，value为小项个数
//                                Map<String, Long> sourceIssueMap = sourceIssues.stream().collect(Collectors.groupingBy(SourceIssue::getType, Collectors.counting()));
//                                SocketManager.initMap(sourceIssueMap);
//
//                                //告诉前端当前项开始了
//                                WebSocketVO<Object> webSocketVO = new WebSocketVO<>();
//                                String type = sourceIssues.get(0).getType();
//                                if (StrUtil.isNotBlank(sourceIssues.get(0).getOtherType())) {
//                                    sourceIssues.get(0).setType(PowerIndexEnum.V.getKey());
//                                    webSocketVO.setRequestId(sourceIssues.get(0).getOtherType() + CnSocketUtil.START_TAG);
//                                    type = sourceIssues.get(0).getOtherType();
//                                } else {
//                                    webSocketVO.setRequestId(sourceIssues.get(0).getType() + CnSocketUtil.START_TAG);
//                                }
//                                FormalTestManager.currentIssue = sourceIssues.get(0);
//                                socketMsg.setData(JSON.toJSONString(sourceIssues.get(0)));
//                                socketMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type);
//                                socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
//                                SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(socketMsg));
//
//                                webSocketVO.setDesc(null);
//                                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
//                            }
                        } else {
                            // 发送下一个脚本与icd校验
                            String icdType = icdTypeList.stream().filter(it -> !icdCheckDataMap.containsKey(it)).findFirst().orElse(null);
                            if (ObjectUtil.isNotNull(icdType)) {
                                PreDetection preDetection = FormalTestManager.devList.stream().filter(obj -> obj.getIcdType().equals(icdType)).findFirst().orElse(null);
                                boolean angleCheck = false;
                                if (ObjectUtil.isNotNull(preDetection)) {
                                    angleCheck = preDetection.getAngle() == 1 ? true : false;
                                }
                                if (angleCheck) {
                                    dataTypeList.add(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.VA.getCode());
                                    dataTypeList.add(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.IA.getCode());
                                } else {
                                    dataTypeList.remove(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.VA.getCode());
                                    dataTypeList.remove(DetectionCodeEnum.REAL_PREFIX.getCode() + DetectionCodeEnum.IA.getCode());
                                }

                                Map<String, Object> map = new HashMap<>(2);
                                map.put("dataType", new ArrayList<>(dataTypeList));
                                map.put("icdType", icdType);
                                socketMsg.setData(JSON.toJSONString(map));
                                socketMsg.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                                socketMsg.setOperateCode(SourceOperateCodeEnum.VERIFY_MAPPING$01.getValue());
                                System.out.println("开始脚本与icd校验:++++++++++");
                                SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                            }
                        }
                    } else {
                        WebSocketVO<String> webSocketVO = new WebSocketVO<>();
                        webSocketVO.setRequestId(SourceOperateCodeEnum.YJC_XYJY.getValue());
                        webSocketVO.setOperateCode(SourceOperateCodeEnum.VERIFY_MAPPING$01.getValue());
                        webSocketVO.setCode(SourceResponseCodeEnum.FAIL.getCode());

                        dataTypeList.removeAll(descList);
                        for (String dataType : dataTypeList) {
                            Map<String, Object> map = new HashMap<>(2);
                            map.put("icdType", icdCheckData.getIcdType());
                            DetectionCodeEnum anEnum = DetectionCodeEnum.getDetectionCodeByCode(dataType.replace(DetectionCodeEnum.REAL_PREFIX.getCode(), ""));
                            map.put("dataType", anEnum.getMessage());
                            webSocketVO.setData(JSON.toJSONString(map));
                            WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
                        }

                        CnSocketUtil.quitSend(param);
                    }
                }
                break;
            case UNPROCESSED_BUSINESS:
                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
                break;
            case DEV_ERROR:
                failComm.addAll(FormalTestManager.devMapMonitorNum.get(socketDataMsg.getData()));
                WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 0));
                completeJudgment(param);
                break;
            case DEV_TARGET:
                failComm.add(socketDataMsg.getData());
                WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 1));
                completeJudgment(param);
                break;
            case RE_OPERATE:
                //出现已经初始化情况，发送用户用户确认是否继续检测
                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
                CnSocketUtil.quitSend(param);
                break;
            case ICD_NOT_FOUND:
                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
                CnSocketUtil.quitSend(param);
                break;
            default:
                WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
                // todo... 这种情况是报文的状态码不一致，需要记录到日志表，以便问题追踪
                break;
        }
    }

    /**
     * 获取错误类型
     *
     * @param desc
     * @param list
     * @return
     */
    public static Integer getErrorType(String desc, DevData.SqlDataDTO.ListDTO list) {
        if (ObjectUtil.isNotNull(list)) {
            if (DetectionCodeEnum.MAG.getCode().equals(desc) || DetectionCodeEnum.DUR.getCode().equals(desc)) {
                if (ObjectUtil.isNull(list.getA()) && ObjectUtil.isNull(list.getB()) && ObjectUtil.isNull(list.getC()) && ObjectUtil.isNull(list.getT())) {
                    return 0;
                } else {
                    return 1;
                }
            } else if (DetectionCodeEnum.I_UNBAN.getCode().equals(desc) || DetectionCodeEnum.V_UNBAN.getCode().equals(desc)) {
                if (ObjectUtil.isNotNull(list.getA()) && list.getA().equals(0.0) && ObjectUtil.isNotNull(list.getB()) && list.getB().equals(1.0) && ObjectUtil.isNotNull(list.getC()) && list.getC().equals(1.0) || ObjectUtil.isNotNull(list.getT()) && list.getT().equals(1.0)) {
                    return 1;
                }
            } else {
                if (ObjectUtil.isNotNull(list.getA()) && list.getA().equals(1.0) && ObjectUtil.isNotNull(list.getB()) && list.getB().equals(1.0) && ObjectUtil.isNotNull(list.getC()) && list.getC().equals(1.0) || ObjectUtil.isNotNull(list.getT()) && list.getT().equals(1.0)) {
                    // 装置上送错误
                    return 1;
                }
            }
        }
        // icd文件与脚本不匹配
        return 0;
    }


    /**
     * 相序校验
     */
    public void devXu(PreDetectionParam param, SocketDataMsg socketDataMsg) {
        String data = socketDataMsg.getData();
        DevData devData = JSON.parseObject(data, DevData.class);
        SocketMsg<String> socketMsg = new SocketMsg<>();
        SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
        if (ObjectUtil.isNotNull(dictDataEnumByCode)) {
            switch (dictDataEnumByCode) {
                case SUCCESS:
                    if (devData.getResult()) {
                        devInfo.add(devData);
                        successComm.add(devData.getId());

                        if (successComm.size() == FormalTestManager.monitorIdListComm.size()) {
                            System.out.println("相序校验接受数据完成---------" + successComm.size() + "__" + FormalTestManager.monitorIdListComm.size());

                            PqScriptIssueParam sourceParam = new PqScriptIssueParam();
                            sourceParam.setPlanId(param.getPlanId());
                            sourceParam.setDevIds(param.getDevIds());
                            sourceParam.setIsPhaseSequence(CommonEnum.PHASE_TEST.getValue());
                            sourceParam.setScriptId(param.getScriptId());
                            sourceParam.setSourceId(param.getSourceId());
                            List<SourceIssue> sourceIssues = scriptDtlsService.listSourceIssue(sourceParam);
                            List<SourceCompareDev> info = new ArrayList<>();
                            if (CollUtil.isNotEmpty(sourceIssues)) {
                                devInfo.stream().sorted(Comparator.comparing(DevData::getId));
                                info.addAll(devIsSource(devInfo, sourceIssues.get(0)));
                            }
                            if (CollUtil.isNotEmpty(info)) {
                                SocketDataMsg dataMsg = new SocketDataMsg();
                                dataMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_02.getValue());
                                dataMsg.setRequestId(SourceOperateCodeEnum.YJC_XUJY.getValue());
                                dataMsg.setCode(SourceResponseCodeEnum.SUCCESS.getCode());

                                for (SourceCompareDev sourceCompareDev : info) {
                                    dataMsg.setData(sourceCompareDev.getDevName() + CnSocketUtil.SPLIT_TAG + sourceCompareDev.getLineNum() + "校验结果:" + sourceCompareDev.getDesc());
                                    WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(dataMsg));
                                }

                                //检测不合格关闭设备服务
                                if (info.stream().anyMatch(it -> !it.getIsQualified())) {
                                    WebSocketVO<String> webSocketVO = new WebSocketVO<>();
                                    webSocketVO.setRequestId(SourceOperateCodeEnum.YJC_XUJY.getValue());
                                    webSocketVO.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_02.getValue());
                                    webSocketVO.setCode(SourceResponseCodeEnum.ALL_FAIL.getCode());
                                    webSocketVO.setData(SourceResponseCodeEnum.ALL_FAIL.getMessage());
                                    WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));

                                    CnSocketUtil.quitSend(param);
                                    return;
                                }


                                //向前端推送消息
                                SocketDataMsg temMsg = new SocketDataMsg();
                                temMsg.setCode(SourceResponseCodeEnum.ALL_SUCCESS.getCode());
                                temMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_02.getValue());
                                temMsg.setRequestId(SourceOperateCodeEnum.YJC_XUJY.getValue());
                                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(temMsg));
                                successComm.clear();
                            }

                            // 后续做系数校准
                            if (param.isCoefficientSelected()) {
                                WebSocketVO<Object> webSocketVO = new WebSocketVO<>();
                                webSocketVO.setRequestId(SourceOperateCodeEnum.Coefficient_Check.getValue());
                                webSocketVO.setOperateCode(SourceOperateCodeEnum.big_start.getValue());
                                webSocketVO.setData(XiNumberManager.devParameterList.get(0));
                                WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));

                                //下发命令获取所有装置通道系数,首先需要获取所有装置，通过所有装置下发获取系数命令，目前只支持单台装置获取系数
                                socketMsg.setRequestId(SourceOperateCodeEnum.Coefficient_Check.getValue());
                                socketMsg.setOperateCode(SourceOperateCodeEnum.DATA_CHNFACTOR$01.getValue());
                                PreDetection preDetection = XiNumberManager.xiDevList.get(0);
                                Map<String, Object> map = new HashMap<>();
                                map.put("devIP", preDetection.getDevIP());
                                map.put("chnNum", preDetection.getDevChns());
                                socketMsg.setData(JSON.toJSONString(map));
                                SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.DEV_TAG, JSON.toJSONString(socketMsg));


                                XiNumberManager.stepNumber = 0;
                                XiNumberManager.devXiList.clear();
                                XiNumberManager.devXiNumDataMap.clear();
                                XiNumberManager.smallDevXiNumDataMap.clear();

                                System.out.println("开始系数校准》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");
                            } else if (param.isFormalTestSelected()) {
                                startFormalScripts(param, null, param.isResumeFormal());
                            } else {
                                //后续什么都不做
                                System.out.println("预检测流程结束-----------------关闭源");
                                //同时关闭设备三个步骤
                                CnSocketUtil.quitSend(param);
                            }
                        }
                    } else {
                        System.out.println("相序校验被抛除的数据：" + data);
                    }
                    break;
                case UNPROCESSED_BUSINESS:

                    break;
                case NORMAL_RESPONSE:
                    if (devData.getResult()) {
                        devInfo.add(devData);
                    } else {
                        System.out.println("相序校验被抛除的数据：" + data);
                    }
                    break;
                case DEV_ERROR:
                    WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 0));
                    CnSocketUtil.quitSend(param);
                    break;
                case DEV_TARGET:
                    WebServiceManager.sendMsg(param.getUserPageId(), MsgUtil.msgToWebData(socketDataMsg, FormalTestManager.devNameMapComm, 1));
                    CnSocketUtil.quitSend(param);
                    break;
                case RE_OPERATE:
                    CnSocketUtil.quitSend(param);
                    break;
                default:
                    WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
                    break;
            }
        }

    }


    // key为 检测大项对应的code，value为当前大项的检测结果
    Map<String, List<DevLineTestResult>> targetTestMap = new HashMap<>();

    public void startFormalAfterProgressRestore(PreDetectionParam param, Integer nextSort) {
        FormalTestManager.resumeFormalPending = false;
        FormalTestManager.resumeNextSort = nextSort;
        if (nextSort == null) {
            WebServiceManager.sendDetectionMessage(param.getUserPageId(), "formal_progress_no_next", null, null, null);
            return;
        }
        startFormalScripts(param, nextSort, false);
    }

    private void startFormalScripts(PreDetectionParam param, Integer startSort, boolean waitForProgressRestore) {
        List<SourceIssue> sourceIssues = buildFormalIssues(param);
        if (ObjectUtil.isNotNull(startSort)) {
            sourceIssues = sourceIssues.stream()
                    .filter(issue -> issue.getIndex() >= startSort)
                    .collect(Collectors.toList());
        }
        sourceIssues = sourceIssues.stream()
                .sorted(Comparator.comparing(SourceIssue::getIndex))
                .collect(Collectors.toList());
        Map<String, List<SourceIssue>> groupedIssues = sourceIssues.stream()
                .collect(Collectors.groupingBy(SourceIssue::getType, LinkedHashMap::new, Collectors.toList()));
        sourceIssues = groupedIssues.values().stream().flatMap(List::stream).collect(Collectors.toList());
        if (!param.isResumeFormal() && CollUtil.isNotEmpty(sourceIssues)) {
            iPqDevService.clearFormalProgressForNewRun(param.getDevIds());
            tableGenService.clearAdData(param.getCode());
        }
        SocketManager.addSourceList(sourceIssues);
        Map<String, Long> sourceIssueMap = sourceIssues.stream()
                .collect(Collectors.groupingBy(SourceIssue::getType, Collectors.counting()));
        SocketManager.initMap(sourceIssueMap);

        if (waitForProgressRestore) {
            FormalTestManager.resumeFormalPending = true;
            WebServiceManager.sendDetectionMessage(param.getUserPageId(), "formal_progress_required", null, null, null);
            return;
        }
        sendFirstFormalIssue(param, sourceIssues);
    }

    private List<SourceIssue> buildFormalIssues(PreDetectionParam param) {
        PqScriptIssueParam issueParam = new PqScriptIssueParam();
        issueParam.setSourceId(param.getSourceName());
        issueParam.setPlanId(param.getPlanId());
        issueParam.setDevIds(param.getDevIds());
        issueParam.setScriptId(param.getScriptId());

        if (!param.isResumeFormal() && SourceOperateCodeEnum.RE_ERROR_TEST.getValue().equals(param.getReCheckType())) {
            Set<Integer> indexes = new HashSet<>();
            StorageParam storageParam = new StorageParam();
            storageParam.setCode(param.getCode());
            storageParam.setScriptId(param.getScriptId());
            param.getDevIds().forEach(devId -> {
                storageParam.setDevId(devId);
                indexes.addAll(adHarmonicService.getIndex(storageParam));
            });
            issueParam.setIndexList(indexes.stream().collect(Collectors.toList()));
            issueParam.setIsPhaseSequence(SourceOperateCodeEnum.RE_ERROR_TEST.getValue());
        } else {
            issueParam.setIsPhaseSequence(CommonEnum.FORMAL_TEST.getValue());
        }
        return pqScriptDtlsService.listSourceIssue(issueParam);
    }

    private void sendFirstFormalIssue(PreDetectionParam param, List<SourceIssue> sourceIssues) {
        if (CollUtil.isEmpty(sourceIssues)) {
            WebServiceManager.sendDetectionMessage(param.getUserPageId(), "formal_progress_no_next", null, null, null);
            return;
        }
        SourceIssue firstIssue = sourceIssues.get(0);
        WebSocketVO<Object> webSocketVO = new WebSocketVO<>();
        String type = firstIssue.getType();
        if (StrUtil.isNotBlank(firstIssue.getOtherType())) {
            firstIssue.setType(PowerIndexEnum.LF.getKey().equals(firstIssue.getOtherType()) ? PowerIndexEnum.F.getKey() : PowerIndexEnum.V.getKey());
            webSocketVO.setRequestId(firstIssue.getOtherType() + CnSocketUtil.START_TAG);
            type = firstIssue.getOtherType();
        } else {
            webSocketVO.setRequestId(firstIssue.getType() + CnSocketUtil.START_TAG);
        }
        FormalTestManager.currentIssue = firstIssue;
        FormalTestManager.resumeFormalStartTime = LocalDateTime.now();
        sendFormalCurrentItem(param, firstIssue, type);

        SocketMsg<String> socketMsg = new SocketMsg<>();
        socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
        socketMsg.setData(JSON.toJSONString(firstIssue));
        socketMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type);
        SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(socketMsg));

        webSocketVO.setDesc(null);
        WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
    }

    private void sendFormalCurrentItem(PreDetectionParam param, SourceIssue issue, String displayType) {
        if (issue == null) {
            return;
        }
        FormalTestManager.currentIssue = issue;
        String type = StrUtil.isNotBlank(displayType) ? displayType : issue.getType();
        PowerIndexEnum powerIndexEnum = PowerIndexEnum.getByKey(type);
        String typeName = powerIndexEnum == null ? type : powerIndexEnum.getDesc();
        FormalCurrentItemVO currentItem = new FormalCurrentItemVO(
                type,
                typeName,
                issue.getIndex(),
                StrUtil.blankToDefault(issue.getDesc(), "当前检测小项")
        );
        WebServiceManager.sendDetectionMessage(param.getUserPageId(), "formal_current_item", "current", currentItem, null);
    }

    /**
     * 添加并且按照slowValueTimeList中的时间去重
     *
     * @param devDataList
     * @param devData
     */
    private void addAndRemoveDuplicate(List<DevData> devDataList, DevData devData) {
        if (ObjectUtil.isNotNull(devData) && CollUtil.isNotEmpty(devData.getSlowValueTimeList())) {
            List<DevData.SlowValueTimeDTO> slowValueTimeList1 = devData.getSlowValueTimeList();

            long count1 = devDataList.stream().flatMap(devData1 -> devData.getSlowValueTimeList().stream()).filter(slowValueTimeDTO -> {
                long count2 = slowValueTimeList1.stream().filter(slowValueTimeDTO1 -> {
                    if (slowValueTimeDTO.getDesc().equals(slowValueTimeDTO1.getDesc())) {
                        DevData.SlowValueTimeDTO.ListDTO list = slowValueTimeDTO.getList();
                        DevData.SlowValueTimeDTO.ListDTO list1 = slowValueTimeDTO1.getList();
                        String a = list.getA();
                        String b = list.getB();
                        String c = list.getC();
                        String t = list.getT();

                        String a1 = list1.getA();
                        String b1 = list1.getB();
                        String c1 = list1.getC();
                        String t1 = list1.getT();
                        if (StrUtil.equals(a, a1) && StrUtil.equals(b, b1) && StrUtil.equals(c, c1) && StrUtil.equals(t, t1)) {
                            return true;
                        }
                    }
                    return false;
                }).count();

                return count2 > 0;
            }).count();

            if (count1 <= 0) {
                devDataList.add(devData);
            }
        }
    }

    /**
     * 正式检测
     */
    public void formalDeal(PreDetectionParam param, SocketDataMsg socketDataMsg) {
        String data = socketDataMsg.getData();
        DevData devData = JSON.parseObject(data, DevData.class); //DevData的id值为 设备id_通道号 这种形式
        SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
        SourceIssue sourceIssue = SocketManager.getSourceList().get(0);
        if (FormalTestManager.isImmediatePause()) {
            successComm.clear();
            FormalTestManager.realDataXiList.clear();
            return;
        }

        switch (Objects.requireNonNull(dictDataEnumByCode)) {
            case SUCCESS:
                if (devData.getResult()) {
                    // 判断是否是长闪数据
                    if (PowerIndexEnum.LF.getKey().equals(sourceIssue.getOtherType())) {
                        List<DevData.SqlDataDTO> sqlData = devData.getSqlData();
                        if (CollUtil.isNotEmpty(sqlData)) {
                            if (isEvenHour(devData.getTime())) {
                                if (FormalTestManager.longFlickerDataCount >= FormalTestManager.monitorIdListComm.size()) {
                                    FormalTestManager.realDataXiList.add(devData);
                                    successComm.add(devData.getId());
                                }

                                //成功收到数据后重置超时统计时间
                                if (SocketManager.clockMap.containsKey(sourceIssue.getIndex())) {
                                    SocketManager.clockMap.put(sourceIssue.getIndex(), 0L);
                                }
                                FormalTestManager.longFlickerDataCount++;
                            }
                        }
                    } else {
                        FormalTestManager.realDataXiList.add(devData);
                        successComm.add(devData.getId());

                        //成功收到数据后重置超时统计时间
                        if (SocketManager.clockMap.containsKey(sourceIssue.getIndex())) {
                            SocketManager.clockMap.put(sourceIssue.getIndex(), 0L);
                        }
                    }

                    //当成功的通道数量和检测通道数量相同时进入
                    if (successComm.size() == FormalTestManager.monitorIdListComm.size()) {
                        System.out.println(sourceIssue.getType() + CnSocketUtil.SPLIT_TAG + sourceIssue.getIndex() + "当前测试小项读取数据已经全部结束。。。。。。。。。");
                        //修改装置为监测中
//                    adPlanService.updateTestState(param.getPlanId(), param.getDevIds());
                        //开启线程进行入库原始数据操作
                        baseDataInsert(FormalTestManager.realDataXiList, sourceIssue, param, SocketManager.valueTypeMap);

                        //调用判断方法
                        Map<String, Integer> textResult = detectionServiceImpl.processing(FormalTestManager.realDataXiList, param, FormalTestManager.devIdMapComm, sourceIssue, dataRule);

                        System.out.println(textResult);
                        //对检测结果组装实体推送给前台
                        assWebJson(param, textResult, socketDataMsg, sourceIssue);

                        //当小项结束后需要删除集合中的小项
                        SocketManager.delSource(sourceIssue.getIndex());
                        System.out.println("当前小项结束进行删除============" + sourceIssue.getType() + CnSocketUtil.SPLIT_TAG + sourceIssue.getIndex());

                        //小项检测完后小项数减一，并更新map
                        long residueCount = 0;
                        if (StrUtil.isNotBlank(sourceIssue.getOtherType())) {
                            residueCount = SocketManager.getSourceTarget(sourceIssue.getOtherType()) - 1;
                            SocketManager.addTargetMap(sourceIssue.getOtherType(), residueCount);
                        } else {
                            residueCount = SocketManager.getSourceTarget(sourceIssue.getType()) - 1;
                            SocketManager.addTargetMap(sourceIssue.getType(), residueCount);
                        }
                        System.out.println("该大项还有" + residueCount + "个小项没有进行检测！！！！！！！！");

                        //当该大项中小项数量变为0，则任务该大项检测结束
                        if (residueCount == 0) {
                            System.out.println(sourceIssue.getType() + sourceIssue.getIndex() + "当前测试大项已经全部结束》》》》》》》》");
                            //当residueCount为0则认为大项中的小项已经全部跑完，开始组装信息推送给前端
                            List<DevLineTestResult> resultList = new ArrayList<>();
                            // 获取当前检测大项的所有设备的检测结果
                            List<DevLineTestResult> allDevTestList = targetTestMap.get(sourceIssue.getType());
                            Map<String, List<DevLineTestResult>> map = allDevTestList.stream().collect(Collectors.groupingBy(DevLineTestResult::getDeviceId));
                            map.forEach((dev, list) -> {
                                DevLineTestResult devTem = new DevLineTestResult();
                                devTem.setDeviceId(dev);
                                devTem.setDeviceName(list.get(0).getDeviceName());
                                Integer[] arr = list.get(0).getChnResult();
                                for (int i = 0; i < arr.length; i++) {
                                    List<Integer[]> arrList = list.stream().map(DevLineTestResult::getChnResult).collect(Collectors.toList());
                                    Integer[] resultArr = getMaxIntArray(arrList);
                                    devTem.setChnResult(resultArr);
                                }
                                resultList.add(devTem);
                            });
                            allDevTestList.clear();
                            WebServiceManager.sendDetectionMessage(param.getUserPageId(), socketDataMsg.getRequestId().split(CnSocketUtil.STEP_TAG)[1] + CnSocketUtil.END_TAG, null, resultList, null);
                        }
                        //在这一步判断是否已经触发暂停按钮
                        if (FormalTestManager.stopFlag
                                && FormalTestManager.isWaitCurrentItemPause()
                                && CollUtil.isNotEmpty(SocketManager.getSourceList())) {
                            FormalTestManager.markPausedAfterCurrentItem();
                            successComm.clear();
                            FormalTestManager.realDataXiList.clear();
                            sendWebSocket(param.getUserPageId(), "preStopTest", "stop", null);
                            return;
                        }

                        //开始进行下一项检测
                        List<SourceIssue> sourceIssueList = SocketManager.getSourceList();
                        if (CollUtil.isNotEmpty(sourceIssueList)) {
                            SourceIssue sourceIssues = SocketManager.getSourceList().get(0);

                            String type = sourceIssues.getType();
                            if (StrUtil.isNotBlank(sourceIssues.getOtherType())) {
                                sourceIssues.setType(PowerIndexEnum.LF.getKey().equals(sourceIssues.getOtherType()) ? PowerIndexEnum.F.getKey() : PowerIndexEnum.V.getKey());
                                type = sourceIssues.getOtherType();
                            }
                            // 如果上一个大项检测完成，则检测下一个大项，并向前端推送消息
                            if (residueCount == 0) {
                                WebServiceManager.sendDetectionMessage(param.getUserPageId(), type + CnSocketUtil.START_TAG, null, new ArrayList<>(), null);
                            }

                            //控源下发下一个小项脚本
                            SocketMsg<String> xuMsg = new SocketMsg<>();
                            xuMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
                            xuMsg.setData(JSON.toJSONString(sourceIssues));
                            xuMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type);
                            FormalTestManager.currentIssue = sourceIssues;
                            sendFormalCurrentItem(param, sourceIssues, type);
                            SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xuMsg));
                        } else {
                            //TODO 是否最终检测完成需要推送给用户
                            PqScriptCheckDataParam checkDataParam = new PqScriptCheckDataParam();
                            checkDataParam.setScriptId(param.getScriptId());
                            checkDataParam.setIsValueTypeName(false);
                            List<String> valueType = iPqScriptCheckDataService.getValueType(checkDataParam);

                            iPqDevService.updateResult(param.getDevIds(), valueType, param.getCode(), param.getUserId(), param.getTemperature(), param.getHumidity(), true);
                            if (Boolean.TRUE.equals(dataCheck)) {
                                resultService.tryNotifyThirdPartyAfterFormalTest(param);
                            }
                            CnSocketUtil.quitSend(param);
                            // 数模式检测全部小项完成 → 释放锁，避免用户必须点"停止"才能让出
                            DetectionLockManager.getInstance()
                                    .releaseIfMatchPage(param.getUserPageId(), "DEV_TEST_FINISHED");
                        }
                        successComm.clear();
                        FormalTestManager.realDataXiList.clear();

                    }
                } else {
                    System.out.println("被抛除的数据：" + data);
                }
                break;
            case UNPROCESSED_BUSINESS:
                break;

            case NORMAL_RESPONSE:
                if (devData.getResult()) {
                    if (SocketManager.clockMap.containsKey(sourceIssue.getIndex())) {
                        SocketManager.clockMap.put(sourceIssue.getIndex(), 0L);
                    }
                    FormalTestManager.realDataXiList.add(devData);
                } else {
                    System.out.println("被抛除的数据：" + data);
                }
                break;
            case DEV_ERROR:

                break;
            case DEV_TARGET:

                break;
            case RE_OPERATE:
                break;
            case MESSAGE_PARSING_ERROR:
                break;
            default:
                WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
                break;
        }
    }


    /**
     * 组装实体推送给前端
     */
    private void assWebJson(PreDetectionParam param, Map<String, Integer> textResult, SocketDataMsg socketDataMsg, SourceIssue sourceIssue) {
        List<DevLineTestResult> devListRes = new ArrayList<>();
        FormalTestManager.devList.forEach(dev -> {
            DevLineTestResult devLineTestResult = new DevLineTestResult();
            devLineTestResult.setDeviceId(dev.getDevId());
            devLineTestResult.setDeviceName(dev.getDevName());

            List<Integer> resultFlagList = new ArrayList<>();
            List<PreDetection.MonitorListDTO> monitorListDTOList = dev.getMonitorList();
            for (PreDetection.MonitorListDTO point : monitorListDTOList) {
                Integer resultFlag = textResult.get(dev.getDevIP() + CnSocketUtil.SPLIT_TAG + point.getLine());
                resultFlagList.add(resultFlag);
            }
            devLineTestResult.setChnResult(resultFlagList.toArray(new Integer[monitorListDTOList.size()]));
            devListRes.add(devLineTestResult);
        });

        if (targetTestMap.containsKey(sourceIssue.getType())) {
            List<DevLineTestResult> devLineTestResultList = targetTestMap.get(sourceIssue.getType());
            devLineTestResultList.addAll(devListRes);
        } else {
            targetTestMap.put(sourceIssue.getType(), devListRes);
        }

        WebSocketVO<List<DevLineTestResult>> webSocketVO = new WebSocketVO<>();
        webSocketVO.setRequestId(socketDataMsg.getRequestId().split(CnSocketUtil.STEP_TAG)[1] + CnSocketUtil.END_TAG);
        webSocketVO.setDesc(sourceIssue.getDesc());
        webSocketVO.setData(devListRes);
        WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
    }

//    private void setNewChnResult(Integer[] oldChnResult, Integer[] newChnResult) {
//        for (int i = 0; i < oldChnResult.length; i++) {
//            if (newChnResult[i] == 2) {
//                oldChnResult[i] = 2;
//                continue;
//            }
//            if (newChnResult[i] == 3 && oldChnResult[i] != 2) {
//                oldChnResult[i] = 3;
//                continue;
//            }
//            if (newChnResult[i] == 4 && oldChnResult[i] != 2) {
//                oldChnResult[i] = 4;
//                continue;
//            }
//            if (newChnResult[i] == 5 && oldChnResult[i] != 2 && oldChnResult[i] != 3 && oldChnResult[i] != 4) {
//                oldChnResult[i] = 5;
//            }
//        }
//    }

    /**
     * 返回大项检测结果，默认遇到 4，5时认为不参与计算
     */
    public Integer[] getMaxIntArray(List<Integer[]> arrays) {
        int length = arrays.get(0).length;
        Integer[] maxArray = new Integer[length];
        for (int i = 0; i < length; i++) {
            int maxValue = -1;
            for (Integer[] array : arrays) {
                int value = array[i];
                if (value != 4 && value != 5) {
                    if (value > maxValue) {
                        maxValue = value;
                    }
                }
            }
            if (maxValue == -1) {
                maxArray[i] = arrays.get(0)[i];
            } else {
                maxArray[i] = maxValue;
            }
        }
        return maxArray;
    }


    /**
     * 退出检测返回
     */
    private void quitDeal(SocketDataMsg socketDataMsg, PreDetectionParam param, String msg) {
        SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
        SourceOperateCodeEnum operateCodeEnum = SourceOperateCodeEnum.getDictDataEnumByCode(socketDataMsg.getOperateCode());
        SocketMsg<String> socketMsg = new SocketMsg<>();
        String s = param.getUserPageId() + CnSocketUtil.DEV_TAG;

        switch (Objects.requireNonNull(dictDataEnumByCode)) {
            case SUCCESS:
                //通讯校验成功
                switch (Objects.requireNonNull(operateCodeEnum)) {
                    case QUIT_INIT_01:
                        //关闭所有
                        SocketManager.removeUser(s);
                        CnSocketUtil.quitSendSource(param);
                        break;
                    case QUIT_INIT_02:
                        socketMsg.setRequestId(SourceOperateCodeEnum.QUITE.getValue());
                        socketMsg.setOperateCode(SourceOperateCodeEnum.QUIT_INIT_01.getValue());
                        SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                        break;
                    case QUIT_INIT_03:
                        socketMsg.setRequestId(SourceOperateCodeEnum.QUITE.getValue());
                        socketMsg.setOperateCode(SourceOperateCodeEnum.QUIT_INIT_02.getValue());
                        SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                        break;
                    default:

                }
                break;
            case UNPROCESSED_BUSINESS:
                break;
            case NO_INIT_DEV:
                switch (operateCodeEnum) {
                    case QUIT_INIT_01:
                        SocketManager.removeUser(s);
                        // CnSocketUtil.quitSendSource(param);
                        break;
                    case QUIT_INIT_02:
                        socketMsg.setRequestId(SourceOperateCodeEnum.QUITE.getValue());
                        socketMsg.setOperateCode(SourceOperateCodeEnum.QUIT_INIT_01.getValue());
                        SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                        break;
                    case QUIT_INIT_03:
                        socketMsg.setRequestId(SourceOperateCodeEnum.QUITE.getValue());
                        socketMsg.setOperateCode(SourceOperateCodeEnum.QUIT_INIT_02.getValue());
                        SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
                        break;
                }
                break;
            default:
                WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
                break;
        }

    }


    /**
     * @param issue
     * @return key为V或I，value为对应的源下发信息
     */
    private Map<String, String> sourceMessage(SourceIssue issue) {
        //（Ua=59.0V,相角=0.0°  Ub=59.0V,相角=0.0°  Uc=59.0V,相角=0.0°）
        Map<String, String> map = new HashMap<>();
        List<SourceIssue.ChannelListDTO> v = issue.getChannelList().stream().filter(x -> x.getChannelType().contains("U")).collect(Collectors.toList());
        List<SourceIssue.ChannelListDTO> i = issue.getChannelList().stream().filter(x -> x.getChannelType().contains("I")).collect(Collectors.toList());
        map.put("V", sourceBuffer(v));
        map.put("I", sourceBuffer(i));
        return map;
    }

    private String sourceBuffer(List<SourceIssue.ChannelListDTO> v) {
        StringBuffer str = new StringBuffer();
        str.append("源(");
        for (SourceIssue.ChannelListDTO dto : v) {
            str.append(dto.getChannelType() + "=" + dto.getFAmp() + ",相角=" + dto.getFPhase() + "° ");
        }
        str.append(")");
        return str.toString();
    }

    private String devMessage(String type,
                              List<DevData.SqlDataDTO> data,
                              List<DevData.SqlDataDTO> dataPhase,
                              boolean angleCheck) {
        StringBuffer str = new StringBuffer();
        if (angleCheck) {
            if (CollUtil.isNotEmpty(data) && CollUtil.isNotEmpty(dataPhase)) {
                if (data.size() == dataPhase.size()) {
                    DevData.SqlDataDTO.ListDTO dto = data.get(0).getList();
                    DevData.SqlDataDTO.ListDTO phase = dataPhase.get(0).getList();
                    str.append("装置(" + type + "a=" + String.format("%.4f", dto.getA()) + ",相角=" + String.format("%.4f", phase.getA()) + "° " +
                            type + "b=" + String.format("%.4f", dto.getB()) + ",相角=" + String.format("%.4f", phase.getB()) + "° " +
                            type + "c=" + String.format("%.4f", dto.getC()) + ",相角=" + String.format("%.4f", phase.getC()) + "° ");
                    str.append(")");
                }
            }
        } else {
            DevData.SqlDataDTO.ListDTO dto = data.get(0).getList();
            str.append("装置(" + type + "a=" + String.format("%.4f", dto.getA()) +
                    type + "b=" + String.format("%.4f", dto.getB()) +
                    type + "c=" + String.format("%.4f", dto.getC()));
            str.append(")");
        }
        return str.toString();
    }

    private List<SourceCompareDev> devIsSource(List<DevData> dev, SourceIssue issue) {
        List<SourceCompareDev> info = new ArrayList<>();
        //相序校验信息
        LinkedHashMap<String, List<DevData>> devMap = dev.stream()
                .sorted(Comparator.comparing(DevData::getId))
                .collect(Collectors.groupingBy(DevData::getId, LinkedHashMap::new, Collectors.toList()));
        //电压
        List<SourceIssue.ChannelListDTO> sourceV = issue.getChannelList().stream().filter(x -> x.getChannelType().contains("U"))
                .sorted(Comparator.comparing(SourceIssue.ChannelListDTO::getChannelType))
                .collect(Collectors.toList());
        //电流
        List<SourceIssue.ChannelListDTO> sourceI = issue.getChannelList().stream().filter(x -> x.getChannelType().contains("I"))
                .sorted(Comparator.comparing(SourceIssue.ChannelListDTO::getChannelType))
                .collect(Collectors.toList());
        Map<String, String> sourceMessageMap = sourceMessage(issue);
        List<String> v = Arrays.asList("VRMS", "VA", "U", "V", "电压");
        List<String> i = Arrays.asList("IRMS", "IA", "I", "I", "电流");
        devMap.forEach((key, value) -> {
            List<DevData.SqlDataDTO> sqlData = value.stream().flatMap(x -> x.getSqlData().stream()).collect(Collectors.toList());
            //电压
            getResult(key, sqlData, sourceMessageMap, sourceV, info, v);
            //电流
            getResult(key, sqlData, sourceMessageMap, sourceI, info, i);
        });
        return info;
    }

    private void getResult(String key,
                           List<DevData.SqlDataDTO> sqlData,
                           Map<String, String> sourceMessageMap,
                           List<SourceIssue.ChannelListDTO> sourceV,
                           List<SourceCompareDev> info,
                           List<String> type
    ) {
        List<DevData.SqlDataDTO> dataV = sqlData.stream().filter(x -> type.get(0).equals(x.getDesc())).collect(Collectors.toList());
        List<DevData.SqlDataDTO> dataVPhase = sqlData.stream().filter(x -> type.get(1).equals(x.getDesc())).collect(Collectors.toList());
        SourceCompareDev compareDev = new SourceCompareDev();
        String[] split = key.split(CnSocketUtil.SPLIT_TAG);
        String devName = null;
        if (FormalTestManager.devNameMapComm.containsKey(split[0])) {
            devName = FormalTestManager.devNameMapComm.get(split[0]);
        }
        compareDev.setDevName(devName);
        compareDev.setLineNum(split[1]);

        boolean angleCheck = false;
        PreDetection preDetection = FormalTestManager.devList.stream().filter(x -> x.getDevIP().equals(split[0])).findFirst().orElse(null);
        if (ObjectUtil.isNotNull(preDetection)) {
            angleCheck = preDetection.getAngle() == 1 ? true : false;
        }
        getSourceCompareDev(type.get(2), dataV, dataVPhase, compareDev, sourceMessageMap.get(type.get(3)), sourceV, type.get(4), angleCheck);
        info.add(compareDev);
    }


    /**
     * 计算是否合格
     *
     * @param data        装置返回信息
     * @param compareDev  返回信息
     * @param channelList 源通道信息
     * @return
     */
    private SourceCompareDev getSourceCompareDev(String type,
                                                 List<DevData.SqlDataDTO> data,
                                                 List<DevData.SqlDataDTO> dataPhase,
                                                 SourceCompareDev compareDev,
                                                 String desc,
                                                 List<SourceIssue.ChannelListDTO> channelList,
                                                 String name,
                                                 boolean angleCheck) {
        //源信息
        Map<String, SourceIssue.ChannelListDTO> sourceMap = channelList.stream()
                .collect(Collectors.toMap(x -> x.getChannelType(), Function.identity()));
        Boolean a = getaBoolean(sourceMap.get(type + "a"), CollUtil.isNotEmpty(data) ? data.get(0).getList().getA() : null,
                CollUtil.isNotEmpty(dataPhase) ? dataPhase.get(0).getList().getA() : null, angleCheck);
        Boolean b = getaBoolean(sourceMap.get(type + "b"), CollUtil.isNotEmpty(data) ? data.get(0).getList().getB() : null,
                CollUtil.isNotEmpty(dataPhase) ? dataPhase.get(0).getList().getB() : null, angleCheck);
        Boolean c = getaBoolean(sourceMap.get(type + "c"), CollUtil.isNotEmpty(data) ? data.get(0).getList().getC() : null,
                CollUtil.isNotEmpty(dataPhase) ? dataPhase.get(0).getList().getC() : null, angleCheck);
        compareDev.setIsQualified(a && b && c);
        compareDev.setDesc(name + (compareDev.getIsQualified() ? "合格->" : "不合格->") + CnSocketUtil.STEP_TAG + desc + CnSocketUtil.STEP_TAG + devMessage(type, data, dataPhase, angleCheck));
        return compareDev;
    }

    /**
     * 相须校验-从幅值、相角两个维度判断是否合格
     *
     * @param channelListDTO 源下发的脚本
     * @param devData        装置返回幅值数据
     * @param devPhase       装置返回相角数据
     * @return
     */
    private Boolean getaBoolean(SourceIssue.ChannelListDTO channelListDTO, Double devData, Double devPhase, boolean angleCheck) {
        Boolean isDev = false;
        Boolean isPhase = false;

        if (ObjectUtil.isNotNull(devData)) {
            isDev = NumberUtil.isIn(BigDecimal.valueOf(devData),
                    BigDecimal.valueOf(channelListDTO.getFAmp() * 0.95),
                    BigDecimal.valueOf(channelListDTO.getFAmp() * 1.05));
        }
        if (angleCheck) {
            if (ObjectUtil.isNotNull(devPhase)) {
                isPhase = phaseBoolean(channelListDTO, devPhase);
            }
        } else {
            isPhase = true;
        }
        return isDev && isPhase;

    }

    /**
     * 判断相角（-180° ~ 180°）
     * （+360° ~ -360°）
     *
     * @param channelListDTO 源下发角度
     * @param devPhase       装置返回角度
     * @return
     */
    private Boolean phaseBoolean(SourceIssue.ChannelListDTO channelListDTO, Double devPhase) {
        devPhase = DetectionUtil.adjustPhase(devPhase);
        Double fPhase = channelListDTO.getFPhase();
        fPhase = DetectionUtil.adjustPhase(fPhase);
        return NumberUtil.isIn(BigDecimal.valueOf(devPhase), BigDecimal.valueOf(fPhase - 1), BigDecimal.valueOf(fPhase + 1));
    }


    /**
     * 暂停后的重新检测
     */
    public void initRestart() {
        this.successComm.clear();
        FormalTestManager.realDataXiList.clear();
    }


    /**
     * 初始化集合
     */
    public void initList(PreDetectionParam param) {
        FormalTestManager.monitorIdListComm.clear();
        FormalTestManager.devList.clear();
        SocketManager.valueTypeMap.clear();
        SocketManager.clockMap.clear();
        successComm.clear();

        FormalTestManager.clearPauseState();

        //初始化相序集合
        this.devInfo.clear();
        //this.devDataMap.clear(); //好像没有用到
        FormalTestManager.realDataXiList.clear();
        this.targetTestMap.clear();

        List<PreDetection> pqDevList = iPqDevService.getDevInfo(param.getDevIds());
        FormalTestManager.devList = pqDevList;
        FormalTestManager.devList.forEach(x -> {
            x.setDevType(x.getIcdType());
        });
        FormalTestManager.devMapMonitorNum = pqDevList.stream().collect(Collectors.toMap(PreDetection::getDevIP, it -> it.getMonitorList().stream().map(PreDetection.MonitorListDTO::getLineId).collect(Collectors.toList())));
        FormalTestManager.monitorIdListComm = pqDevList.stream().flatMap(x -> x.getMonitorList().stream()).map(PreDetection.MonitorListDTO::getLineId).collect(Collectors.toList());

        FormalTestManager.devNameMapComm = pqDevList.stream().collect(Collectors.toMap(PreDetection::getDevIP, PreDetection::getDevName));
        FormalTestManager.devIdMapComm.clear();
        FormalTestManager.devIdMapComm.putAll(pqDevList.stream().collect(Collectors.toMap(PreDetection::getDevIP, PreDetection::getDevId)));

        //初始化有效数据数
        //Map<String, SysRegResVO> sysRegResMap = iSysRegResService.listRegRes();

        //SysTestConfig oneConfig = sysTestConfigService.getOneConfig();
        AdPlan plan = adPlanService.getById(param.getPlanId());
        DictData dictData = dictDataService.getDictDataById(plan.getDataRule());
        if (ObjectUtil.isNotNull(dictData)) {
            dataRule = DictDataEnum.getDictDataEnumByCode(dictData.getCode());
        } else {
            dataRule = DictDataEnum.SECTION_VALUE;
        }
        FormalTestManager.currentTestPlan = plan;

        String code = dictDataService.getDictDataById(plan.getPattern()).getCode();
        FormalTestManager.patternEnum = PatternEnum.getEnum(code);
        //字典树
        SocketManager.valueTypeMap = iPqScriptCheckDataService.getValueTypeMap(param.getScriptId());

        if (param.isCoefficientSelected()) {
            initXiManager(param);
        }

        FormalTestManager.overload = getOverloadResult(param);
        FormalTestManager.checkStartTime = LocalDateTime.now();
        FormalTestManager.reCheckType = param.getReCheckType();
    }


    /**
     * 获取过载测试结果
     *
     * @return 如果检测到电压过载，overload=1；如果检测到电流过载，overload=2；如果检测到电压&&电流过载，overload=3；反之，overload=4
     */
    private int getOverloadResult(PreDetectionParam param) {
        PqSource pqSource = pqSourceService.getPqSourceById(param.getSourceId());
        BigDecimal maxVoltage = pqSource.getMaxVoltage();
        BigDecimal maxCurrent = pqSource.getMaxCurrent();

        PqScriptIssueParam issueParam = new PqScriptIssueParam();
        issueParam.setSourceId(pqSource.getName());
        issueParam.setPlanId(param.getPlanId());
        issueParam.setDevIds(param.getDevIds());
        issueParam.setScriptId(param.getScriptId());
        issueParam.setIsPhaseSequence(CommonEnum.FORMAL_TEST.getValue());
        List<SourceIssue> sourceIssues = pqScriptDtlsService.listSourceIssue(issueParam);

        for (int i = 0; i < sourceIssues.size(); i++) {
            SourceIssue sourceIssue = sourceIssues.get(i);
            List<SourceIssue.ChannelListDTO> channelList = sourceIssue.getChannelList();
            for (int j = 0; j < channelList.size(); j++) {
                SourceIssue.ChannelListDTO channelListDTO = channelList.get(j);
                Double fAmp = channelListDTO.getFAmp();
                String channelType = channelListDTO.getChannelType();

                if (ObjectUtil.isNotNull(fAmp)) {
                    if (channelType.contains("U")) {
                        // 电压判断
                        if (maxVoltage.compareTo(BigDecimal.valueOf(fAmp)) < 0) {
                            return 1;
                        }
                    } else {
                        // 电流判断
                        if (maxCurrent.compareTo(BigDecimal.valueOf(fAmp)) < 0) {
                            return 2;
                        }
                    }
                }
                // 暂态判断
                if (channelListDTO.getDipFlag()) {
                    SourceIssue.ChannelListDTO.DipDataDTO dipData = channelListDTO.getDipData();
                    if (ObjectUtil.isNotNull(dipData)) {
                        Double fTransValue = dipData.getFTransValue();
                        if (ObjectUtil.isNotNull(fTransValue) && ObjectUtil.isNotNull(fAmp)) {
                            if (maxVoltage.compareTo(BigDecimal.valueOf(fTransValue / 100).max(BigDecimal.valueOf(fAmp))) < 0) {
                                return 1;
                            }
                        }
                    }
                }
                // 谐波判断
                if (channelListDTO.getHarmFlag()) {
                    List<SourceIssue.ChannelListDTO.HarmModel> harmList = channelListDTO.getHarmList();
                    double thd = harmList.stream().map(harmModel -> harmModel.getFAmp() * harmModel.getFAmp() / 10000).mapToDouble(x -> x).sum();
                    if (maxVoltage.compareTo(BigDecimal.valueOf(Math.sqrt(1 + thd) * fAmp)) < 0) {
                        return channelType.contains("U") ? 1 : 2;
                    }
                }
                // 间谐波判断
                if (channelListDTO.getInHarmFlag()) {
                    List<SourceIssue.ChannelListDTO.InharmModel> inharmList = channelListDTO.getInharmList();
                    double thd = inharmList.stream().map(harmModel -> harmModel.getFAmp() * harmModel.getFAmp() / 10000).mapToDouble(x -> x).sum();
                    if (maxVoltage.compareTo(BigDecimal.valueOf(Math.sqrt(1 + thd) * fAmp)) < 0) {
                        return channelType.contains("U") ? 1 : 2;
                    }
                }
            }
        }

        return 4;
    }

    //初始化系数校验参数
    private void initXiManager(PreDetectionParam param) {
        XiNumberManager.devParameterList.clear();

        Double v = FormalTestManager.devList.get(0).getDevVolt();
        Double i = FormalTestManager.devList.get(0).getDevCurr();
        CoefficientVO.DevParameter devParameterBig = new CoefficientVO.DevParameter();
        devParameterBig.setDevVolt(BigDecimal.valueOf(v * 1.2).setScale(2, RoundingMode.HALF_UP).doubleValue());
        devParameterBig.setDevCurr(BigDecimal.valueOf(i * 1.2).setScale(2, RoundingMode.HALF_UP).doubleValue());

        CoefficientVO.DevParameter devParameterSmall = new CoefficientVO.DevParameter();
        devParameterSmall.setDevVolt(BigDecimal.valueOf(v * 0.2).setScale(2, RoundingMode.HALF_UP).doubleValue());
        devParameterSmall.setDevCurr(BigDecimal.valueOf(i * 0.2).setScale(2, RoundingMode.HALF_UP).doubleValue());


        XiNumberManager.devParameterList.add(devParameterBig);
        XiNumberManager.devParameterList.add(devParameterSmall);

        PqScriptIssueParam issueParam = new PqScriptIssueParam();
        issueParam.setSourceId(param.getSourceName());
        issueParam.setPlanId(param.getPlanId());
        issueParam.setDevIds(param.getDevIds());
        issueParam.setScriptId(param.getScriptId());
        issueParam.setIsPhaseSequence(CommonEnum.COEFFICIENT_TEST.getValue());
        issueParam.setIndexList(Stream.of(-2, -3).collect(Collectors.toList()));
        List<SourceIssue> sourceIssues = pqScriptDtlsService.listSourceIssue(issueParam);
        for (int j = 0; j < sourceIssues.size(); j++) {
            if (j == 0) {
                sourceIssues.get(j).getChannelList().forEach(it -> {
                    if (it.getChannelType().contains("U")) {
                        it.setFAmp(XiNumberManager.devParameterList.get(0).getDevVolt());
                    } else if (it.getChannelType().contains("I")) {
                        it.setFAmp(XiNumberManager.devParameterList.get(0).getDevCurr());
                    }
                });
            } else {
                sourceIssues.get(j).getChannelList().forEach(it -> {
                    if (it.getChannelType().contains("U")) {
                        it.setFAmp(XiNumberManager.devParameterList.get(1).getDevVolt());
                    } else if (it.getChannelType().contains("I")) {
                        it.setFAmp(XiNumberManager.devParameterList.get(1).getDevCurr());
                    }
                });
            }
        }
        XiNumberManager.xiSourceIssueList = sourceIssues;
        System.out.println(XiNumberManager.xiSourceIssueList);
    }

    /**
     * 判断时间是否为偶数小时
     *
     * @param timeStr
     * @return
     */
    private boolean isEvenHour(String timeStr) {
        LocalDateTime localDateTime = DetectionUtil.timeFormat(timeStr, DetectionUtil.FORMATTER);
        return localDateTime.getHour() % 2 == 0 && localDateTime.getMinute() == 0;
    }

    /**
     * 原始数据入库
     *
     * @author cdf
     * @date 2024/12/29
     */
    private void baseDataInsert(List<DevData> devDataList, SourceIssue sourceIssue, PreDetectionParam param, Map<String, String> checkDataMap) {
        // Runnable runnable = () -> {

        System.out.println("原始数据插入数据库开始执行=========================================");
        List<SimAndDigNonHarmonicResult> simAndDigNonHarmonicResultList = new ArrayList<>();
        List<SimAndDigHarmonicResult> adHarmonicResultList = new ArrayList<>();
        Map<String, String> harmonicRelationMap = new HashMap<>();
        harmonicRelationMap.put(DetectionCodeEnum.V2_50.getCode(), DetectionCodeEnum.U1.getCode());
        harmonicRelationMap.put(DetectionCodeEnum.I2_50.getCode(), DetectionCodeEnum.I1.getCode());
        for (DevData data : devDataList) {
            LocalDateTime localDateTime = DetectionUtil.timeFormat(data.getTime(), DetectionUtil.FORMATTER);
            if (Objects.nonNull(localDateTime)) {

                String[] splitArr = data.getId().split(CnSocketUtil.SPLIT_TAG);
                String temId = FormalTestManager.devIdMapComm.get(splitArr[0]) + CnSocketUtil.SPLIT_TAG + splitArr[1];

                if (nonHarmonicList.contains(sourceIssue.getType())) {
                    for (DevData.SqlDataDTO sqlDataDTO : data.getSqlData()) {
                        DevData.SqlDataDTO.ListDTO listDTO = sqlDataDTO.getList();
                        SimAndDigNonHarmonicResult adNonHarmonicResult = new SimAndDigNonHarmonicResult();
                        adNonHarmonicResult.setTimeId(localDateTime);
                        adNonHarmonicResult.setDevMonitorId(temId);
                        adNonHarmonicResult.setScriptId(param.getScriptId());
                        adNonHarmonicResult.setSort(sourceIssue.getIndex());

                        adNonHarmonicResult.setAdType(checkDataMap.get(sqlDataDTO.getDesc()));
                        adNonHarmonicResult.setDataType(sourceIssue.getDataType());

                        Double a = listDTO.getA();
                        Double b = listDTO.getB();
                        Double c = listDTO.getC();
                        Double d = listDTO.getT();
                        if (Objects.nonNull(a)) {
                            adNonHarmonicResult.setAValue(String.format("%.7f", a));
                        }
                        if (Objects.nonNull(b)) {
                            adNonHarmonicResult.setBValue(String.format("%.7f", b));
                        }
                        if (Objects.nonNull(c)) {
                            adNonHarmonicResult.setCValue(String.format("%.7f", c));
                        }
                        if (Objects.nonNull(d)) {
                            adNonHarmonicResult.setTValue(String.format("%.7f", d));
                        }
                        simAndDigNonHarmonicResultList.add(adNonHarmonicResult);
                    }
                } else {

                    for (int j = 0; j < data.getSqlDataHarm().size(); j++) {
                        DevData.SqlDataHarmDTO sqlDataDTO = data.getSqlDataHarm().get(j);
                        String dui = harmonicRelationMap.get(sqlDataDTO.getDesc());
                        SimAndDigHarmonicResult adHarmonicResult = new SimAndDigHarmonicResult();
                        adHarmonicResult.setTimeId(localDateTime);

                        adHarmonicResult.setDevMonitorId(temId);
                        adHarmonicResult.setScriptId(param.getScriptId());
                        adHarmonicResult.setSort(sourceIssue.getIndex());
                        adHarmonicResult.setAdType(checkDataMap.get(sqlDataDTO.getDesc()));
                        adHarmonicResult.setDataType(sourceIssue.getDataType());

                        if (!PowerIndexEnum.HSV.getKey().equals(sourceIssue.getType()) && !PowerIndexEnum.HSI.getKey().equals(sourceIssue.getType()) && !PowerIndexEnum.HP.getKey().equals(sourceIssue.getType())) {
                            if (CollUtil.isNotEmpty(data.getSqlData())) {
                                DevData.SqlDataDTO.ListDTO vvv = data.getSqlData().stream().filter(it -> it.getDesc().equals(dui)).collect(Collectors.toList()).get(0).getList();
                                Double aV = vvv.getA();
                                Double bV = vvv.getB();
                                Double cV = vvv.getC();
                                if (Objects.nonNull(aV)) {
                                    adHarmonicResult.setAValue1(String.format("%.7f", aV));
                                }
                                if (Objects.nonNull(bV)) {
                                    adHarmonicResult.setBValue1(String.format("%.7f", bV));
                                }
                                if (Objects.nonNull(cV)) {
                                    adHarmonicResult.setCValue1(String.format("%.7f", cV));
                                }
                            }

                        }

                        DevData.SqlDataHarmDTO.ListDTO tem = sqlDataDTO.getList();
                        List<String> a = tem.getA();
                        List<String> b = tem.getB();
                        List<String> c = tem.getC();

                        Class<SimAndDigHarmonicResult> example = (Class<SimAndDigHarmonicResult>) adHarmonicResult.getClass();
                        if (PowerIndexEnum.HSV.getKey().equals(sourceIssue.getType()) || PowerIndexEnum.HSI.getKey().equals(sourceIssue.getType())) {
                            for (int i = 1; i < a.size() + 1; i++) {
                                try {
                                    Field aField = example.getDeclaredField("aValue" + i);
                                    Field bField = example.getDeclaredField("bValue" + i);
                                    Field cField = example.getDeclaredField("cValue" + i);

                                    aField.setAccessible(true);
                                    aField.set(adHarmonicResult, a.get(i - 1));
                                    bField.setAccessible(true);
                                    bField.set(adHarmonicResult, b.get(i - 1));
                                    cField.setAccessible(true);
                                    cField.set(adHarmonicResult, c.get(i - 1));
                                } catch (NoSuchFieldException | IllegalAccessException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            for (int i = 2; i <= a.size() + 1; i++) {
                                try {
                                    Field aField = example.getDeclaredField("aValue" + i);
                                    Field bField = example.getDeclaredField("bValue" + i);
                                    Field cField = example.getDeclaredField("cValue" + i);

                                    aField.setAccessible(true);
                                    aField.set(adHarmonicResult, a.get(i - 2));
                                    bField.setAccessible(true);
                                    bField.set(adHarmonicResult, b.get(i - 2));
                                    cField.setAccessible(true);
                                    cField.set(adHarmonicResult, c.get(i - 2));
                                } catch (NoSuchFieldException | IllegalAccessException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                        adHarmonicResultList.add(adHarmonicResult);
                    }
                }
            }
        }

        if (CollUtil.isNotEmpty(simAndDigNonHarmonicResultList)) {
            Map<String, List<SimAndDigNonHarmonicResult>> map = simAndDigNonHarmonicResultList.stream().collect(Collectors.groupingBy(x -> x.getDevMonitorId() + x.getTimeId() + x.getScriptId() + x.getSort() + x.getAdType() + x.getDataType()));
            List<SimAndDigNonHarmonicResult> info = new ArrayList<>();
            map.forEach((key, value) -> {
                if (value.size() > 1) {
                    System.err.println("重复时间戳->" + key + value);
                } else {
                    info.addAll(value);
                }
            });

            detectionDataDealService.acceptNonHarmonic(info, param.getCode());
        }
        if (CollUtil.isNotEmpty(adHarmonicResultList)) {
            Map<String, List<SimAndDigHarmonicResult>> map = adHarmonicResultList.stream().collect(Collectors.groupingBy(x -> x.getDevMonitorId() + x.getTimeId() + x.getScriptId() + x.getSort() + x.getAdType() + x.getDataType()));
            List<SimAndDigHarmonicResult> info = new ArrayList<>();
            map.forEach((key, value) -> {
                if (value.size() > 1) {
                    System.err.println("重复时间戳->" + key + value);
                } else {
                    info.addAll(value);
                }
            });
            detectionDataDealService.acceptHarmonic(info, param.getCode());
        }
        System.out.println("原始数据插入数据库执行成功=========================================");
        //  };
        //  executorPool.submit(runnable);
    }


    /**
     * 向前端推送消息
     *
     * @param userId       前端用户信息
     * @param requestId
     * @param operatorType
     * @param devParameter
     */
    private void sendWebSocket(String userId, String requestId, String operatorType, CoefficientVO.DevParameter devParameter) {
        WebSocketVO<CoefficientVO.DevParameter> webSocketVO = new WebSocketVO<>();
        webSocketVO.setRequestId(requestId);
        webSocketVO.setOperateCode(operatorType);
        webSocketVO.setData(devParameter);
        WebServiceManager.sendMsg(userId, JSON.toJSONString(webSocketVO));
    }

    public void backCheckState(PreDetectionParam param) {
//        if (CollUtil.isNotEmpty(param.getDevIds()) && StrUtil.isNotBlank(param.getPlanId()) && "1".equals(param.getOperateType())) {
        if (CollUtil.isNotEmpty(param.getDevIds()) && StrUtil.isNotBlank(param.getPlanId())) {
            adPlanService.updateBackTestState(param.getPlanId(), param.getDevIds());
        }
    }

}
