From 24c09b6427ca16314385ea7a23bc4f7943727799 Mon Sep 17 00:00:00 2001
From: 潘志宝 <979469083@qq.com>
Date: 星期三, 14 五月 2025 18:25:21 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java |  199 +++++++++++++++++++++++++++----------------------
 1 files changed, 110 insertions(+), 89 deletions(-)

diff --git a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java
index f39173d..1b3d818 100644
--- a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java
+++ b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java
@@ -4,6 +4,7 @@
 import com.iailab.framework.common.pojo.PageResult;
 import com.iailab.framework.common.service.impl.BaseServiceImpl;
 import com.iailab.module.data.api.point.DataPointApi;
+import com.iailab.module.data.api.point.dto.ApiPointDTO;
 import com.iailab.module.data.api.point.dto.ApiPointValueDTO;
 import com.iailab.module.data.api.point.dto.ApiPointValueQueryDTO;
 import com.iailab.module.model.common.enums.DataTypeEnum;
@@ -27,6 +28,7 @@
 
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
@@ -88,93 +90,127 @@
             return false;
         }
 
-        Double adjustValue = 0.0;
-        ApiPointValueQueryDTO queryDTO;
+
+        // 查询调整用户adjustStartTime 至 adjustStartTime - 预测长度 * 预测粒度 范围的值
         Calendar calendar = Calendar.getInstance();
         calendar.setTimeInMillis(adjustStartTime);
-        Date endTime;
-        Date startTime;
-        List<ApiPointValueDTO> apiPointValueDTOS;
+        Date endTime = calendar.getTime();
+        ItemVO item = mmPredictItemService.getItemByOutPutId(configEntity.getOutputId());
+        if (item == null) {
+            log.info("自动调整失败原因:getItemByOutPutId为null,outputId:" + configEntity.getOutputId());
+            return false;
+        }
+        calendar.add(Calendar.SECOND,item.getPredictLength() * item.getGranularity() * -1);
+        Date startTime = calendar.getTime();
+        ApiPointValueQueryDTO queryDTO = new ApiPointValueQueryDTO();
+        ApiPointDTO pointInfo = dataPointApi.getInfoById(configEntity.getPointId());
+        queryDTO.setPointNo(pointInfo.getPointNo());
+        queryDTO.setEnd(endTime);
+        queryDTO.setStart(startTime);
+        List<ApiPointValueDTO> apiPointValueDTOS = dataPointApi.queryPointHistoryValue(queryDTO);
+        if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
+            log.info("自动调整失败原因:测点数据长度为0。queryDTO:" + queryDTO);
+            return false;
+        }
+        // 过滤掉-2
+        apiPointValueDTOS = apiPointValueDTOS.stream().filter(e -> !Double.valueOf(e.getV()).equals(-2.0)).collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
+            log.info("自动调整失败原因:过滤掉-2之后测点数据长度为0。queryDTO:" + queryDTO);
+            return false;
+        }
+
+        // 获取预测历史结果
+        InfluxModelResultPOJO pojo = new InfluxModelResultPOJO();
+        pojo.setType(DataTypeEnum.FLOAT_LAST_BAK.getCode());
+        pojo.setOutPutId(configEntity.getOutputId());
+        List<InfluxModelResultVO> influxModelResult = influxDBService.queryModelResults(pojo, new Date(adjustStartTime), new Date(adjustStartTime));
+        if (CollectionUtils.isEmpty(influxModelResult)) {
+            log.info("自动调整失败原因:预测历史结果为空。itemNo:" + item.getItemNo() + ",itemName" + item.getItemName() + ",outputId" + configEntity.getOutputId() + ",time" + adjustStartTime);
+            return false;
+        }
+
         // 触发规则
         AutoAdjustTriggerRuleEnum triggerRuleEnum = AutoAdjustTriggerRuleEnum.fromCode(configEntity.getTriggerRule());
+        Double adjustValue = null;
         // 判断是否符合触发条件 并计算调整值
         switch (triggerRuleEnum) {
             case SLOPE:
-                queryDTO = new ApiPointValueQueryDTO();
-                queryDTO.setPointNo(dataPointApi.getInfoById(configEntity.getPointId()).getPointNo());
-                endTime = calendar.getTime();
-                queryDTO.setEnd(endTime);
-                calendar.add(Calendar.MINUTE,-1 * configEntity.getT());
-                startTime = calendar.getTime();
-                queryDTO.setStart(startTime);
-                apiPointValueDTOS = dataPointApi.queryPointHistoryValue(queryDTO);
-                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
-                    log.info("自动调整失败原因:测点数据长度为0");
+                // 计算每个△t的斜率,任意一个大于触发值则认为该区间有调整
+                Calendar slopeCalendar = Calendar.getInstance();
+                slopeCalendar.setTime(startTime);
+                Date slopeStartTime = slopeCalendar.getTime();
+                slopeCalendar.add(Calendar.MINUTE,configEntity.getT());
+                Date slopeEndTime = slopeCalendar.getTime();
+                if (slopeEndTime.after(endTime)) {
+                    log.info("自动调整失败原因:△t设置过大,大于模型预测长度 * 预测粒度。△t:" + configEntity.getT());
                     return false;
                 }
-                apiPointValueDTOS = apiPointValueDTOS.stream().filter(e -> e.getV() != -2).collect(Collectors.toList());
-                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
-                    log.info("自动调整失败原因:测点数据长度为0");
-                    return false;
-                }
-                Optional<ApiPointValueDTO> startOptional = apiPointValueDTOS.stream().filter(e -> e.getT().equals(startTime)).findFirst();
-                if (!startOptional.isPresent()) {
-                    log.info("自动调整失败原因:计算斜率startTime时间点测点值为null,startTime:" + startTime);
-                    return false;
-                }
-                Optional<ApiPointValueDTO> endOptional = apiPointValueDTOS.stream().filter(e -> e.getT().equals(endTime)).findFirst();
-                if (!endOptional.isPresent()) {
-                    log.info("自动调整失败原因:计算斜率endTime时间点测点值为null,endTime:" + endTime);
-                    return false;
-                }
-                ApiPointValueDTO startPointValue = startOptional.get();
-                ApiPointValueDTO endPointValue = endOptional.get();
-
-                // 计算斜率,有正负之分,代表上升或下降
-                double slope = BigDecimal.valueOf(endPointValue.getV() - startPointValue.getV()).divide(BigDecimal.valueOf(configEntity.getT())).doubleValue();
-                //斜率绝对值大于等于触发值则进行调整
-                if (Double.valueOf(Math.abs(slope)).compareTo(configEntity.getTriggerValue()) >= 0) {
-                    //计算调整值
-                    HashMap<String,Object> map = new HashMap<>();
-                    map.put("startValue",startPointValue.getV());
-                    map.put("endValue",endPointValue.getV());
-                    adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), map);
-                } else {
-                    log.info("自动调整失败原因:斜率小于调整值,斜率:" + slope);
-                    return false;
+                while (!slopeEndTime.after(endTime)) {
+                    //计算斜率
+                    //△t开始时间测点值
+                    Date finalSlopeStartTime = slopeStartTime;
+                    Optional<ApiPointValueDTO> startOptional = apiPointValueDTOS.stream().filter(apiPointValueDTO -> apiPointValueDTO.getT().equals(finalSlopeStartTime)).findFirst();
+                    //△t结束时间测点值
+                    Date finalSlopeEndTime = slopeEndTime;
+                    Optional<ApiPointValueDTO> endOptional = apiPointValueDTOS.stream().filter(e -> e.getT().equals(finalSlopeEndTime)).findFirst();
+                    if (startOptional.isPresent() && endOptional.isPresent()) {
+                        ApiPointValueDTO startPointValue = startOptional.get();
+                        ApiPointValueDTO endPointValue = endOptional.get();
+                        // 计算斜率
+                        double slope = BigDecimal.valueOf(endPointValue.getV() - startPointValue.getV()).divide(BigDecimal.valueOf(configEntity.getT())).doubleValue();
+                        // 斜率大于等于触发值则进行调整
+                        if (Double.valueOf(Math.abs(slope)).compareTo(configEntity.getTriggerValue()) >= 0) {
+                            // 计算调整值 并跳出循环
+                            adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), apiPointValueDTOS);
+                            log.info("计算调整值:" + adjustValue + ",斜率:" + slope + ",pointNo:" + pointInfo.getPointNo() + ",pointName:" + pointInfo.getPointName() + ",slopeStartTime:" + slopeStartTime + ",slopeEndTime:" + slopeEndTime);
+                            break;
+                        }
+                    }
+                    // 下一个△t
+                    slopeStartTime = slopeCalendar.getTime();
+                    slopeCalendar.add(Calendar.MINUTE,configEntity.getT());
+                    slopeEndTime = slopeCalendar.getTime();
                 }
                 break;
             case AVERAGE_GAP:
-                queryDTO = new ApiPointValueQueryDTO();
-                queryDTO.setPointNo(dataPointApi.getInfoById(configEntity.getPointId()).getPointNo());
-                endTime = calendar.getTime();
-                queryDTO.setEnd(endTime);
-                calendar.add(Calendar.MINUTE,-1 * configEntity.getT() * 2 + 1);
-                startTime = calendar.getTime();
-                queryDTO.setStart(startTime);
-                apiPointValueDTOS = dataPointApi.queryPointHistoryValue(queryDTO);
-                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
-                    log.info("自动调整失败原因:测点数据长度为0");
+                // 计算每两个△t的平均差,任意一个大于触发值则认为该区间有调整
+                Calendar averageCalendar = Calendar.getInstance();
+                averageCalendar.setTime(startTime);
+                Date averageStartTime = averageCalendar.getTime();
+                averageCalendar.add(Calendar.MINUTE,configEntity.getT());
+                Date averageMiddleTime = averageCalendar.getTime();
+                averageCalendar.add(Calendar.MINUTE,configEntity.getT());
+                Date averageEndTime = averageCalendar.getTime();
+
+                if (averageEndTime.after(endTime)) {
+                    log.info("自动调整失败原因:△t设置过大,△t*2大于模型预测长度 * 预测粒度。△t:" + configEntity.getT());
                     return false;
                 }
-                apiPointValueDTOS = apiPointValueDTOS.stream().filter(e -> e.getV() != -2).collect(Collectors.toList());
-                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
-                    log.info("自动调整失败原因:测点数据长度为0");
-                    return false;
-                }
-                calendar.add(Calendar.MINUTE,configEntity.getT());
-                double startAverage = apiPointValueDTOS.stream().filter(e -> e.getT().before(calendar.getTime())).collect(Collectors.summarizingDouble(ApiPointValueDTO::getV)).getAverage();
-                double endAverage = apiPointValueDTOS.stream().filter(e -> e.getT().compareTo(calendar.getTime()) >= 0).collect(Collectors.summarizingDouble(ApiPointValueDTO::getV)).getAverage();
-                // 计算均值差,大于等于触发值则进行调整
-                if (Double.valueOf(Math.abs(startAverage - endAverage)).compareTo(configEntity.getTriggerValue()) >= 0) {
-                    //计算调整值
-                    HashMap<String,Object> map = new HashMap<>();
-                    map.put("startValue",startAverage);
-                    map.put("endValue",endAverage);
-                    adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), map);
-                } else {
-                    log.info("自动调整失败原因:均值差小于调整值,均值差:" + (startAverage - endAverage));
-                    return false;
+                while (!averageEndTime.after(endTime)) {
+                    //计算均值差
+                    //前△t测点平均值
+                    Date finalAverageStartTime = averageStartTime;
+                    Date finalAverageMiddleTime = averageMiddleTime;
+                    OptionalDouble startAverage = apiPointValueDTOS.stream().filter(e -> e.getT().after(finalAverageStartTime) && !e.getT().after(finalAverageMiddleTime)).mapToDouble(ApiPointValueDTO::getV).average();
+                    //后△t测点平均值
+                    Date finalAverageEndTime = averageEndTime;
+                    OptionalDouble endAverage = apiPointValueDTOS.stream().filter(e -> e.getT().after(finalAverageMiddleTime) && !e.getT().after(finalAverageEndTime)).mapToDouble(ApiPointValueDTO::getV).average();
+                    if (startAverage.isPresent() && endAverage.isPresent()) {
+                        double averageGapValue = startAverage.getAsDouble() - endAverage.getAsDouble();
+                        // 均值差,大于等于触发值则进行调整
+                        if (Double.valueOf(Math.abs(averageGapValue)).compareTo(configEntity.getTriggerValue()) >= 0) {
+                            // 计算调整值 并跳出循环
+                            adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), apiPointValueDTOS);
+                            log.info("计算调整值:" + adjustValue + ",均值差:" + averageGapValue + ",pointNo:" + pointInfo.getPointNo() + ",pointName:" + pointInfo.getPointName() + ",averageStartTime:" + averageStartTime + ",averageMiddleTime:" + averageMiddleTime + ",averageEndTime:" + averageEndTime);
+                            break;
+                        }
+                    }
+
+                    // 下一个△t
+                    averageStartTime = averageMiddleTime;
+                    averageMiddleTime = averageEndTime;
+                    averageCalendar.add(Calendar.MINUTE,configEntity.getT());
+                    averageEndTime = averageCalendar.getTime();
                 }
                 break;
             default:
@@ -185,21 +221,6 @@
         // 调整方向
         adjustValue = adjustValue * configEntity.getAdjustDirection();
 
-        // 获取历史结果
-        ItemVO item = mmPredictItemService.getItemByOutPutId(configEntity.getOutputId());
-        if (item == null) {
-            log.info("自动调整失败原因:getItemByOutPutId为null,outputId:" + configEntity.getOutputId());
-            return false;
-        }
-        Calendar resultCalendar = Calendar.getInstance();
-        resultCalendar.setTimeInMillis(adjustStartTime);
-        Date resultStartTime = resultCalendar.getTime();
-        resultCalendar.add(Calendar.SECOND,configEntity.getAdjustLength() * item.getGranularity());
-        Date resultEndTime = resultCalendar.getTime();
-        InfluxModelResultPOJO pojo = new InfluxModelResultPOJO();
-        pojo.setType(DataTypeEnum.FLOAT_LAST_BAK.getCode());
-        pojo.setOutPutId(configEntity.getOutputId());
-        List<InfluxModelResultVO> influxModelResult = influxDBService.queryModelResults(pojo, resultStartTime, resultEndTime);
 
         List<InfluxModelResultPOJO> lastList = new ArrayList<>();
         for (InfluxModelResultVO resultVO : influxModelResult) {
@@ -212,7 +233,7 @@
         }
         // 相同时间直接覆盖旧值
         influxDBService.asyncWriteModelResults(lastList);
-        log.info("t+l自动调整。configCode:" + configCode + ",adjustValue:" + adjustValue + ",resultStartTime:" + resultStartTime + ",resultEndTime:" + resultEndTime + "调整长度:" + lastList.size());
+        log.info("t+l自动调整。configCode:" + configCode + ",adjustValue:" + adjustValue + ",itemNo:" + item.getItemNo() + ",itemName" + item.getItemName() + ",outputId" + configEntity.getOutputId() + ",adjustTime:" + adjustStartTime);
         return true;
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3