package com.njcn.gather.detection.service.impl;


import cn.hutool.core.bean.BeanUtil;
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.github.yulichang.wrapper.MPJLambdaWrapper;
import com.njcn.gather.detection.pojo.enums.DetectionCodeEnum;
import com.njcn.gather.detection.pojo.enums.ResultEnum;
import com.njcn.gather.detection.pojo.param.PreDetectionParam;
import com.njcn.gather.detection.pojo.po.DevData;
import com.njcn.gather.detection.pojo.vo.DetectionData;
import com.njcn.gather.detection.pojo.vo.DevLineTestResult;
import com.njcn.gather.detection.util.DetectionUtil;
import com.njcn.gather.detection.util.socket.CnSocketUtil;
import com.njcn.gather.detection.util.socket.FormalTestManager;
import com.njcn.gather.device.pojo.vo.PreDetection;
import com.njcn.gather.device.service.IPqDevService;
import com.njcn.gather.device.service.IPqStandardDevGainRecordService;
import com.njcn.gather.err.pojo.param.PqErrSysParam;
import com.njcn.gather.err.pojo.po.PqErrSysDtls;
import com.njcn.gather.err.pojo.vo.ErrDtlsCheckDataVO;
import com.njcn.gather.err.service.IPqErrSysDtlsService;
import com.njcn.gather.monitor.pojo.po.PqMonitor;
import com.njcn.gather.monitor.service.IPqMonitorService;
import com.njcn.gather.plan.pojo.enums.DataSourceEnum;
import com.njcn.gather.report.pojo.enums.PowerIndexEnum;
import com.njcn.gather.script.mapper.PqScriptMapper;
import com.njcn.gather.script.pojo.po.PqScriptCheckData;
import com.njcn.gather.script.pojo.po.SourceIssue;
import com.njcn.gather.script.service.IPqScriptCheckDataService;
import com.njcn.gather.storage.pojo.po.*;
import com.njcn.gather.storage.service.DetectionDataDealService;
import com.njcn.gather.system.cfg.pojo.po.SysTestConfig;
import com.njcn.gather.system.cfg.service.ISysTestConfigService;
import com.njcn.gather.system.dictionary.pojo.enums.DictDataEnum;
import com.njcn.gather.util.StorageUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * @author wr
 * @description
 * @date 2024/12/20 13:52
 */
@Log4j
@Service
@RequiredArgsConstructor
public class DetectionServiceImpl {

    private final IPqErrSysDtlsService pqErrSysDtlsService;
    private final IPqScriptCheckDataService pqScriptCheckDataService;
    private final DetectionDataDealService detectionDataDealService;
    private final ISysTestConfigService sysTestConfigService;
    private final IPqMonitorService pqMonitorService;
    private final IPqDevService pqDevService;
    private final IPqStandardDevGainRecordService pqStandardDevGainRecordService;
    private final PqScriptMapper pqScriptMapper;

    public static final String TYPE_A = "A";
    public static final String TYPE_B = "B";
    public static final String TYPE_C = "C";
    public static final String TYPE_T = "T";
    private final String U = "U";
    private final String I = "I";
    private final String HP = "HP";
    private final String P = "P";
    private final String MAG = "MAG";
    private final String DUR = "DUR";

    private static final Integer INHARMONIC_FLAG = 1;
    private static final Integer HARMONIC_FLAG = 2;

//    @Value("${error.removeCount:14}")
//    private Integer removeErrorValueCount;

    @Data
    @AllArgsConstructor
    public static class VAndIResult {
        private String ip;
        private Integer chnNum;
        private Boolean va;
        private Boolean vb;
        private Boolean vc;
        private Boolean ia;
        private Boolean ib;
        private Boolean ic;
        private Double vaXi;
        private Double vbXi;
        private Double vcXi;
        private Double iaXi;
        private Double ibXi;
        private Double icXi;
        // 皮尔逊相关系数
        private BigDecimal pearsonCorrelationCoefficientVa;
        private BigDecimal pearsonCorrelationCoefficientVb;
        private BigDecimal pearsonCorrelationCoefficientVc;
        private BigDecimal pearsonCorrelationCoefficientIa;
        private BigDecimal pearsonCorrelationCoefficientIb;
        private BigDecimal pearsonCorrelationCoefficientIc;
        // 比值一致性 CV 系数
        private BigDecimal cVCoefficientVa;
        private BigDecimal cVCoefficientVb;
        private BigDecimal cVCoefficientVc;
        private BigDecimal cVCoefficientIa;
        private BigDecimal cVCoefficientIb;
        private BigDecimal cVCoefficientIc;
    }

    public static Map<String, VAndIResult> vAndIResultMap = null;


    /**
     * 开始处理指标类型
     * 一共20组数据，开始处理格式
     * 返回值：key为设备id_通道号，value为检测结果
     */
    public Map<String, Integer> processing(List<DevData> dev, PreDetectionParam detection, Map<String, String> devIdMapComm, SourceIssue issue, DictDataEnum dataRule) {
        Map<String, List<DevData>> devDataMap = dev.stream().collect(Collectors.groupingBy(DevData::getId));
        Map<String, Integer> stringBooleanMap = new LinkedHashMap<>();
        devDataMap.forEach(((key, value) -> {
            stringBooleanMap.put(key, DetectionIndexProcessing(value, detection.getCode(), detection.getErrorSysId(), devIdMapComm, dataRule, issue));
        }));
        return stringBooleanMap;
    }

    /**
     * 取值的方法
     * 1.根据源参数下发，获得所检测项目的误差体系
     * 2.根据数据处理原则，先将原始20组数据进行处理，是任意，还是部分
     * 3.根据误差体系筛选出，在范围内的数据，然后根据最大误差值是不是在合理范围内
     *
     * @param dev         原始数据
     * @param sourceIssue 源下发的参数
     * @return
     */
    public Integer DetectionIndexProcessing(List<DevData> dev, String code, String errorSysId, Map<String, String> devIdMapComm, DictDataEnum dataRule, SourceIssue sourceIssue) {
        PqErrSysParam.DetectionParam param = new PqErrSysParam.DetectionParam();
        param.setIndex(sourceIssue.getIndex());
        param.setScriptId(sourceIssue.getScriptId());
        param.setErrorSysId(errorSysId);
        param.setUn(sourceIssue.getFUn());
        param.setIn(sourceIssue.getFIn());
        SysTestConfig oneConfig = sysTestConfigService.getOneConfig();
        List<ErrDtlsCheckDataVO> errDtlsCheckData = pqErrSysDtlsService.listByPqErrSysIdAndTypes(param);
        PowerIndexEnum powerIndexEnum = PowerIndexEnum.getByKey(sourceIssue.getType());
        if (StrUtil.isNotBlank(sourceIssue.getOtherType())) {
            powerIndexEnum = PowerIndexEnum.getByKey(sourceIssue.getOtherType());
        }

        switch (powerIndexEnum) {
            /**
             * 频率
             */
            case FREQ:
                return isQualified(dev, devIdMapComm, errDtlsCheckData, PowerIndexEnum.FREQ.getKey(), sourceIssue, dataRule, code, oneConfig.getScale());
            case P:
                return isQualified(dev, devIdMapComm, errDtlsCheckData, PowerIndexEnum.P.getKey(), sourceIssue, dataRule, code, oneConfig.getScale());
            case ANGLE:
                return isQualified(dev, devIdMapComm, errDtlsCheckData, PowerIndexEnum.ANGLE.getKey(), sourceIssue, dataRule, code, oneConfig.getScale());
            /**
             * 电压
             */
            case V:
                return isQualified(dev, devIdMapComm, errDtlsCheckData, PowerIndexEnum.V.getKey(), sourceIssue, dataRule, code, oneConfig.getScale());
            /**
             * 电流
             */
            case I:
                return isQualified(dev, devIdMapComm, errDtlsCheckData, PowerIndexEnum.I.getKey(), sourceIssue, dataRule, code, oneConfig.getScale());
            /**
             * 谐波
             */
            case HV:
            case HI:
                SimAndDigHarmonicResult harmV = isHarmQualified(dev, devIdMapComm, errDtlsCheckData, U, sourceIssue, dataRule, HARMONIC_FLAG, oneConfig.getScale());
                SimAndDigHarmonicResult harmI = isHarmQualified(dev, devIdMapComm, errDtlsCheckData, I, sourceIssue, dataRule, HARMONIC_FLAG, oneConfig.getScale());
                return resultFlag(harmV, harmI, code);
            /**
             * 间谐波
             */
            case HSV:
            case HSI:
                SimAndDigHarmonicResult harmInV = isHarmQualified(dev, devIdMapComm, errDtlsCheckData, U, sourceIssue, dataRule, INHARMONIC_FLAG, oneConfig.getScale());
                SimAndDigHarmonicResult harmInI = isHarmQualified(dev, devIdMapComm, errDtlsCheckData, I, sourceIssue, dataRule, INHARMONIC_FLAG, oneConfig.getScale());
                return resultFlag(harmInV, harmInI, code);
            /**
             * 三相电压不平衡度
             */
            case IMBV:
                return isUnBalanceOrFlickerQualified(dev, devIdMapComm, errDtlsCheckData, U, sourceIssue, dataRule, code, oneConfig.getScale());
            /**
             * 三相电流不平衡度
             */
            case IMBA:
                return isUnBalanceOrFlickerQualified(dev, devIdMapComm, errDtlsCheckData, I, sourceIssue, dataRule, code, oneConfig.getScale());
            /**
             * 谐波有功功率
             */
            case HP:
                SimAndDigHarmonicResult harmP = isHarmQualified(dev, devIdMapComm, errDtlsCheckData, HP, sourceIssue, dataRule, 2, oneConfig.getScale());
                if (ObjectUtil.isNotNull(harmP)) {
                    detectionDataDealService.acceptHarmonicResult(Arrays.asList(harmP), code);
                    return harmP.getResultFlag();
                }
                return 4;
            /**
             * 闪变
             */
            case F:
            case LF:
                return isUnBalanceOrFlickerQualified(dev, devIdMapComm, errDtlsCheckData, DetectionCodeEnum.PST.getCode(), sourceIssue, dataRule, code, oneConfig.getScale());
            /**
             * 暂态
             */
            case VOLTAGE:
                return isVoltageQualified(dev, devIdMapComm, errDtlsCheckData, sourceIssue, dataRule, code, oneConfig.getScale());
            default:
                return isUnknownQualified(dev, devIdMapComm, errDtlsCheckData, sourceIssue, dataRule, code, oneConfig.getScale());
        }
    }

    public <T extends BaseResult> Integer resultFlag(T v, T i, String code) {
        List<T> info = new ArrayList<>();
        if (ObjectUtil.isNotNull(v)) {
            info.add(v);
        }
        if (ObjectUtil.isNotNull(i)) {
            info.add(i);
        }
        if (CollUtil.isNotEmpty(info)) {
            detectionDataDealService.acceptHarmonicResult(info, code);
            return StorageUtil.getInteger(info.stream().map(x -> x.getResultFlag()).distinct().collect(Collectors.toList()));
        }
        return 4;
    }

    public Integer isUnknownQualified(List<DevData> dev,
                                      Map<String, String> devIdMapComm,
                                      List<ErrDtlsCheckDataVO> errDtlsCheckData,
                                      SourceIssue sourceIssue,
                                      DictDataEnum dataRule,
                                      String code, Integer scale) {
        List<SimAndDigNonHarmonicResult> info = new ArrayList<>();
        List<SimAndDigHarmonicResult> harmonicResultList = new ArrayList<>();
        List<String> devValueTypeList = sourceIssue.getDevValueTypeList();
        //非谐波指标
        List<String> harmDesc = dev.stream().flatMap(x -> x.getSqlData().stream()).map(DevData.SqlDataDTO::getDesc).distinct().collect(Collectors.toList());
        //谐波类型
        List<String> inHarm = dev.stream().flatMap(x -> x.getSqlDataHarm().stream()).map(DevData.SqlDataHarmDTO::getDesc).distinct().collect(Collectors.toList());
        for (String s : devValueTypeList) {
            String devIndex = s.split("\\$")[1];
            if (harmDesc.contains(devIndex)) {
                //基本数据(频率，电压，电流)
                Map<String, List<Double>> map = devListMap(dev, dataRule, devIndex);
                SimAndDigNonHarmonicResult result = new SimAndDigNonHarmonicResult();
                String[] split = dev.get(0).getId().split("_");
                String devID = devIdMapComm.get(split[0]);
                result.setDevMonitorId(devID + "_" + split[1]);
                result.setScriptId(sourceIssue.getScriptId());
                result.setSort(sourceIssue.getIndex());
                result.setDataType(sourceIssue.getDataType());
                Integer isQualified;
                List<ErrDtlsCheckDataVO> dtlsCheckData = errDtlsCheckData.stream().filter(x -> x.getValueTypeCode().equals(s.split("\\$")[1])).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(dtlsCheckData)) {
                    result.setAdType(dtlsCheckData.get(0).getValueType());
                    isQualified = dtlsCheckData.get(0).getIsQualified();
                } else {
                    isQualified = 4;
                }
                List<DetectionData> resultFlag = new ArrayList<>();
                map.forEach((key, value) -> {
                    List<ErrDtlsCheckDataVO> checkData = dtlsCheckData.stream().filter(x -> key.equals(x.getPhase())).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(checkData)) {
                        DetectionData detectionData;
                        if (DUR.equals(devIndex)) {
                            detectionData = rangeDURComparisonList(value, isQualified, new ArrayList<>(), sourceIssue.getFFreq(), checkData.get(0).getValue(), dataRule, scale);
                        } else {
                            detectionData = rangeComparisonList(value, isQualified, new ArrayList<>(), null, checkData.get(0).getValue(), dataRule, scale);
                        }
                        if (key.equals(TYPE_T)) {
                            result.setTValue(JSON.toJSONString(detectionData));
                        }
                        if (key.equals(TYPE_A)) {
                            result.setAValue(JSON.toJSONString(detectionData));
                        }
                        if (key.equals(TYPE_B)) {
                            result.setBValue(JSON.toJSONString(detectionData));
                        }
                        if (key.equals(TYPE_C)) {
                            result.setCValue(JSON.toJSONString(detectionData));
                        }
                        resultFlag.add(detectionData);
                    }
                });
                result.setResultFlag(setResultFlag(resultFlag));
                info.add(result);
            }

            if (inHarm.contains(devIndex)) {
                String fundCode = "";
                String harmCode = "";
                Integer num = 1;
                String type = "";
                Double fData = 1.0;
                if (devIndex.contains("V")) {
                    fundCode = DetectionCodeEnum.U1.getCode();
                    num = 2;
                    type = U;
                    fData = sourceIssue.getFUn();
                    if (devIndex.contains("50")) {
                        harmCode = DetectionCodeEnum.V2_50.getCode();
                    }
                    if (devIndex.contains("49")) {
                        harmCode = DetectionCodeEnum.SV_1_49.getCode();
                    }
                }
                if (devIndex.contains("I")) {
                    fundCode = DetectionCodeEnum.I1.getCode();
                    type = I;
                    fData = sourceIssue.getFIn();
                    if (devIndex.contains("50")) {
                        harmCode = DetectionCodeEnum.I2_50.getCode();
                    }
                    if (devIndex.contains("49")) {
                        harmCode = DetectionCodeEnum.SI_1_49.getCode();
                    }
                }
                if (devIndex.contains("HP")) {
                    type = HP;
                    harmCode = DetectionCodeEnum.P2_50.getCode();
                    fData = (sourceIssue.getFIn() * sourceIssue.getFUn()) * 0.01;
                }
                Map<String, Map<Double, List<Double>>> devHarmMap = devHarmListMap(dev, sourceIssue, dataRule, fundCode, harmCode, num);
                if (CollUtil.isNotEmpty(devHarmMap)) {
                    SimAndDigHarmonicResult harmonicResult = new SimAndDigHarmonicResult();
                    String[] split = dev.get(0).getId().split("_");
                    String devID = devIdMapComm.get(split[0]);
                    harmonicResult.setDevMonitorId(devID + "_" + split[1]);
                    harmonicResult.setScriptId(sourceIssue.getScriptId());
                    harmonicResult.setSort(sourceIssue.getIndex());
                    Integer isQualified;
                    String valueTypeCode;
                    List<ErrDtlsCheckDataVO> dtlsCheckData = errDtlsCheckData.stream().filter(x -> x.getValueTypeCode().equals(s.split("\\$")[1])).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(dtlsCheckData)) {
                        harmonicResult.setAdType(dtlsCheckData.get(0).getValueType());
                        isQualified = dtlsCheckData.get(0).getIsQualified();
                    } else {
                        isQualified = 4;
                    }
                    //电压下百分比给百分比直接算 电流是是下百分比给的是幅值要转换算
                    List<DetectionData> integerBooleanA = harmRangeComparison(isQualified, new ArrayList<>(), type, TYPE_A, sourceIssue, dataRule, devHarmMap.get(TYPE_A), fData, num, scale);
                    List<DetectionData> integerBooleanB = harmRangeComparison(isQualified, new ArrayList<>(), type, TYPE_B, sourceIssue, dataRule, devHarmMap.get(TYPE_B), fData, num, scale);
                    List<DetectionData> integerBooleanC = harmRangeComparison(isQualified, new ArrayList<>(), type, TYPE_C, sourceIssue, dataRule, devHarmMap.get(TYPE_C), fData, num, scale);
                    harmonicResult.setDataType(sourceIssue.getDataType());
                    reflectHarmonic(false, "a", integerBooleanA, harmonicResult, num);
                    reflectHarmonic(false, "b", integerBooleanB, harmonicResult, num);
                    reflectHarmonic(false, "c", integerBooleanC, harmonicResult, num);
                    List<DetectionData> list = new ArrayList<>();
                    list.addAll(integerBooleanA.stream().distinct().collect(Collectors.toList()));
                    list.addAll(integerBooleanB.stream().distinct().collect(Collectors.toList()));
                    list.addAll(integerBooleanC.stream().distinct().collect(Collectors.toList()));
                    harmonicResult.setResultFlag(setResultFlag(list));
                    harmonicResultList.add(harmonicResult);
                }
            }

        }

        if (CollUtil.isNotEmpty(info)) {
            detectionDataDealService.acceptNonHarmonicResult(info, code);
        }
        if (CollUtil.isNotEmpty(harmonicResultList)) {
            detectionDataDealService.acceptHarmonicResult(harmonicResultList, code);
        }
        return 4;
    }

    /**
     * 判断值是否在误差范围内，有则进行判断否则则不进行计算（非谐波类型）
     *
     * @param dev              处理过后的数据
     * @param devIdMapComm     设备id映射表 key为设备ip，value为设备id
     * @param errDtlsCheckData 误差体系
     * @param type             (电压或者电流或者频率或者功率)
     * @param sourceIssue      源下发所对应的参数
     * @param dataRule         数据处理原则
     * @param code             源下发的装置通道code(->desc)
     * @return
     */
    public Integer isQualified(List<DevData> dev,
                               Map<String, String> devIdMapComm,
                               List<ErrDtlsCheckDataVO> errDtlsCheckData,
                               String type,
                               SourceIssue sourceIssue,
                               DictDataEnum dataRule,
                               String code, Integer scale) {
        List<SimAndDigNonHarmonicResult> info = new ArrayList<>();
        List<String> devValueTypeList = sourceIssue.getDevValueTypeList();
        for (String s : devValueTypeList) {
            String[] splitArr = s.split("\\$");
            // 根据数据处理规则取值。key为相别，value为值列表
            Map<String, List<Double>> map = devListMap(dev, dataRule, splitArr[1]);
            List<ErrDtlsCheckDataVO> dtlsCheckData = null;
            if (CollUtil.isNotEmpty(errDtlsCheckData)) {
                dtlsCheckData = errDtlsCheckData.stream().filter(x -> x.getValueTypeCode().equals(splitArr[1])).collect(Collectors.toList());
            }
            Double fData = 1.0;
            if (PowerIndexEnum.V.getKey().equals(type)) {
                fData = sourceIssue.getFUn();
            }
            if (PowerIndexEnum.I.getKey().equals(type)) {
                fData = sourceIssue.getFIn();
            }
            if (PowerIndexEnum.FREQ.getKey().equals(type)) {
                fData = sourceIssue.getFFreq();
            }
            if (PowerIndexEnum.P.getKey().equals(type)) {
                if (!DetectionCodeEnum.PF.getCode().equals(splitArr[1]) && !DetectionCodeEnum.TOTPF.getCode().equals(splitArr[1])) {
                    Boolean valueType = pqScriptMapper.selectScriptIsValueType(sourceIssue.getScriptId());
                    if (valueType) {
                        fData = sourceIssue.getFUn() * sourceIssue.getFIn() / 100;
                    }
                    Double finalFData = fData;
                    dtlsCheckData.stream().forEach(x -> x.setValue(x.getValue() * finalFData));
                }
            }
//            if (ResultUnitEnum.ANGLE.getCode().equals(type)) {
//                fData = null;
//            }
            SimAndDigNonHarmonicResult result = new SimAndDigNonHarmonicResult();
            String[] split = dev.get(0).getId().split("_");
            String devID = devIdMapComm.get(split[0]);
            result.setDevMonitorId(devID + "_" + split[1]);
            result.setScriptId(sourceIssue.getScriptId());
            result.setSort(sourceIssue.getIndex());
            result.setDataType(sourceIssue.getDataType());
            List<PqErrSysDtls> pqErrSysDtls = new ArrayList<>();
            Integer isQualified = 4;
            if (CollUtil.isNotEmpty(dtlsCheckData)) {
                result.setAdType(dtlsCheckData.get(0).getValueType());
                isQualified = dtlsCheckData.get(0).getIsQualified();
                if (CollUtil.isNotEmpty(dtlsCheckData.get(0).getErrSysDtls())) {
                    pqErrSysDtls = dtlsCheckData.get(0).getErrSysDtls();
                }
            }
            result.setResultFlag(isQualified);
            if (map.containsKey(TYPE_T)) {
                List<ErrDtlsCheckDataVO> checkDataT = dtlsCheckData.stream().filter(x -> TYPE_T.equals(x.getPhase())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(checkDataT)) {
                    DetectionData t = rangeComparisonList(map.get(TYPE_T), isQualified, pqErrSysDtls, fData, checkDataT.get(0).getValue(), dataRule, scale);
                    result.setTValue(JSON.toJSONString(t));
                    result.setResultFlag(t.getIsData());
                }
            } else {
                List<DetectionData> resultFlag = new ArrayList<>();
                Map<String, BiConsumer<SimAndDigNonHarmonicResult, DetectionData>> setters = new HashMap<>();
                setters.put(TYPE_A, (r, d) -> r.setAValue(JSON.toJSONString(d)));
                setters.put(TYPE_B, (r, d) -> r.setBValue(JSON.toJSONString(d)));
                setters.put(TYPE_C, (r, d) -> r.setCValue(JSON.toJSONString(d)));

                List<String> phases = Arrays.asList(TYPE_A, TYPE_B, TYPE_C);
                for (String phase : phases) {
                    List<ErrDtlsCheckDataVO> checkData = dtlsCheckData.stream()
                            .filter(x -> phase.equals(x.getPhase()))
                            .collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(checkData)) {
                        List<Double> phaseValue = map.get(phase);
                        if (PowerIndexEnum.ANGLE.getKey().equals(type)) {
                            phaseValue = phaseValue.stream().map(x -> {
                                // 原始误差值
                                double originDiff = x - checkData.get(0).getValue();
                                // 转换误差值
                                double translateDiff = Math.abs(originDiff) - 360;
                                if (Math.abs(translateDiff) <= 10) {
                                    return Math.abs(x);
                                } else {
                                    return x;
                                }
                            }).collect(Collectors.toList());
                        }
                        // 注意：如果map中不存在该phase的键，phaseValue可能为null，需确保map包含该键
                        DetectionData detectionData = rangeComparisonList(phaseValue, isQualified, pqErrSysDtls, fData, checkData.get(0).getValue(), dataRule, scale);
                        resultFlag.add(detectionData);
                        BiConsumer<SimAndDigNonHarmonicResult, DetectionData> setter = setters.get(phase);
                        if (setter != null) {
                            setter.accept(result, detectionData);
                        } else {
                            // 处理未定义的setter的情况
                            throw new IllegalArgumentException("Setter not defined for phase: " + phase);
                        }
                    }
                }
                result.setResultFlag(setResultFlag(resultFlag));
            }
            info.add(result);
        }
        if (CollUtil.isNotEmpty(info)) {
            detectionDataDealService.acceptNonHarmonicResult(info, code);
            List<Integer> resultFlag = info.stream().map(SimAndDigNonHarmonicResult::getResultFlag).distinct().collect(Collectors.toList());
            return StorageUtil.getInteger(resultFlag);
        }
        return 4;
    }

    /**
     * 判断值是否在误差范围内，有则进行判断否则则不进行计算（谐波类型）
     *
     * @param dev              处理过后的数据
     * @param errDtlsCheckData 误差体系
     * @param type             (电压还是电流)
     * @param sourceIssue      源下发所对应的参数
     * @param dataRule         数据处理原则
     * @param num              区分谐波还是间谐波 1：间谐波，2：谐波
     * @return
     */
    public SimAndDigHarmonicResult isHarmQualified(List<DevData> dev,
                                                   Map<String, String> devIdMapComm,
                                                   List<ErrDtlsCheckDataVO> errDtlsCheckData,
                                                   String type,
                                                   SourceIssue sourceIssue,
                                                   DictDataEnum dataRule,
                                                   Integer num, Integer scale) {
        Double fDataA = 1.0;
        Double fDataB = 1.0;
        Double fDataC = 1.0;
        String fundCode = "";
        String harmCode = "";
        if (U.equals(type)) {
            fDataA = sourceIssue.getChannelList().stream().filter(x -> x.getChannelType().contains("Ua")).findFirst().get().getFAmp();
            fDataB = sourceIssue.getChannelList().stream().filter(x -> x.getChannelType().contains("Ub")).findFirst().get().getFAmp();
            fDataC = sourceIssue.getChannelList().stream().filter(x -> x.getChannelType().contains("Uc")).findFirst().get().getFAmp();
            fundCode = DetectionCodeEnum.U1.getCode();
            if (num == 1) {
                harmCode = DetectionCodeEnum.SV_1_49.getCode();
            } else {
                harmCode = DetectionCodeEnum.V2_50.getCode();
            }
        }
        if (I.equals(type)) {
            fDataA = sourceIssue.getChannelList().stream().filter(x -> x.getChannelType().contains("Ia")).findFirst().get().getFAmp();
            fDataB = sourceIssue.getChannelList().stream().filter(x -> x.getChannelType().contains("Ib")).findFirst().get().getFAmp();
            fDataC = sourceIssue.getChannelList().stream().filter(x -> x.getChannelType().contains("Ic")).findFirst().get().getFAmp();
            fundCode = DetectionCodeEnum.I1.getCode();
            if (num == 1) {
                harmCode = DetectionCodeEnum.SI_1_49.getCode();
            } else {
                harmCode = DetectionCodeEnum.I2_50.getCode();
            }
        }
        if (HP.equals(type)) {
            fDataA = (sourceIssue.getFIn() * sourceIssue.getFUn()) * 0.01;
            fDataB = (sourceIssue.getFIn() * sourceIssue.getFUn()) * 0.01;
            fDataC = (sourceIssue.getFIn() * sourceIssue.getFUn()) * 0.01;
            harmCode = DetectionCodeEnum.P2_50.getCode();
        }
//        if (P.equals(type)) {
//            fData = (sourceIssue.getFIn() * sourceIssue.getFUn()) * 0.01;
//            harmCode = DetectionCodeEnum.P_FUND.getCode();
//        }
        Map<String, Map<Double, List<Double>>> devMap = devHarmListMap(dev, sourceIssue, dataRule, fundCode, harmCode, num);
        if (CollUtil.isNotEmpty(devMap)) {
            SimAndDigHarmonicResult harmonicResult = new SimAndDigHarmonicResult();
            String[] split = dev.get(0).getId().split("_");
            String devID = devIdMapComm.get(split[0]);
            harmonicResult.setDevMonitorId(devID + "_" + split[1]);
            harmonicResult.setScriptId(sourceIssue.getScriptId());
            harmonicResult.setSort(sourceIssue.getIndex());
            List<PqErrSysDtls> pqErrSysDtls = new ArrayList<>();
            Integer isQualified = 4;
            if (CollUtil.isNotEmpty(errDtlsCheckData)) {
                String finalHarmCode = harmCode;
                List<ErrDtlsCheckDataVO> adDtlsCheckData = errDtlsCheckData.stream().filter(x -> finalHarmCode.equals(x.getValueTypeCode())).collect(Collectors.toList());
                harmonicResult.setAdType(adDtlsCheckData.get(0).getValueType());
                isQualified = adDtlsCheckData.get(0).getIsQualified();
                if (CollUtil.isNotEmpty(adDtlsCheckData.get(0).getErrSysDtls())) {
                    pqErrSysDtls = adDtlsCheckData.get(0).getErrSysDtls();
                }
            }
            List<DetectionData> integerBooleanA = harmRangeComparison(isQualified, pqErrSysDtls, type, TYPE_A, sourceIssue, dataRule, devMap.get(TYPE_A), fDataA, num, scale);
            List<DetectionData> integerBooleanB = harmRangeComparison(isQualified, pqErrSysDtls, type, TYPE_B, sourceIssue, dataRule, devMap.get(TYPE_B), fDataB, num, scale);
            List<DetectionData> integerBooleanC = harmRangeComparison(isQualified, pqErrSysDtls, type, TYPE_C, sourceIssue, dataRule, devMap.get(TYPE_C), fDataC, num, scale);
            harmonicResult.setDataType(sourceIssue.getDataType());
            reflectHarmonic(false, "a", integerBooleanA, harmonicResult, num);
            reflectHarmonic(false, "b", integerBooleanB, harmonicResult, num);
            reflectHarmonic(false, "c", integerBooleanC, harmonicResult, num);
            List<DetectionData> list = new ArrayList<>();
            list.addAll(integerBooleanA.stream().filter(x -> 1 != x.getNum()).distinct().collect(Collectors.toList()));
            list.addAll(integerBooleanB.stream().filter(x -> 1 != x.getNum()).distinct().collect(Collectors.toList()));
            list.addAll(integerBooleanC.stream().filter(x -> 1 != x.getNum()).distinct().collect(Collectors.toList()));
            harmonicResult.setResultFlag(setResultFlag(list));
            return harmonicResult;
        }
        return null;
    }

    /**
     * 判断值是否在误差范围内，有则进行判断否则则不进行计算（三相不平衡和闪变）
     *
     * @param dev              处理过后的数据
     * @param errDtlsCheckData 误差体系
     * @param type             (电压还是电流)
     * @param sourceIssue      源下发所对应的参数
     * @param dataRule         数据处理原则
     * @return
     */
    public Integer isUnBalanceOrFlickerQualified(List<DevData> dev,
                                                 Map<String, String> devIdMapComm,
                                                 List<ErrDtlsCheckDataVO> errDtlsCheckData,
                                                 String type,
                                                 SourceIssue sourceIssue,
                                                 DictDataEnum dataRule,
                                                 String code, Integer scale) {
        List<SimAndDigNonHarmonicResult> info = new ArrayList<>();
        List<PqScriptCheckData> checkData = pqScriptCheckDataService.list(new MPJLambdaWrapper<PqScriptCheckData>()
                .eq(PqScriptCheckData::getScriptIndex, sourceIssue.getIndex())
                .eq(PqScriptCheckData::getScriptId, sourceIssue.getScriptId())
        );
        List<String> devValueTypeList = sourceIssue.getDevValueTypeList();
        for (String s : devValueTypeList) {
            String[] splitArr = s.split("\\$");
            Map<String, List<Double>> map = devListMap(dev, dataRule, splitArr[1]);
            if (CollUtil.isNotEmpty(map)) {
                List<ErrDtlsCheckDataVO> dtlsCheckData = null;
                if (CollUtil.isNotEmpty(errDtlsCheckData)) {
                    dtlsCheckData = errDtlsCheckData.stream().filter(x -> x.getValueTypeCode().equals(s.split("\\$")[1])).collect(Collectors.toList());
                }
                Double fData = 1.0;
                if (U.equals(type)) {
                    fData = sourceIssue.getFUn();
                }
                if (I.equals(type)) {
                    fData = sourceIssue.getFIn();
                }
                SimAndDigNonHarmonicResult result = new SimAndDigNonHarmonicResult();
                String[] split = dev.get(0).getId().split("_");
                String devID = devIdMapComm.get(split[0]);
                result.setDevMonitorId(devID + "_" + split[1]);
                result.setScriptId(sourceIssue.getScriptId());
                result.setSort(sourceIssue.getIndex());
                result.setDataType(sourceIssue.getDataType());
                List<PqErrSysDtls> pqErrSysDtls = new ArrayList<>();
                Integer isQualified = 4;
                if (CollUtil.isNotEmpty(dtlsCheckData)) {
                    result.setAdType(dtlsCheckData.get(0).getValueType());
                    isQualified = dtlsCheckData.get(0).getIsQualified();
                    if (CollUtil.isNotEmpty(dtlsCheckData.get(0).getErrSysDtls())) {
                        pqErrSysDtls = dtlsCheckData.get(0).getErrSysDtls();
                    }
                }
                result.setResultFlag(isQualified);
                // 闪变
                if (DetectionCodeEnum.PST.getCode().equals(splitArr[1]) || DetectionCodeEnum.PLT.getCode().equals(splitArr[1]) || DetectionCodeEnum.SeqV.getCode().equals(splitArr[1]) || DetectionCodeEnum.SeqA.getCode().equals(splitArr[1])) {

                    //取出源所对应的相别信息
                    List<PqScriptCheckData> channelTypeAList = checkData.stream()
                            .filter(x -> TYPE_A.equals(x.getPhase()))
                            .collect(Collectors.toList());
                    Double channelDataA = channelTypeAList.get(0).getValue();
                    if (DetectionCodeEnum.SeqV.getCode().equals(splitArr[1]) || DetectionCodeEnum.SeqA.getCode().equals(splitArr[1])) {
                        channelDataA = BigDecimal.valueOf(channelDataA / 100 * fData)
                                .setScale(scale, RoundingMode.HALF_UP)
                                .doubleValue();
                    }
                    DetectionData a = rangeComparisonList(map.get(TYPE_A), isQualified, pqErrSysDtls, fData, channelDataA, dataRule, scale);
                    result.setAValue(JSON.toJSONString(a));

                    List<PqScriptCheckData> channelTypeBList = checkData.stream()
                            .filter(x -> TYPE_B.equals(x.getPhase()))
                            .collect(Collectors.toList());
                    Double channelDataB = channelTypeBList.get(0).getValue();
                    if (DetectionCodeEnum.SeqV.getCode().equals(splitArr[1]) || DetectionCodeEnum.SeqA.getCode().equals(splitArr[1])) {
                        channelDataB = BigDecimal.valueOf(channelDataB / 100 * fData)
                                .setScale(scale, RoundingMode.HALF_UP)
                                .doubleValue();
                    }
                    DetectionData b = rangeComparisonList(map.get(TYPE_B), isQualified, pqErrSysDtls, fData, channelDataB, dataRule, scale);
                    result.setBValue(JSON.toJSONString(b));

                    List<PqScriptCheckData> channelTypeCList = checkData.stream()
                            .filter(x -> TYPE_C.equals(x.getPhase()))
                            .collect(Collectors.toList());
                    Double channelDataC = channelTypeCList.get(0).getValue();
                    if (DetectionCodeEnum.SeqV.getCode().equals(splitArr[1]) || DetectionCodeEnum.SeqA.getCode().equals(splitArr[1])) {
                        channelDataC = BigDecimal.valueOf(channelDataC / 100 * fData)
                                .setScale(scale, RoundingMode.HALF_UP)
                                .doubleValue();
                    }
                    DetectionData c = rangeComparisonList(map.get(TYPE_C), isQualified, pqErrSysDtls, fData, channelDataC, dataRule, scale);
                    result.setCValue(JSON.toJSONString(c));

                    result.setResultFlag(setResultFlag(Arrays.asList(a, b, c)));
                } else {
                    // 三项不平衡
                    List<PqScriptCheckData> channelTypeBList = checkData.stream()
                            .filter(x -> TYPE_T.equals(x.getPhase()))
                            .collect(Collectors.toList());
                    DetectionData t = rangeComparisonList(map.get(TYPE_B), isQualified, pqErrSysDtls, fData, channelTypeBList.get(0).getValue(), dataRule, scale);
                    result.setTValue(JSON.toJSONString(t));
                    result.setResultFlag(setResultFlag(Arrays.asList(t)));
                }
                info.add(result);
            }
        }
        if (CollUtil.isNotEmpty(info)) {
            detectionDataDealService.acceptNonHarmonicResult(info, code);
            List<Integer> resultFlag = info.stream().map(SimAndDigNonHarmonicResult::getResultFlag).distinct().collect(Collectors.toList());
            return StorageUtil.getInteger(resultFlag);
        }
        return 4;
    }


    /**
     * 判断值是否在误差范围内，有则进行判断否则则不进行计算（暂态）
     * <p>
     * （假如都符合，则选取最开始合格的，都不合格，取最开始不合格的）
     * 方案一 分项问题
     * 分别计算各个相别是否合格
     * 不合格电压幅值的层级最高
     * <p>
     * 方案二 不分项问题
     * 以电压幅值最低的作为比较相别
     *
     * @param dev              处理过后的数据
     * @param errDtlsCheckData 误差体系
     * @param sourceIssue      源下发所对应的参数
     * @param dataRule         数据处理原则
     * @param code             计划code
     * @return
     */
    public Integer isVoltageQualified(List<DevData> dev,
                                      Map<String, String> devIdMapComm,
                                      List<ErrDtlsCheckDataVO> errDtlsCheckData,
                                      SourceIssue sourceIssue,
                                      DictDataEnum dataRule,
                                      String code,
                                      Integer scale
    ) {
        //电压幅值处理数据
        Map<String, List<Double>> mag = devListMap(dev, dataRule, MAG);
        //暂降时间处理数据
        Map<String, List<Double>> dur = devListMap(dev, dataRule, DUR);
        //理论上根据检测脚本，能知道误差体系，可以知道多个误差体系
        //暂态电压下多少就是多少
        List<ErrDtlsCheckDataVO> magErrList = errDtlsCheckData.stream().filter(x -> MAG.equals(x.getValueTypeCode())).collect(Collectors.toList());
        List<ErrDtlsCheckDataVO> durErrList = errDtlsCheckData.stream().filter(x -> DUR.equals(x.getValueTypeCode())).collect(Collectors.toList());
        SimAndDigNonHarmonicResult magResult = voltageResult(dev.get(0).getId(), devIdMapComm, sourceIssue, dataRule, mag, magErrList, sourceIssue.getFUn(), MAG, scale);
        SimAndDigNonHarmonicResult durResult = voltageResult(dev.get(0).getId(), devIdMapComm, sourceIssue, dataRule, dur, durErrList, sourceIssue.getFFreq(), DUR, scale);
        if (CollUtil.isNotEmpty(mag.get(TYPE_B)) && CollUtil.isNotEmpty(mag.get(TYPE_C))) {
            conclusion(magResult, durResult);
        }
        detectionDataDealService.acceptNonHarmonicResult(Arrays.asList(magResult, durResult), code);
        List<Integer> numbers = Arrays.asList(magResult.getResultFlag(), durResult.getResultFlag()).stream().distinct().collect(Collectors.toList());
        return StorageUtil.getInteger(numbers);
    }

    /**
     * @param magResult 电压幅值结果
     * @param durResult 持续时间结果
     * @Description:
     * @Author: wr
     * @Date: 2025/4/9 18:54
     */
    private void conclusion(SimAndDigNonHarmonicResult magResult, SimAndDigNonHarmonicResult durResult) {
        if (magResult.getResultFlag() == 1) {
            if (durResult.getResultFlag() != 2) {
                setTValueBasedOnAValue(magResult, durResult);
            } else {
                setTValueBasedOnAValue(magResult, durResult, false);
            }
        } else if (magResult.getResultFlag() == 2) {
            setTValueBasedOnAValue(magResult, durResult, true);
        } else {
            setTValueBasedOnAValue(magResult, durResult);
        }
    }

    private void setTValueBasedOnAValue(SimAndDigNonHarmonicResult magResult, SimAndDigNonHarmonicResult durResult, Boolean isMag) {
        DetectionData a;
        DetectionData b;
        DetectionData c;
        if (isMag) {
            a = JSON.parseObject(magResult.getAValue(), DetectionData.class);
            b = JSON.parseObject(magResult.getBValue(), DetectionData.class);
            c = JSON.parseObject(magResult.getCValue(), DetectionData.class);
        } else {
            a = JSON.parseObject(durResult.getAValue(), DetectionData.class);
            b = JSON.parseObject(durResult.getBValue(), DetectionData.class);
            c = JSON.parseObject(durResult.getCValue(), DetectionData.class);
        }
        if (a.getIsData() == 2) {
            setTValueBasedOnAValue(magResult, durResult);
        } else if (b.getIsData() == 2) {
            setTValueBasedOnBValue(magResult, durResult);
        } else if (c.getIsData() == 2) {
            setTValueBasedOnCValue(magResult, durResult);
        }
    }

    /**
     * @param magResult 电压幅值结果
     * @param durResult 持续时间结果
     * @Description:
     * @Author: wr
     */
    private void setTValueBasedOnAValue(SimAndDigNonHarmonicResult magResult, SimAndDigNonHarmonicResult durResult) {
        magResult.setTValue(magResult.getAValue());
        durResult.setTValue(durResult.getAValue());
    }

    private void setTValueBasedOnBValue(SimAndDigNonHarmonicResult magResult, SimAndDigNonHarmonicResult durResult) {
        magResult.setTValue(magResult.getBValue());
        durResult.setTValue(durResult.getBValue());
    }

    private void setTValueBasedOnCValue(SimAndDigNonHarmonicResult magResult, SimAndDigNonHarmonicResult durResult) {
        magResult.setTValue(magResult.getCValue());
        durResult.setTValue(durResult.getCValue());
    }

    /**
     * @param devId            装置监测点id(ip_通道)
     * @param devIdMapComm     ip_通道,装置名称
     * @param sourceIssue      源下发信息
     * @param dataRule         数据处理原则
     * @param mag
     * @param errDtlsCheckData
     * @param fData
     * @Description:
     * @return: com.njcn.gather.storage.pojo.po.SimAndDigNonHarmonicResult
     * @Author: wr
     * @Date: 2024/12/30 14:54
     */
    private SimAndDigNonHarmonicResult voltageResult(String devId,
                                                     Map<String, String> devIdMapComm,
                                                     SourceIssue sourceIssue,
                                                     DictDataEnum dataRule,
                                                     Map<String, List<Double>> mag,
                                                     List<ErrDtlsCheckDataVO> errDtlsCheckData,
                                                     Double fData,
                                                     String dur,
                                                     Integer scale
    ) {
        SimAndDigNonHarmonicResult result = new SimAndDigNonHarmonicResult();
        String[] split = devId.split("_");
        String devID = devIdMapComm.get(split[0]);
        result.setDevMonitorId(devID + "_" + split[1]);
        result.setScriptId(sourceIssue.getScriptId());
        result.setSort(sourceIssue.getIndex());
        result.setDataType(sourceIssue.getDataType());
        List<PqErrSysDtls> magErrList = new ArrayList<>();
        Integer isQualified = 4;
        if (CollUtil.isNotEmpty(errDtlsCheckData)) {
            result.setAdType(errDtlsCheckData.get(0).getValueType());
            isQualified = errDtlsCheckData.get(0).getIsQualified();
            if (CollUtil.isNotEmpty(errDtlsCheckData.get(0).getErrSysDtls())) {
                magErrList = errDtlsCheckData.get(0).getErrSysDtls();
            }
        }
        List<SourceIssue.ChannelListDTO> channelTypeBList = sourceIssue.getChannelList().stream()
                .filter(x -> ("Ub").equals(x.getChannelType()))
                .collect(Collectors.toList());

        DetectionData b = setDetectionData(isQualified, dataRule, mag, fData, dur, magErrList, channelTypeBList, TYPE_B, scale);
        result.setBValue(JSON.toJSONString(b));

        List<SourceIssue.ChannelListDTO> channelTypeCList = sourceIssue.getChannelList().stream()
                .filter(x -> ("Uc").equals(x.getChannelType()))
                .collect(Collectors.toList());
        DetectionData c = setDetectionData(isQualified, dataRule, mag, fData, dur, magErrList, channelTypeCList, TYPE_C, scale);
        result.setCValue(JSON.toJSONString(c));

        if (CollUtil.isNotEmpty(mag.get(TYPE_B)) && CollUtil.isNotEmpty(mag.get(TYPE_C))) {
            //取出源所对应的相别信息
            List<SourceIssue.ChannelListDTO> channelTypeAList = sourceIssue.getChannelList().stream()
                    .filter(x -> ("Ua").equals(x.getChannelType()))
                    .collect(Collectors.toList());
            DetectionData a = setDetectionData(isQualified, dataRule, mag, fData, dur, magErrList, channelTypeAList, TYPE_A, scale);
            result.setAValue(JSON.toJSONString(a));
            result.setResultFlag(setResultFlag(Arrays.asList(a, b, c)));
        } else {
            List<SourceIssue.ChannelListDTO> channelTypeAList = sourceIssue.getChannelList().stream()
                    .filter(x -> x.getChannelType().contains("Ua"))
                    .sorted(Comparator.comparing(
                            x -> Optional.ofNullable(x.getDipData())
                                    .map(SourceIssue.ChannelListDTO.DipDataDTO::getFTransValue)
                                    .orElse(Double.NaN)
                    ))
                    .collect(Collectors.toList());
            DetectionData a = setDetectionData(isQualified, dataRule, mag, fData, dur, magErrList, channelTypeAList, TYPE_A, scale);
            if (CollUtil.isEmpty(mag.get(TYPE_A))) {
                a.setIsData(2);
            }
            result.setAValue(JSON.toJSONString(a));
            result.setTValue(JSON.toJSONString(a));
            result.setResultFlag(a.getIsData());
        }
        return result;
    }

    private DetectionData setDetectionData(Integer isQualified,
                                           DictDataEnum dataRule,
                                           Map<String, List<Double>> mag,
                                           Double fData,
                                           String dur,
                                           List<PqErrSysDtls> magErrList,
                                           List<SourceIssue.ChannelListDTO> channelTypeCList,
                                           String type, Integer scale) {
        DetectionData data;
        if (DUR.equals(dur)) {
            data = rangeDURComparisonList(mag.get(type), isQualified, magErrList, fData, channelTypeCList.get(0).getDipData().getRetainTime(), dataRule, scale);
        } else {
            data = rangeComparisonList(mag.get(type), isQualified, magErrList, fData, channelTypeCList.get(0).getDipData().getFTransValue(), dataRule, scale);
        }
        return data;
    }


    private Integer setResultFlag(List<DetectionData> numbers) {
        List<Integer> isData = numbers.stream().filter(x -> ObjectUtil.isNotNull(x.getData())).map(DetectionData::getIsData).distinct().collect(Collectors.toList());
        return StorageUtil.getInteger(isData);
    }


    /**
     * 处理非谐波类型取值
     *
     * @param dev
     * @param dataRule
     */
    public Map<String, List<Double>> devListMap(List<DevData> dev, DictDataEnum dataRule, String desc) {
        Map<String, List<Double>> map = new HashMap<>(3);

        List<DevData.SqlDataDTO> sqlDataDTOS = dev.stream().flatMap(x -> x.getSqlData().stream().filter(j -> desc.equals(j.getDesc())))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(sqlDataDTOS)) {
            List<DevData.SqlDataDTO.ListDTO> list = sqlDataDTOS.stream().map(DevData.SqlDataDTO::getList).collect(Collectors.toList());
            List<Double> a = list.stream()
                    .filter(x -> ObjectUtil.isNotNull(x.getA()))
                    .map(x -> x.getA().doubleValue())
                    .sorted(Comparator.comparing(Double::doubleValue).reversed())
                    .collect(Collectors.toList());
            List<Double> b = list.stream()
                    .filter(x -> ObjectUtil.isNotNull(x.getB()))
                    .map(x -> x.getB().doubleValue())
                    .sorted(Comparator.comparing(Double::doubleValue).reversed())
                    .collect(Collectors.toList());
            List<Double> c = list.stream()
                    .filter(x -> ObjectUtil.isNotNull(x.getC()))
                    .map(x -> x.getC().doubleValue())
                    .sorted(Comparator.comparing(Double::doubleValue).reversed())
                    .collect(Collectors.toList());
            List<Double> t = list.stream().filter(x -> ObjectUtil.isNotNull(x.getT()))
                    .map(x -> x.getT().doubleValue())
                    .sorted(Comparator.comparing(Double::doubleValue).reversed())
                    .collect(Collectors.toList());
            switch (dataRule) {
                case SECTION_VALUE:
                    a = DetectionUtil.getSectionValueDoubles(a);
                    b = DetectionUtil.getSectionValueDoubles(b);
                    c = DetectionUtil.getSectionValueDoubles(c);
                    t = DetectionUtil.getSectionValueDoubles(t);
                    break;
                case CP95_VALUE:
                    a = DetectionUtil.getCP95Doubles(a);
                    b = DetectionUtil.getCP95Doubles(b);
                    c = DetectionUtil.getCP95Doubles(c);
                    t = DetectionUtil.getCP95Doubles(t);
                    break;
                case AVG_VALUE:
                    a = DetectionUtil.getAvgDoubles(a);
                    b = DetectionUtil.getAvgDoubles(b);
                    c = DetectionUtil.getAvgDoubles(c);
                    t = DetectionUtil.getAvgDoubles(t);
                    break;
            }
            map.put(TYPE_A, a);
            map.put(TYPE_B, b);
            map.put(TYPE_C, c);
            if (CollUtil.isNotEmpty(t)) {
                map.put(TYPE_T, t);
            }
        }
        return map;
    }

    private <T extends BaseResult> void reflectHarmonic(boolean isContrast, String phase, List<DetectionData> integerBooleanA, T harmonicResult, Integer num) {
        if (!isContrast) {
            Map<Double, DetectionData> dataMap = integerBooleanA.stream().collect(Collectors.toMap(DetectionData::getNum, Function.identity()));
            dataMap.forEach((key, value) -> {
                try {
                    // 设置 id 字段;
                    Field idField = SimAndDigHarmonicResult.class.getDeclaredField(phase + "Value" + (num == 1 ? (int) (key + 0.5) : key.intValue()));
                    idField.setAccessible(true);
                    if (ObjectUtil.isNull(value.getIsData())) {
                        idField.set(harmonicResult, value.getData());
                    } else {
                        idField.set(harmonicResult, JSON.toJSONString(value));
                    }
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                } catch (NoSuchFieldException e) {
                    throw new RuntimeException(e);
                }
            });
        } else {
            Map<Double, List<DetectionData>> dataMap = integerBooleanA.stream().collect(Collectors.groupingBy(DetectionData::getNum));
            dataMap.forEach((key, valueList) -> {
                try {
                    // 设置 id 字段;
                    Field idField = ContrastHarmonicResult.class.getDeclaredField(phase + "Value" + (num == 1 ? (int) (key + 0.5) : key.intValue()));
                    idField.setAccessible(true);
                    idField.set(harmonicResult, JSON.toJSONString(valueList));
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                } catch (NoSuchFieldException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * @param pqErrSysDtls 误差体系
     * @param type         U,I
     * @param phase        A,B,C
     * @param sourceIssue  源下发的值（谐波）
     * @param dataRule     数据处理原则
     * @param devMap
     * @param fData        额定值
     * @param harmonicFlag 1：间谐波，2：谐波
     * @param scale        小数点位数
     * @return
     */
    public List<DetectionData> harmRangeComparison(Integer isQualified,
                                                   List<PqErrSysDtls> pqErrSysDtls,
                                                   String type,
                                                   String phase,
                                                   SourceIssue sourceIssue,
                                                   DictDataEnum dataRule,
                                                   Map<Double, List<Double>> devMap,
                                                   Double fData, Integer harmonicFlag, Integer scale) {
        List<DetectionData> info = new ArrayList<>();
        //根据谐波几次相值/额定值
        Map<Double, Double> issueHarmMap;
        if (HP.equals(type)) {
            List<PqScriptCheckData> checkData = pqScriptCheckDataService.list(new MPJLambdaWrapper<PqScriptCheckData>()
                    .eq(PqScriptCheckData::getScriptIndex, sourceIssue.getIndex())
                    .eq(PqScriptCheckData::getPhase, phase)
                    .eq(PqScriptCheckData::getScriptId, sourceIssue.getScriptId())
            );
            issueHarmMap = checkData.stream().collect(Collectors.toMap(PqScriptCheckData::getHarmNum, x -> x.getValue() * fData));
        } else {
            Double percent;
            if (I.equals(type)) {
                //电流是百分比转换成赋值算的
                percent = fData * 0.01;
            } else {
                //电压是百分比算的
                percent = 1.0;
            }
            if (1 == harmonicFlag) {
                issueHarmMap = sourceIssue.getChannelList().stream()
                        .filter(x -> (type + phase.toLowerCase()).equals(x.getChannelType()))
                        .flatMap(x -> x.getInharmList().stream())
                        .collect(Collectors.toMap(SourceIssue.ChannelListDTO.InharmModel::getInharm, x -> BigDecimal.valueOf(x.getFAmp()).multiply(BigDecimal.valueOf(percent)).doubleValue()));
            } else {
                issueHarmMap = sourceIssue.getChannelList().stream()
                        .filter(x -> (type + phase.toLowerCase()).equals(x.getChannelType()))
                        .flatMap(x -> x.getHarmList().stream())
                        .collect(Collectors.toMap(SourceIssue.ChannelListDTO.HarmModel::getHarm, x -> BigDecimal.valueOf(x.getFAmp()).multiply(BigDecimal.valueOf(percent)).doubleValue()));
            }
        }
        Map<Double, PqErrSysDtls> errSysDtlMap = new LinkedHashMap<>();
        issueHarmMap.forEach((key, value) -> {
            //获得误差体系
            List<PqErrSysDtls> errSysDtls = pqErrSysDtls.stream().filter(x -> rangeComparison(startRadiusEnd(x.getStartValue(), fData, value, x.getConditionType(), scale),
                    x.getStartFlag(),
                    startRadiusEnd(x.getEndValue(), fData, value, x.getConditionType(), scale),
                    x.getEndFlag(),
                    value)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(errSysDtls)) {
                errSysDtlMap.put(key, errSysDtls.get(0));
            } else {
                errSysDtlMap.put(key, null);
            }
        });
        if (CollUtil.isNotEmpty(devMap)) {
            devMap.forEach((harm, harmDataList) -> {
                PqErrSysDtls errSysDtl = errSysDtlMap.get(harm);
                DetectionData data = new DetectionData();
                data.setIsData(isQualified);
                data.setNum(harm);

                if (CollUtil.isNotEmpty(harmDataList)) {
                    BigDecimal bd = BigDecimal.valueOf(harmDataList.get(0));
                    bd = bd.setScale(scale, RoundingMode.HALF_UP);
                    data.setData(bd.doubleValue());
                }
                Double channelData = issueHarmMap.get(harm);
                data.setResultData(channelData);
                if (ObjectUtil.isNotNull(errSysDtl)) {
                    PqErrSysDtls errSys = BeanUtil.copyProperties(errSysDtl, PqErrSysDtls.class);
                    errSys.setMaxErrorValue(maxErrorMultiply(errSys, fData, issueHarmMap.get(harm), scale));
                    data.setUnit(errSysDtl.getErrorUnit());
                    data.setRadius(-errSys.getMaxErrorValue() + "~" + errSys.getMaxErrorValue());
                    setDetection(dataRule, harmDataList, errSys, data, channelData, fData, scale);
                }
                info.add(data);
            });
        }
        return info;
    }

    private void isData(DictDataEnum dataRule, List<Double> harmDataList, DetectionData data, List<Double> qualifiedList, Integer scale) {
        if (CollUtil.isNotEmpty(qualifiedList)) {
            BigDecimal bd = BigDecimal.valueOf(qualifiedList.get(0));
            bd = bd.setScale(scale, RoundingMode.HALF_UP);
            data.setData(bd.doubleValue());
            switch (dataRule) {
                case AT_WILL_VALUE:
                case CP95_VALUE:
                case AVG_VALUE:
                    if (qualifiedList.size() > 0) {
                        data.setIsData(1);
                    } else {
                        data.setIsData(2);
                    }
                    break;
                case SECTION_VALUE:
                case Own_value:
                    if (qualifiedList.size() == harmDataList.size()) {
                        data.setIsData(1);
                    } else {
                        List<Double> subtract = CollectionUtils.subtract(harmDataList, qualifiedList).stream().collect(Collectors.toList());
                        bd = BigDecimal.valueOf(subtract.get(0));
                        bd = bd.setScale(scale, RoundingMode.HALF_UP);
                        data.setData(bd.doubleValue());
                        data.setIsData(2);
                    }
                    break;
            }
        } else {
            data.setIsData(2);
        }
    }

    /**
     * @param dev         原始数据
     * @param sourceIssue 源下发参数
     * @param dataRule    数据处理原则
     * @param fundCode    装置下发基波code
     * @param harmCode    装置下发谐波信息
     * @param num         区分谐波还是间谐波 1：间谐波，2：谐波
     * @return
     */
    public Map<String, Map<Double, List<Double>>> devHarmListMap(List<DevData> dev,
                                                                 SourceIssue sourceIssue,
                                                                 DictDataEnum dataRule,
                                                                 String fundCode,
                                                                 String harmCode,
                                                                 Integer num) {
        Map<String, Map<Double, List<Double>>> map = new HashMap<>(3);
        List<Double> harmNum = new ArrayList<>();
        if (1 == num) {
            harmNum.addAll(sourceIssue.getChannelList().stream()
                    .flatMap(x -> x.getInharmList().stream().map(f -> f.getInharm()))
                    .sorted().distinct().collect(Collectors.toList()));
        } else {
            harmNum.add(1.0);
            harmNum.addAll(sourceIssue.getChannelList().stream()
                    .flatMap(x -> x.getHarmList().stream().map(f -> f.getHarm()))
                    .sorted().distinct().collect(Collectors.toList()));
        }
        for (DevData devData : dev) {
            List<DevData.SqlDataDTO> sqlDataDTOS = devData.getSqlData();
            Optional<DevData.SqlDataDTO> first = Optional.empty();
            if (CollUtil.isNotEmpty(sqlDataDTOS)) {
                first = sqlDataDTOS.stream().filter(x -> x.getDesc().equals(fundCode)).collect(Collectors.toList()).stream().findFirst();
            }
            DevData.SqlDataDTO fund = null;
            if (first.isPresent()) {
                fund = first.get();
            }
            List<DevData.SqlDataHarmDTO> harmList = devData.getSqlDataHarm().stream().filter(x -> x.getDesc().equals(harmCode)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(harmList)) {
                DevData.SqlDataHarmDTO harm = harmList.get(0);
                if (ObjectUtil.isNotNull(fund)) {
                    harmPut(TYPE_A, map, harmNum, harm, String.valueOf(fund.getList().getA()), num);
                    harmPut(TYPE_B, map, harmNum, harm, String.valueOf(fund.getList().getB()), num);
                    harmPut(TYPE_C, map, harmNum, harm, String.valueOf(fund.getList().getC()), num);
                } else {
                    harmPut(TYPE_A, map, harmNum, harm, "1.0", num);
                    harmPut(TYPE_B, map, harmNum, harm, "1.0", num);
                    harmPut(TYPE_C, map, harmNum, harm, "1.0", num);
                }
            }

        }
        map.forEach((typeKey, typeValue) -> {
            typeValue.remove(0.0);
            typeValue.forEach((key, value) -> {
                value.sort(Comparator.comparing(Double::doubleValue).reversed());
                if (CollUtil.isNotEmpty(value)) {
                    List<Double> newValue = new ArrayList<>();
                    switch (dataRule) {
                        case SECTION_VALUE:
                            newValue.addAll(DetectionUtil.getSectionValueDoubles(value));
                            break;
                        case CP95_VALUE:
                            newValue.addAll(DetectionUtil.getCP95Doubles(value));
                            break;
                        case AVG_VALUE:
                            newValue.addAll(DetectionUtil.getAvgDoubles(value));
                        case Own_value:
                        case AT_WILL_VALUE:
                            newValue.addAll(value);
                            break;
                    }
                    value.clear();
                    value.addAll(newValue);
                }
            });
        });
        return map;
    }

    /**
     * 处理数据是否合格
     *
     * @param list         原始的数据
     * @param pqErrSysDtls 误差体系
     * @param data         源下发的额定信息（额定电压，额定电流）
     * @param channelData  源下发的通道信息的值包括 {Ua, Ub, Uc, Ux, Ia, Ib, Ic, Ix ,NULL}
     * @param dataRule     数据处理原则
     * @returnd
     */
    public DetectionData rangeComparisonList(List<Double> list, Integer isQualified, List<PqErrSysDtls> pqErrSysDtls, Double data, Double channelData, DictDataEnum dataRule, Integer scale) {
        DetectionData detectionData = new DetectionData();
        detectionData.setIsData(isQualified);
        if (CollUtil.isNotEmpty(list)) {
            BigDecimal bd = BigDecimal.valueOf(list.get(0));
            bd = bd.setScale(scale, RoundingMode.HALF_UP);
            detectionData.setData(bd.doubleValue());
            detectionData.setResultData(channelData);
            //先根据源所下发的数据，是否在误差体系范围内在则可以进行误差体系判断
            //获得误差体系
            List<PqErrSysDtls> errSysDtls = pqErrSysDtls.stream().filter(x -> rangeComparison(startRadiusEnd(x.getStartValue(), data, channelData, x.getConditionType(), scale),
                    x.getStartFlag(),
                    startRadiusEnd(x.getEndValue(), data, channelData, x.getConditionType(), scale),
                    x.getEndFlag(),
                    channelData)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(errSysDtls)) {
                PqErrSysDtls errSysDtl = BeanUtil.copyProperties(errSysDtls.get(0), PqErrSysDtls.class);
                detectionData.setUnit(errSysDtl.getErrorUnit());
                errSysDtl.setMaxErrorValue(maxErrorMultiply(errSysDtl, data, channelData, scale));
                detectionData.setRadius(-errSysDtl.getMaxErrorValue() + "~" + errSysDtl.getMaxErrorValue());

                // 处理相对值-标准值为0的问题
                if (errSysDtl.getValueType() == 2 && errSysDtl.getErrorValueType() == 1 && channelData == 0) {
                    detectionData.setIsData(ResultEnum.NO_ERROR_SYS.getValue());
                } else {
                    setDetection(dataRule, list, errSysDtl, detectionData, channelData, data, scale);
                }
            }
        }
        return detectionData;
    }

    public DetectionData rangeDURComparisonList(List<Double> list, Integer isQualified, List<PqErrSysDtls> pqErrSysDtls, Double data, Double channelData, DictDataEnum dataRule, Integer scale) {
        DetectionData detectionData = new DetectionData();
        detectionData.setIsData(isQualified);
        if (CollUtil.isNotEmpty(list)) {
            BigDecimal bd = BigDecimal.valueOf(list.get(0));
            bd = bd.setScale(scale, RoundingMode.HALF_UP);
            detectionData.setData(bd.doubleValue());
            detectionData.setResultData(BigDecimal.valueOf(1.0 / data).doubleValue() * channelData);

            //先根据源所下发的数据，是否在误差体系范围内在则可以进行误差体系判断
            //获得误差体系
            List<PqErrSysDtls> errSysDtls = pqErrSysDtls.stream().filter(x -> rangeComparison(startRadiusEnd(x.getStartValue(), data, channelData, x.getConditionType(), scale),
                    x.getStartFlag(),
                    startRadiusEnd(x.getEndValue(), data, channelData, x.getConditionType(), scale),
                    x.getEndFlag(),
                    channelData)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(errSysDtls)) {
                PqErrSysDtls errSysDtl = BeanUtil.copyProperties(errSysDtls.get(0), PqErrSysDtls.class);
                NumberFormat nf = NumberFormat.getInstance();
                nf.setMaximumFractionDigits(6);
                nf.setGroupingUsed(false);
                detectionData.setUnit(errSysDtl.getErrorUnit());
                detectionData.setRadius(nf.format(BigDecimal.valueOf(-1.0 / data))
                        + "~" + nf.format(BigDecimal.valueOf(1.0 / data)));
                List<Double> qualifiedList = list.stream()
                        .filter(x -> NumberUtil.isIn(BigDecimal.valueOf(x.doubleValue()),
                                BigDecimal.valueOf(1.0 / data * (channelData - errSysDtl.getMaxErrorValue())),
                                BigDecimal.valueOf(1.0 / data * (channelData + errSysDtl.getMaxErrorValue())))
                        ).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(qualifiedList)) {
                    BigDecimal subtract = BigDecimal.valueOf(qualifiedList.get(0))
                            .subtract(BigDecimal.valueOf(1.0 / data * (channelData))).setScale(scale, RoundingMode.HALF_UP);
                    detectionData.setErrorData(subtract);
                } else {
                    BigDecimal subtract = BigDecimal.valueOf(list.get(0))
                            .subtract(BigDecimal.valueOf(1.0 / data * (channelData))).setScale(scale, RoundingMode.HALF_UP);
                    detectionData.setErrorData(subtract);
                }
                isData(dataRule, list, detectionData, qualifiedList, scale);
            }
        }
        return detectionData;
    }

    /**
     * 先判断在范围的数据，在进行误差体系的判断
     *
     * @param startValue 开始值
     * @param startFlag  是否包含
     * @param endValue   结束值
     * @param endFlag    是否包含
     * @param devData    装置上送值
     * @return
     */
    public Boolean rangeComparison(Double startValue, Integer startFlag, Double endValue, Integer endFlag, Double devData) {
        Boolean minBool = null;
        Boolean maxBool = null;
        if (ObjectUtil.isNotNull(startValue)) {
            if (1 == startFlag) {
                minBool = NumberUtil.isGreaterOrEqual(BigDecimal.valueOf(devData), BigDecimal.valueOf(startValue));
            } else {
                minBool = NumberUtil.isGreater(BigDecimal.valueOf(devData), BigDecimal.valueOf(startValue));
            }

        }
        if (ObjectUtil.isNotNull(endValue)) {
            if (1 == endFlag) {
                maxBool = NumberUtil.isLessOrEqual(BigDecimal.valueOf(devData), BigDecimal.valueOf(endValue));
            } else {
                maxBool = NumberUtil.isLess(BigDecimal.valueOf(devData), BigDecimal.valueOf(endValue));
            }
        }
        if (ObjectUtil.isNotNull(minBool) && ObjectUtil.isNotNull(maxBool)) {
            return minBool && maxBool;
        } else {
            if (ObjectUtil.isNotNull(minBool)) {
                return minBool;
            }
            if (ObjectUtil.isNotNull(maxBool)) {
                return maxBool;
            }
        }
        return true;
    }

    /**
     * 计算数据误差值(装置返回的值 - 源通道下发的值)
     *
     * @param devData     装置返回值
     * @param channelData 通道值
     * @param ratedValue  额定值
     * @param error
     * @param scale       小数点位数
     * @return
     */
    public BigDecimal devSubtractChannelData(Double devData, Double channelData, Double ratedValue, PqErrSysDtls error, Integer scale) {
        //计算装置值返回值 - 源下发值的数据 = 差值
//        BigDecimal subtract = BigDecimal.valueOf(devData).setScale(scale, RoundingMode.HALF_UP).subtract(BigDecimal.valueOf(channelData));
        BigDecimal subtract = BigDecimal.valueOf(devData).subtract(BigDecimal.valueOf(channelData));
//        if(ratedValue == 0 || channelData == 0){
//            return BigDecimal.valueOf(Double.MAX_VALUE);
//        }
        //只有相对值需要%比较，绝对值直接相减就行
        if (2 == error.getValueType()) {
            switch (error.getErrorValueType()) {
                case 0:
                    //下发的谐波电压幅值，返回的是谐波电压含有率，拿（含有率值*基波 - 源下发对应谐波值幅值）/ 额定值
                    return subtract.multiply(BigDecimal.valueOf(100))
                            .divide(BigDecimal.valueOf(ratedValue), scale, RoundingMode.HALF_UP);
                case 1:
                    //todo 当谐波电压和间谐波电压默认都是按照相对值误差进行计算（用户关心的是含有率）
                    //下发的谐波电压幅值，返回的是谐波电压含有率，拿（含有率值*基波 - 源下发对应谐波值幅值）/ 下发的幅值
                    return subtract.multiply(BigDecimal.valueOf(100))
                            .divide(BigDecimal.valueOf(channelData), scale, RoundingMode.HALF_UP);
            }
        }
        return subtract;
    }

    /**
     * 用于计算误差体系的范围的（0：标称值 1：谐波值 2：值类型）
     *
     * @param value     误差值
     * @param ratedData 额定值
     * @param harmData  谐波下发值（百分数->含油率）
     * @param type      误差值类型
     * @return
     */
    public Double startRadiusEnd(Double value, Double ratedData, Double harmData, Integer type, Integer scale) {
        if (ObjectUtil.isNotNull(value)) {
            switch (type) {
                case 0:
                    return BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(ratedData))
                            .setScale(scale, RoundingMode.HALF_UP).doubleValue();
                case 1:
                    return BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(harmData))
                            .setScale(scale, RoundingMode.HALF_UP).doubleValue();
                default:
                    return value;
            }
        }
        return value;
    }


    /**
     * 用于计算最大误差值的范围的
     * （2绝对值-值比较（默认）	0绝对值-标称值（额定电压）	1绝对值-标准值（源下发直谐波如:H2）	0相对值-标称值	1相对值-标准值）
     *
     * @param error     最大误差值对象
     * @param ratedData 额定值
     * @param harmData  谐波下发值（百分数->含油率）
     * @return
     * @parm scale 小数点位数
     */
    public Double maxErrorMultiply(PqErrSysDtls error, Double ratedData, Double harmData, Integer scale) {
        Double errorValue = error.getMaxErrorValue();
        //1绝对值
        if (1 == error.getValueType()) {
            switch (error.getErrorValueType()) {
                //绝对值-标称值= 最大误差值 * 额定电压
                case 0:
                    return BigDecimal.valueOf(errorValue).multiply(BigDecimal.valueOf(ratedData))
                            .setScale(scale, RoundingMode.HALF_UP).doubleValue();
                //绝对值-标准值 = 最大误差值 * 谐波下发值
                case 1:
                    return BigDecimal.valueOf(errorValue).multiply(BigDecimal.valueOf(harmData))
                            .setScale(scale, RoundingMode.HALF_UP).doubleValue();
            }
        }
        //2相对值
        if (2 == error.getValueType()) {
            switch (error.getErrorValueType()) {
                //相对值-标称值 | 相对值-标准值 = 最大误差值 * 100
                case 0:
                case 1:
                    return BigDecimal.valueOf(errorValue).multiply(BigDecimal.valueOf(100))
                            .setScale(scale, RoundingMode.HALF_UP).doubleValue();
            }
        }
        return errorValue;
    }

    public Double multiply(String devData, String channelData) {
        BigDecimal volValue = new BigDecimal(devData);
//        BigDecimal result = volValue.multiply(new BigDecimal(channelData).setScale(4, RoundingMode.HALF_UP));
        return volValue.doubleValue();
    }

    /**
     * 处理谐波原始数据
     *
     * @param type    A,b,c
     * @param map     初始化集合
     * @param harmNum 多少次谐波集合
     * @param harm    基波信息
     * @param fund    2-50次谐波信息
     */
    public void harmPut(String type, Map<String, Map<Double, List<Double>>> map, List<Double> harmNum, DevData.SqlDataHarmDTO harm, String fund, Integer num) {
        if (map.containsKey(type)) {
            Map<Double, List<Double>> integerListMap = map.get(type);
            integerListMap.get(0.0).add(multiply(fund, fund));
            for (Double i : harmNum) {
                if (integerListMap.containsKey(i)) {
                    if (i.equals(1.0) && num != 1) {
                        integerListMap.get(1.0).add(multiply(fund, fund));
                    } else {
                        double v = (num == 1 ? i : (i - num));
                        if (type.equals("A")) {
                            if ((int) v < harm.getList().getA().size()) {
                                integerListMap.get(i).add(multiply(harm.getList().getA().get((int) v), fund));
                            }

                        }
                        if (type.equals("B")) {
                            if ((int) v < harm.getList().getB().size()) {
                                integerListMap.get(i).add(multiply(harm.getList().getB().get((int) v), fund));
                            }
                        }
                        if (type.equals("C")) {
                            if ((int) v < harm.getList().getC().size()) {
                                integerListMap.get(i).add(multiply(harm.getList().getC().get((int) v), fund));
                            }
                        }
                    }
                }
            }
        } else {
            Map<Double, List<Double>> integerListMap = new LinkedHashMap<>(50);
            List<Double> integerList = new ArrayList<>();
            integerList.add(multiply(fund, fund));
            integerListMap.put(0.0, integerList);
            for (Double i : harmNum) {
                integerList = new ArrayList<>();
                if (i.equals(1.0) && num != 1) {
                    integerList.add(multiply(fund, fund));
                    integerListMap.put(1.0, integerList);
                } else {
                    double v = (num == 1 ? i : (i - num));
                    if (type.equals("A")) {
                        if ((int) v < harm.getList().getA().size()) {
                            integerList.add(multiply(harm.getList().getA().get((int) v), fund));
                        }
                    }
                    if (type.equals("B")) {
                        if ((int) v < harm.getList().getB().size()) {
                            integerList.add(multiply(harm.getList().getB().get((int) v), fund));
                        }
                    }
                    if (type.equals("C")) {
                        if ((int) v < harm.getList().getC().size()) {
                            integerList.add(multiply(harm.getList().getC().get((int) v), fund));
                        }
                    }
                    integerListMap.put(i, integerList);
                }
            }
            map.put(type, integerListMap);
        }
    }

    /**
     * @param dataRule     数据处理原则
     * @param harmDataList 原始数据集合
     * @param errSysDtl    误差体系
     * @param data         初始化原始数据
     * @param channelData  源下发的数据
     * @param ratedValue   额定值
     * @Description:
     * @Author: wr
     * @Date: 2024/12/29 18:10
     */
    private void setDetection(DictDataEnum dataRule, List<Double> harmDataList, PqErrSysDtls errSysDtl, DetectionData data, Double channelData, Double ratedValue, Integer scale) {
        if (CollUtil.isNotEmpty(harmDataList)) {
            // 存放合格的数据
            List<Double> qualifiedList = harmDataList.stream()
                    .filter(x -> channelData == 0 ? NumberUtil.isIn(devSubtractChannelData(x, channelData, ratedValue, errSysDtl, scale),
                            BigDecimal.valueOf(-errSysDtl.getMaxErrorValue()),
                            BigDecimal.valueOf(errSysDtl.getMaxErrorValue()))
                            :
                            x != 0 && NumberUtil.isIn(devSubtractChannelData(x, channelData, ratedValue, errSysDtl, scale),
                                    BigDecimal.valueOf(-errSysDtl.getMaxErrorValue()),
                                    BigDecimal.valueOf(errSysDtl.getMaxErrorValue()))).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(qualifiedList)) {
                switch (dataRule) {
                    case AT_WILL_VALUE:
                    case CP95_VALUE:
                    case AVG_VALUE:
                        data.setErrorData(devSubtractChannelData(qualifiedList.get(0), channelData, ratedValue, errSysDtl, scale));
                        break;
                    case SECTION_VALUE:
                    case Own_value:
                        if (qualifiedList.size() == harmDataList.size()) {
                            data.setErrorData(devSubtractChannelData(qualifiedList.get(0), channelData, ratedValue, errSysDtl, scale));
                        } else {
                            List<Double> subtract = CollectionUtils.subtract(harmDataList, qualifiedList).stream().collect(Collectors.toList());
                            BigDecimal bd = BigDecimal.valueOf(subtract.get(0));
                            bd = bd.setScale(scale, RoundingMode.HALF_UP);
                            data.setData(bd.doubleValue());
                            data.setErrorData(devSubtractChannelData(subtract.get(0), channelData, ratedValue, errSysDtl, scale));
                        }
                        break;
                }
            } else {
                data.setErrorData(devSubtractChannelData(harmDataList.get(0), channelData, ratedValue, errSysDtl, scale));
            }
            isData(dataRule, harmDataList, data, qualifiedList, scale);
        }
    }

    /**
     * 比对式正式检测-处理数据
     *
     * @param devDataList         被检设备数据
     * @param standardDevDataList 与之对齐的标准设备数据
     * @param parsIp              配对关系 key为被检设备ip_通道号，value为标准设备ip_通道号
     * @param devIdMapComm        设备id映射关系  key为被检设备ip，value为被检设备id
     * @param testItemCodeList    检测项code列表
     * @param errorSysId          误差体系id
     * @param dataRule            数据处理原则
     * @param numMap              第几次检测 key为设备id_通道号，value为第几次检测
     * @param code                结果表code
     * @param waveNum             第几次录波
     * @param dataSourceEnum      数据源类型
     * @return key为被检设备ip_通道号、value为是否合格（1合格 2不合格 4无法处理）
     */
    public List<DevLineTestResult> processing(List<DevData> devDataList, List<DevData> standardDevDataList, Map<String, String> parsIp, Map<String, String> devIdMapComm, List<String> testItemCodeList, String errorSysId, DictDataEnum dataRule, Map<String, Integer> numMap, String code, Integer waveNum, DataSourceEnum dataSourceEnum) {
        Map<String, List<DevData>> devDataMap = devDataList.stream().collect(Collectors.groupingBy(obj -> obj.getId().split("_")[0]));
        Map<String, List<DevData>> standardDevDataMap = standardDevDataList.stream().collect(Collectors.groupingBy(DevData::getId));

        // 所有监测点的结果
        List<DevLineTestResult> allResultList = new ArrayList<>();
        devDataMap.forEach((devIp, devValueList) -> {
            //单一监测点的结果
            List<DevLineTestResult> resultList = new ArrayList<>();
            Map<String, List<DevData>> devMonitorMap = devValueList.stream().collect(Collectors.groupingBy(DevData::getId, TreeMap::new, Collectors.toList()));

            String devId = devIdMapComm.get(devIp);
            Map<String, List<Integer>> chnResultMap = new HashMap<>();
            devMonitorMap.forEach((devMoniterId, devData) -> {
                String[] split = devMoniterId.split(CnSocketUtil.SPLIT_TAG);
                Map<String, Integer> map = singleMonitorProcessing(devData, standardDevDataMap.get(parsIp.get(devMoniterId)), devIdMapComm, testItemCodeList, errorSysId, dataRule, numMap.get(devId + CnSocketUtil.SPLIT_TAG + split[1]), code, waveNum, dataSourceEnum);
                map.forEach((key, value) -> {
                    DevLineTestResult devLineTestResult = new DevLineTestResult();
                    devLineTestResult.setDeviceId(devId);
                    devLineTestResult.setScriptName(key);
                    List<Integer> chnResult = chnResultMap.getOrDefault(key, new ArrayList<>());
                    chnResult.add(value);
                    chnResultMap.put(key, chnResult);
                    resultList.add(devLineTestResult);
                });
            });

            resultList.forEach(devLineTestResult -> {
                List<Integer> chnResult = chnResultMap.get(devLineTestResult.getScriptName());
                devLineTestResult.setChnResult(chnResult.toArray(new Integer[chnResult.size()]));
            });

            allResultList.addAll(resultList);
        });

        return allResultList;
    }

    /**
     * 处理单个监测点的数据
     *
     * @param devDataList         被检设备数据
     * @param standardDevDataList 与之对齐的标准设备数据
     * @param devIdMapComm        设备id映射关系  key为被检设备ip，value为被检设备id
     * @param testItemCodeList    检测项code列表
     * @param errorSysId          误差体系id
     * @param dataRule            数据处理原则
     * @param num                 第几次检测
     * @param code                结果表code
     * @param waveNum             第几次录波
     * @param dataSourceEnum      数据源类型
     * @return
     */
    private Map<String, Integer> singleMonitorProcessing(List<DevData> devDataList, List<DevData> standardDevDataList, Map<String, String> devIdMapComm, List<String> testItemCodeList, String errorSysId, DictDataEnum dataRule, Integer num, String code, Integer waveNum, DataSourceEnum dataSourceEnum) {
        Map<String, Integer> resultMap = new HashMap<>();
        if (CollUtil.isNotEmpty(devDataList) && CollUtil.isNotEmpty(standardDevDataList) && CollUtil.isNotEmpty(testItemCodeList)) {
            devDataList = devDataList.stream().sorted(Comparator.comparing(DevData::getTime)).collect(Collectors.toList());
            standardDevDataList = standardDevDataList.stream().sorted(Comparator.comparing(DevData::getTime)).collect(Collectors.toList());

            boolean isRemoveMaxElement = ObjectUtil.isNotNull(waveNum) ? false : true;
//            List<Double> freqStdDevData = standardDevDataList.stream().flatMap(standardDevData -> standardDevData.getSqlData().stream())
//                    .filter(sqlDataDTO -> DetectionCodeEnum.FREQ.getCode().equals(sqlDataDTO.getDesc()))
//                    .map(sqlDataDTO -> sqlDataDTO.getList().getT()).collect(Collectors.toList());

//            Double maxFreq = CollUtil.isNotEmpty(freqStdDevData) ? CollUtil.max(freqStdDevData) : null;
//            Double minFreq = CollUtil.isNotEmpty(freqStdDevData) ? CollUtil.min(freqStdDevData) : null;

//            if (maxFreq != null && minFreq != null) {
//                isRemoveMaxElement = DictDataEnum.AVG_VALUE.equals(dataRule);
//                double freqErrorValue = maxFreq - minFreq;
//                if (NumberUtil.isGreaterOrEqual(BigDecimal.valueOf(freqErrorValue), BigDecimal.valueOf(0.02))) {
//                    isRemoveMaxElement = isRemoveMaxElement && true;
//                }
//            }

            // 处理谐波数据
            SysTestConfig oneConfig = sysTestConfigService.getOneConfig();
            String[] split1 = devDataList.get(0).getId().split("_");
            String devMonitorId = devIdMapComm.get(split1[0]) + "_" + split1[1];
            PqMonitor pqMonitor = pqMonitorService.getByDevMonitorId(devMonitorId);
            boolean isStar = DetectionCodeEnum.STAR.getCode().equals(pqMonitor.getConnection());
            boolean isDelta = DetectionCodeEnum.DELTA.getCode().equals(pqMonitor.getConnection());
            Double fUn = pqMonitorService.getRatedVoltage(devMonitorId);
            boolean isExitDelta = this.isExitDeltaIndex(devIdMapComm.get(split1[0]), devDataList);
            if (isStar) {
                fUn = BigDecimal.valueOf(fUn).divide(BigDecimal.valueOf(Math.sqrt(3)), oneConfig.getScale(), RoundingMode.HALF_UP).doubleValue();
            }
//            if (isDelta && !isExitDelta) {
//                fUn = BigDecimal.valueOf(fUn).divide(BigDecimal.valueOf(Math.sqrt(3)), oneConfig.getScale(), RoundingMode.HALF_UP).doubleValue();
//            }
            Double fIn = pqMonitorService.getRatedCurrent(devMonitorId);
            Double fHz = 50.0;
            for (String testItemCode : testItemCodeList) {
                String[] split = testItemCode.split("\\$");
                DetectionCodeEnum anEnum = DetectionCodeEnum.getDetectionCodeByCode(split[1]);
                if (isStar && (anEnum == DetectionCodeEnum.PVRMS || anEnum == DetectionCodeEnum.PV2_50 || anEnum == DetectionCodeEnum.PSV_1_49) || isDelta && (anEnum == DetectionCodeEnum.VRMS || anEnum == DetectionCodeEnum.V2_50 || anEnum == DetectionCodeEnum.SV_1_49)) {
                    continue;
                }
                String scriptType = split[1];
                if (isDelta) {
                    if (DetectionCodeEnum.PVRMS.getCode().equals(scriptType)) {
                        scriptType = DetectionCodeEnum.VRMS.getCode();
                    }
                    if (DetectionCodeEnum.PV2_50.getCode().equals(scriptType)) {
                        scriptType = DetectionCodeEnum.V2_50.getCode();
                    }
                    if (DetectionCodeEnum.PSV_1_49.getCode().equals(scriptType)) {
                        scriptType = DetectionCodeEnum.SV_1_49.getCode();
                    }
                }
                List<PqErrSysDtls> pqErrSysDtls = pqErrSysDtlsService.listPqErrSysDtlsByPqErrSysIdAndScriptType(errorSysId, scriptType);

                switch (anEnum) {
                    case FREQ:
//                        if (ObjectUtil.isNull(waveNum)) {
//                            devDataList.stream().forEach(devData -> devData.getSqlData().stream().filter(sqlData -> sqlData.getDesc().equals(DetectionCodeEnum.FREQ.getCode())).findFirst().ifPresent(sqlData -> {
//                                DevData.SqlDataDTO.ListDTO listDTO = sqlData.getList();
//                                listDTO.setT(55.0);
//                                sqlData.setList(listDTO);
//                            }));
//                        }
                        resultMap.put(PowerIndexEnum.FREQ.getKey(), isQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, true, fHz, DetectionCodeEnum.FREQ.getCode(), dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case VRMS:
                    case PVRMS:
                        // 如果是角型接法且存在角型接法的一些指标，则不进行使用角型接线的指标。反之，则使用相别的指标。
                        resultMap.put(PowerIndexEnum.V.getKey(), isQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, true, fUn, (isDelta && isExitDelta ? DetectionCodeEnum.PVRMS.getCode() : DetectionCodeEnum.VRMS.getCode()), dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case IRMS:
//                        if (ObjectUtil.isNotNull(waveNum) && (waveNum.equals(2) || waveNum.equals(5))) {
//                            devDataList.stream().forEach(devData -> devData.getSqlData().stream().filter(sqlData -> sqlData.getDesc().equals(DetectionCodeEnum.IRMS.getCode())).findFirst().ifPresent(sqlData -> {
//                                DevData.SqlDataDTO.ListDTO listDTO = sqlData.getList();
//                                listDTO.setA(1.5);
//                                listDTO.setC(1.5);
//                                sqlData.setList(listDTO);
//                            }));
//                        }
                        resultMap.put(PowerIndexEnum.I.getKey(), isQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, true, fIn, DetectionCodeEnum.IRMS.getCode(), dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case V_UNBAN:
                        resultMap.put(PowerIndexEnum.IMBV.getKey(), isQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, false, fUn, DetectionCodeEnum.V_UNBAN.getCode(), dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case I_UNBAN:
                        resultMap.put(PowerIndexEnum.IMBA.getKey(), isQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, false, fIn, DetectionCodeEnum.I_UNBAN.getCode(), dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case V2_50:
                    case PV2_50:
                        resultMap.put(PowerIndexEnum.HV.getKey(), isHarmQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, U, fUn, HARMONIC_FLAG, isDelta && isExitDelta, dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case I2_50:
                        resultMap.put(PowerIndexEnum.HI.getKey(), isHarmQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, I, fIn, HARMONIC_FLAG, isDelta && isExitDelta, dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case P2_50:
                        resultMap.put(PowerIndexEnum.HP.getKey(), isHarmQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, HP, fUn * fIn, HARMONIC_FLAG, isDelta && isExitDelta, dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case SV_1_49:
                    case PSV_1_49:
                        resultMap.put(PowerIndexEnum.HSV.getKey(), isHarmQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, U, fUn, INHARMONIC_FLAG, isDelta && isExitDelta, dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case SI_1_49:
                        resultMap.put(PowerIndexEnum.HSI.getKey(), isHarmQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, I, fIn, INHARMONIC_FLAG, isDelta && isExitDelta, dataRule, num, code, oneConfig.getScale(), waveNum, dataSourceEnum, isRemoveMaxElement));
                        break;
                    case PST:
                        resultMap.put(PowerIndexEnum.F.getKey(), isQualified(devDataList, standardDevDataList, devIdMapComm, pqErrSysDtls, true, fUn, DetectionCodeEnum.PST.getCode(), dataRule, num, code, oneConfig.getScale(), waveNum, DataSourceEnum.MINUTE_STATISTICS_AVG, isRemoveMaxElement));
                        break;
                    case UNKNOWN_ERROR:
                        break;
                }
            }
        }
        return resultMap;
    }

    /**
     * 判断是否存在角型接法的一些线电压指标
     *
     * @param devId       设备id
     * @param devDataList 监测点数据
     * @return
     */
    public boolean isExitDeltaIndex(String devId, List<DevData> devDataList) {
        if (CollUtil.isNotEmpty(devDataList)) {
            List<String> deltaIndex = Arrays.asList(DetectionCodeEnum.PVRMS.getCode(),
                    DetectionCodeEnum.PV2_50.getCode(),
                    DetectionCodeEnum.PSV_1_49.getCode(),
                    DetectionCodeEnum.PU1.getCode());
            DevData devData = devDataList.get(0);
            List<DevData.SqlDataDTO> sqlData = devData.getSqlData();
            List<DevData.SqlDataHarmDTO> sqlDataHarm = devData.getSqlDataHarm();

            if (CollUtil.isNotEmpty(sqlData) && CollUtil.isNotEmpty(sqlDataHarm)) {
                List<String> descList = sqlData.stream().map(DevData.SqlDataDTO::getDesc).filter(desc -> deltaIndex.contains(desc)).collect(Collectors.toList());
                descList.addAll(sqlDataHarm.stream().map(DevData.SqlDataHarmDTO::getDesc).filter(desc -> deltaIndex.contains(desc)).collect(Collectors.toList()));
                if (descList.containsAll(deltaIndex)) {
                    List<PreDetection> devInfo = pqDevService.getDevInfo(Collections.singletonList(devId));
                    if (devInfo.get(0).getUsePhaseIndex() == 1) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        }
        return false;
    }


    /**
     * 处理非谐波数据
     *
     * @param devDataList         被检设备数据
     * @param standardDevDataList 与之对齐的标准设备数据
     * @param devIdMapComm        设备id映射表 key为被检设备ip，value为被检设备id
     * @param errSysDtls          误差体系
     * @param isNotUnblance       不是三项不平衡
     * @param fData               额定值
     * @param desc                检测项类型
     * @param dataRule            数据处理原则
     * @param num                 第几次检测
     * @param code                结果表code
     * @param scale               小数点位数
     * @param waveNum             第几次录波
     * @param dataSourceEnum      数据源类型
     * @return
     */
    private Integer isQualified(List<DevData> devDataList,
                                List<DevData> standardDevDataList,
                                Map<String, String> devIdMapComm,
                                List<PqErrSysDtls> errSysDtls,
                                boolean isNotUnblance,
                                Double fData,
                                String desc,
                                DictDataEnum dataRule,
                                Integer num,
                                String code,
                                Integer scale,
                                Integer waveNum,
                                DataSourceEnum dataSourceEnum,
                                boolean isRemoveMaxElement) {
        List<ContrastNonHarmonicResult> info = new ArrayList<>();
        if (CollUtil.isNotEmpty(devDataList) && CollUtil.isNotEmpty(standardDevDataList) && CollUtil.isNotEmpty(errSysDtls)) {

            Map<String, List<List<Double>>> phaseValueList = this.getPhaseValueList(devDataList, standardDevDataList, desc);
            Map<String, List<List<Double>>> map = devListMap(phaseValueList, dataRule, isRemoveMaxElement);
            if (ObjectUtil.isNull(map)) {
                return 4;
            }
            ContrastNonHarmonicResult result = new ContrastNonHarmonicResult();
            result.setWaveNum(waveNum);

            String devId = devDataList.get(0).getId();
            String stdId = standardDevDataList.get(0).getId();

            String[] split1 = devId.split(CnSocketUtil.SPLIT_TAG);
            String[] split2 = stdId.split(CnSocketUtil.SPLIT_TAG);
            result.setNum(num);
            String devMonitorId = devIdMapComm.get(split1[0]) + "_" + split1[1];
            result.setDevMonitorId(devMonitorId);
            String stdDevMonitorId = devIdMapComm.get(split2[0]) + "_" + split2[1];
            result.setStdDevMonitorId(stdDevMonitorId);
            result.setAdType(errSysDtls.get(0).getScriptType());
            result.setDataType(dataSourceEnum.getValue());
            if (ObjectUtil.isNotNull(waveNum)) {
                result.setDataType(DataSourceEnum.WAVE_DATA.getValue());
            }

            Map<String, List<Double>> validData = this.getValidData(standardDevDataList, desc);

            Integer validGroupNum = 0;
            if (map.containsKey(TYPE_T)) {
                if (ObjectUtil.isNotNull(validData)) {
                    List<Double> tValidDataList = validData.get(TYPE_T);
                    validGroupNum = this.getValidGroupNum(tValidDataList, null, errSysDtls, fData, scale, dataRule);
                }
                List<DetectionData> tList = rangeComparisonList(map.get(TYPE_T).get(0), map.get(TYPE_T).get(1), errSysDtls, fData, scale, dataRule);
                this.setValidGroupNum(tList, validGroupNum);
                result.setTValue(JSON.toJSONString(tList));
                result.setResultFlag(setResultFlag(tList));
            } else {
                List<DetectionData> resultFlag = new ArrayList<>();
                Map<String, BiConsumer<ContrastNonHarmonicResult, List<DetectionData>>> setters = new HashMap<>();
                List<String> phases = new ArrayList<>();
                if (isNotUnblance) {
                    setters.put(TYPE_A, (r, d) -> r.setAValue(JSON.toJSONString(d)));
                    setters.put(TYPE_C, (r, d) -> r.setCValue(JSON.toJSONString(d)));
                    phases.add(TYPE_A);
                    phases.add(TYPE_C);
                }
                setters.put(TYPE_B, (r, d) -> r.setBValue(JSON.toJSONString(d)));
                phases.add(TYPE_B);

                for (String phase : phases) {
                    if (ObjectUtil.isNotNull(validData)) {
                        List<Double> validDataList = validData.get(phase);
                        validGroupNum = this.getValidGroupNum(validDataList, null, errSysDtls, fData, scale, dataRule);
                    }

                    List<DetectionData> phaseList = rangeComparisonList(map.get(phase).get(0), map.get(phase).get(1), errSysDtls, fData, scale, dataRule);
                    this.setValidGroupNum(phaseList, validGroupNum);
                    resultFlag.addAll(phaseList);
                    if (FormalTestManager.isTesting && ObjectUtil.isNull(waveNum)) { //只有“正式检测并且不是录波数据”的时候才能进入这段代码，重新计算、切换误差体系额操作不会进入这段代码，提升效率。
//                    if (true) { //只有“正式检测并且不是录波数据”的时候才能进入这段代码，重新计算、切换误差体系额操作不会进入这段代码，提升效率。
                        if (DetectionCodeEnum.PVRMS.getCode().equals(desc) || DetectionCodeEnum.VRMS.getCode().equals(desc) || DetectionCodeEnum.IRMS.getCode().equals(desc)) {
                            Integer phaseResultFlag = setResultFlag(phaseList);
                            boolean b = phaseResultFlag == 2 ? true : false;

                            SysTestConfig oneConfig = sysTestConfigService.getOneConfig();
                            if (b && oneConfig.getCoefficient() == 1) {
                                BigDecimal pearsonCorrelationCoefficient = DetectionUtil.getPearsonCorrelationCoefficient(phaseValueList.get(phase).get(0), phaseValueList.get(phase).get(1));
                                if (NumberUtil.isGreaterOrEqual(pearsonCorrelationCoefficient, BigDecimal.valueOf(0.8))) {
                                    BigDecimal cvCoefficient = DetectionUtil.getCvCoefficient(phaseValueList.get(phase).get(0), phaseValueList.get(phase).get(1));
                                    if (NumberUtil.isLess(cvCoefficient, BigDecimal.valueOf(0.05))) {
                                        int maxNum = pqStandardDevGainRecordService.getMaxNum(stdDevMonitorId, devMonitorId);
                                        // 如果没有超出次数限制
                                        if (maxNum + 1 <= 5) {
                                            VAndIResult vAndIResult = vAndIResultMap.getOrDefault(stdId, new VAndIResult(split2[0], Integer.valueOf(split2[1]), false, false, false, false, false, false,
                                                    1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
                                                    BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO,
                                                    BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.2)));

                                            Double newXi = DetectionUtil.getNewXi(map.get(phase).get(0), map.get(phase).get(1));
                                            switch (phase) {
                                                case TYPE_A:
                                                    if (DetectionCodeEnum.IRMS.getCode().equals(desc)) {
                                                        vAndIResult.setIa(b);
                                                        vAndIResult.setIaXi(newXi);
                                                        vAndIResult.setPearsonCorrelationCoefficientIa(pearsonCorrelationCoefficient);
                                                        vAndIResult.setCVCoefficientIa(cvCoefficient);
                                                    } else {
                                                        vAndIResult.setVa(b);
                                                        vAndIResult.setVaXi(newXi);
                                                        vAndIResult.setPearsonCorrelationCoefficientVa(pearsonCorrelationCoefficient);
                                                        vAndIResult.setCVCoefficientVa(cvCoefficient);
                                                    }
                                                    break;
                                                case TYPE_B:
                                                    if (DetectionCodeEnum.IRMS.getCode().equals(desc)) {
                                                        vAndIResult.setIb(b);
                                                        vAndIResult.setIbXi(newXi);
                                                        vAndIResult.setPearsonCorrelationCoefficientIb(pearsonCorrelationCoefficient);
                                                        vAndIResult.setCVCoefficientIb(cvCoefficient);
                                                    } else {
                                                        vAndIResult.setVb(b);
                                                        vAndIResult.setVbXi(newXi);
                                                        vAndIResult.setPearsonCorrelationCoefficientVb(pearsonCorrelationCoefficient);
                                                        vAndIResult.setCVCoefficientVb(cvCoefficient);
                                                    }
                                                    break;
                                                case TYPE_C:
                                                    if (DetectionCodeEnum.IRMS.getCode().equals(desc)) {
                                                        vAndIResult.setIc(b);
                                                        vAndIResult.setIcXi(newXi);
                                                        vAndIResult.setPearsonCorrelationCoefficientIc(pearsonCorrelationCoefficient);
                                                        vAndIResult.setCVCoefficientIc(cvCoefficient);
                                                    } else {
                                                        vAndIResult.setVc(b);
                                                        vAndIResult.setVcXi(newXi);
                                                        vAndIResult.setPearsonCorrelationCoefficientVc(pearsonCorrelationCoefficient);
                                                        vAndIResult.setCVCoefficientVc(cvCoefficient);
                                                    }
                                                    break;
                                                default:
                                                    break;
                                            }

                                            vAndIResultMap.put(stdId, vAndIResult);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    BiConsumer<ContrastNonHarmonicResult, List<DetectionData>> setter = setters.get(phase);
                    setter.accept(result, phaseList);
                }
                result.setResultFlag(setResultFlag(resultFlag));
            }
            info.add(result);
        }

        detectionDataDealService.acceptNonHarmonicResult(info, code);
        List<Integer> resultFlag = info.stream().map(ContrastNonHarmonicResult::getResultFlag).distinct().collect(Collectors.toList());
        return StorageUtil.getInteger(resultFlag);
    }

    private Map<String, List<Double>> getValidData(List<DevData> dev, String desc) {
        List<Double> aDev = new ArrayList<>();
        List<Double> bDev = new ArrayList<>();
        List<Double> cDev = new ArrayList<>();
        List<Double> tDev = new ArrayList<>();

        for (int i = 0; i < dev.size(); i++) {
            List<DevData.SqlDataDTO> devSqlData = dev.get(i).getSqlData();

            String finalDesc = desc;
            List<DevData.SqlDataDTO.ListDTO> devList = devSqlData.stream().filter(j -> finalDesc.equals(j.getDesc()))
                    .map(DevData.SqlDataDTO::getList).collect(Collectors.toList());

            if (CollUtil.isEmpty(devList)) {
                return null;
            }
            aDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getA()))
                    .map(x -> x.getA().doubleValue())
                    .collect(Collectors.toList()));
            bDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getB()))
                    .map(x -> x.getB().doubleValue())
                    .collect(Collectors.toList()));
            cDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getC()))
                    .map(x -> x.getC().doubleValue())
                    .collect(Collectors.toList()));
            tDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getT()))
                    .map(x -> x.getT().doubleValue())
                    .collect(Collectors.toList()));
        }

        return new HashMap() {
            {
                put(TYPE_A, aDev);
                put(TYPE_B, bDev);
                put(TYPE_C, cDev);
                put(TYPE_T, tDev);
            }
        };
    }

    private Map<String, Map<Double, List<Double>>> getHarmValidData(List<DevData> dev, String fundCode, String harmCode, Integer harmonicFlag) {
        // key为相别、value{key为谐波次数，value为按数据处理原则处理后的数据}
        Map<String, Map<Double, List<Double>>> devMap = new HashMap<>(3);

        List<Double> harmNum = new ArrayList<>();
        if (1 == harmonicFlag) {
            harmNum.addAll(Stream.iterate(0.5, x -> x + 1.0).limit(50).collect(Collectors.toList()));
        } else {
            harmNum.addAll(Stream.iterate(1.0, x -> x + 1.0).limit(50).collect(Collectors.toList()));
        }

        for (int i = 0; i < dev.size(); i++) {
            List<DevData.SqlDataDTO> devSqlData = dev.get(i).getSqlData();

            Optional<DevData.SqlDataDTO> first1 = Optional.empty();

            if (CollUtil.isNotEmpty(devSqlData)) {
                first1 = devSqlData.stream().filter(j -> fundCode.equals(j.getDesc())).collect(Collectors.toList()).stream().findFirst();
            }

            DevData.SqlDataDTO fund1 = null;
            if (first1.isPresent()) {
                fund1 = first1.get();
            }

            List<DevData.SqlDataHarmDTO> devHarmList = dev.get(i).getSqlDataHarm().stream().filter(x -> harmCode.equals(x.getDesc())).collect(Collectors.toList());

            if (CollUtil.isEmpty(devHarmList)) {
                return null;
            }

            if (CollUtil.isNotEmpty(devHarmList)) {
                DevData.SqlDataHarmDTO devHarm = devHarmList.get(0);
                if (ObjectUtil.isNotNull(fund1)) {
                    harmPut(TYPE_A, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getA()), harmonicFlag);
                    harmPut(TYPE_B, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getB()), harmonicFlag);
                    harmPut(TYPE_C, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getC()), harmonicFlag);
                } else {
                    harmPut(TYPE_A, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_B, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_C, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                }
            }
        }
        return devMap;
    }

    private Integer getValidGroupNum(List<Double> devDataList, List<Double> U1List, List<PqErrSysDtls> errSysDtls, Double fData, Integer scale, DictDataEnum dataRule) {
        int result = 0;
        if (dataRule.getCode().equals(DictDataEnum.Own_value.getCode()) || dataRule.getCode().equals(DictDataEnum.SECTION_VALUE.getCode())) {
            return 1;
        } else {
            for (int i = 0; i < devDataList.size(); i++) {
                Double U1 = CollUtil.isNotEmpty(U1List) ? U1List.get(i) : null;
                Double stdDevData = BigDecimal.valueOf(devDataList.get(i)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                Double devData = BigDecimal.valueOf(devDataList.get(i)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                DetectionData detectionData = new DetectionData();
                detectionData.setIsData(ResultEnum.NO_ERROR_SYS.getValue());

                //获得误差体系
                List<PqErrSysDtls> errSysDtls1 = errSysDtls.stream().filter(x -> rangeComparison(startRadiusEnd(x.getStartValue(), fData, stdDevData, x.getConditionType(), scale),
                        x.getStartFlag(),
                        startRadiusEnd(x.getEndValue(), fData, stdDevData, x.getConditionType(), scale),
                        x.getEndFlag(),
                        ObjectUtil.isNotNull(U1) ? stdDevData * U1 * 0.01 : stdDevData)).collect(Collectors.toList());
                detectionData.setData(devData);
                detectionData.setResultData(stdDevData);
                if (CollUtil.isNotEmpty(errSysDtls1)) {
                    result++;

                }
            }
        }

        return result;
    }

    private Map<Double, Integer> getHarmValidGroupNum(Map<Double, List<Double>> devDataMap, List<Double> U1List, List<PqErrSysDtls> errSysDtls, Double fData, Integer scale, DictDataEnum dataRule) {
        Map<Double, Integer> resultMap = new HashMap<>();
        devDataMap.forEach((harmNum, dataList) -> {
            if (dataRule.getCode().equals(DictDataEnum.Own_value.getCode()) || dataRule.getCode().equals(DictDataEnum.SECTION_VALUE.getCode())) {
                resultMap.put(harmNum, 1);
            } else {
                Integer validGroupNum = 0;
                for (int i = 0; i < dataList.size(); i++) {
                    Double U1 = CollUtil.isNotEmpty(U1List) ? U1List.get(i) : null;
                    Double stdDevData = BigDecimal.valueOf(dataList.get(i)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                    Double devData = BigDecimal.valueOf(dataList.get(i)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                    DetectionData detectionData = new DetectionData();
                    detectionData.setIsData(ResultEnum.NO_ERROR_SYS.getValue());

                    //获得误差体系
                    List<PqErrSysDtls> errSysDtls1 = errSysDtls.stream().filter(x -> rangeComparison(startRadiusEnd(x.getStartValue(), fData, stdDevData, x.getConditionType(), scale),
                            x.getStartFlag(),
                            startRadiusEnd(x.getEndValue(), fData, stdDevData, x.getConditionType(), scale),
                            x.getEndFlag(),
                            ObjectUtil.isNotNull(U1) ? stdDevData * U1 * 0.01 : stdDevData)).collect(Collectors.toList());
                    detectionData.setData(devData);
                    detectionData.setResultData(stdDevData);
                    if (CollUtil.isNotEmpty(errSysDtls1)) {
                        validGroupNum++;
                    }
                }
                resultMap.put(harmNum, validGroupNum);
            }
        });
        return resultMap;
    }

    private void setValidGroupNum(List<DetectionData> tList, Integer validGroupNum) {
        tList.forEach(detectionData -> {
            detectionData.setValidGroupNum(validGroupNum);
        });
    }

    private void setHarmValidGroupNum(List<DetectionData> integerBooleanA, Map<Double, Integer> harmValidGroupNumA) {
        integerBooleanA.forEach(detectionData -> {
            Double harmNum = detectionData.getNum();
            Integer validGroupNum = harmValidGroupNumA.get(harmNum);
            detectionData.setValidGroupNum(validGroupNum);
        });
    }


    /**
     * 处理谐波数据
     *
     * @param devDataList         被检设备数据
     * @param standardDevDataList 与之对齐的标准设备数据
     * @param devIdMapComm        设备id映射表 key为被检设备ip，value为被检设备id
     * @param errSysDtls          误差体系
     * @param fData               额定值
     * @param type                U或I、用来区分电压或电流
     * @param harmonicFlag        1：间谐波，2：谐波
     * @param isUseDelta          是否使用角型接线的一些指标
     * @param dataRule            数据处理原则
     * @param num                 第几次检测
     * @param code                结果表code
     * @param scale               小数点位数
     * @param waveNum             第几次录波
     * @param dataSourceEnum      数据源类型
     * @return
     */
    public Integer isHarmQualified(List<DevData> devDataList,
                                   List<DevData> standardDevDataList,
                                   Map<String, String> devIdMapComm,
                                   List<PqErrSysDtls> errSysDtls,
                                   String type,
                                   Double fData,
                                   Integer harmonicFlag,
                                   boolean isUseDelta,
                                   DictDataEnum dataRule,
                                   Integer num,
                                   String code,
                                   Integer scale,
                                   Integer waveNum,
                                   DataSourceEnum dataSourceEnum,
                                   boolean isRemoveMaxElement) {
        List<ContrastHarmonicResult> info = new ArrayList<>();
        if (CollUtil.isNotEmpty(devDataList) && CollUtil.isNotEmpty(standardDevDataList) && CollUtil.isNotEmpty(errSysDtls)) {
            String fundCode = "";
            String harmCode = "";
            if (U.equals(type)) {
                fundCode = DetectionCodeEnum.U1.getCode();
                if (isUseDelta) {
                    fundCode = DetectionCodeEnum.PU1.getCode();
                }
                if (harmonicFlag == 1) {
                    harmCode = DetectionCodeEnum.SV_1_49.getCode();
                    if (isUseDelta) {
                        harmCode = DetectionCodeEnum.PSV_1_49.getCode();
                    }
                } else {
                    harmCode = DetectionCodeEnum.V2_50.getCode();
                    if (isUseDelta) {
                        harmCode = DetectionCodeEnum.PV2_50.getCode();
                    }
                }
            }
            if (I.equals(type)) {
                fundCode = DetectionCodeEnum.I1.getCode();
                if (harmonicFlag == 1) {
                    harmCode = DetectionCodeEnum.SI_1_49.getCode();
                } else {
                    harmCode = DetectionCodeEnum.I2_50.getCode();
                }
            }
            if (HP.equals(type)) {
//                fData = fData * 0.01;
                harmCode = DetectionCodeEnum.P2_50.getCode();
            }

            Map<String, List<Map<Double, List<Double>>>> devMap = devHarmListMap(devDataList, standardDevDataList, fundCode, harmCode, harmonicFlag, dataRule, isRemoveMaxElement);
            if (ObjectUtil.isNull(devMap)) {
                return 4;
            }
            ContrastHarmonicResult result = new ContrastHarmonicResult();
            result.setWaveNum(waveNum);

            String[] split1 = devDataList.get(0).getId().split("_");
            String[] split2 = standardDevDataList.get(0).getId().split("_");
            result.setNum(num);
            result.setDevMonitorId(devIdMapComm.get(split1[0]) + "_" + split1[1]);
            result.setStdDevMonitorId(devIdMapComm.get(split2[0]) + "_" + split2[1]);
            result.setAdType(errSysDtls.get(0).getScriptType());
            result.setDataType(dataSourceEnum.getValue());
            if (ObjectUtil.isNotNull(waveNum)) {
                result.setDataType(DataSourceEnum.WAVE_DATA.getValue());
            }

            Map<String, Map<Double, List<Double>>> harmValidData = this.getHarmValidData(standardDevDataList, fundCode, harmCode, harmonicFlag);

            List<DetectionData> integerBooleanA = harmRangeComparison(devMap.get(TYPE_A).get(0), devMap.get(TYPE_A).get(1), errSysDtls, type, fData, scale, dataRule);
            List<DetectionData> integerBooleanB = harmRangeComparison(devMap.get(TYPE_B).get(0), devMap.get(TYPE_B).get(1), errSysDtls, type, fData, scale, dataRule);
            List<DetectionData> integerBooleanC = harmRangeComparison(devMap.get(TYPE_C).get(0), devMap.get(TYPE_C).get(1), errSysDtls, type, fData, scale, dataRule);

            Map<String, Map<Double, List<Double>>> U1ListMap = this.getU1ListMap(standardDevDataList, fundCode, harmCode, harmonicFlag);
            Map<Double, Integer> harmValidGroupNumA = this.getHarmValidGroupNum(harmValidData.get(TYPE_A), U1ListMap.get(TYPE_A).get(0.0), errSysDtls, fData, scale, dataRule);
            this.setHarmValidGroupNum(integerBooleanA, harmValidGroupNumA);

            Map<Double, Integer> harmValidGroupNumB = this.getHarmValidGroupNum(harmValidData.get(TYPE_B), U1ListMap.get(TYPE_B).get(0.0), errSysDtls, fData, scale, dataRule);
            this.setHarmValidGroupNum(integerBooleanB, harmValidGroupNumB);

            Map<Double, Integer> harmValidGroupNumC = this.getHarmValidGroupNum(harmValidData.get(TYPE_C), U1ListMap.get(TYPE_C).get(0.0), errSysDtls, fData, scale, dataRule);
            this.setHarmValidGroupNum(integerBooleanC, harmValidGroupNumC);

            reflectHarmonic(true, "a", integerBooleanA, result, harmonicFlag);
            reflectHarmonic(true, "b", integerBooleanB, result, harmonicFlag);
            reflectHarmonic(true, "c", integerBooleanC, result, harmonicFlag);
            List<DetectionData> list = new ArrayList<>();
            list.addAll(integerBooleanA.stream().filter(x -> 1 != x.getNum()).distinct().collect(Collectors.toList()));
            list.addAll(integerBooleanB.stream().filter(x -> 1 != x.getNum()).distinct().collect(Collectors.toList()));
            list.addAll(integerBooleanC.stream().filter(x -> 1 != x.getNum()).distinct().collect(Collectors.toList()));
            result.setResultFlag(setResultFlag(list));
            info.add(result);
        }

        detectionDataDealService.acceptHarmonicResult(info, code);
        List<Integer> resultFlag = info.stream().map(ContrastHarmonicResult::getResultFlag).distinct().collect(Collectors.toList());
        return StorageUtil.getInteger(resultFlag);
    }

    private Map<String, Map<Double, List<Double>>> getU1ListMap(List<DevData> devDataList, String fundCode, String harmCode, Integer harmonicFlag) {
        Map<String, Map<Double, List<Double>>> resultMap = new HashMap<>(3);

        // key为相别、value{key为谐波次数，value为按数据处理原则处理后的数据}
        Map<String, Map<Double, List<Double>>> devMap = new HashMap<>(3);

        List<Double> harmNum = new ArrayList<>();
        if (1 == harmonicFlag) {
            harmNum.addAll(Stream.iterate(0.5, x -> x + 1.0).limit(50).collect(Collectors.toList()));
        } else {
            harmNum.addAll(Stream.iterate(1.0, x -> x + 1.0).limit(50).collect(Collectors.toList()));
        }

        for (int i = 0; i < devDataList.size(); i++) {
            List<DevData.SqlDataDTO> standardDevSqlData = devDataList.get(i).getSqlData();

            Optional<DevData.SqlDataDTO> first1 = Optional.empty();

            if (CollUtil.isNotEmpty(standardDevSqlData)) {
                first1 = standardDevSqlData.stream().filter(j -> fundCode.equals(j.getDesc())).collect(Collectors.toList()).stream().findFirst();
            }

            DevData.SqlDataDTO fund1 = null;
            if (first1.isPresent()) {
                fund1 = first1.get();
            }

            List<DevData.SqlDataHarmDTO> devHarmList = devDataList.get(i).getSqlDataHarm().stream().filter(x -> harmCode.equals(x.getDesc())).collect(Collectors.toList());

            if (CollUtil.isEmpty(devHarmList)) {
                return null;
            }

            if (CollUtil.isNotEmpty(devHarmList)) {
                DevData.SqlDataHarmDTO devHarm = devHarmList.get(0);
                if (ObjectUtil.isNotNull(fund1)) {
                    harmPut(TYPE_A, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getA()), harmonicFlag);
                    harmPut(TYPE_B, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getB()), harmonicFlag);
                    harmPut(TYPE_C, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getC()), harmonicFlag);
                } else {
                    harmPut(TYPE_A, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_B, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_C, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                }
            }
        }
        resultMap.put(TYPE_A, devMap.get(TYPE_A));
        resultMap.put(TYPE_B, devMap.get(TYPE_C));
        resultMap.put(TYPE_C, devMap.get(TYPE_C));

        return resultMap;
    }


    /**
     * 处理非谐波类取值
     *
     * @param dataRule 数据处理原则
     */
    public Map<String, List<List<Double>>> devListMap(Map<String, List<List<Double>>> phaseValueList, DictDataEnum dataRule, boolean isRemoveMaxElement) {
        Map<String, List<List<Double>>> resultMap = new HashMap<>(3);

        List<Double> aDev = new ArrayList<>();
        List<Double> aStandardDev = new ArrayList<>();

        if (phaseValueList.containsKey(TYPE_A)) {
            if (phaseValueList.get(TYPE_A).size() >= 1) {
                aDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_A).get(0), Double.class));
                aStandardDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_A).get(1), Double.class));
            } else {
                log.error("数据异常，phaseValueList.get(TYPE_A).size()=" + phaseValueList.get(TYPE_A).size());
            }
        } else {
            log.equals("数据异常，phaseValueList.containsKey(TYPE_A)=" + phaseValueList.containsKey(TYPE_A));
        }

        List<Double> bDev = new ArrayList<>();
        List<Double> bStandardDev = new ArrayList<>();

        if (phaseValueList.containsKey(TYPE_B)) {
            if (phaseValueList.get(TYPE_B).size() >= 1) {
                bDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_B).get(0), Double.class));
                bStandardDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_B).get(1), Double.class));
            } else {
                log.error("数据异常，phaseValueList.get(TYPE_B).size()=" + phaseValueList.get(TYPE_B).size());
            }
        } else {
            log.equals("数据异常，phaseValueList.containsKey(TYPE_B)=" + phaseValueList.containsKey(TYPE_B));
        }

        List<Double> cDev = new ArrayList<>();
        List<Double> cStandardDev = new ArrayList<>();
        if (phaseValueList.containsKey(TYPE_C)) {
            if (phaseValueList.get(TYPE_C).size() >= 1) {
                cDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_C).get(0), Double.class));
                cStandardDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_C).get(1), Double.class));
            } else {
                log.error("数据异常，phaseValueList.get(TYPE_C).size()=" + phaseValueList.get(TYPE_C).size());
            }
        } else {
            log.equals("数据异常，phaseValueList.containsKey(TYPE_C)=" + phaseValueList.containsKey(TYPE_C));
        }

        List<Double> tDev = new ArrayList<>();
        List<Double> tStandardDev = new ArrayList<>();
        if (phaseValueList.containsKey(TYPE_T)) {
            if (phaseValueList.get(TYPE_T).size() >= 1) {
                tDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_T).get(0), Double.class));
                tStandardDev.addAll(BeanUtil.copyToList(phaseValueList.get(TYPE_T).get(1), Double.class));
            } else {
                log.error("数据异常，phaseValueList.get(TYPE_T).size()=" + phaseValueList.get(TYPE_T).size());
            }
        } else {
            log.equals("数据异常，phaseValueList.containsKey(TYPE_T)=" + phaseValueList.containsKey(TYPE_T));
        }

        if (isRemoveMaxElement) {
            List<Double> aErrorValueList = new ArrayList<>();
            List<Double> bErrorValueList = new ArrayList<>();
            List<Double> cErrorValueList = new ArrayList<>();
            List<Double> tErrorValueList = new ArrayList<>();
            for (int i = 0; i < aStandardDev.size(); i++) {
                aErrorValueList.add(Math.abs(aStandardDev.get(i) - aDev.get(i)));
            }
            for (int i = 0; i < bStandardDev.size(); i++) {
                bErrorValueList.add(Math.abs(bStandardDev.get(i) - bDev.get(i)));
            }
            for (int i = 0; i < cStandardDev.size(); i++) {
                cErrorValueList.add(Math.abs(cStandardDev.get(i) - cDev.get(i)));
            }
            for (int i = 0; i < tStandardDev.size(); i++) {
                tErrorValueList.add(Math.abs(tStandardDev.get(i) - tDev.get(i)));
            }
            List<Integer> aErrorValueIdxs = DetectionUtil.sort(aErrorValueList, false);
            List<Integer> bErrorValueIdxs = DetectionUtil.sort(bErrorValueList, false);
            List<Integer> cErrorValueIdxs = DetectionUtil.sort(cErrorValueList, false);
            List<Integer> tErrorValueIdxs = DetectionUtil.sort(tErrorValueList, false);

            int removeCount = aErrorValueIdxs.size() / 2;
            List<Double> newArray = DetectionUtil.getNewArray(aStandardDev, aErrorValueIdxs.subList(removeCount, aErrorValueIdxs.size()));
            aStandardDev.clear();
            aStandardDev.addAll(newArray);
            newArray = DetectionUtil.getNewArray(aDev, aErrorValueIdxs.subList(removeCount, aErrorValueIdxs.size()));
            aDev.clear();
            aDev.addAll(newArray);

            removeCount = bErrorValueIdxs.size() / 2;
            newArray = DetectionUtil.getNewArray(bStandardDev, bErrorValueIdxs.subList(removeCount, bErrorValueIdxs.size()));
            bStandardDev.clear();
            bStandardDev.addAll(newArray);
            newArray = DetectionUtil.getNewArray(bDev, bErrorValueIdxs.subList(removeCount, bErrorValueIdxs.size()));
            bDev.clear();
            bDev.addAll(newArray);

            removeCount = cErrorValueIdxs.size() / 2;
            newArray = DetectionUtil.getNewArray(cStandardDev, cErrorValueIdxs.subList(removeCount, cErrorValueIdxs.size()));
            cStandardDev.clear();
            cStandardDev.addAll(newArray);
            newArray = DetectionUtil.getNewArray(cDev, cErrorValueIdxs.subList(removeCount, cErrorValueIdxs.size()));
            cDev.clear();
            cDev.addAll(newArray);

            removeCount = tErrorValueIdxs.size() / 2;
            newArray = DetectionUtil.getNewArray(tStandardDev, tErrorValueIdxs.subList(removeCount, tErrorValueIdxs.size()));
            tStandardDev.clear();
            tStandardDev.addAll(newArray);
            newArray = DetectionUtil.getNewArray(tDev, tErrorValueIdxs.subList(removeCount, tErrorValueIdxs.size()));
            tDev.clear();
            tDev.addAll(newArray);
        }

        switch (dataRule) {
            case SECTION_VALUE: {
                List<Integer> aIdxs = DetectionUtil.sort(aStandardDev, false);
                List<Integer> bIdxs = DetectionUtil.sort(bStandardDev, false);
                List<Integer> cIdxs = DetectionUtil.sort(cStandardDev, false);
                List<Integer> tIdxs = DetectionUtil.sort(tStandardDev, false);
                if (aStandardDev.size() > 2) {
                    aStandardDev.remove(0);
                    aStandardDev.remove(aStandardDev.size() - 1);
                    List<Double> newArray = DetectionUtil.getNewArray(aDev, aIdxs.subList(1, aIdxs.size() - 1));
                    aDev.clear();
                    aDev.addAll(newArray);
                }
                if (bStandardDev.size() > 2) {
                    bStandardDev.remove(0);
                    bStandardDev.remove(bStandardDev.size() - 1);
                    List<Double> newArray = DetectionUtil.getNewArray(bDev, bIdxs.subList(1, bIdxs.size() - 1));
                    bDev.clear();
                    bDev.addAll(newArray);
                }
                if (cStandardDev.size() > 2) {
                    cStandardDev.remove(0);
                    cStandardDev.remove(cStandardDev.size() - 1);
                    List<Double> newArray = DetectionUtil.getNewArray(cDev, cIdxs.subList(1, cIdxs.size() - 1));
                    cDev.clear();
                    cDev.addAll(newArray);
                }
                if (tStandardDev.size() > 2) {
                    tStandardDev.remove(0);
                    tStandardDev.remove(tStandardDev.size() - 1);
                    List<Double> newArray = DetectionUtil.getNewArray(tDev, tIdxs.subList(1, tIdxs.size() - 1));
                    tDev.clear();
                    tDev.addAll(newArray);
                }
            }
            break;
            case CP95_VALUE: {
                List<Integer> aIdxs = DetectionUtil.sort(aStandardDev, false);
                List<Integer> bIdxs = DetectionUtil.sort(bStandardDev, false);
                List<Integer> cIdxs = DetectionUtil.sort(cStandardDev, false);
                List<Integer> tIdxs = DetectionUtil.sort(tStandardDev, false);
                if (CollUtil.isNotEmpty(aStandardDev)) {
                    int cp95Idx = DetectionUtil.getCP95Idx(aStandardDev);
                    aStandardDev = Collections.singletonList(aStandardDev.get(cp95Idx));
                    aDev = Collections.singletonList(aDev.get(aIdxs.get(cp95Idx)));
                }
                if (CollUtil.isNotEmpty(bStandardDev)) {
                    int cp95Idx = DetectionUtil.getCP95Idx(bStandardDev);
                    bStandardDev = Collections.singletonList(bStandardDev.get(cp95Idx));
                    bDev = Collections.singletonList(bDev.get(bIdxs.get(cp95Idx)));
                }
                if (CollUtil.isNotEmpty(cStandardDev)) {
                    int cp95Idx = DetectionUtil.getCP95Idx(cStandardDev);
                    cStandardDev = Collections.singletonList(cStandardDev.get(cp95Idx));
                    cDev = Collections.singletonList(cDev.get(cIdxs.get(cp95Idx)));
                }
                if (CollUtil.isNotEmpty(tStandardDev)) {
                    int cp95Idx = DetectionUtil.getCP95Idx(tStandardDev);
                    tStandardDev = Collections.singletonList(tStandardDev.get(cp95Idx));
                    tDev = Collections.singletonList(tDev.get(tIdxs.get(cp95Idx)));
                }
            }
            break;
            case AVG_VALUE:
                aDev = DetectionUtil.getAvgDoubles(aDev);
                bDev = DetectionUtil.getAvgDoubles(bDev);
                cDev = DetectionUtil.getAvgDoubles(cDev);
                tDev = DetectionUtil.getAvgDoubles(tDev);

                aStandardDev = DetectionUtil.getAvgDoubles(aStandardDev);
                bStandardDev = DetectionUtil.getAvgDoubles(bStandardDev);
                cStandardDev = DetectionUtil.getAvgDoubles(cStandardDev);
                tStandardDev = DetectionUtil.getAvgDoubles(tStandardDev);
                break;
            case Own_value:
                break;
            case AT_WILL_VALUE:
                if (isRemoveMaxElement) {
                    if (CollUtil.isNotEmpty(aStandardDev) && CollUtil.isNotEmpty(aDev)) {
                        aStandardDev = aStandardDev.subList(aStandardDev.size() - 1, aStandardDev.size());
                        aDev = aDev.subList(aDev.size() - 1, aDev.size());
                    }
                    if (CollUtil.isNotEmpty(bStandardDev) && CollUtil.isNotEmpty(bDev)) {
                        bStandardDev = bStandardDev.subList(bStandardDev.size() - 1, bStandardDev.size());
                        bDev = bDev.subList(bDev.size() - 1, bDev.size());
                    }
                    if (CollUtil.isNotEmpty(cStandardDev) && CollUtil.isNotEmpty(cDev)) {
                        cStandardDev = cStandardDev.subList(cStandardDev.size() - 1, cStandardDev.size());
                        cDev = cDev.subList(cDev.size() - 1, cDev.size());
                    }
                    if (CollUtil.isNotEmpty(tStandardDev) && CollUtil.isNotEmpty(tDev)) {
                        tStandardDev = tStandardDev.subList(tStandardDev.size() - 1, tStandardDev.size());
                        tDev = tDev.subList(tDev.size() - 1, tDev.size());
                    }
                } else {
                    List<Double> aErrorValueList = new ArrayList<>();
                    List<Double> bErrorValueList = new ArrayList<>();
                    List<Double> cErrorValueList = new ArrayList<>();
                    List<Double> tErrorValueList = new ArrayList<>();
                    for (int i = 0; i < aStandardDev.size(); i++) {
                        aErrorValueList.add(Math.abs(aStandardDev.get(i) - aDev.get(i)));
                    }
                    for (int i = 0; i < bStandardDev.size(); i++) {
                        bErrorValueList.add(Math.abs(bStandardDev.get(i) - bDev.get(i)));
                    }
                    for (int i = 0; i < cStandardDev.size(); i++) {
                        cErrorValueList.add(Math.abs(cStandardDev.get(i) - cDev.get(i)));
                    }
                    for (int i = 0; i < tStandardDev.size(); i++) {
                        tErrorValueList.add(Math.abs(tStandardDev.get(i) - tDev.get(i)));
                    }
                    List<Integer> aErrorValueIdxs = DetectionUtil.sort(aErrorValueList, true);
                    List<Integer> bErrorValueIdxs = DetectionUtil.sort(bErrorValueList, true);
                    List<Integer> cErrorValueIdxs = DetectionUtil.sort(cErrorValueList, true);
                    List<Integer> tErrorValueIdxs = DetectionUtil.sort(tErrorValueList, true);

                    if (CollUtil.isNotEmpty(aStandardDev) && CollUtil.isNotEmpty(aDev)) {
                        Double v = aStandardDev.get(aErrorValueIdxs.get(0));
                        aStandardDev.clear();
                        aStandardDev.add(v);
                        v = aDev.get(aErrorValueIdxs.get(0));
                        aDev.clear();
                        aDev.add(v);
                    }

                    if (CollUtil.isNotEmpty(bStandardDev) && CollUtil.isNotEmpty(bDev)) {
                        Double v = bStandardDev.get(bErrorValueIdxs.get(0));
                        bStandardDev.clear();
                        bStandardDev.add(v);
                        v = bDev.get(bErrorValueIdxs.get(0));
                        bDev.clear();
                        bDev.add(v);
                    }

                    if (CollUtil.isNotEmpty(cStandardDev) && CollUtil.isNotEmpty(cDev)) {
                        Double v = cStandardDev.get(cErrorValueIdxs.get(0));
                        cStandardDev.clear();
                        cStandardDev.add(v);
                        v = cDev.get(cErrorValueIdxs.get(0));
                        cDev.clear();
                        cDev.add(v);
                    }

                    if (CollUtil.isNotEmpty(tStandardDev) && CollUtil.isNotEmpty(tDev)) {
                        Double v = tStandardDev.get(tErrorValueIdxs.get(0));
                        tStandardDev.clear();
                        tStandardDev.add(v);
                        v = tDev.get(tErrorValueIdxs.get(0));
                        tDev.clear();
                        tDev.add(v);
                    }
                }
                break;
        }
        resultMap.put(TYPE_A, Arrays.asList(aDev, aStandardDev));
        resultMap.put(TYPE_B, Arrays.asList(bDev, bStandardDev));
        resultMap.put(TYPE_C, Arrays.asList(cDev, cStandardDev));
        if (CollUtil.isNotEmpty(tDev)) {
            resultMap.put(TYPE_T, Arrays.asList(tDev, tStandardDev));
        }
        return resultMap;
    }

    private Map<String, List<List<Double>>> getPhaseValueList(List<DevData> dev, List<DevData> standardDev, String desc) {
        Map<String, List<List<Double>>> resultMap = new HashMap<>(3);
        List<Double> aDev = new ArrayList<>();
        List<Double> aStandardDev = new ArrayList<>();
        List<Double> bDev = new ArrayList<>();
        List<Double> bStandardDev = new ArrayList<>();
        List<Double> cDev = new ArrayList<>();
        List<Double> cStandardDev = new ArrayList<>();
        List<Double> tDev = new ArrayList<>();
        List<Double> tStandardDev = new ArrayList<>();

        for (int i = 0; i < dev.size(); i++) {
            List<DevData.SqlDataDTO> devSqlData = dev.get(i).getSqlData();
            List<DevData.SqlDataDTO> standardDevSqlData = standardDev.get(i).getSqlData();

            String finalDesc = desc;
            List<DevData.SqlDataDTO.ListDTO> devList = devSqlData.stream().filter(j -> finalDesc.equals(j.getDesc()))
                    .map(DevData.SqlDataDTO::getList).collect(Collectors.toList());
            List<DevData.SqlDataDTO.ListDTO> standardDevList = standardDevSqlData.stream().filter(j -> finalDesc.equals(j.getDesc()))
                    .map(DevData.SqlDataDTO::getList).collect(Collectors.toList());

            if (CollUtil.isEmpty(devList) || CollUtil.isEmpty(standardDevList)) {
                return null;
            }

            aDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getA()))
                    .map(x -> x.getA().doubleValue())
                    .collect(Collectors.toList()));
            aStandardDev.addAll(standardDevList.stream().filter(x -> ObjectUtil.isNotNull(x.getA()))
                    .map(x -> x.getA().doubleValue())
                    .collect(Collectors.toList()));

            bDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getB()))
                    .map(x -> x.getB().doubleValue())
                    .collect(Collectors.toList()));

            bStandardDev.addAll(standardDevList.stream().filter(x -> ObjectUtil.isNotNull(x.getB()))
                    .map(x -> x.getB().doubleValue())
                    .collect(Collectors.toList()));

            cDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getC()))
                    .map(x -> x.getC().doubleValue())
                    .collect(Collectors.toList()));

            cStandardDev.addAll(standardDevList.stream().filter(x -> ObjectUtil.isNotNull(x.getC()))
                    .map(x -> x.getC().doubleValue())
                    .collect(Collectors.toList()));

            tDev.addAll(devList.stream().filter(x -> ObjectUtil.isNotNull(x.getT()))
                    .map(x -> x.getT().doubleValue())
                    .collect(Collectors.toList()));
            tStandardDev.addAll(standardDevList.stream().filter(x -> ObjectUtil.isNotNull(x.getT()))
                    .map(x -> x.getT().doubleValue())
                    .collect(Collectors.toList()));
        }

        resultMap.put(TYPE_A, Arrays.asList(aDev, aStandardDev));
        resultMap.put(TYPE_B, Arrays.asList(bDev, bStandardDev));
        resultMap.put(TYPE_C, Arrays.asList(cDev, cStandardDev));
        resultMap.put(TYPE_T, Arrays.asList(tDev, tStandardDev));

        return resultMap;
    }

    /**
     * 处理谐波类取值
     *
     * @param dev          被检设备原始数据
     * @param standardDev  与之对齐的标准设备原始数据
     * @param fundCode     装置下发基波code
     * @param harmCode     装置下发谐波信息
     * @param harmonicFlag 1：间谐波，2：谐波
     * @param dataRule     数据处理原则
     * @return
     */
    public Map<String, List<Map<Double, List<Double>>>> devHarmListMap(List<DevData> dev,
                                                                       List<DevData> standardDev,
                                                                       String fundCode,
                                                                       String harmCode,
                                                                       Integer harmonicFlag,
                                                                       DictDataEnum dataRule, boolean isRemoveMaxElement) {
        Map<String, List<Map<Double, List<Double>>>> resultMap = new HashMap<>(3);

        // key为相别、value{key为谐波次数，value为按数据处理原则处理后的数据}
        Map<String, Map<Double, List<Double>>> devMap = new HashMap<>(3);
        Map<String, Map<Double, List<Double>>> standardDevMap = new HashMap<>(3);

        List<Double> harmNum = new ArrayList<>();
        if (1 == harmonicFlag) {
            harmNum.addAll(Stream.iterate(0.5, x -> x + 1.0).limit(50).collect(Collectors.toList()));
        } else {
            harmNum.addAll(Stream.iterate(1.0, x -> x + 1.0).limit(50).collect(Collectors.toList()));
        }

        for (int i = 0; i < dev.size(); i++) {
            List<DevData.SqlDataDTO> devSqlData = dev.get(i).getSqlData();
            List<DevData.SqlDataDTO> standardDevSqlData = standardDev.get(i).getSqlData();

            Optional<DevData.SqlDataDTO> first1 = Optional.empty();
            Optional<DevData.SqlDataDTO> first2 = Optional.empty();

            if (CollUtil.isNotEmpty(devSqlData) && CollUtil.isNotEmpty(standardDevSqlData)) {
                first1 = devSqlData.stream().filter(j -> fundCode.equals(j.getDesc())).collect(Collectors.toList()).stream().findFirst();
                first2 = standardDevSqlData.stream().filter(j -> fundCode.equals(j.getDesc())).collect(Collectors.toList()).stream().findFirst();
            }

            DevData.SqlDataDTO fund1 = null;
            DevData.SqlDataDTO fund2 = null;
            if (first1.isPresent()) {
                fund1 = first1.get();
            }
            if (first2.isPresent()) {
                fund2 = first2.get();
            }

            List<DevData.SqlDataHarmDTO> devHarmList = dev.get(i).getSqlDataHarm().stream().filter(x -> harmCode.equals(x.getDesc())).collect(Collectors.toList());
            List<DevData.SqlDataHarmDTO> stdDevHarmList = standardDev.get(i).getSqlDataHarm().stream().filter(x -> harmCode.equals(x.getDesc())).collect(Collectors.toList());

            if (CollUtil.isEmpty(devHarmList) || CollUtil.isEmpty(stdDevHarmList)) {
                return null;
            }

            if (CollUtil.isNotEmpty(devHarmList) && CollUtil.isNotEmpty(stdDevHarmList)) {
                DevData.SqlDataHarmDTO devHarm = devHarmList.get(0);
                DevData.SqlDataHarmDTO stdDevHarm = stdDevHarmList.get(0);
                if (ObjectUtil.isNotNull(fund1) && ObjectUtil.isNotNull(fund2)) {
                    harmPut(TYPE_A, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getA()), harmonicFlag);
                    harmPut(TYPE_A, standardDevMap, harmNum, stdDevHarm, String.valueOf(fund2.getList().getB()), harmonicFlag);
                    harmPut(TYPE_B, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getB()), harmonicFlag);
                    harmPut(TYPE_B, standardDevMap, harmNum, stdDevHarm, String.valueOf(fund2.getList().getC()), harmonicFlag);
                    harmPut(TYPE_C, devMap, harmNum, devHarm, String.valueOf(fund1.getList().getC()), harmonicFlag);
                    harmPut(TYPE_C, standardDevMap, harmNum, stdDevHarm, String.valueOf(fund2.getList().getC()), harmonicFlag);
                } else {
                    harmPut(TYPE_A, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_A, standardDevMap, harmNum, stdDevHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_B, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_B, standardDevMap, harmNum, stdDevHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_C, devMap, harmNum, devHarm, "1.0", harmonicFlag);
                    harmPut(TYPE_C, standardDevMap, harmNum, stdDevHarm, "1.0", harmonicFlag);
                }
            }
        }
        standardDevMap.forEach((phase, harmonicMap) -> {
            harmonicMap.forEach((harmonicNum, value) -> {
                List<Double> devPhaseHarmData = devMap.get(phase).get(harmonicNum);
                if (isRemoveMaxElement) {
                    List<Double> errorValueList = new ArrayList<>();
                    for (int i = 0; i < value.size(); i++) {
                        errorValueList.add(Math.abs(value.get(i) - devPhaseHarmData.get(i)));
                    }

                    List<Integer> idxErrorValueList = DetectionUtil.sort(errorValueList, false);
                    int removeCount = idxErrorValueList.size() / 2;
                    List<Double> newArray = DetectionUtil.getNewArray(value, idxErrorValueList.subList(removeCount, idxErrorValueList.size()));
                    value.clear();
                    value.addAll(newArray);
                    newArray = DetectionUtil.getNewArray(devPhaseHarmData, idxErrorValueList.subList(removeCount, idxErrorValueList.size()));
                    devPhaseHarmData.clear();
                    devPhaseHarmData.addAll(newArray);
                }

                if (CollUtil.isNotEmpty(value)) {

                    switch (dataRule) {
                        case SECTION_VALUE: {
                            List<Integer> idx = DetectionUtil.sort(value, false);
                            if (value.size() > 2) {
                                value.remove(0);
                                value.remove(value.size() - 1);
                                List<Double> newArray = DetectionUtil.getNewArray(devPhaseHarmData, idx.subList(1, idx.size() - 1));
                                devPhaseHarmData.clear();
                                devPhaseHarmData.addAll(newArray);
                            }
                        }
                        break;
                        case CP95_VALUE:
                            if (CollUtil.isNotEmpty(value)) {
                                List<Integer> idx = DetectionUtil.sort(value, false);
                                int cp95Idx = DetectionUtil.getCP95Idx(value);
                                List<Double> newValue = Collections.singletonList(value.get(cp95Idx));
                                value.clear();
                                value.addAll(newValue);
                                Double devCP95Data = devPhaseHarmData.get(idx.get(cp95Idx));
                                devPhaseHarmData.clear();
                                devPhaseHarmData.add(devCP95Data);
                            }
                            break;
                        case AVG_VALUE:
                            List<Double> avgDoubles = DetectionUtil.getAvgDoubles(value);
                            value.clear();
                            value.addAll(avgDoubles);
                            List<Double> devAvgData = DetectionUtil.getAvgDoubles(devMap.get(phase).get(harmonicNum));
                            devPhaseHarmData.clear();
                            devPhaseHarmData.addAll(devAvgData);
                            break;
                        case Own_value:
                            break;
                        case AT_WILL_VALUE:
                            if (isRemoveMaxElement) {
                                if (CollUtil.isNotEmpty(value)) {
                                    Double v = value.get(value.size() - 1);
                                    value.clear();
                                    value.add(v);
                                }
                                if (CollUtil.isNotEmpty(devPhaseHarmData)) {
                                    Double v = devPhaseHarmData.get(devPhaseHarmData.size() - 1);
                                    devPhaseHarmData.clear();
                                    devPhaseHarmData.add(v);
                                }
                            } else {
                                List<Double> errorValueList = new ArrayList<>();
                                for (int i = 0; i < value.size(); i++) {
                                    errorValueList.add(Math.abs(value.get(i) - devPhaseHarmData.get(i)));
                                }

                                List<Integer> idxErrorValueList = DetectionUtil.sort(errorValueList, true);
                                Double v = value.get(idxErrorValueList.get(0));
                                value.clear();
                                value.add(v);
                                v = devPhaseHarmData.get(idxErrorValueList.get(0));
                                devPhaseHarmData.clear();
                                devPhaseHarmData.add(v);
                            }
                            break;
                    }
                }
            });
        });

        resultMap.put(TYPE_A, Arrays.asList(devMap.get(TYPE_A), standardDevMap.get(TYPE_A)));
        resultMap.put(TYPE_B, Arrays.asList(devMap.get(TYPE_B), standardDevMap.get(TYPE_B)));
        resultMap.put(TYPE_C, Arrays.asList(devMap.get(TYPE_C), standardDevMap.get(TYPE_C)));
        return resultMap;
    }

    /**
     * 处理非谐波类取值
     *
     * @param devDataList         被检设备数据
     * @param standardDevDataList 与之对齐的标准设备数据
     * @param pqErrSysDtls        误差体系
     * @param fData               额定值
     * @param scale               小数点精度
     * @param dataRule            数据处理原则
     * @return
     */
    public List<DetectionData> rangeComparisonList(List<Double> devDataList,
                                                   List<Double> standardDevDataList,
                                                   List<PqErrSysDtls> pqErrSysDtls,
                                                   Double fData,
                                                   Integer scale,
                                                   DictDataEnum dataRule) {
        return this.getDetectionDataList(devDataList, standardDevDataList, null, pqErrSysDtls, fData, null, scale, dataRule);
    }

    /**
     * 处理谐波类取值
     *
     * @param devMap         被检设备（间）谐波数据
     * @param standardDevMap 与之对齐的标准设备（间）谐波数据
     * @param pqErrSysDtls   误差体系
     * @param type           U或者I或者HP
     * @param fData          额定值
     * @param scale          小数点精度
     * @param dataRule       数据处理原则
     * @return
     */
    public List<DetectionData> harmRangeComparison(Map<Double, List<Double>> devMap,
                                                   Map<Double, List<Double>> standardDevMap,
                                                   List<PqErrSysDtls> pqErrSysDtls,
                                                   String type,
                                                   Double fData,
                                                   Integer scale,
                                                   DictDataEnum dataRule) {
        List<DetectionData> detectionDataList = new ArrayList<>();
        List<Double> U1List = new ArrayList<>();
        if (U.equals(type)) {
            U1List.addAll(standardDevMap.get(0.0));
        }
        standardDevMap.forEach((harmonicNum, stdDataList) -> {
            if (harmonicNum != 0.0) {
                detectionDataList.addAll(this.getDetectionDataList(devMap.get(harmonicNum), stdDataList, U1List, pqErrSysDtls, fData, harmonicNum, scale, dataRule));
            }
        });
        return detectionDataList;
    }

    /**
     * 获取某一相的检测结果数据
     *
     * @param devDataList         被检设备数据
     * @param standardDevDataList 与之对齐的标准设备数据
     * @param U1List              基波电压有效值
     * @param pqErrSysDtls        误差体系
     * @param fData               额定值
     * @param harmonicNum         (间)谐波次数
     * @param scale               小数点精度
     * @param dataRule            数据处理原则
     * @return
     */
    private List<DetectionData> getDetectionDataList(List<Double> devDataList, List<Double> standardDevDataList, List<Double> U1List, List<PqErrSysDtls> pqErrSysDtls, Double fData, Double harmonicNum, Integer scale, DictDataEnum dataRule) {
        List<DetectionData> detectionDataList = new ArrayList<>();
        boolean flag = false;
        for (int i = 0; i < standardDevDataList.size(); i++) {
            Double U1 = CollUtil.isNotEmpty(U1List) ? U1List.get(i) : null;
            Double stdDevData = BigDecimal.valueOf(standardDevDataList.get(i)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
            Double devData = BigDecimal.valueOf(devDataList.get(i)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
            DetectionData detectionData = new DetectionData();
            detectionData.setIsData(ResultEnum.NO_ERROR_SYS.getValue());

            //获得误差体系
            List<PqErrSysDtls> errSysDtls = pqErrSysDtls.stream().filter(x -> rangeComparison(startRadiusEnd(x.getStartValue(), fData, stdDevData, x.getConditionType(), scale),
                    x.getStartFlag(),
                    startRadiusEnd(x.getEndValue(), fData, stdDevData, x.getConditionType(), scale),
                    x.getEndFlag(),
                    ObjectUtil.isNotNull(U1) ? stdDevData * U1 * 0.01 : stdDevData)).collect(Collectors.toList());
            detectionData.setData(devData);
            detectionData.setResultData(stdDevData);
            if (CollUtil.isNotEmpty(errSysDtls)) {
                detectionData.setNum(harmonicNum);
                PqErrSysDtls errSysDtl = BeanUtil.copyProperties(errSysDtls.get(0), PqErrSysDtls.class);
                detectionData.setUnit(errSysDtl.getErrorUnit());
                detectionData.setErrorDtlId(errSysDtl.getId());
                errSysDtl.setMaxErrorValue(maxErrorMultiply(errSysDtl, fData, ObjectUtil.isNotNull(U1) ? stdDevData * U1 * 0.01 : stdDevData, scale));
                detectionData.setRadius(-errSysDtl.getMaxErrorValue() + "~" + errSysDtl.getMaxErrorValue());

                BigDecimal errorData = devSubtractChannelData(devData, stdDevData, fData, errSysDtl, scale);
                detectionData.setErrorData(errorData);

                boolean in = NumberUtil.isIn(errorData,
                        BigDecimal.valueOf(-errSysDtl.getMaxErrorValue()),
                        BigDecimal.valueOf(errSysDtl.getMaxErrorValue()));

                if (in) {
                    detectionData.setIsData(ResultEnum.QUALIFIED.getValue());
                    if (dataRule == DictDataEnum.AT_WILL_VALUE) {
                        flag = true;
                    }
                } else {
                    detectionData.setIsData(ResultEnum.NOT_QUALIFIED.getValue());
                }
            }
            if (dataRule == DictDataEnum.AT_WILL_VALUE) {
                detectionDataList.clear();
            }
            detectionDataList.add(detectionData);
            if (flag) {
                break;
            }
        }

        return detectionDataList;
    }
}
