xusl 1 рік тому
батько
коміт
fedc4a4842

+ 24 - 0
ipfcst/ipfcst-console/src/main/java/com/jiayue/ipfcst/console/job/ForecastPowerUltraShortTermOneJob.java

@@ -0,0 +1,24 @@
+package com.jiayue.ipfcst.console.job;
+
+import com.jiayue.ipfcst.console.service.ForecastPowerUltraShortTermOneService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+/**
+ * 超短期执行任务
+ *
+ * @author zzy
+ * @version 3.0
+ */
+@Service @EnableScheduling public class ForecastPowerUltraShortTermOneJob {
+
+  @Autowired private ForecastPowerUltraShortTermOneService forecastPowerUltraShortTermOneService;
+
+  @Scheduled(fixedDelay = 60000)
+  public void executeForecast() {
+    this.forecastPowerUltraShortTermOneService.executeForecast();
+  }
+
+}

+ 492 - 1
ipfcst/ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ForecastPowerShortTermOneService.java

@@ -1,15 +1,29 @@
 package com.jiayue.ipfcst.console.service;
 
+import com.jiayue.ipfcst.common.core.exception.BusinessException;
+import com.jiayue.ipfcst.common.core.util.CommonUtil;
+import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
+import com.jiayue.ipfcst.common.core.util.DateTimeUtil;
+import com.jiayue.ipfcst.common.core.util.NumberUtils;
+import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
+import com.jiayue.ipfcst.common.data.constant.enums.PredictionModelEnum;
 import com.jiayue.ipfcst.common.data.entity.*;
-import com.jiayue.ipfcst.common.data.repository.ForecastPowerShortTermOneRepository;
+import com.jiayue.ipfcst.common.data.repository.*;
 import com.jiayue.ipfcst.common.data.service.BaseService;
+import com.jiayue.ipfcst.console.util.Constant;
+import com.sun.istack.internal.NotNull;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.time.DateFormatUtils;
+import org.apache.commons.lang.time.DateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
@@ -17,7 +31,28 @@ public class ForecastPowerShortTermOneService extends BaseService {
 
   @Autowired
   ForecastPowerShortTermOneRepository forecastPowerShortTermOneRepository;
+  @Autowired
+  ForecastPowerShortTermOneHisRepository forecastPowerShortTermHisRepository;
+  @Autowired
+  ElectricFieldService electricFieldService;
+  @Autowired
+  ManualInterventionService manualInterventionService;
+  @Autowired
+  DataLimitationRepository dataLimitationRepository;
+  @Autowired
+  ManualInterventionRatioService manualInterventionRatioService;
+
 
+  /**
+   * 保存
+   *
+   * @param forecastPowerShortTermList
+   * @return
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public void saveAll(List<ForecastPowerShortTermOne> forecastPowerShortTermList) {
+    forecastPowerShortTermOneRepository.saveAll(forecastPowerShortTermList);
+  }
 
   /**
    * 按时间段删除数据
@@ -33,5 +68,461 @@ public class ForecastPowerShortTermOneService extends BaseService {
     forecastPowerShortTermOneRepository.saveAll(listDq);
   }
 
+  /**
+   * 生成短期预测功率,短期预测功率为云下载数据,这里不进行覆盖更新,只针对短期预测数据不足时补充
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public void buildForecastPowerShortTerm(@NotNull final Long startTime, @NotNull final Long endTime) {
+    this.getForecastPowerShortTerm(startTime, endTime);
+  }
+
+  /**
+   * 获取短期预测功率,当数据库中短期预测记录不足查询所需时,进行本地化计算, 用于上报专用
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 预测功率结果集
+   */
+  @SuppressWarnings("WeakerAccess")
+  @Transactional(propagation = Propagation.REQUIRED)
+  public List<ForecastPowerShortTermOneHis> getForecastPowerShortTerm(@NotNull final Long startTime,
+                                                                   @NotNull final Long endTime) {
+    List<ForecastPowerShortTermOneHis> forecastPowerShortTermHiss = getForecastPowerShortTermHis(startTime, endTime);
+    // 删除当日生成的短期历史记录
+    this.forecastPowerShortTermHisRepository.deleteToday(forecastPowerShortTermHiss.get(0).getForecastTime(),
+      forecastPowerShortTermHiss.get(forecastPowerShortTermHiss.size() - 1).getForecastTime());
+    // 保存短期历史记录
+    this.forecastPowerShortTermHisRepository.saveAll(forecastPowerShortTermHiss);
+    return forecastPowerShortTermHiss;
+  }
+
+
+  //
+  public List<ForecastPowerShortTermOneHis> getForecastPowerShortTermHis(@NotNull final Long startTime, @NotNull final Long endTime) {
+    log.info("开始获取短期预测功率" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
+
+    // 查询场站信息
+    ElectricField electricFieldInfo = electricFieldService.get();
+    // 查询预测时间点对应的开机容量
+    Map<Long, BigDecimal> openCapacityMap = null;
+    try {
+      openCapacityMap = super.queryOpenCapacity(startTime, endTime, electricFieldInfo.getCapacity());
+    } catch (BusinessException e) {
+      log.error("预测数据生成获取开机容量出错:" + CommonUtil.printStackTraceToString(e));
+    }
+    // 查询短期预测功率
+    List<ForecastPowerShortTermOne> forecastPowerShortTerms =
+      this.forecastPowerShortTermOneRepository.findByForecastTimeBetween(startTime, endTime);
+    forecastPowerShortTerms.sort(Comparator.comparing(ForecastPowerShortTermOne::getForecastTime));
+    log.info("查询现有短期预测记录数:" + forecastPowerShortTerms.size());
+    // 判断查询结果是否满足查询所需
+    Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
+    Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
+    log.info("获取所需记录数:" + moments);
+    if (moments > forecastPowerShortTerms.size()) {
+      Map<Long, List<ForecastPowerShortTermOne>> forecastPowerShortTermsMap =
+        forecastPowerShortTerms.stream().collect(Collectors.groupingBy(ForecastPowerShortTermOne::getForecastTime));
+      // 如果查询结果少于所需预测数,则进行本地化计算,补齐预测记录
+      List<ForecastPowerShortTermOne> addForecastPowerShortTermList = new ArrayList<>();
+      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
+        if (forecastPowerShortTermsMap.get(tempTime) == null) {
+          // 缺失时间点
+          ForecastPowerShortTermOne _forecastPowerShortTerms = this.generateForecastPowerShortTerm(tempTime,
+            electricFieldInfo, openCapacityMap.get(tempTime));
+          addForecastPowerShortTermList.add(_forecastPowerShortTerms);
+        }
+      }
+
+      if (!addForecastPowerShortTermList.isEmpty()) {
+        // 保存短期预测
+        this.forecastPowerShortTermOneRepository.saveAll(addForecastPowerShortTermList);
+        // 将补齐的预测功率追加到查询预测功率结果集中
+        forecastPowerShortTerms.addAll(addForecastPowerShortTermList);
+      }
+    }
+    forecastPowerShortTerms.sort(Comparator.comparing(ForecastPowerShortTermOne::getForecastTime));
+    //-----------------------------------------------------开始预测数据上下限的判断----------------------------------------------------
+    List<DataLimitation> dataLimitationList = dataLimitationRepository.findByLimitTimeBetween(startTime, endTime);
+    dataLimitationList.sort(Comparator.comparing(DataLimitation::getLimitTime));
+    Map<Long, Map> limitMap = new HashMap<>();
+    int limitFlag = 0;
+    if (dataLimitationList.size() > 0) {
+      for (DataLimitation dataLimitation : dataLimitationList) {
+        Map<String, BigDecimal> limitValMap = new HashMap<>();
+        limitValMap.put("max", dataLimitation.getUpperLimit());
+        limitValMap.put("min", dataLimitation.getLowerLimit());
+        limitMap.put(dataLimitation.getLimitTime(), limitValMap);
+      }
+
+      for (Long tempDateTime = startTime; tempDateTime < endTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
+        Map map = limitMap.get(tempDateTime);
+        if (map != null) {
+          BigDecimal maxBig = (BigDecimal) map.get("max");
+          BigDecimal minBig = (BigDecimal) map.get("min");
+          BigDecimal fps = forecastPowerShortTerms.get(limitFlag).getFpValue();
+          if (maxBig!=null){
+            if (fps.compareTo(maxBig) == 1) {
+              // 预测值大于设置的上限,用上限值替换
+              ForecastPowerShortTermOne forecastPowerShortTerm = new ForecastPowerShortTermOne();
+              forecastPowerShortTerm.setFpValue(maxBig);
+              forecastPowerShortTerm.setPredictionModelEnum(PredictionModelEnum.E7);
+              forecastPowerShortTerm.setForecastTime(forecastPowerShortTerms.get(limitFlag).getForecastTime());
+              forecastPowerShortTerms.set(limitFlag, forecastPowerShortTerm);
+            }
+          }
+          if (minBig!=null){
+            if (fps.compareTo(minBig) == -1) {
+              // 预测值小于设置的下限,用下限值替换
+              ForecastPowerShortTermOne forecastPowerShortTerm = new ForecastPowerShortTermOne();
+              forecastPowerShortTerm.setFpValue(minBig);
+              forecastPowerShortTerm.setPredictionModelEnum(PredictionModelEnum.E7);
+              forecastPowerShortTerm.setForecastTime(forecastPowerShortTerms.get(limitFlag).getForecastTime());
+              forecastPowerShortTerms.set(limitFlag, forecastPowerShortTerm);
+            }
+          }
+        }
+        limitFlag++;
+      }
+    }
+    //-----------------------------------------------------结束预测数据上下限的判断----------------------------------------------------
+
+    //-----------------------------------------------------开始进行人工干预数值的判断----------------------------------------------------
+
+    List<ManualInterventionData> manualInterventionDataList = manualInterventionService.queryManualIntervention(startTime, endTime, "0");
+    manualInterventionDataList.sort(Comparator.comparing(ManualInterventionData::getInterveneTime));
+    Map<Long, BigDecimal> mMap = new HashMap<>();
+    int flag = 0;
+    if (manualInterventionDataList.size() > 0) {
+      for (ManualInterventionData manualInterventionData : manualInterventionDataList) {
+        mMap.put(manualInterventionData.getInterveneTime(), manualInterventionData.getInterveneData());
+      }
+      for (Long tempDateTime = startTime; tempDateTime < endTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
+        ForecastPowerShortTermOne forecastPowerShortTerm = new ForecastPowerShortTermOne();
+        BigDecimal ma = mMap.get(tempDateTime);
+        if (ma != null) {
+          forecastPowerShortTerm.setFpValue(ma);
+          forecastPowerShortTerm.setPredictionModelEnum(PredictionModelEnum.E6);
+          // 如果有人工设置的数据 则改点替换为人工设置的数据
+          forecastPowerShortTerm.setForecastTime(forecastPowerShortTerms.get(flag).getForecastTime());
+          forecastPowerShortTerms.set(flag, forecastPowerShortTerm);
+        }
+        flag++;
+      }
+    }
+
+    //-----------------------------------------------------人工干预数据判断结束----------------------------------------------------
+
+    // 处理短期历史记录
+    List<ForecastPowerShortTermOneHis> forecastPowerShortTermHiss = new ArrayList<>();
+    ForecastPowerShortTermOneHis forecastPowerShortTermHis;
+    Long systemTime = System.currentTimeMillis();
+
+    //获取数据下限参数
+    String lowerPredictionLimit = super.getSysParameter("LowerPredictionLimit", "0");
+    BigDecimal lpl = new BigDecimal(lowerPredictionLimit);
+    for (ForecastPowerShortTermOne _forecastPowerShortTerm : forecastPowerShortTerms) {
+      forecastPowerShortTermHis = new ForecastPowerShortTermOneHis();
+      forecastPowerShortTermHis.setForecastTime(_forecastPowerShortTerm.getForecastTime());
+      forecastPowerShortTermHis.setTheoryValue(_forecastPowerShortTerm.getFpValue());
+      forecastPowerShortTermHis.setCapacity(electricFieldInfo.getCapacity());
+      // 预测可用功率=预测*(开机容量/装机容量)
+      BigDecimal ableValue =
+        _forecastPowerShortTerm.getFpValue().multiply(openCapacityMap.get(_forecastPowerShortTerm.getForecastTime()))
+          .divide(electricFieldInfo.getCapacity(), 2, BigDecimal.ROUND_HALF_UP);
+
+      forecastPowerShortTermHis.setAbleValue(ableValue.compareTo(lpl) == -1?lpl:ableValue);
+      forecastPowerShortTermHis.setPredictionModelEnum(_forecastPowerShortTerm.getPredictionModelEnum());
+      forecastPowerShortTermHis.setGenDate(new Date());
+      forecastPowerShortTermHis.setSuCapacity(openCapacityMap.get(_forecastPowerShortTerm.getForecastTime()));
+      // 设置提前几天预测
+      forecastPowerShortTermHis.setForecastHowLongAgo(DateMomentUtil.getDaysBetweenTwoDate(systemTime,
+        forecastPowerShortTermHis.getForecastTime()));
+      forecastPowerShortTermHiss.add(forecastPowerShortTermHis);
+    }
+    //-----------------------------------------------------系数判断开始----------------------------------------------------
+    List<ManualInterventionRatioData> manualInterventionRatioDataList = manualInterventionRatioService.queryManualInterventionRatio(startTime, endTime, "0");
+
+    //如果有人工干预系数设置记录
+    if(manualInterventionRatioDataList.size() > 0){
+      //循环所有记录
+      for(ManualInterventionRatioData manualInterventionRatioData :manualInterventionRatioDataList){
+        for (Long tempTime = manualInterventionRatioData.getInterveneStartTime(); tempTime <= manualInterventionRatioData.getInterveneEndTime(); tempTime = tempTime + 15 * 60 * 1000L) {
+          //循环所有超短期的值
+          int mrflag = 0;
+          for (ForecastPowerShortTermOneHis f : forecastPowerShortTermHiss) {
+            //如果该时间设置了系数则数值*系数
+            if(f.getForecastTime().equals(tempTime)){
+              BigDecimal fpValue = f.getAbleValue().multiply(new BigDecimal(manualInterventionRatioData.getRatio().toString())).setScale(2, BigDecimal.ROUND_HALF_UP);
+              //如果计算后的数据大于装机容量 则fpValue=装机容量
+              if((fpValue).compareTo(new BigDecimal(electricFieldInfo.getCapacity().toString())) > 0){
+                fpValue = new BigDecimal(electricFieldInfo.getCapacity().toString());
+              }
+              f.setAbleValue(fpValue);
+              f.setTheoryValue(fpValue);
+              f.setGenDate(new Date());
+              f.setPredictionModelEnum(PredictionModelEnum.E10);
+              forecastPowerShortTermHiss.set(mrflag, f);
+
+            }
+            mrflag++;
+          }
+        }
+      }
+    }
+    //-----------------------------------------------------系数判断结束----------------------------------------------------
+
+    //-----------------------------------------------------浙江光伏负偏差---------------------------------------------------
+    try {
+      String negative_deviation = super.getSysParameter("negative_deviation", "0");
+      if (electricFieldInfo.getProvinceEnum().toString().equals("E33")&&electricFieldInfo.getElectricFieldTypeEnum().toString().equals("E1")&&!negative_deviation.equals("0")&&!negative_deviation.equals("")){
+        int mrflag = 0;
+        for (ForecastPowerShortTermOneHis f : forecastPowerShortTermHiss) {
+          f.setAbleValue(f.getAbleValue().subtract(new BigDecimal(negative_deviation)));
+          f.setTheoryValue(f.getTheoryValue().subtract(new BigDecimal(negative_deviation)));
+          f.setGenDate(new Date());
+          f.setPredictionModelEnum(PredictionModelEnum.E10);
+          forecastPowerShortTermHiss.set(mrflag, f);
+          mrflag++;
+        }
+      }
+    }catch (Exception e){
+      e.printStackTrace();
+      log.info("负偏差计算错误,请检查negative_deviation参数是否为数字");
+    }
+
+    //-----------------------------------------------------浙江光伏负偏差---------------------------------------------------
+
+    //-----------------------------------------------------系数判断结束----------------------------------------------------
+
+    // 按预测时间升序
+    forecastPowerShortTermHiss.sort(Comparator.comparing(ForecastPowerShortTermOneHis::getForecastTime));
+    return forecastPowerShortTermHiss;
+  }
+
+
+  /**
+   * 获取一体化短期预测功率,当数据库中短期预测记录不足查询所需时,进行本地化计算, 用于上报专用
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 预测功率结果集
+   */
+  @SuppressWarnings("WeakerAccess")
+  @Transactional(propagation = Propagation.REQUIRED)
+  public List<ForecastPowerShortTermOneHis> getInForecastPowerShortTerm(@NotNull final Long startTime,
+                                                                     @NotNull final Long endTime) {
+    log.info("开始获取短期预测功率" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
+    // 查询场站信息
+    ElectricField electricFieldInfo = electricFieldService.get();
+    // 查询预测时间点对应的开机容量
+    Map<Long, BigDecimal> openCapacityMap = null;
+    try {
+      openCapacityMap = super.queryOpenCapacity(startTime, endTime, electricFieldInfo.getCapacity());
+    } catch (BusinessException e) {
+      log.error("预测数据生成获取开机容量出错:" + CommonUtil.printStackTraceToString(e));
+    }
+    // 查询短期预测功率
+    List<ForecastPowerShortTermOne> forecastPowerShortTerms =
+      this.forecastPowerShortTermOneRepository.findByForecastTimeBetween(startTime, endTime);
+    forecastPowerShortTerms.sort(Comparator.comparing(ForecastPowerShortTermOne::getForecastTime));
+    log.info("查询现有短期预测记录数:" + forecastPowerShortTerms.size());
+    // 判断查询结果是否满足查询所需
+    Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
+    Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
+    log.info("获取所需记录数:" + moments);
+    if (moments > forecastPowerShortTerms.size()) {
+      Map<Long, List<ForecastPowerShortTermOne>> forecastPowerShortTermsMap =
+        forecastPowerShortTerms.stream().collect(Collectors.groupingBy(ForecastPowerShortTermOne::getForecastTime));
+      // 如果查询结果少于所需预测数,则进行本地化计算,补齐预测记录
+      List<ForecastPowerShortTermOne> addForecastPowerShortTermList = new ArrayList<>();
+      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
+        if (forecastPowerShortTermsMap.get(tempTime) == null) {
+          // 缺失时间点
+          ForecastPowerShortTermOne _forecastPowerShortTerms = this.generateForecastPowerShortTerm(tempTime,
+            electricFieldInfo, openCapacityMap.get(tempTime));
+          addForecastPowerShortTermList.add(_forecastPowerShortTerms);
+        }
+      }
+
+      if (!addForecastPowerShortTermList.isEmpty()) {
+        // 保存短期预测
+        this.forecastPowerShortTermOneRepository.saveAll(addForecastPowerShortTermList);
+        // 将补齐的预测功率追加到查询预测功率结果集中
+        forecastPowerShortTerms.addAll(addForecastPowerShortTermList);
+      }
+    }
+    forecastPowerShortTerms.sort(Comparator.comparing(ForecastPowerShortTermOne::getForecastTime));
 
+    // 处理短期历史记录
+    List<ForecastPowerShortTermOneHis> forecastPowerShortTermHiss = new ArrayList<>();
+    ForecastPowerShortTermOneHis forecastPowerShortTermHis;
+    Long systemTime = System.currentTimeMillis();
+
+
+    for (ForecastPowerShortTermOne _forecastPowerShortTerm : forecastPowerShortTerms) {
+      forecastPowerShortTermHis = new ForecastPowerShortTermOneHis();
+      forecastPowerShortTermHis.setForecastTime(_forecastPowerShortTerm.getForecastTime());
+      forecastPowerShortTermHis.setTheoryValue(_forecastPowerShortTerm.getFpValue());
+      forecastPowerShortTermHis.setCapacity(electricFieldInfo.getCapacity());
+      // 预测可用功率=预测*(开机容量/装机容量)
+      BigDecimal ableValue =
+        _forecastPowerShortTerm.getFpValue().multiply(openCapacityMap.get(_forecastPowerShortTerm.getForecastTime()))
+          .divide(electricFieldInfo.getCapacity(), 2, BigDecimal.ROUND_HALF_UP);
+
+      forecastPowerShortTermHis.setAbleValue(ableValue);
+      forecastPowerShortTermHis.setPredictionModelEnum(_forecastPowerShortTerm.getPredictionModelEnum());
+      forecastPowerShortTermHis.setGenDate(new Date());
+      forecastPowerShortTermHis.setSuCapacity(openCapacityMap.get(_forecastPowerShortTerm.getForecastTime()));
+      // 设置提前几天预测
+      forecastPowerShortTermHis.setForecastHowLongAgo(DateMomentUtil.getDaysBetweenTwoDate(systemTime,
+        forecastPowerShortTermHis.getForecastTime()));
+      forecastPowerShortTermHiss.add(forecastPowerShortTermHis);
+    }
+
+    // 按预测时间升序
+    forecastPowerShortTermHiss.sort(Comparator.comparing(ForecastPowerShortTermOneHis::getForecastTime));
+
+    return forecastPowerShortTermHiss;
+  }
+
+  @Transactional(propagation = Propagation.REQUIRED)
+  public void inSaveHis(List<ForecastPowerShortTermOneHis> forecastPowerShortTermHiss) {
+
+    // 删除当日生成的短期历史记录
+    this.forecastPowerShortTermHisRepository.deleteToday(forecastPowerShortTermHiss.get(0).getForecastTime(),
+      forecastPowerShortTermHiss.get(forecastPowerShortTermHiss.size() - 1).getForecastTime());
+    // 保存短期历史记录
+    this.forecastPowerShortTermHisRepository.saveAll(forecastPowerShortTermHiss);
+  }
+
+  /**
+   * 补数生成单点短期预测功率
+   *
+   * @param tempTime 预测时间
+   * @return 预测功率
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public ForecastPowerShortTermOne generateForecastPowerShortTerm(@NotNull final Long tempTime,
+                                                               ElectricField electricFieldInfo,
+                                                               BigDecimal openCapacity) {
+    ForecastPowerShortTermOne forecastPowerShortTerms;
+    // 根据场站类型调用不同的短期预测模型
+    if (ElectricFieldTypeEnum.E2.equals(electricFieldInfo.getElectricFieldTypeEnum())) {
+      // 风预测
+      forecastPowerShortTerms = this.generateWindPowerShortTerm(tempTime, openCapacity);
+    } else {
+      // 光预测
+      forecastPowerShortTerms = this.generateSolarPowerShortTerm(tempTime, openCapacity, electricFieldInfo);
+    }
+    return forecastPowerShortTerms;
+  }
+
+  /**
+   * 光短期功率预测
+   *
+   * @param tempTime 预测时间
+   * @return 短期预测功率
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public ForecastPowerShortTermOne generateSolarPowerShortTerm(@NotNull final Long tempTime, BigDecimal openCapacity,
+                                                            ElectricField electricFieldInfo) {
+    System.out.println("光补数");
+    ForecastPowerShortTermOne forecastPowerShortTerm = new ForecastPowerShortTermOne();
+    forecastPowerShortTerm.setForecastTime(tempTime);
+    BigDecimal tempValue;
+    BigDecimal randomValue = new BigDecimal(CommonUtil.getRandom(97, 99) / 100.0);
+    if (DateTimeUtil.checkInSunriseAndSunset(tempTime, electricFieldInfo.getLongitude().doubleValue(),
+      electricFieldInfo.getLatitude().doubleValue())) {
+      // 2021-4-22 xsl修改补数取固定系数
+      String a = Constant.forecastCoe(tempTime,electricFieldInfo.getElectricFieldTypeEnum());
+      System.out.println(a);
+      tempValue = new BigDecimal(a);
+    } else {
+      // 日升日落
+      tempValue = BigDecimal.ZERO;
+    }
+
+    forecastPowerShortTerm.setFpValue(NumberUtils.multiply(tempValue, openCapacity).multiply(randomValue).setScale(2, BigDecimal.ROUND_HALF_UP));
+    forecastPowerShortTerm.setGenDate(new Date());
+    forecastPowerShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
+    return forecastPowerShortTerm;
+  }
+
+
+  /**
+   * 风短期功率预测
+   *
+   * @param tempTime 预测时间
+   * @return 短期预测功率
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public ForecastPowerShortTermOne generateWindPowerShortTerm(@NotNull final Long tempTime, BigDecimal openCapacity) {
+    System.out.println("风补数");
+    ForecastPowerShortTermOne forecastPowerShortTerm = new ForecastPowerShortTermOne();
+    forecastPowerShortTerm.setForecastTime(tempTime);
+    BigDecimal randomValue = new BigDecimal(CommonUtil.getRandom(97, 99) / 100.0d);
+    // 2021-4-22 xsl修改补数取固定系数
+    BigDecimal tempValue = new BigDecimal(Constant.forecastCoe(tempTime,ElectricFieldTypeEnum.E2));
+    forecastPowerShortTerm.setFpValue(NumberUtils.multiply(tempValue, openCapacity).multiply(randomValue).setScale(2, BigDecimal.ROUND_HALF_UP));
+    forecastPowerShortTerm.setGenDate(new Date());
+    forecastPowerShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
+    return forecastPowerShortTerm;
+  }
+
+  /**
+   * 根据条件查询
+   *
+   * @param startTimeStr 开始时间
+   * @param endTimeStr   结束时间
+   * @return map
+   */
+  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
+  public Map<String, Object> getForecastPowerShortTermDrawing(String startTimeStr, String endTimeStr) {
+    Map<String, Object> map = new HashMap<>();
+    Long startTime = 0L;
+    Long endTime = 0L;
+    if (StringUtils.isNotEmpty(startTimeStr)) {
+      startTime = Long.parseLong(startTimeStr);
+    } else {
+      Calendar c = Calendar.getInstance();
+
+      startTime = c.getTimeInMillis() - DateUtils.getFragmentInMilliseconds(c, Calendar.DAY_OF_MONTH) + 24 * 60 * 60 * 1000;
+    }
+    if (StringUtils.isNotEmpty(endTimeStr)) {
+      endTime = Long.parseLong(endTimeStr);
+    } else {
+      Calendar c = Calendar.getInstance();
+
+      endTime = c.getTimeInMillis() - DateUtils.getFragmentInMilliseconds(c, Calendar.DAY_OF_MONTH) + 4 * 24 * 60 * 60 * 1000;
+    }
+
+
+
+    map.put("list", forecastPowerShortTermOneRepository.findByForecastTimeBetween(startTime, endTime));// 结果集
+
+    return map;
+  }
+  /**
+   * 查询回传数据
+   * @param stTime         开始时间
+   * @param eTime          结束时间
+   * @return
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public String[] findSendData(Long stTime,Long eTime,List<ForecastPowerShortTermOne> list){
+
+    List<ForecastPowerShortTermOne> collect = list.stream().filter(s -> s.getForecastTime() >= stTime && s.getForecastTime() <= eTime).collect(Collectors.toList());
+    String[] datas = new String[list.size()];
+    if(null != collect && collect.size() > 0){
+      int index = 0;
+      for(ForecastPowerShortTermOne f:collect){
+        datas[index] = String.valueOf(f.getFpValue());
+        index++;
+      }
+    }
+    return datas;
+  }
 }

+ 562 - 0
ipfcst/ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ForecastPowerUltraShortTermOneService.java

@@ -0,0 +1,562 @@
+package com.jiayue.ipfcst.console.service;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.jiayue.ipfcst.common.core.exception.BusinessException;
+import com.jiayue.ipfcst.common.core.util.CommonUtil;
+import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
+import com.jiayue.ipfcst.common.core.util.DateTimeUtil;
+import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
+import com.jiayue.ipfcst.common.data.constant.enums.PredictionModelEnum;
+import com.jiayue.ipfcst.common.data.entity.*;
+import com.jiayue.ipfcst.common.data.repository.*;
+import com.jiayue.ipfcst.common.data.service.BaseService;
+import com.sun.istack.internal.NotNull;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.time.DateFormatUtils;
+import org.apache.commons.lang.time.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 超短期功率预测业务
+ *
+ * @author xsl
+ * @version 3.0
+ * @since 2020/4/22 18:24
+ */
+@Service
+@Slf4j
+public class ForecastPowerUltraShortTermOneService extends BaseService {
+  @Autowired
+  ElectricFieldService electricFieldService;
+  @Autowired
+  ForecastPowerShortTermOneRepository forecastPowerShortTermOneRepository;
+  @Autowired
+  SysParameterService sysParameterService;
+  @Autowired
+  PowerStationStatusDataRepository powerStationStatusDataRepository;
+  @Autowired
+  ForecastPowerUltraShortTermOneRepository forecastPowerUltraShortTermOneRepository;
+  @Autowired
+  ForecastPowerUltraShortTermOneHisRepository forecastPowerUltraShortTermOneHisRepository;
+  @Autowired
+  ManualInterventionService manualInterventionService;
+  @Autowired
+  ForecastPowerShortTermOneService forecastPowerShortTermOneService;
+  @Autowired
+  ManualInterventionRatioService manualInterventionRatioService;
+
+//  @Autowired
+//  UltraShortTermCoefficientRepository ultraShortTermCoefficientRepository;
+//  @Autowired
+//  RepairPlanRepository repairPlanRepository;
+
+
+  /**
+   * 生成超短期预测功率,自动更新覆盖预测功率
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public void buildForecastPowerUltraShortTerm(@NotNull final Long startTime, @NotNull final Long endTime) {
+    this.getForecastPowerUltraShortTerm(startTime, endTime);
+  }
+  /**
+   * 获取超短期预测功率,当数据库中超短期预测记录不足查询所需时,进行本地化计算,用于上报专用
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 预测功率结果集
+   */
+  @SuppressWarnings("WeakerAccess")
+  @Transactional(propagation = Propagation.REQUIRED)
+  public List<ForecastPowerUltraShortTermOneHis> getForecastPowerUltraShortTerm(@NotNull final Long startTime, @NotNull final Long endTime) {
+    log.info("开始获取超短期实时预测功率" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
+
+    Long monentTime = 0L;
+    try {
+      monentTime = DateMomentUtil.getMomentTime(new Date().getTime(), 1, 15 * 60 * 1000L);
+    } catch (Exception e) {
+      log.error("获取当前时刻错误",e);
+    }
+    //为了保证回传和超短期数据一直,当数据库中有预测数据时,直接返回数据
+    List<ForecastPowerUltraShortTermOneHis> byForecastTimeBetweenAndGenDate = this.forecastPowerUltraShortTermOneHisRepository.findByForecastTimeBetweenAndGenDate(startTime, endTime, new Date(monentTime));
+
+
+    int moment = DateMomentUtil.getIntervalMoment(startTime, endTime,15*60*1000l);
+
+
+    if (byForecastTimeBetweenAndGenDate.size() >= moment) {
+      return byForecastTimeBetweenAndGenDate;
+    }
+
+
+    // 查询场站信息
+    ElectricField electricFieldInfo = electricFieldService.get();
+    // 查询预测时间点对应的开机容量
+    Map<Long, BigDecimal> openCapacityMap = null;
+    try {
+      openCapacityMap = super.queryOpenCapacity(startTime, endTime, electricFieldInfo.getCapacity());
+    } catch (BusinessException e) {
+      log.error("预测数据生成获取开机容量出错:" + CommonUtil.printStackTraceToString(e));
+    }
+
+
+    List<ForecastPowerUltraShortTermOne> forecastPowerUltraShortTermList = new ArrayList<>();
+    List<ForecastPowerUltraShortTermOne> tempList = this.forecastPowerUltraShortTermOneRepository.findByForecastTimeBetween(startTime, endTime);
+    for (ForecastPowerUltraShortTermOne f:tempList){
+      if (Integer.parseInt(DateFormatUtils.format(f.getForecastTime(),"mm"))%15==0){
+        forecastPowerUltraShortTermList.add(f);
+      }
+    }
+
+    Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
+    Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
+    log.info("获取所需记录数:" + moments);
+
+    if (moments > forecastPowerUltraShortTermList.size()) {
+      Map<Long, List<ForecastPowerUltraShortTermOne>> forecastPowerShortTermsMap = forecastPowerUltraShortTermList.stream().collect(Collectors.groupingBy(ForecastPowerUltraShortTermOne::getForecastTime));
+      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
+        if (forecastPowerShortTermsMap.get(tempTime) == null) {
+          log.info("文件超短期缺点:"+tempTime+" forecastPowerShortTermsMap里个数:"+forecastPowerShortTermsMap.size());
+          BigDecimal tempValue;
+          if (ElectricFieldTypeEnum.E1.equals(electricFieldInfo.getElectricFieldTypeEnum())) {
+            if (DateTimeUtil.checkInSunriseAndSunset(startTime, electricFieldInfo.getLongitude().doubleValue(), electricFieldInfo.getLatitude().doubleValue())) {
+              tempValue = new BigDecimal(CommonUtil.getRandom(1, 70) / 100.0d);
+            } else {
+              // 日升日落
+              tempValue = BigDecimal.ZERO;
+            }
+          } else {
+            tempValue = new BigDecimal(CommonUtil.getRandom(1, 70) / 100.0d);
+          }
+          tempValue = tempValue.multiply(electricFieldInfo.getCapacity()).setScale(2, BigDecimal.ROUND_HALF_UP);
+          ForecastPowerUltraShortTermOne forecastPowerUltraShortTerm = new ForecastPowerUltraShortTermOne();
+          forecastPowerUltraShortTerm.setGenDate(new Date(monentTime));
+          forecastPowerUltraShortTerm.setForecastTime(tempTime);
+          forecastPowerUltraShortTerm.setFpValue(tempValue);
+          forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
+          forecastPowerUltraShortTerm.setCoefficientValue(new BigDecimal(-0.99).setScale(2,BigDecimal.ROUND_HALF_UP));
+          forecastPowerUltraShortTerm.setDifferenceValue(new BigDecimal(-0.99).setScale(2,BigDecimal.ROUND_HALF_UP));
+          // 保存超短期实时预测记录
+          this.forecastPowerUltraShortTermOneRepository.save(forecastPowerUltraShortTerm);
+          forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);
+        }
+      }
+    }
+    log.info("生成超短期实时预测功率记录数:" + forecastPowerUltraShortTermList.size());
+    // 按预测时刻升序
+    forecastPowerUltraShortTermList.sort(Comparator.comparing(ForecastPowerUltraShortTermOne::getForecastTime));
+
+//    int qn_yth = sysParameterService.getTranSysParameter("qn_yth", "0");
+//
+//    if(qn_yth != 0){
+//      //一体化消减
+//      List<RepairPlan> list = repairPlanRepository.findAll();
+//      if(list.size()>0){
+//        log.info("===========执行一体化对超短期上报数据调整(消减容量)");
+//        for (int i = 0; i < forecastPowerUltraShortTermList.size(); i++) {
+//          ForecastPowerUltraShortTerm forecastPowerUltraShortTerm = forecastPowerUltraShortTermList.get(i);
+//          List<RepairPlan> collect = list.stream().filter(r -> r.getStartTime().getTime() <= forecastPowerUltraShortTerm.getForecastTime() && forecastPowerUltraShortTerm.getForecastTime() < r.getEndTime().getTime()).collect(Collectors.toList());
+//          if(collect.size()>0){
+//
+//            BigDecimal capacityCurtailment = collect.get(0).getCapacityCurtailment();
+//            BigDecimal fpValue = forecastPowerUltraShortTermList.get(i).getFpValue();
+//
+//            //消减后的容量
+//            BigDecimal subtract = fpValue.subtract(capacityCurtailment);
+//            if(subtract.compareTo(new BigDecimal(0)) <= 0){
+//              subtract = new BigDecimal(0);
+//            }
+//            forecastPowerUltraShortTermList.get(i).setFpValue(subtract);
+//            log.info("一体化对超短期上报数据调整=》时间:{};消减容量为:{};调整前:{};调整后:{}", DateFormatUtils.format(forecastPowerUltraShortTermList.get(i).getForecastTime(),"yyyy-MM-dd HH:mm"),capacityCurtailment, fpValue, subtract);
+//          }
+//
+//        }
+//        log.info("===========结束一体化对超短期上报数据调整(消减容量)");
+//      }
+//
+//
+//
+//      List<UltraShortTermCoefficient> ultraShortTermCoefficientList = ultraShortTermCoefficientRepository.findByParseTimeBetween(new Date(startTime-2*15*60*1000l), new Date(startTime-15*60*1000l));
+//
+//      if(ultraShortTermCoefficientList.size()>0){
+//        log.info("===========执行一体化对超短期上报数据调整(系数)");
+//        for (int i = 0; i < forecastPowerUltraShortTermList.size(); i++) {
+//          ForecastPowerUltraShortTerm forecastPowerUltraShortTerm = forecastPowerUltraShortTermList.get(i);
+//          List<UltraShortTermCoefficient> collect = ultraShortTermCoefficientList.stream().filter(u -> u.getTime().getTime() == forecastPowerUltraShortTerm.getForecastTime()).collect(Collectors.toList());
+//
+//          if(collect.size()>0){
+//            BigDecimal coefficient = collect.get(0).getCoefficient();
+//            BigDecimal fpValue = forecastPowerUltraShortTermList.get(i).getFpValue();
+//            BigDecimal coefficientAfter = fpValue.multiply(coefficient).setScale(2,BigDecimal.ROUND_DOWN);
+//
+//            forecastPowerUltraShortTermList.get(i).setFpValue(coefficientAfter);
+//            log.info("一体化对超短期上报数据调整=》时间:{};系数为:{};调整前:{};调整后:{}", DateFormatUtils.format(forecastPowerUltraShortTermList.get(i).getForecastTime(),"yyyy-MM-dd HH:mm"),coefficient, fpValue, coefficientAfter);
+//          }
+//        }
+//        log.info("===========结束一体化对超短期上报数据调整(系数)");
+//      }
+//    }
+//
+//
+
+
+    // 处理超短期历史记录
+    List<ForecastPowerUltraShortTermOneHis> forecastPowerUltraShortTermHiss = new ArrayList<>();
+
+    ForecastPowerUltraShortTermOneHis forecastPowerUltraShortTermHis;
+    int n = 1;
+    // 生成超短期历史数据
+    BigDecimal openCapacity;
+    //生成数据
+    for (ForecastPowerUltraShortTermOne forecastPowerUltraShortTerm : forecastPowerUltraShortTermList) {
+      forecastPowerUltraShortTermHis = new ForecastPowerUltraShortTermOneHis();
+      openCapacity = openCapacityMap.get(forecastPowerUltraShortTerm.getForecastTime());
+      forecastPowerUltraShortTermHis.setForecastTime(forecastPowerUltraShortTerm.getForecastTime());
+      forecastPowerUltraShortTermHis.setSuCapacity(openCapacity);
+      forecastPowerUltraShortTermHis.setCapacity(electricFieldInfo.getCapacity());
+      forecastPowerUltraShortTermHis.setForecastHowLongAgo(n++);
+      forecastPowerUltraShortTermHis.setTheoryValue(forecastPowerUltraShortTerm.getFpValue());
+      // 预测可用功率=预测*(开机容量/装机容量)
+      BigDecimal fpValue = forecastPowerUltraShortTerm.getFpValue().multiply(openCapacity)
+        .divide(electricFieldInfo.getCapacity(), 2, BigDecimal.ROUND_HALF_UP);
+      forecastPowerUltraShortTermHis.setAbleValue(fpValue);
+      forecastPowerUltraShortTermHis.setPredictionModelEnum(forecastPowerUltraShortTerm.getPredictionModelEnum());
+      forecastPowerUltraShortTermHis.setDifferenceValue(forecastPowerUltraShortTerm.getDifferenceValue());
+      forecastPowerUltraShortTermHis.setCoefficientValue(forecastPowerUltraShortTerm.getCoefficientValue());
+      forecastPowerUltraShortTermHis.setGenDate(new Date(monentTime));
+      forecastPowerUltraShortTermHiss.add(forecastPowerUltraShortTermHis);
+    }
+//    List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHiss = forecastPowerUltraShortTermHiss1.stream().filter(t -> t.getForecastHowLongAgo() <=16).collect(Collectors.toList());
+    // 获取实际功率替换超短期点位参数
+    Integer replacePoint = 0;
+    String realpower_replace_cdq = sysParameterService.getSysParameter("realpower_replace_cdq", "0");
+    replacePoint = Integer.valueOf(realpower_replace_cdq);
+    if (replacePoint <= forecastPowerUltraShortTermHiss.size() && replacePoint > 0) {
+      Long pre5Time = 0l;
+      Date systemDate = new Date();
+      try {
+        // 获取前5分钟时刻
+        pre5Time = DateMomentUtil.getMomentTime(systemDate.getTime() - 5 * 60 * 1000, 1, 5 * 60 * 1000L);
+      } catch (Exception e) {
+        log.error("超短期数据用实际功率替换生成时刻步长错误", e);
+        pre5Time = DateMomentUtil.getDayStartTime(systemDate.getTime());
+      }
+      List<PowerStationStatusData> realPowerList = powerStationStatusDataRepository.findByTimeBetween(new Date(pre5Time), new Date(pre5Time + 5 * 60 * 1000));
+      if (realPowerList.size() > 0) {
+        // 按时间降序排列
+        realPowerList.sort(Comparator.comparing(PowerStationStatusData::getTime).reversed());
+        // 获取最后一条最新的实际功率
+        PowerStationStatusData realPower = realPowerList.get(0);
+        // 将实际功率替换到对应的超短期点位上
+        ForecastPowerUltraShortTermOneHis d = forecastPowerUltraShortTermHiss.get(replacePoint - 1);
+        if (realPower.getRealValue().compareTo(new BigDecimal(0)) != -1) {
+          d.setAbleValue(realPower.getRealValue());
+        }
+      }
+    }
+
+    //-----------------------------------------------------开始进行人工干预数值的判断----------------------------------------------------
+    //-----------------------------------------------------点位判断开始----------------------------------------------------
+    List<ManualInterventionData> manualInterventionDataList = manualInterventionService.queryManualIntervention(startTime, endTime, "1");
+    manualInterventionDataList.sort(Comparator.comparing(ManualInterventionData::getInterveneTime));
+    Map<Long, BigDecimal> mMap = new HashMap<>();
+    int flag = 0;
+    if (manualInterventionDataList.size() > 0) {
+      for (ManualInterventionData manualInterventionData : manualInterventionDataList) {
+        mMap.put(manualInterventionData.getInterveneTime(), manualInterventionData.getInterveneData());
+      }
+      for (ForecastPowerUltraShortTermOneHis forecastPowerUltraShortTermHis1 : forecastPowerUltraShortTermHiss) {
+        BigDecimal ma = mMap.get(forecastPowerUltraShortTermHis1.getForecastTime());
+        if (ma != null) {
+          forecastPowerUltraShortTermHis1.setAbleValue(ma.setScale(2, BigDecimal.ROUND_HALF_UP));
+          forecastPowerUltraShortTermHis1.setTheoryValue(ma.setScale(2, BigDecimal.ROUND_HALF_UP));
+          forecastPowerUltraShortTermHis1.setGenDate(new Date(monentTime));
+          forecastPowerUltraShortTermHis1.setPredictionModelEnum(PredictionModelEnum.E6);
+          forecastPowerUltraShortTermHiss.set(flag, forecastPowerUltraShortTermHis1);
+        }
+        flag++;
+      }
+    }
+    //-----------------------------------------------------点位判断结束----------------------------------------------------
+    //-----------------------------------------------------系数判断开始----------------------------------------------------
+    //获取今日凌晨00:00
+    long mStartTime = DateUtil.beginOfDay(DateTime.now()).getTime();
+    long mEndTime = mStartTime + 24*60*60*1000l - 1000;
+    List<ManualInterventionRatioData> manualInterventionRatioDataList = manualInterventionRatioService.queryManualInterventionRatio(mStartTime, mEndTime, "1");
+
+    //如果有人工干预系数设置记录
+    if(manualInterventionRatioDataList.size() > 0){
+      //循环所有记录
+      for(ManualInterventionRatioData manualInterventionRatioData :manualInterventionRatioDataList){
+        for (Long tempTime = manualInterventionRatioData.getInterveneStartTime(); tempTime <= manualInterventionRatioData.getInterveneEndTime(); tempTime = tempTime + 15 * 60 * 1000L) {
+          //循环所有超短期的值
+          int mrflag = 0;
+          for (ForecastPowerUltraShortTermOneHis forecastPowerUltraShortTermHis1 : forecastPowerUltraShortTermHiss) {
+            //如果该时间设置了系数则数值*系数
+            if(forecastPowerUltraShortTermHis1.getForecastTime().equals(tempTime)){
+              BigDecimal ableValue = forecastPowerUltraShortTermHis1.getAbleValue().multiply(new BigDecimal(manualInterventionRatioData.getRatio().toString())).setScale(2, BigDecimal.ROUND_HALF_UP);
+              //如果计算后的数据大于装机容量 则ableValue=装机容量
+              if((ableValue).compareTo(new BigDecimal(electricFieldInfo.getCapacity().toString())) > 0){
+                ableValue = new BigDecimal(electricFieldInfo.getCapacity().toString());
+              }
+              forecastPowerUltraShortTermHis1.setAbleValue(ableValue);
+              forecastPowerUltraShortTermHis1.setTheoryValue(ableValue);
+              forecastPowerUltraShortTermHis1.setGenDate(new Date(monentTime));
+              forecastPowerUltraShortTermHis1.setPredictionModelEnum(PredictionModelEnum.E10);
+              forecastPowerUltraShortTermHiss.set(mrflag, forecastPowerUltraShortTermHis1);
+            }
+            mrflag++;
+          }
+        }
+      }
+    }
+    //-----------------------------------------------------系数判断结束----------------------------------------------------
+
+
+
+    String lowerPredictionLimit = super.getSysParameter("LowerPredictionLimit", "0");
+    BigDecimal lpl = new BigDecimal(lowerPredictionLimit);
+
+    forecastPowerUltraShortTermHiss.forEach(s->{
+      if(s.getAbleValue().compareTo(lpl)==-1){
+        s.setAbleValue(lpl);
+      }
+    });
+    // 获取当前时刻标记时间
+//    Long nowMomentTime;
+//    try {
+//      nowMomentTime = DateMomentUtil.getMomentTime(System.currentTimeMillis(), 1, 15 * 60 * 1000L);
+//    } catch (Exception e) {
+//      log.error("时刻步长错误", e);
+//      nowMomentTime = DateMomentUtil.getDayStartTime(System.currentTimeMillis());
+//    }
+
+    //-----------------------------------------------------浙江光伏负偏差---------------------------------------------------
+
+    try {
+      String negative_deviation = super.getSysParameter("negative_deviation", "0");
+      if (electricFieldInfo.getProvinceEnum().toString().equals("E33")&&electricFieldInfo.getElectricFieldTypeEnum().toString().equals("E1")&&!negative_deviation.equals("0")&&!negative_deviation.equals("")){
+        int mrflag = 0;
+        for (ForecastPowerUltraShortTermOneHis f : forecastPowerUltraShortTermHiss) {
+          f.setAbleValue(f.getAbleValue().subtract(new BigDecimal(negative_deviation)));
+          f.setTheoryValue(f.getTheoryValue().subtract(new BigDecimal(negative_deviation)));
+          f.setGenDate(new Date());
+          f.setPredictionModelEnum(PredictionModelEnum.E10);
+          forecastPowerUltraShortTermHiss.set(mrflag, f);
+          mrflag++;
+        }
+      }
+    }catch (Exception e){
+      e.printStackTrace();
+      log.info("负偏差计算错误,请检查negative_deviation参数是否为数字");
+    }
+    //-----------------------------------------------------浙江光伏负偏差---------------------------------------------------
+    //-----------------------------------------------------人工干预数据判断结束----------------------------------------------------
+    // 删除当前时刻标记时间生成的超短期历史记录
+    this.forecastPowerUltraShortTermOneHisRepository.deleteNowMoment(startTime, endTime, new Date(monentTime));
+    // 保存超短期历史记录
+    this.forecastPowerUltraShortTermOneHisRepository.saveAll(forecastPowerUltraShortTermHiss);
+    return forecastPowerUltraShortTermHiss;
+  }
+
+  /**
+   * 执行超短期预测
+   */
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = RuntimeException.class)
+  public void executeForecast() {
+    // 根据场站类型执行相应超短期预测
+    try {
+      // 获取查询时间,从当前时间所处时间点标记时间开始查询,截至到96个时间点对应的标记时间
+      String cdqUpMin = super.getSysParameter("CDQ_UP_MIN", "0");
+      Long calTime = DateMomentUtil.getMomentTime(System.currentTimeMillis() + Integer.parseInt(cdqUpMin) * 1000 * 60, 1, 15 * 60 * 1000L);
+      Long startTime = calTime + 15 * 1000 * 60L;
+      String llcdq_point = super.getSysParameter("FILE_LLCDQ_POINT", "16");
+      Integer forecastPoints = Integer.parseInt(llcdq_point);
+      Integer forecastMinutes = forecastPoints * 15;
+      // 结束时间增加15分钟为了防止文件先生成,实时表中最后一个时间点没有点位的问题
+      Long endTime = DateUtils.addMinutes(new Date(startTime), forecastMinutes).getTime();
+
+      // 查询该时间段内的短期预测功率
+      List<ForecastPowerShortTermOne> forecastPowerShortTermList = this.forecastPowerShortTermOneRepository.findByForecastTimeBetween(startTime, endTime);
+
+      Map<Long, List<ForecastPowerShortTermOne>> forecastPowerShortTermsMap =
+        forecastPowerShortTermList.stream().collect(Collectors.groupingBy(ForecastPowerShortTermOne::getForecastTime));
+      // 查询场站信息
+      ElectricField electricField = this.getElectricField();
+      Map<Long, BigDecimal> openCapacityMap = null;
+      try {
+        openCapacityMap = super.queryOpenCapacity(startTime, endTime, electricField.getCapacity());
+      } catch (BusinessException e) {
+        log.error("预测数据生成获取开机容量出错:" + CommonUtil.printStackTraceToString(e));
+      }
+      List<ForecastPowerShortTermOne> addForecastPowerShortTermList = new ArrayList<>();
+      // 判断短期数据是否缺点
+      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + 15 * 60 * 1000L) {
+        if (forecastPowerShortTermsMap.get(tempTime) == null) {
+          // 缺失时间点
+          ForecastPowerShortTermOne forecastPowerShortTerms = null;
+          if (ElectricFieldTypeEnum.E1.compareTo(electricField.getElectricFieldTypeEnum()) == 0) {
+            forecastPowerShortTerms = forecastPowerShortTermOneService.generateSolarPowerShortTerm(tempTime, openCapacityMap.get(tempTime), electricField);
+          } else {
+            forecastPowerShortTerms = forecastPowerShortTermOneService.generateWindPowerShortTerm(tempTime, openCapacityMap.get(tempTime));
+          }
+          addForecastPowerShortTermList.add(forecastPowerShortTerms);
+        }
+      }
+      if (!addForecastPowerShortTermList.isEmpty()) {
+        // 保存短期预测
+        this.forecastPowerShortTermOneRepository.saveAll(addForecastPowerShortTermList);
+        // 将补齐的预测功率追加到查询预测功率结果集中
+        forecastPowerShortTermList.addAll(addForecastPowerShortTermList);
+      }
+      forecastPowerShortTermList.sort(Comparator.comparing(ForecastPowerShortTermOne::getForecastTime));
+
+      if (ElectricFieldTypeEnum.E1.compareTo(electricField.getElectricFieldTypeEnum()) == 0) {
+        // 光伏电站
+        this.executeForecastForlight(forecastPowerShortTermList, electricField.getCapacity());
+      } else if (ElectricFieldTypeEnum.E2.compareTo(electricField.getElectricFieldTypeEnum()) == 0) {
+        // 风力电场
+        this.executeForecastForWind(forecastPowerShortTermList, electricField.getCapacity());
+      } else {
+        log.error("场站类型非法!");
+      }
+    } catch (BusinessException e) {
+      log.error("获取场站信息出错!", e);
+    } catch (Exception e) {
+      log.error("系统运行错误!", e);
+    }
+  }
+
+  /**
+   * 执行风电场超短期预测
+   *
+   * @param forecastPowerShortTermList 短期预测结果集
+   * @param capacity                   装机容量
+   */
+  private List<ForecastPowerUltraShortTermOne> executeForecastForWind(final List<ForecastPowerShortTermOne> forecastPowerShortTermList, final BigDecimal capacity) {
+    List<ForecastPowerUltraShortTermOne> forecastPowerUltraShortTermList = new ArrayList<>();
+    ForecastPowerUltraShortTermOne forecastPowerUltraShortTerm;
+    //获取系统参数cdqjsfs,超短期计算方式,0为默认乘系数的方式,1为根据可用功率计算的方式
+    String cdqjsfs = electricFieldService.getSysParameter("cdqjsfs", "1");
+    log.info("参数cdqjsfs值为:" + cdqjsfs + ",超短期计算方式,0为默认乘系数的方式,1为根据可用功率计算的方式。");
+    BigDecimal stPower, ustPower,ustPowers;
+    // 查询当前时间点标记时间前10分钟的可用功率
+    Date currentTime = new Date(System.currentTimeMillis());
+    Date startTime = DateUtils.addMinutes(currentTime, -10);
+    Date endTime = DateUtils.addMinutes(currentTime, 1);
+    List<PowerStationStatusData> powerStationStatusDataList = this.powerStationStatusDataRepository.findByTimeBetween(startTime, endTime);
+    List<PowerStationStatusData> filterList = powerStationStatusDataList.stream().filter(t -> t.getAbleValue().compareTo(new BigDecimal("-1")) == 1).collect(Collectors.toList());
+    String coe = super.getSysParameter("CDQ_COE", "1.05");
+
+    Long monentTime = 0L;
+    try {
+      monentTime = DateMomentUtil.getMomentTime(new Date().getTime(), 1, 15 * 60 * 1000L);
+    } catch (Exception e) {
+      log.error("获取当前时刻错误",e);
+    }
+    if (filterList.size() > 0) {
+      // 获取当前时刻对应的短期
+      List<ForecastPowerShortTermOne> currentForecastPowerShortTermList;
+      BigDecimal currentForecastPowerValue = BigDecimal.ZERO;
+      try {
+        Long currentMoment = DateMomentUtil.getMomentTime(currentTime.getTime(), 1, 15 * 60 * 1000L);
+        currentForecastPowerShortTermList = this.forecastPowerShortTermOneRepository.findByForecastTimeBetween(currentMoment, currentMoment);
+        if (currentForecastPowerShortTermList.size()>0){
+          currentForecastPowerValue = currentForecastPowerShortTermList.get(0).getFpValue();
+        }
+        else{
+          // 当前时间没有对应的短期,用实际功率最近的一个替换
+          filterList.sort(Comparator.comparing(PowerStationStatusData::getTime).reversed());
+          currentForecastPowerValue = filterList.get(0).getAbleValue();
+        }
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+
+      BigDecimal sumAbleValue = filterList.stream().map(PowerStationStatusData::getAbleValue)
+        .reduce(BigDecimal.ZERO, BigDecimal::add);
+      BigDecimal averageAbleValue = sumAbleValue.divide(new BigDecimal(filterList.size()), 2, BigDecimal.ROUND_HALF_UP);
+      //可用-短期差值
+      BigDecimal deviationValue = averageAbleValue.subtract(currentForecastPowerValue);
+      for (int i = 0; i < forecastPowerShortTermList.size(); i++) {
+        forecastPowerUltraShortTerm = new ForecastPowerUltraShortTermOne();
+        forecastPowerUltraShortTerm.setForecastTime(forecastPowerShortTermList.get(i).getForecastTime());
+        forecastPowerUltraShortTerm.setGenDate(new Date(monentTime));
+        //短期
+        stPower = forecastPowerShortTermList.get(i).getFpValue();
+        //短期*系数
+        ustPowers = stPower.multiply(new BigDecimal(coe)).setScale(2, BigDecimal.ROUND_HALF_UP);
+        // 如果短期预测小于等于0,则超短期为0
+        if (stPower.doubleValue() <= 0) {
+          forecastPowerUltraShortTerm.setFpValue(BigDecimal.ZERO);
+          forecastPowerUltraShortTerm.setDifferenceValue(BigDecimal.ZERO);
+          forecastPowerUltraShortTerm.setCoefficientValue(BigDecimal.ZERO);
+          forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
+        } else {
+          BigDecimal xzjdq = deviationValue.add(stPower).setScale(2, BigDecimal.ROUND_HALF_UP);
+          String cdqjsfsZbxz = electricFieldService.getSysParameter("cdqjsfsZbxz", "0.4");
+          log.debug("参数cdqjsfsZbxz值为:" + cdqjsfsZbxz + ",超短期计算方式,可用和短期的差值加短期占比。");
+          String cdqjsfsZbdq = electricFieldService.getSysParameter("cdqjsfsZbdq", "0.6");
+          log.debug("参数cdqjsfsZbdq值为:" + cdqjsfsZbdq + ",超短期计算方式,短期占比。");
+          ustPower = xzjdq.multiply(new BigDecimal(cdqjsfsZbxz)).setScale(2, BigDecimal.ROUND_HALF_UP).add(stPower.multiply(new BigDecimal(cdqjsfsZbdq)).setScale(2, BigDecimal.ROUND_HALF_UP));
+          if (ustPower.doubleValue() > capacity.doubleValue()) {
+            // 如果超短期结果超出装机容量,则超短期结果为装机容量
+            forecastPowerUltraShortTerm.setFpValue(capacity);
+          } else if (ustPower.doubleValue() < 0) {
+            // 如果超短期结果小于0,则超短期结果为0
+            forecastPowerUltraShortTerm.setFpValue(BigDecimal.ZERO);
+          }else{
+            if(cdqjsfs.equals("1")){
+              forecastPowerUltraShortTerm.setFpValue(ustPower);
+              forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E5);
+            }else{
+              forecastPowerUltraShortTerm.setFpValue(ustPowers);
+              forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E9);
+            }
+          }
+          forecastPowerUltraShortTerm.setDifferenceValue(ustPower);
+          forecastPowerUltraShortTerm.setCoefficientValue(ustPowers);
+        }
+
+        forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);
+      }
+    } else {
+      log.info("库中没有可用,本次可用计算数据采用短期*系数的方式生成数据");
+
+      // 短期乘以系数
+      for (int i = 0; i < forecastPowerShortTermList.size(); i++) {
+        stPower = forecastPowerShortTermList.get(i).getFpValue();
+        ustPower = stPower.multiply(new BigDecimal(coe)).setScale(2, BigDecimal.ROUND_HALF_UP);
+        forecastPowerUltraShortTerm = new ForecastPowerUltraShortTermOne();
+        forecastPowerUltraShortTerm.setForecastTime(forecastPowerShortTermList.get(i).getForecastTime());
+        forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E9);
+        forecastPowerUltraShortTerm.setCoefficientValue(ustPower);
+        forecastPowerUltraShortTerm.setDifferenceValue(new BigDecimal(-0.99).setScale(2,BigDecimal.ROUND_HALF_UP));
+        forecastPowerUltraShortTerm.setFpValue(ustPower);
+        forecastPowerUltraShortTerm.setGenDate(new Date(monentTime));
+        forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);
+      }
+    }
+    // 保存超短期预测结果
+    this.forecastPowerUltraShortTermOneRepository.deleteByForecastTimeBetween(forecastPowerUltraShortTermList.get(0).getForecastTime(), forecastPowerUltraShortTermList.get(forecastPowerShortTermList.size()-1).getForecastTime());
+    this.forecastPowerUltraShortTermOneRepository.saveAll(forecastPowerUltraShortTermList);
+
+    return forecastPowerUltraShortTermList;
+  }
+
+  private void executeForecastForlight(final List<ForecastPowerShortTermOne> forecastPowerShortTermList, final BigDecimal capacity) {
+    // 暂时光超短期预测方法=风超短期预测方法
+    this.executeForecastForWind(forecastPowerShortTermList, capacity);
+  }
+
+}