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 implements MmPredictInfluenceFactorService { @Autowired private MmItemResultJsonService mmItemResultJsonService; @Autowired private DataPointApi dataPointApi; @Autowired private MmPredictInfluenceFactorResultService influenceFactorResultService; @Override public PageResult page(MmPredictInfluenceFactorPageReqVO params) { IPage 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 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 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 params = new HashMap<>(); params.put("isEnable",1); List influenceFactorConfigs = baseDao.selectList(params); // 根据统计方式分组 Map> patternMap = influenceFactorConfigs.stream().collect(Collectors.groupingBy(MmPredictInfluenceFactorHandleVO::getPattern)); List resultList = new ArrayList<>(influenceFactorConfigs.size()); for (Map.Entry> entry : patternMap.entrySet()) { List influenceFactors = entry.getValue(); // 缓存 因素预测项id-结果,相同因素预测项id只用计算一次 HashMap 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 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 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 dataList = dataPointApi.queryPointHistoryValue(queryDTO); if (CollectionUtils.isEmpty(dataList)) { return null; } dataList = completionData(influenceFactor.getPredictlength(),dataList,predictTime,influenceTime,point.getMinfreqid()); Map 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 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 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 completionData(int length, List 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 result = new ArrayList<>(); long start = startTime.getTime(); long end = endTime.getTime(); long oneMin = 1000L * DataPointFreqEnum.getEumByCode(minfreqid).getValue(); long mins = (end - start) / oneMin; //找出缺少项 Map sourceDataMap = new HashMap<>(dataList.size()); for (ApiPointValueDTO pv : dataList) { sourceDataMap.put(pv.getT().getTime(), pv.getV()); } Map 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 lastItem = null; for (Map.Entry 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 dataMap) { for (Map.Entry item : dataMap.entrySet()) { if (item.getValue() != null) { return item.getValue(); } } return 0.0; } }