package org.jeecg.modules.dynamicStaticAnalysis.algorithm;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.math.MathUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.swagger.models.auth.In;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.modules.checkData.dynamicStaticGeometricData.entity.RailInspectionEquipmentItem;
import org.jeecg.modules.checkData.dynamicStaticGeometricData.entity.RailInspectionEquipmentItemDetail;
import org.jeecg.modules.checkData.dynamicStaticGeometricData.service.IRailInspectionEquipmentItemDetailService;
import org.jeecg.modules.checkData.dynamicStaticGeometricData.service.IRailInspectionEquipmentItemService;
import org.jeecg.modules.checkData.equipmentCheckData.entity.MovementCheckDataUnitDeviceMap;
import org.jeecg.modules.checkData.equipmentCheckData.entity.MovementCourse;
import org.jeecg.modules.checkData.equipmentCheckData.entity.MovementCourseInfo;
import org.jeecg.modules.checkData.equipmentCheckData.service.IMovementCheckDataUnitDeviceMapService;
import org.jeecg.modules.checkData.equipmentCheckData.service.IMovementCourseInfoService;
import org.jeecg.modules.checkData.equipmentCheckData.service.IMovementCourseService;
import org.jeecg.modules.dynamicStaticAnalysis.entity.*;
import org.jeecg.modules.dynamicStaticAnalysis.mapper.AnalysisAlgorithmMapper;
import org.jeecg.modules.dynamicStaticAnalysis.service.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 分析算法
 */
@Service
public class AnalysisAlgorithm {
    @Resource
    private AnalysisAlgorithmMapper analysisAlgorithmMapper;
    @Resource
    private IAnalysisBatchService analysisBatchService;
    @Resource
    private IAnalysisBatchCheckDataMapService analysisBatchCheckDataMapService;
    @Resource
    private IMovementCourseInfoService movementCourseInfoService;
    @Resource
    private IMovementCourseService movementCourseService;
    @Resource
    private IRailInspectionEquipmentItemService railInspectionEquipmentItemService;
    @Resource
    private IRailInspectionEquipmentItemDetailService railInspectionEquipmentItemDetailService;
    @Resource
    private IMovementCheckDataUnitDeviceMapService movementCheckDataUnitDeviceMapService;
    @Resource
    private IAnalysisBatchUnitDeviceService analysisBatchUnitDeviceService;
    @Resource
    private IAnalysisBatchUnitDeviceTransfiniteService analysisBatchUnitDeviceTransfiniteService;
    @Resource
    private IAnalysisBatchUnitDevicePointScoreService analysisBatchUnitDevicePointScoreService;
    @Resource
    private IConfigLabourCheckService configLabourCheckService;

    /**
     * 分析
     */
    public void analysis(String analysisBatchId) {
        // 1.映射单元格
        // 1.1 获取分析批次数据
        AnalysisBatch analysisBatch = analysisBatchService.getById(analysisBatchId);
        List<AnalysisBatchCheckDataMap> analysisBatchCheckDataMapList = analysisBatchCheckDataMapService.lambdaQuery()
                .eq(AnalysisBatchCheckDataMap::getAnalysisBatchId, analysisBatchId)
                .list();
        // 1.2 按公里数正序排序所有1-钢轨,2-曲线,3-竖曲线,4-道岔
        List<Map<String, Object>> unitDeviceList = analysisAlgorithmMapper.getUnitDevice(analysisBatch.getLightRailId(), analysisBatch.getLineAliasId());

        Map<String, Map<String, Object>> unitDeviceTable = new TreeMap<>();

        // 1.3 获取检查数据
        for (AnalysisBatchCheckDataMap checkDataMap : analysisBatchCheckDataMapList) {


            // 检查数据类型 1-人工静态检查 2-轨检仪静态检查 3-轨检车检查 4-添乘仪检查
            if (1 == checkDataMap.getEkType()) {
                List<MovementCheckDataUnitDeviceMap> movementCheckDataUnitDeviceMaps = new ArrayList<>();

                // 1 获取人工检查数据
                List<MovementCourse> checkItemList = movementCourseService.lambdaQuery()
                        .eq(MovementCourse::getMovementMasterId, checkDataMap.getEkId())
                        .list();
                List<MovementCourseInfo> checkItemItemDetailList = movementCourseInfoService.lambdaQuery()
                        .eq(MovementCourseInfo::getMovementMasterId, checkDataMap.getEkId())
                        .list();
                Map<String, List<MovementCourseInfo>> checkItemItemDetailMap = checkItemItemDetailList.stream()
                        .collect(Collectors.groupingBy(MovementCourseInfo::getMovementCourseId));

                // 2 循环遍历检查项目比较【开始-结束】来映射关联关系
                for (MovementCourse checkItem : checkItemList) {
                    // 2.1 这里可能出现开始时间比结束时间大的情况
                    BigDecimal checkItemStartingMileage = checkItem.getCourseStartingMileage();
                    BigDecimal checkItemEndMileage = checkItem.getCourseEndMileage();
                    if (checkItemStartingMileage.compareTo(checkItemEndMileage) > 0) {
                        checkItemStartingMileage = checkItem.getCourseEndMileage();
                        checkItemEndMileage = checkItem.getCourseStartingMileage();
                    }


                    // 2.2 单元设备中心里程落在检查项目【开始-结束】这个区间视为这个区间的单元设备
                    for (Map<String, Object> unitDevice : unitDeviceList) {
                        BigDecimal startMileage = Convert.toBigDecimal(unitDevice.get("startMileage"));
                        BigDecimal endMileage = Convert.toBigDecimal(unitDevice.get("endMileage"));
                        BigDecimal centerMileage = startMileage.add(endMileage).divide(new BigDecimal("2"), 3, RoundingMode.HALF_UP);
                        unitDevice.put("centerMileage", centerMileage);
                        // 2.2.1 命中检查项目
                        if (checkItemStartingMileage.compareTo(centerMileage) <= 0 && checkItemEndMileage.compareTo(centerMileage) > 0) {
                            List<MovementCourseInfo> movementCourseInfos = checkItemItemDetailMap.get(checkItem.getId());
                            if (ObjectUtil.isNotEmpty(movementCourseInfos)) {
                                // 1 处理3个格子映射问题
                                Map<String, List<MovementCourseInfo>> trackCodeMap = movementCourseInfos.stream()
                                        .collect(Collectors.groupingBy(MovementCourseInfo::getTrackCode));
                                int size = trackCodeMap.size();
                                BigDecimal averageDec = checkItemEndMileage.subtract(checkItemStartingMileage).divide(new BigDecimal(size), 3, RoundingMode.HALF_UP);
                                List<String> trackCodes = trackCodeMap.keySet().stream()
                                        .mapToInt(Integer::valueOf)
                                        .sorted()
                                        .mapToObj(String::valueOf)
                                        .collect(Collectors.toList());
                                BigDecimal currentStartMileage = checkItemStartingMileage;
                                BigDecimal currentEndEndMileage = checkItemStartingMileage.add(averageDec);
                                for (String trackCode : trackCodes) {
                                    // 2.命中格子
                                    if (currentStartMileage.compareTo(centerMileage) <= 0 && currentEndEndMileage.compareTo(centerMileage) > 0) {
                                        String unitCode = Convert.toStr(unitDevice.get("unitCode"));
                                        // 人工检查数据
                                        List<MovementCourseInfo> labourCheck = trackCodeMap.get(trackCode);
                                        unitDevice.put("labourCheck", labourCheck);
                                        unitDeviceTable.putIfAbsent(unitCode, unitDevice);

                                        // 保存单元-测点数据
                                        for (MovementCourseInfo movementCourseInfo : labourCheck) {
                                            MovementCheckDataUnitDeviceMap movementCheckDataUnitDeviceMap = new MovementCheckDataUnitDeviceMap();
                                            movementCheckDataUnitDeviceMap.setId(UUIDGenerator.generate());
                                            movementCheckDataUnitDeviceMap.setCheckType(1);// 人工检查
                                            movementCheckDataUnitDeviceMap.setUnitId(Convert.toStr(unitDevice.get("id")));
                                            movementCheckDataUnitDeviceMap.setUnitCode(Convert.toStr(unitDevice.get("unitCode")));
                                            movementCheckDataUnitDeviceMap.setUnitType(Convert.toInt(unitDevice.get("type")));
                                            movementCheckDataUnitDeviceMap.setUnitTypeName(Convert.toStr(unitDevice.get("typeName")));
                                            movementCheckDataUnitDeviceMap.setUnitStartingMileage(Convert.toBigDecimal(unitDevice.get("startMileage")));
                                            movementCheckDataUnitDeviceMap.setUnitCenterMileage(centerMileage);
                                            movementCheckDataUnitDeviceMap.setUnitEndMileage(Convert.toBigDecimal(unitDevice.get("endMileage")));
                                            movementCheckDataUnitDeviceMap.setCheckId(checkItem.getMovementMasterId());
                                            movementCheckDataUnitDeviceMap.setCheckItemId(checkItem.getId());
                                            movementCheckDataUnitDeviceMap.setCheckItemStartingMileage(checkItem.getCourseStartingMileage());
                                            movementCheckDataUnitDeviceMap.setCheckItemEndMileage(checkItem.getCourseEndMileage());
                                            movementCheckDataUnitDeviceMap.setCheckItemText(movementCourseInfo.getTrackCode());
                                            movementCheckDataUnitDeviceMap.setCheckDetailId(movementCourseInfo.getId());
                                            movementCheckDataUnitDeviceMap.setCheckDetailStartingMileage(currentStartMileage);
                                            movementCheckDataUnitDeviceMap.setCheckDetailEndMileage(currentEndEndMileage);
                                            movementCheckDataUnitDeviceMap.setTrackGauge(movementCourseInfo.getTrackGauge());
                                            movementCheckDataUnitDeviceMap.setLevel(movementCourseInfo.getLevel());
                                            movementCheckDataUnitDeviceMap.setTriangularPit(movementCourseInfo.getTriangularPit());
                                            movementCheckDataUnitDeviceMap.setMeasurePoint(movementCourseInfo.getMeasurePoint());
                                            movementCheckDataUnitDeviceMap.setDirection(movementCourseInfo.getDirection());
                                            movementCheckDataUnitDeviceMap.setHeight(movementCourseInfo.getHeight());
                                            movementCheckDataUnitDeviceMap.setStructure(movementCourseInfo.getStructure());
                                            movementCheckDataUnitDeviceMap.setRectification(movementCourseInfo.getRectification());
                                            movementCheckDataUnitDeviceMaps.add(movementCheckDataUnitDeviceMap);
                                        }

                                    }
                                    currentStartMileage = currentEndEndMileage;
                                    currentEndEndMileage = currentEndEndMileage.add(averageDec);
                                }

                            }
                        }
                    }
                }

                // 保存之前先删除
                movementCheckDataUnitDeviceMapService.lambdaUpdate().eq(MovementCheckDataUnitDeviceMap::getCheckId, checkDataMap.getEkId()).remove();
                movementCheckDataUnitDeviceMapService.saveBatch(movementCheckDataUnitDeviceMaps);
            } else if (2 == checkDataMap.getEkType()) {
                List<MovementCheckDataUnitDeviceMap> movementCheckDataUnitDeviceMaps = new ArrayList<>();

                // 1 获取轨检仪静态检查
                List<RailInspectionEquipmentItem> checkItemList = railInspectionEquipmentItemService.lambdaQuery()
                        .eq(RailInspectionEquipmentItem::getRailInspectionEquipmentId, checkDataMap.getEkId())
                        .list();
                List<RailInspectionEquipmentItemDetail> checkItemItemDetailList = railInspectionEquipmentItemDetailService.lambdaQuery()
                        .eq(RailInspectionEquipmentItemDetail::getRailInspectionEquipmentId, checkDataMap.getEkId())
                        .list();
                Map<String, List<RailInspectionEquipmentItemDetail>> checkItemItemDetailMap = checkItemItemDetailList.stream()
                        .collect(Collectors.groupingBy(RailInspectionEquipmentItemDetail::getRailInspectionEquipmentItemId));

                // 2 循环遍历检查项目比较【开始-结束】来映射关联关系
                for (RailInspectionEquipmentItem checkItem : checkItemList) {
                    // 2.1 这里可能出现开始时间比结束时间大的情况
                    BigDecimal checkItemStartingMileage = checkItem.getCourseStartingMileage();
                    BigDecimal checkItemEndMileage = checkItem.getCourseEndMileage();
                    if (checkItemStartingMileage.compareTo(checkItemEndMileage) > 0) {
                        checkItemStartingMileage = checkItem.getCourseEndMileage();
                        checkItemEndMileage = checkItem.getCourseStartingMileage();
                    }


                    // 2.2 单元设备中心里程落在检查项目【开始-结束】这个区间视为这个区间的单元设备
                    for (Map<String, Object> unitDevice : unitDeviceList) {
                        BigDecimal startMileage = Convert.toBigDecimal(unitDevice.get("startMileage"));
                        BigDecimal endMileage = Convert.toBigDecimal(unitDevice.get("endMileage"));
                        BigDecimal centerMileage = startMileage.add(endMileage).divide(new BigDecimal("2"), 3, RoundingMode.HALF_UP);
                        unitDevice.put("centerMileage", centerMileage);

                        // 2.2.1 命中检查项目
                        if (checkItemStartingMileage.compareTo(centerMileage) <= 0 && checkItemEndMileage.compareTo(centerMileage) > 0) {
                            List<RailInspectionEquipmentItemDetail> movementCourseInfos = checkItemItemDetailMap.get(checkItem.getId());
                            for (RailInspectionEquipmentItemDetail info : movementCourseInfos) {
                                String checkItemKey = info.getCheckItem();
                                BigDecimal bigDecimal = new BigDecimal(checkItemKey);
                                BigDecimal multiply = bigDecimal.multiply(new BigDecimal("1000"));
                                info.setCheckItem(String.valueOf(multiply.intValue()));
                            }

                            if (ObjectUtil.isNotEmpty(movementCourseInfos)) {
                                // 1.处理3个格子映射问题
                                Map<String, List<RailInspectionEquipmentItemDetail>> trackCodeMap = movementCourseInfos.stream()
                                        .collect(Collectors.groupingBy(RailInspectionEquipmentItemDetail::getCheckItem));
                                int size = trackCodeMap.size();
                                BigDecimal averageDec = checkItemEndMileage.subtract(checkItemStartingMileage).divide(new BigDecimal(size), 3, RoundingMode.HALF_UP);

                                List<String> trackCodes = trackCodeMap.keySet().stream()
                                        .mapToInt(Integer::valueOf)
                                        .sorted()
                                        .mapToObj(String::valueOf)
                                        .collect(Collectors.toList());
                                BigDecimal currentStartMileage = checkItemStartingMileage;
                                BigDecimal currentEndEndMileage = checkItemStartingMileage.add(averageDec);
                                for (String trackCode : trackCodes) {
                                    // 2.命中格子
                                    if (currentStartMileage.compareTo(centerMileage) <= 0 && currentEndEndMileage.compareTo(centerMileage) > 0) {
                                        String unitCode = Convert.toStr(unitDevice.get("unitCode"));
                                        // 轨检仪检查数据
                                        List<RailInspectionEquipmentItemDetail> railDevice = trackCodeMap.get(trackCode);
                                        unitDevice.put("railDevice", railDevice);

                                        unitDeviceTable.putIfAbsent(unitCode, unitDevice);

                                        // 保存单元-测点数据
                                        // 保存单元-测点数据
                                        for (RailInspectionEquipmentItemDetail movementCourseInfo : railDevice) {
                                            MovementCheckDataUnitDeviceMap movementCheckDataUnitDeviceMap = new MovementCheckDataUnitDeviceMap();
                                            movementCheckDataUnitDeviceMap.setId(UUIDGenerator.generate());
                                            movementCheckDataUnitDeviceMap.setCheckType(2);// 2-轨检仪静态检查
                                            movementCheckDataUnitDeviceMap.setUnitId(Convert.toStr(unitDevice.get("id")));
                                            movementCheckDataUnitDeviceMap.setUnitCode(Convert.toStr(unitDevice.get("unitCode")));
                                            movementCheckDataUnitDeviceMap.setUnitType(Convert.toInt(unitDevice.get("type")));
                                            movementCheckDataUnitDeviceMap.setUnitTypeName(Convert.toStr(unitDevice.get("typeName")));
                                            movementCheckDataUnitDeviceMap.setUnitStartingMileage(Convert.toBigDecimal(unitDevice.get("startMileage")));
                                            movementCheckDataUnitDeviceMap.setUnitCenterMileage(centerMileage);
                                            movementCheckDataUnitDeviceMap.setUnitEndMileage(Convert.toBigDecimal(unitDevice.get("endMileage")));
                                            movementCheckDataUnitDeviceMap.setCheckId(checkItem.getRailInspectionEquipmentId());
                                            movementCheckDataUnitDeviceMap.setCheckItemId(checkItem.getRailInspectionEquipmentId());
                                            movementCheckDataUnitDeviceMap.setCheckItemStartingMileage(checkItem.getCourseStartingMileage());
                                            movementCheckDataUnitDeviceMap.setCheckItemEndMileage(checkItem.getCourseEndMileage());
                                            movementCheckDataUnitDeviceMap.setCheckItemText(movementCourseInfo.getCheckItem());
                                            movementCheckDataUnitDeviceMap.setCheckDetailId(movementCourseInfo.getId());
                                            movementCheckDataUnitDeviceMap.setCheckDetailStartingMileage(currentStartMileage);
                                            movementCheckDataUnitDeviceMap.setCheckDetailEndMileage(currentEndEndMileage);
                                            movementCheckDataUnitDeviceMap.setTrackGauge(movementCourseInfo.getTrackGauge());
                                            movementCheckDataUnitDeviceMap.setLevel(movementCourseInfo.getLevel());
                                            movementCheckDataUnitDeviceMap.setTriangularPit(movementCourseInfo.getTriangularPit());
                                            movementCheckDataUnitDeviceMap.setMeasurePoint(movementCourseInfo.getMeasurePoint());
                                            movementCheckDataUnitDeviceMaps.add(movementCheckDataUnitDeviceMap);
                                        }
                                    }
                                    currentStartMileage = currentEndEndMileage;
                                    currentEndEndMileage = currentEndEndMileage.add(averageDec);
                                }
                            }
                        }
                    }
                }
                // 保存之前先删除
                movementCheckDataUnitDeviceMapService.lambdaUpdate().eq(MovementCheckDataUnitDeviceMap::getCheckId, checkDataMap.getEkId()).remove();
                movementCheckDataUnitDeviceMapService.saveBatch(movementCheckDataUnitDeviceMaps);
            } else if (3 == checkDataMap.getEkType()) {

            } else {

            }
        }


        // 2.计算超限&计算评分
        if (ObjectUtil.isNotEmpty(unitDeviceTable)) {
            for (Map.Entry<String, Map<String, Object>> entry : unitDeviceTable.entrySet()) {
                Map<String, Object> unitDevice = entry.getValue();

                // 1.计算超限
                List<MovementCourseInfo> labourCheckList = (List<MovementCourseInfo>) unitDevice.get("labourCheck");
                if (ObjectUtil.isNotEmpty(labourCheckList)) {
                    // 1.计算超限
                    JSONObject allowValue = JSONObject.parseObject(analysisBatch.getAllowValue());
                    Integer bigTrackGauge = Convert.toInt(allowValue.get("bigTrackGauge")); // 大轨距
                    Integer smallTrackGauge = Convert.toInt(allowValue.get("smallTrackGauge")); // 小轨距
                    Integer allowLevel = Convert.toInt(allowValue.get("level")); // 水平
                    Integer allowTriangularPit = Convert.toInt(allowValue.get("triangularPit")); // 三角坑
                    Integer allowHeight = Convert.toInt(allowValue.get("height")); // 高低
                    Integer allowDirection = Convert.toInt(allowValue.get("direction")); // 轨向


                    boolean isTransfinite = false;
                    String allowValueSave = "";
                    String measurePointValue = "";
                    String transfiniteType = "";
                    for (MovementCourseInfo movementCourseInfo : labourCheckList) {

                        // 轨距
                        Integer trackGauge = Convert.toInt(movementCourseInfo.getTrackGauge());
                        if (ObjectUtil.isNotEmpty(trackGauge)) {
                            if (trackGauge > bigTrackGauge) {
                                isTransfinite = true;
                                allowValueSave = bigTrackGauge.toString();
                                measurePointValue = trackGauge.toString();
                                transfiniteType = "大轨距";
                                break;
                            } else if (trackGauge < smallTrackGauge) {
                                isTransfinite = true;
                                allowValueSave = smallTrackGauge.toString();
                                measurePointValue = trackGauge.toString();
                                transfiniteType = "小轨距";
                                break;
                            }
                        }

                        // 水平
                        Integer level = Convert.toInt(movementCourseInfo.getLevel());
                        if (ObjectUtil.isNotEmpty(level)) {
                            if (level > allowLevel) {
                                isTransfinite = true;
                                allowValueSave = allowLevel.toString();
                                measurePointValue = level.toString();
                                transfiniteType = "水平";
                                break;
                            }
                        }

                        //三角坑
                        Integer triangularPit = Convert.toInt(movementCourseInfo.getTriangularPit());
                        if (ObjectUtil.isNotEmpty(triangularPit)) {
                            if (triangularPit > allowTriangularPit) {
                                isTransfinite = true;
                                allowValueSave = allowTriangularPit.toString();
                                measurePointValue = triangularPit.toString();
                                transfiniteType = "三角坑";
                                break;
                            }
                        }

                        // 高低
                        Integer height = Convert.toInt(movementCourseInfo.getHeight());
                        if (ObjectUtil.isNotEmpty(height)) {
                            if (height > allowHeight) {
                                isTransfinite = true;
                                allowValueSave = allowHeight.toString();
                                measurePointValue = height.toString();
                                transfiniteType = "高低";
                                break;
                            }
                        }

                        // 轨向
                        Integer direction = Convert.toInt(movementCourseInfo.getDirection());
                        if (ObjectUtil.isNotEmpty(direction)) {
                            if (direction > allowDirection) {
                                isTransfinite = true;
                                allowValueSave = allowDirection.toString();
                                measurePointValue = direction.toString();
                                transfiniteType = "轨向";
                                break;
                            }
                        }


                    }

                    Integer isWork = 1;
                    String reasonLabel = "";
                    JSONArray dispatchingList = JSONArray.parseArray(analysisBatch.getDispatching());
                    for (Object obj : dispatchingList) {
                        JSONObject dispatching = (JSONObject) obj;
                        String reasonValue = String.valueOf(dispatching.get("reasonValue"));
                        reasonLabel = String.valueOf(dispatching.get("reasonLabel"));
                        if ("static_limit".equals(reasonValue)) {
                            Boolean isWorkTemp = Boolean.valueOf(dispatching.get("isWork").toString());
                            if (isWorkTemp) {
                                isWork = 1;
                            } else {
                                isWork = 0;
                            }
                        }
                    }

                    // 超限
                    if (isTransfinite) {
                        AnalysisBatchUnitDeviceTransfinite analysisBatchUnitDeviceTransfinite = new AnalysisBatchUnitDeviceTransfinite();
                        analysisBatchUnitDeviceTransfinite.setId(UUIDGenerator.generate());
                        analysisBatchUnitDeviceTransfinite.setTransfiniteGrade(1);
                        analysisBatchUnitDeviceTransfinite.setTransfiniteGradeName(reasonLabel);
                        analysisBatchUnitDeviceTransfinite.setTransfiniteType(transfiniteType);
                        analysisBatchUnitDeviceTransfinite.setAllowValue(allowValueSave);
                        analysisBatchUnitDeviceTransfinite.setMeasurePointValue(measurePointValue);
                        analysisBatchUnitDeviceTransfinite.setIsWork(isWork);
                        unitDevice.put("transfinite", analysisBatchUnitDeviceTransfinite);
                    }


                }


                // 2.计算评分
                if (ObjectUtil.isNotEmpty(labourCheckList)) {
                    Integer analysisType = analysisBatch.getAnalysisType();

                    Integer finalTrackGauge = null;
                    Integer finalLevel = null;
                    Integer finalTriangularPit = null;
                    Integer finalHeight = null;
                    Integer finalDirection = null;

                    int sumTrackGauge = 0;
                    int sumLevel = 0;
                    int sumTriangularPit = 0;
                    int sumHeight = 0;
                    int sumDirection = 0;

                    int maxTrackGauge = 0;
                    int maxLevel = 0;
                    int maxTriangularPit = 0;
                    int maxHeight = 0;
                    int maxDirection = 0;

                    int avgTrackGauge = 0;
                    int avgLevel = 0;
                    int avgTriangularPit = 0;
                    int avgHeight = 0;
                    int avgDirection = 0;


                    int trackGaugeSize = 0;
                    int levelSize = 0;
                    int triangularPitSize = 0;
                    int heightSize = 0;
                    int directionSize = 0;

                    // 循环计算均值/峰值
                    for (MovementCourseInfo movementCourseInfo : labourCheckList) {
                        // 轨距
                        Integer trackGauge = Convert.toInt(movementCourseInfo.getTrackGauge());
                        if (ObjectUtil.isNotEmpty(trackGauge)) {
                            trackGauge = Math.abs(trackGauge);
                            // 均值
                            sumTrackGauge = sumTrackGauge + trackGauge;
                            trackGaugeSize++;
                            avgTrackGauge = sumTrackGauge / trackGaugeSize;
                            // 峰值
                            if (trackGauge > maxTrackGauge) {
                                maxTrackGauge = trackGauge;
                            }

                            if (1 == analysisType) {
                                finalTrackGauge = avgTrackGauge;
                            } else {
                                finalTrackGauge = maxLevel;
                            }

                        }

                        // 水平
                        Integer level = Convert.toInt(movementCourseInfo.getLevel());
                        if (ObjectUtil.isNotEmpty(level)) {
                            level = Math.abs(level);
                            // 均值
                            sumLevel = sumLevel + level;
                            levelSize++;
                            avgLevel = sumLevel / levelSize;
                            // 峰值
                            if (level > maxLevel) {
                                maxLevel = level;
                            }

                            if (1 == analysisType) {
                                finalLevel = avgLevel;
                            } else {
                                finalLevel = maxLevel;
                            }
                        }

                        //三角坑
                        Integer triangularPit = Convert.toInt(movementCourseInfo.getTriangularPit());
                        if (ObjectUtil.isNotEmpty(triangularPit)) {
                            triangularPit = Math.abs(triangularPit);
                            // 均值
                            sumTriangularPit = sumTriangularPit + triangularPit;
                            triangularPitSize++;
                            avgTriangularPit = sumTriangularPit / triangularPitSize;
                            // 峰值
                            if (triangularPit > maxTriangularPit) {
                                maxTriangularPit = triangularPit;
                            }

                            if (1 == analysisType) {
                                finalTriangularPit = avgTriangularPit;
                            } else {
                                finalTriangularPit = maxTriangularPit;
                            }
                        }

                        // 高低
                        Integer height = Convert.toInt(movementCourseInfo.getHeight());
                        if (ObjectUtil.isNotEmpty(height)) {
                            height = Math.abs(height);
                            // 均值
                            sumHeight = sumHeight + height;
                            heightSize++;
                            avgHeight = sumHeight / heightSize;
                            // 峰值
                            if (height > maxHeight) {
                                maxHeight = height;
                            }

                            if (1 == analysisType) {
                                finalHeight = avgHeight;
                            } else {
                                finalHeight = maxHeight;
                            }
                        }


                        // 轨向
                        Integer direction = Convert.toInt(movementCourseInfo.getDirection());
                        if (ObjectUtil.isNotEmpty(direction)) {
                            direction = Math.abs(direction);
                            // 均值
                            sumDirection = sumDirection + direction;
                            directionSize++;
                            avgDirection = sumDirection / directionSize;
                            // 峰值
                            if (direction > maxDirection) {
                                maxDirection = direction;
                            }

                            if (1 == analysisType) {
                                finalDirection = avgDirection;
                            } else {
                                finalDirection = maxDirection;
                            }
                        }
                    }

                    ConfigLabourCheck configLabour = configLabourCheckService.lambdaQuery()
                            .eq(ConfigLabourCheck::getSpeedMax, analysisBatch.getSpeedMax())
                            .eq(ConfigLabourCheck::getSpeedMin, analysisBatch.getSpeedMin())
                            .eq(ConfigLabourCheck::getDelFlag, "0")
                            .last("limit 1")
                            .one();

                    // 1-钢轨,2-曲线,3-竖曲线,4-道岔
                    Integer type = Convert.toInt(unitDevice.get("type"));
                    JSONObject jsonObject = null;
                    if (type == 1) {
                        jsonObject = JSONObject.parseObject(configLabour.getRail());
                    } else if (type == 2) {
                        jsonObject = JSONObject.parseObject(configLabour.getCurve());
                    } else if (type == 3) {
                        jsonObject = JSONObject.parseObject(configLabour.getVerticalCurve());
                    } else if (type == 4) {
                        jsonObject = JSONObject.parseObject(configLabour.getRailSwitch());
                    }

                    BigDecimal trackGaugeWeightValues = jsonObject.getBigDecimal("trackGauge");
                    BigDecimal directionWeightValues = jsonObject.getBigDecimal("direction");
                    BigDecimal triangularPitWeightValues = jsonObject.getBigDecimal("triangularPit");
                    BigDecimal heightWeightValues = jsonObject.getBigDecimal("height");
                    BigDecimal levelWeightValues = jsonObject.getBigDecimal("level");
                    // 总单元得分
                    BigDecimal sumUnitScore = null;
                    // 轨距单元得分
                    BigDecimal trackGaugeUnitScore;
                    List<AnalysisBatchUnitDevicePointScore> scoreList = new ArrayList<>();
                    if (ObjectUtil.isNotEmpty(finalTrackGauge)) {
                        trackGaugeUnitScore = trackGaugeWeightValues.multiply(new BigDecimal(finalTrackGauge.toString()));
                        if (sumUnitScore == null) {
                            sumUnitScore = BigDecimal.ZERO;
                        }
                        sumUnitScore = sumUnitScore.add(trackGaugeUnitScore);

                        AnalysisBatchUnitDevicePointScore score = new AnalysisBatchUnitDevicePointScore();
                        score.setId(UUIDGenerator.generate());
                        score.setAnalysisType(analysisType);
                        score.setSpeedMax(analysisBatch.getSpeedMax());
                        score.setSpeedMin(analysisBatch.getSpeedMin());
                        score.setAnalysisBatchId(analysisBatch.getId());
                        score.setAnalysisBatchCode(analysisBatch.getAnalysisBatchCode());
                        score.setAnalysisBatchUnitDeviceId("轨距");
                        score.setPointValue(finalTrackGauge);
                        score.setWeightValues(trackGaugeWeightValues);
                        score.setPointScore(trackGaugeUnitScore);
                        scoreList.add(score);


                    }
                    // 轨向单元得分
                    BigDecimal directionGaugeUnitScore = null;
                    if (ObjectUtil.isNotEmpty(finalDirection)) {
                        directionGaugeUnitScore = directionWeightValues.multiply(new BigDecimal(finalDirection.toString()));

                        if (sumUnitScore == null) {
                            sumUnitScore = BigDecimal.ZERO;
                        }
                        sumUnitScore = sumUnitScore.add(directionGaugeUnitScore);

                        AnalysisBatchUnitDevicePointScore score = new AnalysisBatchUnitDevicePointScore();
                        score.setId(UUIDGenerator.generate());
                        score.setAnalysisType(analysisType);
                        score.setSpeedMax(analysisBatch.getSpeedMax());
                        score.setSpeedMin(analysisBatch.getSpeedMin());
                        score.setAnalysisBatchId(analysisBatch.getId());
                        score.setAnalysisBatchCode(analysisBatch.getAnalysisBatchCode());
                        score.setAnalysisBatchUnitDeviceId("轨向");
                        score.setPointValue(finalDirection);
                        score.setWeightValues(directionGaugeUnitScore);
                        score.setPointScore(directionGaugeUnitScore);
                        scoreList.add(score);
                    }
                    // 三角坑单元得分
                    BigDecimal triangularPitGaugeUnitScore;
                    if (ObjectUtil.isNotEmpty(finalTriangularPit)) {
                        triangularPitGaugeUnitScore = triangularPitWeightValues.multiply(new BigDecimal(finalTriangularPit.toString()));
                        if (sumUnitScore == null) {
                            sumUnitScore = BigDecimal.ZERO;
                        }
                        sumUnitScore = sumUnitScore.add(triangularPitGaugeUnitScore);

                        AnalysisBatchUnitDevicePointScore score = new AnalysisBatchUnitDevicePointScore();
                        score.setId(UUIDGenerator.generate());
                        score.setAnalysisType(analysisType);
                        score.setSpeedMax(analysisBatch.getSpeedMax());
                        score.setSpeedMin(analysisBatch.getSpeedMin());
                        score.setAnalysisBatchId(analysisBatch.getId());
                        score.setAnalysisBatchCode(analysisBatch.getAnalysisBatchCode());
                        score.setAnalysisBatchUnitDeviceId("三角坑");
                        score.setPointValue(finalTriangularPit);
                        score.setWeightValues(triangularPitWeightValues);
                        score.setPointScore(triangularPitGaugeUnitScore);
                        scoreList.add(score);
                    }
                    // 高低单元得分
                    BigDecimal heightGaugeUnitScore;
                    if (ObjectUtil.isNotEmpty(finalHeight)) {
                        heightGaugeUnitScore = heightWeightValues.multiply(new BigDecimal(finalHeight.toString()));
                        if (sumUnitScore == null) {
                            sumUnitScore = BigDecimal.ZERO;
                        }
                        sumUnitScore = sumUnitScore.add(heightGaugeUnitScore);

                        AnalysisBatchUnitDevicePointScore score = new AnalysisBatchUnitDevicePointScore();
                        score.setId(UUIDGenerator.generate());
                        score.setAnalysisType(analysisType);
                        score.setSpeedMax(analysisBatch.getSpeedMax());
                        score.setSpeedMin(analysisBatch.getSpeedMin());
                        score.setAnalysisBatchId(analysisBatch.getId());
                        score.setAnalysisBatchCode(analysisBatch.getAnalysisBatchCode());
                        score.setAnalysisBatchUnitDeviceId("高低");
                        score.setPointValue(finalHeight);
                        score.setWeightValues(heightWeightValues);
                        score.setPointScore(heightGaugeUnitScore);
                        scoreList.add(score);
                    }
                    // 水平单元得分
                    BigDecimal levelUnitScore;
                    if (ObjectUtil.isNotEmpty(finalLevel)) {
                        levelUnitScore = levelWeightValues.multiply(new BigDecimal(finalLevel.toString()));
                        if (sumUnitScore == null) {
                            sumUnitScore = BigDecimal.ZERO;
                        }
                        sumUnitScore = sumUnitScore.add(levelUnitScore);

                        AnalysisBatchUnitDevicePointScore score = new AnalysisBatchUnitDevicePointScore();
                        score.setId(UUIDGenerator.generate());
                        score.setAnalysisType(analysisType);
                        score.setSpeedMax(analysisBatch.getSpeedMax());
                        score.setSpeedMin(analysisBatch.getSpeedMin());
                        score.setAnalysisBatchId(analysisBatch.getId());
                        score.setAnalysisBatchCode(analysisBatch.getAnalysisBatchCode());
                        score.setAnalysisBatchUnitDeviceId("高低");
                        score.setPointValue(finalLevel);
                        score.setWeightValues(levelWeightValues);
                        score.setPointScore(levelUnitScore);
                        scoreList.add(score);
                    }
                    unitDevice.put("labourCheckScore", sumUnitScore);
                    unitDevice.put("labourCheckScoreList", scoreList);

                }


            }
        }


        // 3.保存算法结果
        if (ObjectUtil.isNotEmpty(unitDeviceTable)) {
            List<AnalysisBatchUnitDevice> analysisBatchUnitDevices = new ArrayList<>();
            for (Map.Entry<String, Map<String, Object>> entry : unitDeviceTable.entrySet()) {
                Map<String, Object> unitDevice = entry.getValue();
                AnalysisBatchUnitDevice analysisBatchUnitDevice = new AnalysisBatchUnitDevice();
                analysisBatchUnitDevice.setId(UUIDGenerator.generate());
                analysisBatchUnitDevice.setAnalysisBatchId(analysisBatch.getId());
                analysisBatchUnitDevice.setAnalysisBatchCode(analysisBatch.getAnalysisBatchCode());
                analysisBatchUnitDevice.setUnitId(Convert.toStr(unitDevice.get("id")));
                analysisBatchUnitDevice.setUnitCode(Convert.toStr(unitDevice.get("unitCode")));
                analysisBatchUnitDevice.setUnitDeviceCode(Convert.toStr(unitDevice.get("deviceCode")));
                analysisBatchUnitDevice.setUnitType(Convert.toInt(unitDevice.get("type")));
                analysisBatchUnitDevice.setUnitTypeName(Convert.toStr(unitDevice.get("typeName")));
                analysisBatchUnitDevice.setUnitStartingMileage(Convert.toBigDecimal(unitDevice.get("startMileage")));
                analysisBatchUnitDevice.setUnitCenterMileage(Convert.toBigDecimal(unitDevice.get("centerMileage")));
                analysisBatchUnitDevice.setUnitEndMileage(Convert.toBigDecimal(unitDevice.get("endMileage")));
                Object labourCheckData = unitDevice.get("labourCheck");

                if (ObjectUtil.isNotEmpty(labourCheckData)) {
                    analysisBatchUnitDevice.setLabourCheck(1);
                } else {
                    analysisBatchUnitDevice.setLabourCheck(0);
                }
                BigDecimal labourCheckScore = (BigDecimal) unitDevice.get("labourCheckScore");
                // -1代表未评分
                if (labourCheckScore == null) {
                    analysisBatchUnitDevice.setLabourCheckScore(new BigDecimal("-1"));
                } else {
                    analysisBatchUnitDevice.setLabourCheckScore(labourCheckScore);

                    // 先写死
                    analysisBatchUnitDevice.setUnitScore(labourCheckScore);
                    analysisBatchUnitDevice.setUnitScoreLevel(3);
                }

                Object railDeviceData = unitDevice.get("railDevice");
                if (ObjectUtil.isNotEmpty(railDeviceData)) {
                    analysisBatchUnitDevice.setRailDeviceCheck(1);
                } else {
                    analysisBatchUnitDevice.setRailDeviceCheck(0);
                }
                analysisBatchUnitDevices.add(analysisBatchUnitDevice);


                // 保存超限
                Object transfiniteData = unitDevice.get("transfinite");
                if (ObjectUtil.isNotEmpty(transfiniteData)) {
                    AnalysisBatchUnitDeviceTransfinite transfinite = (AnalysisBatchUnitDeviceTransfinite) transfiniteData;
                    transfinite.setAnalysisBatchUnitDeviceId(analysisBatchUnitDevice.getId());
                    transfinite.setAnalysisBatchId(analysisBatchUnitDevice.getAnalysisBatchId());
                    transfinite.setAnalysisBatchCode(analysisBatchUnitDevice.getAnalysisBatchCode());
                    transfinite.setUnitId(analysisBatchUnitDevice.getUnitId());
                    transfinite.setUnitCode(analysisBatchUnitDevice.getUnitCode());
                    transfinite.setUnitType(analysisBatchUnitDevice.getUnitType());
                    transfinite.setUnitTypeName(analysisBatchUnitDevice.getUnitTypeName());
                    analysisBatchUnitDeviceTransfiniteService.lambdaUpdate().eq(AnalysisBatchUnitDeviceTransfinite::getAnalysisBatchUnitDeviceId, analysisBatchUnitDevice.getId()).remove();
                    analysisBatchUnitDeviceTransfiniteService.save(transfinite);
                }

                // 保存得分
                List<AnalysisBatchUnitDevicePointScore> scoreList = (List<AnalysisBatchUnitDevicePointScore>) unitDevice.get("labourCheckScoreList");
                if (ObjectUtil.isNotEmpty(scoreList)) {

                    for (AnalysisBatchUnitDevicePointScore score : scoreList) {
                        score.setAnalysisBatchUnitDeviceId(analysisBatchUnitDevice.getId());
                        score.setAnalysisBatchId(analysisBatchUnitDevice.getAnalysisBatchId());
                        score.setAnalysisBatchCode(analysisBatchUnitDevice.getAnalysisBatchCode());
                        score.setUnitId(analysisBatchUnitDevice.getUnitId());
                        score.setUnitCode(analysisBatchUnitDevice.getUnitCode());
                        score.setUnitType(analysisBatchUnitDevice.getUnitType());
                        score.setUnitTypeName(analysisBatchUnitDevice.getUnitTypeName());
                    }
                    analysisBatchUnitDevicePointScoreService.lambdaUpdate().eq(AnalysisBatchUnitDevicePointScore::getAnalysisBatchUnitDeviceId, analysisBatchUnitDevice.getId()).remove();
                    analysisBatchUnitDevicePointScoreService.saveBatch(scoreList);
                }

            }
            analysisBatchUnitDeviceService.lambdaUpdate().eq(AnalysisBatchUnitDevice::getAnalysisBatchId, analysisBatchId).remove();
            analysisBatchUnitDeviceService.saveBatch(analysisBatchUnitDevices);
        }

    }
}