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