From 3180878150f6e22b30394f745008d81cb80af12d Mon Sep 17 00:00:00 2001
From: Jay <csj123456>
Date: 星期四, 17 四月 2025 13:58:02 +0800
Subject: [PATCH] 新增累计真实值和累计预测值的导出

---
 iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictInfluenceFactorServiceImpl.java |  302 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 302 insertions(+), 0 deletions(-)

diff --git a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictInfluenceFactorServiceImpl.java b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictInfluenceFactorServiceImpl.java
new file mode 100644
index 0000000..cc97a76
--- /dev/null
+++ b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictInfluenceFactorServiceImpl.java
@@ -0,0 +1,302 @@
+package com.iailab.module.model.mcs.pre.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.impl.BaseServiceImpl;
+import com.iailab.framework.common.util.date.DateUtils;
+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.data.enums.DataPointFreqEnum;
+import com.iailab.module.model.api.mcs.dto.MmPredictInfluenceFactorHandleReqVO;
+import com.iailab.module.model.mcs.pre.dao.MmPredictInfluenceFactorDao;
+import com.iailab.module.model.mcs.pre.entity.MmPredictInfluenceFactorConfigEntity;
+import com.iailab.module.model.mcs.pre.entity.MmPredictInfluenceFactorResultEntity;
+import com.iailab.module.model.mcs.pre.enums.InfluenceFactorPatternEnum;
+import com.iailab.module.model.mcs.pre.service.MmItemResultJsonService;
+import com.iailab.module.model.mcs.pre.service.MmPredictInfluenceFactorResultService;
+import com.iailab.module.model.mcs.pre.service.MmPredictInfluenceFactorService;
+import com.iailab.module.model.mcs.pre.vo.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class MmPredictInfluenceFactorServiceImpl extends BaseServiceImpl<MmPredictInfluenceFactorDao, MmPredictInfluenceFactorConfigEntity> implements MmPredictInfluenceFactorService {
+
+    @Autowired
+    private MmItemResultJsonService mmItemResultJsonService;
+
+    @Autowired
+    private DataPointApi dataPointApi;
+
+    @Autowired
+    private MmPredictInfluenceFactorResultService influenceFactorResultService;
+
+    @Override
+    public PageResult<MmPredictInfluenceFactorConfigVO> page(MmPredictInfluenceFactorPageReqVO params) {
+        IPage<MmPredictInfluenceFactorConfigVO> page = baseDao.selectPage(params);
+        return new PageResult<>(page.getRecords(), page.getTotal());
+    }
+
+    @Override
+    public MmPredictInfluenceFactorConfigVO getInfo(String id) {
+        return baseDao.getInfo(id);
+    }
+
+    @Override
+    public void create(MmPredictInfluenceFactorConfigVO vo) {
+        MmPredictInfluenceFactorConfigEntity entity = new MmPredictInfluenceFactorConfigEntity();
+        String configId = UUID.randomUUID().toString();
+        entity.setId(configId);
+        entity.setOutputId(vo.getOutputId());
+        entity.setPattern(vo.getPattern());
+        entity.setIsEnable(vo.getIsEnable());
+        entity.setCreateTime(new Date());
+        baseDao.insert(entity);
+
+        // 添加因素
+        if (CollectionUtils.isEmpty(vo.getInfluenceFactors())) {
+            return;
+        }
+        List<MmPredictInfluenceFactorVO> influenceFactors = vo.getInfluenceFactors();
+        influenceFactors.forEach(e -> {
+            e.setId(UUID.randomUUID().toString());
+            e.setConfigId(configId);
+        });
+
+        baseDao.insertInfluenceFactor(influenceFactors);
+    }
+
+    @Override
+    public void update(MmPredictInfluenceFactorConfigVO vo) {
+        MmPredictInfluenceFactorConfigEntity entity = new MmPredictInfluenceFactorConfigEntity();
+        entity.setId(vo.getId());
+        entity.setOutputId(vo.getOutputId());
+        entity.setPattern(vo.getPattern());
+        entity.setIsEnable(vo.getIsEnable());
+        baseDao.updateById(entity);
+
+        // 删除因素
+        baseDao.deleteInfluenceFactor(vo.getId());
+        // 添加因素
+        if (CollectionUtils.isEmpty(vo.getInfluenceFactors())) {
+            return;
+        }
+        List<MmPredictInfluenceFactorVO> influenceFactors = vo.getInfluenceFactors();
+        influenceFactors.forEach(e -> {
+            if (StringUtils.isBlank(e.getId())) {
+                e.setId(UUID.randomUUID().toString());
+            }
+            e.setConfigId(vo.getId());
+        });
+
+        baseDao.insertInfluenceFactor(influenceFactors);
+
+    }
+
+    @Override
+    public void delete(String id) {
+        // 删除因素
+        baseDao.deleteById(id);
+    }
+
+    @Override
+    public void influenceFactorHandle(MmPredictInfluenceFactorHandleReqVO reqVO) {
+        // 影响时间
+        Date influenceTime = new Date(reqVO.getInfluenceTime());
+        // 判断影响时间一定是历史时间
+        if (influenceTime.after(new Date())) {
+            log.info("计算影响因素失败:影响时间大于当前时间");
+            return;
+        }
+        // 查询所有影响因素
+        Map<String, Object> params = new HashMap<>();
+        params.put("isEnable",1);
+        List<MmPredictInfluenceFactorHandleVO> influenceFactorConfigs = baseDao.selectList(params);
+
+        // 根据统计方式分组
+        Map<String, List<MmPredictInfluenceFactorHandleVO>> patternMap = influenceFactorConfigs.stream().collect(Collectors.groupingBy(MmPredictInfluenceFactorHandleVO::getPattern));
+        List<MmPredictInfluenceFactorResultEntity> resultList = new ArrayList<>(influenceFactorConfigs.size());
+        for (Map.Entry<String, List<MmPredictInfluenceFactorHandleVO>> entry : patternMap.entrySet()) {
+            List<MmPredictInfluenceFactorHandleVO> influenceFactors = entry.getValue();
+            // 缓存 因素预测项id-结果,相同因素预测项id只用计算一次
+            HashMap<String,Double> values = new HashMap<>();
+            switch (InfluenceFactorPatternEnum.fromCode(entry.getKey())) {
+                case ACCUMULATE:
+                    for (MmPredictInfluenceFactorHandleVO influenceFactor : influenceFactors) {
+                        Double value = influenceFactorAccumulateCalculate(influenceFactor, values, influenceTime);
+                        if (value == null) {
+                            continue;
+                        }
+                        MmPredictInfluenceFactorResultEntity resultEntity = new MmPredictInfluenceFactorResultEntity();
+                        resultEntity.setFactorId(influenceFactor.getId());
+                        resultEntity.setTime(influenceTime);
+                        resultEntity.setValue(value);
+                        resultList.add(resultEntity);
+                    }
+                    break;
+                case ACCURACY:
+                    for (MmPredictInfluenceFactorHandleVO influenceFactor : influenceFactors) {
+                        Double value = influenceFactorAccuracyCalculate(influenceFactor, values, influenceTime);
+                        if (value == null) {
+                            continue;
+                        }
+                        MmPredictInfluenceFactorResultEntity resultEntity = new MmPredictInfluenceFactorResultEntity();
+                        resultEntity.setFactorId(influenceFactor.getId());
+                        resultEntity.setTime(influenceTime);
+                        resultEntity.setValue(value);
+                        resultList.add(resultEntity);
+                    }
+                    break;
+                default:
+            }
+        }
+        if (CollectionUtils.isEmpty(resultList)) {
+            return;
+        }
+        influenceFactorResultService.insert(resultList);
+
+    }
+
+    private Double influenceFactorAccuracyCalculate(MmPredictInfluenceFactorHandleVO influenceFactor, HashMap<String, Double> values, Date influenceTime) {
+        if (values.containsKey(influenceFactor.getFactorOutputId())) {
+            return values.get(influenceFactor.getFactorOutputId());
+        }
+        // 根据 预测长度 和 预测粒度 推算预测时间
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(influenceTime);
+        calendar.add(Calendar.SECOND,-1 * influenceFactor.getPredictlength() * influenceFactor.getGranularity());
+        Date predictTime = calendar.getTime();
+        // 获取result_json,预测历史数据
+        List<Object[]> predictData = mmItemResultJsonService.getData(influenceFactor.getFactorOutputId(), predictTime, DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
+        if (CollectionUtils.isEmpty(predictData)) {
+            return null;
+        }
+        // 获取真实测点历史值
+        ApiPointValueQueryDTO queryDTO = new ApiPointValueQueryDTO();
+        ApiPointDTO point = dataPointApi.getInfoById(influenceFactor.getPointid());
+        queryDTO.setPointNo(point.getPointNo());
+        queryDTO.setStart(predictTime);
+        queryDTO.setEnd(influenceTime);
+        List<ApiPointValueDTO> dataList = dataPointApi.queryPointHistoryValue(queryDTO);
+        if (CollectionUtils.isEmpty(dataList)) {
+            return null;
+        }
+        dataList = completionData(influenceFactor.getPredictlength(),dataList,predictTime,influenceTime,point.getMinfreqid());
+        Map<String, Double> dataMap = dataList.stream().collect(Collectors.toMap(e -> DateUtils.format(e.getT(), DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND), ApiPointValueDTO::getV, (e1, e2) -> e1));
+        // 计算精确度误差
+        int sum = 0;
+        for (int i = 0; i < predictData.size(); i++) {
+            Object[] objects = predictData.get(i);
+            if (dataMap.containsKey(objects[0].toString())) {
+                double abs = Math.abs(new BigDecimal(objects[1].toString()).subtract(BigDecimal.valueOf(dataMap.get(objects[0].toString()))).doubleValue());
+                if (abs > influenceFactor.getDeviationValue()) {
+                    sum++;
+                }
+            }
+        }
+
+        double value = BigDecimal.valueOf(sum).divide(BigDecimal.valueOf(predictData.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
+
+        values.put(influenceFactor.getFactorOutputId(),value);
+        return value;
+    }
+
+    private Double influenceFactorAccumulateCalculate(MmPredictInfluenceFactorHandleVO influenceFactor, HashMap<String, Double> values,Date influenceTime) {
+        if (values.containsKey(influenceFactor.getFactorOutputId())) {
+            return values.get(influenceFactor.getFactorOutputId());
+        }
+        // 根据 预测长度 和 预测粒度 推算预测时间
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(influenceTime);
+        calendar.add(Calendar.SECOND,-1 * influenceFactor.getPredictlength() * influenceFactor.getGranularity());
+        Date predictTime = calendar.getTime();
+        // 获取result_json,预测历史数据
+        double[] predictData = mmItemResultJsonService.getSimpleData(influenceFactor.getFactorOutputId(), predictTime, influenceFactor.getPredictlength());
+        if (predictData == null || predictData.length == 0) {
+            return null;
+        }
+        // 获取真实测点历史值
+        ApiPointValueQueryDTO queryDTO = new ApiPointValueQueryDTO();
+        ApiPointDTO point = dataPointApi.getInfoById(influenceFactor.getPointid());
+        queryDTO.setPointNo(point.getPointNo());
+        queryDTO.setStart(predictTime);
+        queryDTO.setEnd(influenceTime);
+        List<ApiPointValueDTO> dataList = dataPointApi.queryPointHistoryValue(queryDTO);
+        if (CollectionUtils.isEmpty(dataList)) {
+            return null;
+        }
+        dataList = completionData(influenceFactor.getPredictlength(),dataList,predictTime,influenceTime,point.getMinfreqid());
+        // 计算累计量误差
+        double value = Math.abs(dataList.stream().mapToDouble(ApiPointValueDTO::getV).sum() - Arrays.stream(predictData).sum());
+
+        values.put(influenceFactor.getFactorOutputId(),value);
+        return value;
+    }
+
+    private List<ApiPointValueDTO> completionData(int length, List<ApiPointValueDTO> dataList, Date startTime, Date endTime, String minfreqid) {
+        if (CollectionUtils.isEmpty(dataList) || length == dataList.size()) {
+            return dataList;
+        } else if (length < dataList.size()) {
+            return dataList.subList(dataList.size() - length, dataList.size());
+        }
+
+        List<ApiPointValueDTO> result = new ArrayList<>();
+        long start = startTime.getTime();
+        long end = endTime.getTime();
+        long oneMin = 1000L * DataPointFreqEnum.getEumByCode(minfreqid).getValue();
+        long mins = (end - start) / oneMin;
+
+        //找出缺少项
+        Map<Long, Double> sourceDataMap = new HashMap<>(dataList.size());
+        for (ApiPointValueDTO pv : dataList) {
+            sourceDataMap.put(pv.getT().getTime(), pv.getV());
+        }
+
+        Map<Long, Double> dataMap = new LinkedHashMap<>();
+        for (int i = 0; i < mins; i++) {
+            Long key = start + oneMin * i;
+            Double value = sourceDataMap.get(key);
+            dataMap.put(key, value);
+        }
+
+        //补充缺少项
+        int k = 0;
+        Map.Entry<Long, Double> lastItem = null;
+        for (Map.Entry<Long, Double> item : dataMap.entrySet()) {
+            if (k == 0 && item.getValue() == null) {
+                item.setValue(getFirstValue(dataMap));
+            } else if (item.getValue() == null) {
+                item.setValue(lastItem.getValue());
+            }
+            k++;
+            lastItem = item;
+
+            ApiPointValueDTO dataEntity = new ApiPointValueDTO();
+            dataEntity.setT(new Date(item.getKey()));
+            dataEntity.setV(item.getValue());
+            result.add(dataEntity);
+        }
+        return result;
+    }
+
+    private Double getFirstValue(Map<Long, Double> dataMap) {
+        for (Map.Entry<Long, Double> item : dataMap.entrySet()) {
+            if (item.getValue() != null) {
+                return item.getValue();
+            }
+        }
+        return 0.0;
+    }
+}

--
Gitblit v1.9.3