Commit da08b3c5 authored by ZWT's avatar ZWT

feat(能源管理系统): 间开优化定时任务

1.开发间开优化长期间开优化定时任务,完成并网流程绿电消纳优先策略;
2.开发间开优化长期间开优化定时任务,完成并网流程消峰平谷策略;
3.开发间开优化中短期间开优化定时任务,创建定时任务并添加配置;
4.抽取间开优化定时任务逻辑处理父类,对长期间开优化定时任务/中短期间开优化定时任务代码结构进行优化;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent 3ebfc8f9
package pps.core.space.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import pps.cloud.base.service.IBasePowerLineCloudService;
import pps.cloud.base.service.IBaseWellheadCloudService;
import pps.cloud.base.service.data.base_power_line_plant.DynamicQueryBasePowerLinePlantInput;
import pps.cloud.base.service.data.base_power_line_plant.DynamicQueryBasePowerLinePlantOutput;
import pps.cloud.base.service.data.base_price_strategy_detail.GetBasePriceStrategyDetailInput;
import pps.cloud.base.service.data.base_price_strategy_detail.GetBasePriceStrategyDetailOutput;
import pps.cloud.base.service.data.base_wellhead.DynamicQueryBaseWellheadInput;
import pps.cloud.base.service.data.base_wellhead.DynamicQueryBaseWellheadOutput;
import pps.cloud.prediction.service.IPlantPredictedPowerCloudService;
......@@ -14,14 +20,14 @@ import pps.cloud.prediction.service.data.plant_predicted_power_data.DynamicQuery
import pps.cloud.prediction.service.data.plant_predicted_power_data.DynamicQueryPlantPredictedPowerOutput;
import pps.core.common.constant.BusinessConstant;
import pps.core.common.entity.BaseModel;
import pps.core.space.entity.SpaceInstitutionDetailEnt;
import pps.core.space.entity.SpaceInstitutionDurationEnt;
import pps.core.space.entity.SpaceInstitutionWellheadView;
import pps.core.common.utils.BaseUtils;
import pps.core.space.entity.*;
import pps.core.space.enums.BusinessError;
import pps.core.space.mapper.SpaceInstitutionDetailMapper;
import pps.core.space.mapper.SpaceInstitutionDurationMapper;
import pps.core.space.mapper.SpaceInstitutionWellheadViewMapper;
import pps.core.space.service.data.SpaceOptimizeWellheadAndPlant;
import pps.core.space.utils.ServiceUtil;
import xstartup.base.XContext;
import xstartup.base.exception.XServiceException;
import xstartup.data.XListResult;
......@@ -246,4 +252,343 @@ public class SpaceOptimizeBaseService {
);
});
}
/**
* 创建间开优化信息
*
* @param periodDTOList 时期数据主义者
* @param detailId 详细信息id
* @param lineId 线路id
* @param executionCycleForMonth 月执行周期
* @param optimizeDeadline 优化截止日期
* @return {@link String}
*/
public String createOptimizePeriod(List<SpaceOptimizePeriodDTO> periodDTOList, String detailId,
String lineId, String executionCycleForMonth, Date optimizeDeadline) {
SpaceOptimizePeriodDTO periodDTO = new SpaceOptimizePeriodDTO();
BaseUtils.setBaseModelDefaultForJob(periodDTO);
periodDTO.setInstitutionId(detailId);
periodDTO.setLineId(lineId);
periodDTO.setExecutionCycle(executionCycleForMonth);
periodDTO.setOptimizeDeadline(optimizeDeadline);
periodDTOList.add(periodDTO);
return periodDTO.getId();
}
/**
* 创建间开优化井口信息
*
* @param wellheadDTOList 井口dtolist
* @param periodId 期间id
* @param wellheadId 井口id
* @param wellNumber 井号
* @return {@link String}
*/
public String createOptimizeWellhead(List<SpaceOptimizeWellheadDTO> wellheadDTOList, String periodId,
String wellheadId, String wellNumber) {
SpaceOptimizeWellheadDTO wellheadDTO = new SpaceOptimizeWellheadDTO();
BaseUtils.setBaseModelDefaultForJob(wellheadDTO);
wellheadDTO.setPeriodId(periodId);
wellheadDTO.setWellheadId(wellheadId);
wellheadDTO.setWellNumber(wellNumber);
wellheadDTOList.add(wellheadDTO);
return wellheadDTO.getId();
}
/**
* 创建间开优化井口区间配置信息
*
* @param durationDTOList 持续时间dtolist
* @param periodId 期间id
* @param recordId 记录id
* @param wellheadId 井口id
* @param generationTypeKey 生成类型密钥
* @param openWellTime 开井时间
* @param endTimeString 结束时间字符串
*/
public void createOptimizeDuration(List<SpaceOptimizeDurationDTO> durationDTOList, String periodId,
String recordId, String wellheadId, String generationTypeKey,
String openWellTime, String endTimeString) {
SpaceOptimizeDurationDTO durationDTO = new SpaceOptimizeDurationDTO();
BaseUtils.setBaseModelDefaultForJob(durationDTO);
durationDTO.setRecordId(recordId);
durationDTO.setPeriodId(periodId);
durationDTO.setWellheadId(wellheadId);
durationDTO.setGenerationTypeKey(generationTypeKey);
durationDTO.setIsOptimize(BusinessConstant.ZERO);
durationDTO.setOpenWellTime(openWellTime);
durationDTO.setCloseWellTime(endTimeString);
durationDTOList.add(durationDTO);
}
/**
* 创建间开原始间开区间
*
* @param unOptimizeDurationList 取消优化工期列表
* @param durationEnt 持续时间ent
* @param periodId 期间id
* @param recordId 记录id
* @param wellheadId 井口id
*/
public void createUnOptimizeDuration(List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
SpaceInstitutionDurationEnt durationEnt,
String periodId, String recordId, String wellheadId) {
SpaceOptimizeDurationDTO durationDTO = new SpaceOptimizeDurationDTO();
BaseUtils.setBaseModelDefaultForJob(durationDTO);
durationDTO.setRecordId(recordId);
durationDTO.setPeriodId(periodId);
durationDTO.setWellheadId(wellheadId);
durationDTO.setIsOptimize(BusinessConstant.ONE);
durationDTO.setOpenWellTime(durationEnt.getOpenWellTime());
durationDTO.setCloseWellTime(durationEnt.getCloseWellTime());
unOptimizeDurationList.add(durationDTO);
}
/**
* 绿电消纳策略
*
* @param wellheadDTOList 井口dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param durationDTOList 持续时间dtolist
* @param wellheadViewList 井口视图列表
* @param avgPowerList 平均功率列表
* @param durationMap 持续时间图
* @param detail 细节
* @param periodId 期间id
*/
public void greenElectricityConsumptionStrategy(List<SpaceOptimizeWellheadDTO> wellheadDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceInstitutionWellheadView> wellheadViewList,
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList, Map<String, List<SpaceInstitutionDurationEnt>> durationMap,
SpaceInstitutionDetailEnt detail, String periodId) {
//时间差
int between = 0;
//启动间隔累积
int startInterval = 0;
//判断是否第一口井
boolean isFirstWellhead;
//第一口井启动时间
DateTime firstStartTime = null;
//井口累积运行总功率
BigDecimal totalOperatingPower = BigDecimal.ZERO;
for (int w = 0, wellheadSize = wellheadViewList.size(); w < wellheadSize; w++) {
SpaceInstitutionWellheadView wellhead = wellheadViewList.get(w);
String wellheadId = wellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, periodId, wellheadId, wellhead.getWellNumber());
//取当前井口最大发电量
BigDecimal serviceRating = wellhead.getServiceRating();
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellhead);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
}
if (w == 0) {
//第一个井口
isFirstWellhead = true;
totalOperatingPower.add(serviceRating);
} else {
//累加
totalOperatingPower = totalOperatingPower.add(serviceRating);
startInterval = startInterval + detail.getStartInterval();
isFirstWellhead = false;
}
for (int d = 0, durationSize = durationConfigList.size(); d < durationSize; d++) {
SpaceInstitutionDurationEnt duration = durationConfigList.get(d);
String openWellTime = duration.getOpenWellTime();
DateTime startTime = DateUtil.parse(openWellTime + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
DateTime endTime = DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
//第一次启动
if (d == 0) {
//第一口井的启动时间
if (isFirstWellhead) {
firstStartTime = startTime;
//计算开井时间
int startIndex = 0;
for (int a = 0, avgPowerSize = avgPowerList.size(); a < avgPowerSize; a++) {
DynamicQueryPlantPredictedPowerOutput predictedPower = avgPowerList.get(a);
//当日时间段平均光伏出力>=第一口井运行负荷时,该时间为第一口井运行时间
if (predictedPower.getPower().compareTo(serviceRating) >= BusinessConstant.ZERO) {
startIndex = a;
break;
}
}
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
String startTimeString = start.getHourTime() + start.getMinTime();
//计算第一次关井时间,按照间开时间段顺延
int startDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
DateTime endTimeOptimize = startTime.offset(DateField.MINUTE, startDuration);
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
startTimeString, endTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT)
);
//计算时间偏移
DateTime startTimeOptimize = DateUtil.parse(startTimeString, BusinessConstant.TIME_FORMAT);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(startTimeOptimize, startTime);
}
//其它井口的第一次启动时间
else {
DateTime startTimeOffset = firstStartTime.offset(DateField.MINUTE, startInterval);
int startIndex = -1;
BigDecimal add = serviceRating.add(totalOperatingPower);
for (int a = 0, avgPowerSize = avgPowerList.size(); a < avgPowerSize; a++) {
DynamicQueryPlantPredictedPowerOutput predictedPower = avgPowerList.get(a);
if (DateUtil.parse(predictedPower.getHourTime() + predictedPower.getMinTime(), BusinessConstant.TIME_FORMAT)
.compareTo(startTimeOffset) >= 0) {
//判断第一口井启动时间+启动间隔时日平均光伏出力-前两口井的运行功率是否为正数
if (predictedPower.getPower().compareTo(add) >= 0) {
//确定第二口井第一次开井时间为第一口井启动时间+启动间隔
startIndex = a;
break;
}
}
}
if (startIndex > -1) {
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
DateTime startTimeOptimize = DateUtil.parse(start.getHourTime() + start.getMinTime(), BusinessConstant.TIME_FORMAT);
//计算未优化启动间隔
int openDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
DateTime endTimeOptimize = startTimeOptimize.offset(DateField.MINUTE, openDuration);
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
openWellTime, BaseUtils.getEndTimeString(endTimeOptimize)
);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(endTimeOptimize, endTime);
} else {
//无法优化
}
}
} else {
DateTime offset = startTime.offset(DateField.MINUTE, between);
if (offset.compareTo(BusinessConstant.DATE_FLAG) > 0) {
//如果时间超过当天,舍弃
continue;
}
//计算偏移
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
offset.toString(BusinessConstant.MINUTES_FORMAT),
BaseUtils.getEndTimeString(DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT)
.offset(DateField.MINUTE, between))
);
}
}
}
}
/**
* 消峰平谷策略
*
* @param context 上下文
* @param wellheadDTOList 井口dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param durationDTOList 持续时间dtolist
* @param wellheadViewList 井口视图列表
* @param durationMap 持续时间图
* @param detail 细节
* @param lineId 线路id
* @param monthNum 月份
* @param midPeriodId 中期id
*/
public void peakEliminationAndValleyLevelingStrategy(XContext context, List<SpaceOptimizeWellheadDTO> wellheadDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceInstitutionWellheadView> wellheadViewList,
Map<String, List<SpaceInstitutionDurationEnt>> durationMap, SpaceInstitutionDetailEnt detail,
String lineId, int monthNum, String midPeriodId) {
//通过线路ID和月份获取市电峰谷策略明细配置
List<GetBasePriceStrategyDetailOutput> strategyDetailList = ServiceUtil.getStrategyDetailList(context,
GetBasePriceStrategyDetailInput.builder()
.lineId(lineId)
.strategyMonth(String.valueOf(monthNum))
.build()
);
if (CollUtil.isEmpty(strategyDetailList)) {
//没有配置,不优化
return;
}
//获取第一段谷电阶段的开始时间为第一口井的开井时间
Optional<GetBasePriceStrategyDetailOutput> low = strategyDetailList.stream()
.filter(s -> !StringUtils.isAnyBlank(s.getEndTime(), s.getStartTime()) && StringUtils.equals("LOW", s.getPeriodTypeKey()))
.findFirst();
if (!low.isPresent()) {
//没有谷电,不优化
return;
}
GetBasePriceStrategyDetailOutput strategyDetailOutput = low.get();
//第一口井启动时间
DateTime firstStartTime = DateUtil.parse(strategyDetailOutput.getStartTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
DateTime firstEndTime = DateUtil.parse(strategyDetailOutput.getEndTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
//判断是否第一口井
boolean isFirstWellhead;
//时间差
int between = 0;
//启动间隔累积
int startInterval = 0;
for (int w = 0, wellheadSize = wellheadViewList.size(); w < wellheadSize; w++) {
SpaceInstitutionWellheadView wellhead = wellheadViewList.get(w);
String wellheadId = wellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, midPeriodId, wellheadId, wellhead.getWellNumber());
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellhead);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, midPeriodId, recordId, wellheadId);
}
if (w == 0) {
//第一个井口
isFirstWellhead = true;
} else {
//计算启动间隔
startInterval = startInterval + detail.getStartInterval();
isFirstWellhead = false;
}
for (int d = 0, durationSize = durationConfigList.size(); d < durationSize; d++) {
SpaceInstitutionDurationEnt duration = durationConfigList.get(d);
String openWellTime = duration.getOpenWellTime();
DateTime startTime = DateUtil.parse(openWellTime + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
DateTime endTime = DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
//第一次启动
if (d == 0) {
//第一口井的启动时间
if (isFirstWellhead) {
//计算优化后的时间差优化后的第一口井开井时间-优化前第一次开井时间
int startDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
//第一次关井时间按照启动时长顺延
DateTime endTimeOptimize = startTime.offset(DateField.MINUTE, startDuration);
this.createOptimizeDuration(durationDTOList, midPeriodId, recordId, wellheadId, null,
strategyDetailOutput.getStartTime(), endTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT)
);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(firstEndTime, endTime);
}//其它井口的第一次启动时间
else {
//其它井启动时间:第一口井启动时间+启动间隔
DateTime startTimeOffset = firstStartTime.offset(DateField.MINUTE, startInterval);
DateTime endTimeOffset = firstEndTime.offset(DateField.MINUTE, startInterval);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(firstEndTime, endTime);
this.createOptimizeDuration(durationDTOList, midPeriodId, recordId, wellheadId, null,
startTimeOffset.toString(BusinessConstant.MINUTES_FORMAT), endTimeOffset.toString(BusinessConstant.MINUTES_FORMAT)
);
}
} else {
//计算偏移
DateTime offset = startTime.offset(DateField.MINUTE, between);
if (offset.compareTo(BusinessConstant.DATE_FLAG) > 0) {
//如果时间超过当天,舍弃
continue;
}
this.createOptimizeDuration(durationDTOList, midPeriodId, recordId, wellheadId, null,
offset.toString(BusinessConstant.MINUTES_FORMAT), BaseUtils.getEndTimeString(
DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT)
.offset(DateField.MINUTE, between)
)
);
}
}
}
}
}
\ No newline at end of file
package pps.core.space.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import pps.cloud.base.service.data.base_price_strategy_detail.GetBasePriceStrategyDetailInput;
import pps.cloud.base.service.data.base_price_strategy_detail.GetBasePriceStrategyDetailOutput;
import pps.cloud.prediction.service.data.plant_predicted_power_data.DynamicQueryPlantPredictedPowerInput;
import pps.cloud.prediction.service.data.plant_predicted_power_data.DynamicQueryPlantPredictedPowerOutput;
import pps.cloud.space.service.ISpaceOptimizeMidCloudService;
......@@ -16,14 +11,15 @@ import pps.core.common.utils.BaseUtils;
import pps.core.space.entity.*;
import pps.core.space.mapper.SpaceInstitutionDurationMapper;
import pps.core.space.service.data.SpaceOptimizeWellheadAndPlant;
import pps.core.space.utils.ServiceUtil;
import xstartup.annotation.XService;
import xstartup.base.XContext;
import xstartup.data.XServiceResult;
import xstartup.helper.XTransactionHelper;
import java.math.BigDecimal;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 中短期间开优化Cloud模块
......@@ -53,10 +49,10 @@ public class SpaceOptimizeMidCloudServiceImpl extends SpaceOptimizeBaseService i
//月份要加一
int monthNum = date.month() + 1;
SpaceInstitutionDurationMapper durationMapper = context.getBean(SpaceInstitutionDurationMapper.class);
List<SpaceOptimizeMidPeriodView> midPeriodList = new ArrayList<>(32);
List<SpaceOptimizeMidWellheadView> midWellheadList = new ArrayList<>(64);
List<SpaceOptimizeMidDurationView> midDurationList = new ArrayList<>(128);
List<SpaceOptimizeMidDurationView> unOptimizeDurationList = new ArrayList<>(128);
List<SpaceOptimizePeriodDTO> midPeriodList = new ArrayList<>(32);
List<SpaceOptimizeWellheadDTO> midWellheadList = new ArrayList<>(64);
List<SpaceOptimizeDurationDTO> midDurationList = new ArrayList<>(128);
List<SpaceOptimizeDurationDTO> unOptimizeDurationList = new ArrayList<>(128);
String executionCycleForWeek = BaseUtils.getExecutionCycleForWeek(date);
DateTime optimizeDeadline = DateUtil.beginOfDay(DateUtil.nextWeek());
//下一周
......@@ -66,7 +62,7 @@ public class SpaceOptimizeMidCloudServiceImpl extends SpaceOptimizeBaseService i
String detailId = detail.getId();
String lineId = detail.getLineId();
//创建记录
String midPeriodId = this.createOptimizeMidPeriod(midPeriodList, detailId, lineId, executionCycleForWeek, optimizeDeadline);
String midPeriodId = super.createOptimizePeriod(midPeriodList, detailId, lineId, executionCycleForWeek, optimizeDeadline);
switch (detail.getGridTypeKey()) {
//并网型优化
case "1":
......@@ -95,7 +91,7 @@ public class SpaceOptimizeMidCloudServiceImpl extends SpaceOptimizeBaseService i
//光伏出力峰值大于等于井口总功率:绿电消纳优先策略
if (powerMax.compareTo(wellheadTotalPower) >= BusinessConstant.ZERO) {
//---------------------------------绿电消纳策略---------------------------------
this.greenElectricityConsumptionStrategy(midWellheadList, unOptimizeDurationList, midDurationList,
super.greenElectricityConsumptionStrategy(midWellheadList, unOptimizeDurationList, midDurationList,
wellheadViewList, avgPowerList, durationMap, detail, midPeriodId);
} else {
//遍历井口,按发电功率大于等于光伏出力峰值条件分组
......@@ -106,15 +102,15 @@ public class SpaceOptimizeMidCloudServiceImpl extends SpaceOptimizeBaseService i
//光伏出力峰值<任何一口井的运行功率:消峰平谷策略
if (size == lowWellheadListSize) {
//---------------------------------消峰平谷策略---------------------------------
this.peakEliminationAndValleyLevelingStrategy(context, midWellheadList, unOptimizeDurationList, midDurationList, wellheadViewList,
super.peakEliminationAndValleyLevelingStrategy(context, midWellheadList, unOptimizeDurationList, midDurationList, wellheadViewList,
durationMap, detail, lineId, monthNum, midPeriodId);
}
//光伏出力峰值>=线路哪部分井口运行功率:满足的部分井口采用绿电消纳优先,不满足的井采用消峰平谷
else {
List<SpaceInstitutionWellheadView> highWellheadList = collect.get(true);
this.greenElectricityConsumptionStrategy(midWellheadList, unOptimizeDurationList, midDurationList,
super.greenElectricityConsumptionStrategy(midWellheadList, unOptimizeDurationList, midDurationList,
highWellheadList, avgPowerList, durationMap, detail, midPeriodId);
this.peakEliminationAndValleyLevelingStrategy(context, midWellheadList, unOptimizeDurationList, midDurationList, lowWellheadList,
super.peakEliminationAndValleyLevelingStrategy(context, midWellheadList, unOptimizeDurationList, midDurationList, lowWellheadList,
durationMap, detail, lineId, monthNum, midPeriodId);
}
}
......@@ -175,338 +171,8 @@ public class SpaceOptimizeMidCloudServiceImpl extends SpaceOptimizeBaseService i
/*-----------------------------------private-----------------------------------*/
/**
* 消峰平谷策略
*
* @param context 上下文
* @param midWellheadList 长井口列表
* @param unOptimizeDurationList 取消优化工期列表
* @param midDurationList 长期清单
* @param wellheadViewList 井口视图列表
* @param durationMap 持续时间图
* @param detail 细节
* @param lineId 线路id
* @param monthNum 月份
* @param midPeriodId 长周期id
*/
private void peakEliminationAndValleyLevelingStrategy(XContext context, List<SpaceOptimizeMidWellheadView> midWellheadList, List<SpaceOptimizeMidDurationView> unOptimizeDurationList,
List<SpaceOptimizeMidDurationView> midDurationList, List<SpaceInstitutionWellheadView> wellheadViewList,
Map<String, List<SpaceInstitutionDurationEnt>> durationMap, SpaceInstitutionDetailEnt detail,
String lineId, int monthNum, String midPeriodId) {
//通过线路ID和月份获取市电峰谷策略明细配置
List<GetBasePriceStrategyDetailOutput> strategyDetailList = ServiceUtil.getStrategyDetailList(context,
GetBasePriceStrategyDetailInput.builder()
.lineId(lineId)
.strategyMonth(String.valueOf(monthNum))
.build()
);
if (CollUtil.isEmpty(strategyDetailList)) {
//没有配置,不优化
return;
}
//获取第一段谷电阶段的开始时间为第一口井的开井时间
Optional<GetBasePriceStrategyDetailOutput> low = strategyDetailList.stream()
.filter(s -> !StringUtils.isAnyBlank(s.getEndTime(), s.getStartTime()) && StringUtils.equals("LOW", s.getPeriodTypeKey()))
.findFirst();
if (!low.isPresent()) {
//没有谷电,不优化
return;
}
GetBasePriceStrategyDetailOutput strategyDetailOutput = low.get();
//第一口井启动时间
DateTime firstStartTime = DateUtil.parse(strategyDetailOutput.getStartTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
DateTime firstEndTime = DateUtil.parse(strategyDetailOutput.getEndTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
//判断是否第一口井
boolean isFirstWellhead;
//时间差
int between = 0;
//启动间隔累积
int startInterval = 0;
for (int w = 0, wellheadSize = wellheadViewList.size(); w < wellheadSize; w++) {
SpaceInstitutionWellheadView wellhead = wellheadViewList.get(w);
String wellheadId = wellhead.getWellheadId();
String recordId = this.createOptimizeMidWellhead(midWellheadList, midPeriodId, wellheadId, wellhead.getWellNumber());
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellhead);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeMidDuration(unOptimizeDurationList, durationEnt, midPeriodId, recordId, wellheadId);
}
if (w == 0) {
//第一个井口
isFirstWellhead = true;
} else {
//计算启动间隔
startInterval = startInterval + detail.getStartInterval();
isFirstWellhead = false;
}
for (int d = 0, durationSize = durationConfigList.size(); d < durationSize; d++) {
SpaceInstitutionDurationEnt duration = durationConfigList.get(d);
String openWellTime = duration.getOpenWellTime();
DateTime startTime = DateUtil.parse(openWellTime + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
DateTime endTime = DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
//第一次启动
if (d == 0) {
//第一口井的启动时间
if (isFirstWellhead) {
//计算优化后的时间差优化后的第一口井开井时间-优化前第一次开井时间
int startDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
//第一次关井时间按照启动时长顺延
DateTime endTimeOptimize = startTime.offset(DateField.MINUTE, startDuration);
this.createOptimizeMidDuration(midDurationList, midPeriodId, recordId, wellheadId, null,
strategyDetailOutput.getStartTime(), endTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT)
);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(firstEndTime, endTime);
}//其它井口的第一次启动时间
else {
//其它井启动时间:第一口井启动时间+启动间隔
DateTime startTimeOffset = firstStartTime.offset(DateField.MINUTE, startInterval);
DateTime endTimeOffset = firstEndTime.offset(DateField.MINUTE, startInterval);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(firstEndTime, endTime);
this.createOptimizeMidDuration(midDurationList, midPeriodId, recordId, wellheadId, null,
startTimeOffset.toString(BusinessConstant.MINUTES_FORMAT), endTimeOffset.toString(BusinessConstant.MINUTES_FORMAT)
);
}
} else {
//计算偏移
DateTime offset = startTime.offset(DateField.MINUTE, between);
if (offset.compareTo(BusinessConstant.DATE_FLAG) > 0) {
//如果时间超过当天,舍弃
continue;
}
this.createOptimizeMidDuration(midDurationList, midPeriodId, recordId, wellheadId, null,
offset.toString(BusinessConstant.MINUTES_FORMAT), BaseUtils.getEndTimeString(
DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT)
.offset(DateField.MINUTE, between)
)
);
}
}
}
}
/**
* 绿电消纳策略
*
* @param midWellheadList 长井口列表
* @param unOptimizeDurationList 取消优化工期列表
* @param midDurationList 长期清单
* @param wellheadViewList 井口视图列表
* @param avgPowerList 平均功率列表
* @param durationMap 持续时间图
* @param detail 细节
* @param midPeriodId 长周期id
*/
private void greenElectricityConsumptionStrategy(List<SpaceOptimizeMidWellheadView> midWellheadList, List<SpaceOptimizeMidDurationView> unOptimizeDurationList,
List<SpaceOptimizeMidDurationView> midDurationList, List<SpaceInstitutionWellheadView> wellheadViewList,
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList, Map<String, List<SpaceInstitutionDurationEnt>> durationMap,
SpaceInstitutionDetailEnt detail, String midPeriodId) {
//时间差
int between = 0;
//启动间隔累积
int startInterval = 0;
//判断是否第一口井
boolean isFirstWellhead;
//第一口井启动时间
DateTime firstStartTime = null;
//井口累积运行总功率
BigDecimal totalOperatingPower = BigDecimal.ZERO;
for (int w = 0, wellheadSize = wellheadViewList.size(); w < wellheadSize; w++) {
SpaceInstitutionWellheadView wellhead = wellheadViewList.get(w);
String wellheadId = wellhead.getWellheadId();
String recordId = this.createOptimizeMidWellhead(midWellheadList, midPeriodId, wellheadId, wellhead.getWellNumber());
//取当前井口最大发电量
BigDecimal serviceRating = wellhead.getServiceRating();
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellhead);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeMidDuration(unOptimizeDurationList, durationEnt, midPeriodId, recordId, wellheadId);
}
if (w == 0) {
//第一个井口
isFirstWellhead = true;
totalOperatingPower.add(serviceRating);
} else {
//累加
totalOperatingPower = totalOperatingPower.add(serviceRating);
startInterval = startInterval + detail.getStartInterval();
isFirstWellhead = false;
}
for (int d = 0, durationSize = durationConfigList.size(); d < durationSize; d++) {
SpaceInstitutionDurationEnt duration = durationConfigList.get(d);
String openWellTime = duration.getOpenWellTime();
DateTime startTime = DateUtil.parse(openWellTime + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
DateTime endTime = DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT);
//第一次启动
if (d == 0) {
//第一口井的启动时间
if (isFirstWellhead) {
firstStartTime = startTime;
//计算开井时间
int startIndex = 0;
for (int a = 0, avgPowerSize = avgPowerList.size(); a < avgPowerSize; a++) {
DynamicQueryPlantPredictedPowerOutput predictedPower = avgPowerList.get(a);
//当日时间段平均光伏出力>=第一口井运行负荷时,该时间为第一口井运行时间
if (predictedPower.getPower().compareTo(serviceRating) >= BusinessConstant.ZERO) {
startIndex = a;
break;
}
}
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
String startTimeString = start.getHourTime() + start.getMinTime();
//计算第一次关井时间,按照间开时间段顺延
int startDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
DateTime endTimeOptimize = startTime.offset(DateField.MINUTE, startDuration);
this.createOptimizeMidDuration(midDurationList, midPeriodId, recordId, wellheadId, null,
startTimeString, endTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT)
);
//计算时间偏移
DateTime startTimeOptimize = DateUtil.parse(startTimeString, BusinessConstant.TIME_FORMAT);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(startTimeOptimize, startTime);
}
//其它井口的第一次启动时间
else {
DateTime startTimeOffset = firstStartTime.offset(DateField.MINUTE, startInterval);
int startIndex = -1;
BigDecimal add = serviceRating.add(totalOperatingPower);
for (int a = 0, avgPowerSize = avgPowerList.size(); a < avgPowerSize; a++) {
DynamicQueryPlantPredictedPowerOutput predictedPower = avgPowerList.get(a);
if (DateUtil.parse(predictedPower.getHourTime() + predictedPower.getMinTime(), BusinessConstant.TIME_FORMAT)
.compareTo(startTimeOffset) >= 0) {
//判断第一口井启动时间+启动间隔时日平均光伏出力-前两口井的运行功率是否为正数
if (predictedPower.getPower().compareTo(add) >= 0) {
//确定第二口井第一次开井时间为第一口井启动时间+启动间隔
startIndex = a;
break;
}
}
}
if (startIndex > -1) {
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
DateTime startTimeOptimize = DateUtil.parse(start.getHourTime() + start.getMinTime(), BusinessConstant.TIME_FORMAT);
//计算未优化启动间隔
int openDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
DateTime endTimeOptimize = startTimeOptimize.offset(DateField.MINUTE, openDuration);
this.createOptimizeMidDuration(midDurationList, midPeriodId, recordId, wellheadId, null,
openWellTime, BaseUtils.getEndTimeString(endTimeOptimize)
);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(endTimeOptimize, endTime);
} else {
//无法优化
}
}
} else {
DateTime offset = startTime.offset(DateField.MINUTE, between);
if (offset.compareTo(BusinessConstant.DATE_FLAG) > 0) {
//如果时间超过当天,舍弃
continue;
}
//计算偏移
this.createOptimizeMidDuration(midDurationList, midPeriodId, recordId, wellheadId, null,
offset.toString(BusinessConstant.MINUTES_FORMAT),
BaseUtils.getEndTimeString(DateUtil.parse(duration.getCloseWellTime() + BusinessConstant.INITIALIZATION_SECOND, BusinessConstant.TIME_FORMAT)
.offset(DateField.MINUTE, between))
);
}
}
}
}
/**
* 创建中短期优化信息
*
* @param midPeriodList 中期清单
* @param detailId 详细信息id
* @param lineId 线路id
* @param executionCycleForMonth 月执行周期
* @param optimizeDeadline 优化截止日期
* @return {@link String}
*/
private String createOptimizeMidPeriod(List<SpaceOptimizeMidPeriodView> midPeriodList, String detailId, String lineId, String executionCycleForMonth, Date optimizeDeadline) {
SpaceOptimizeMidPeriodView longPeriod = new SpaceOptimizeMidPeriodView();
BaseUtils.setBaseModelDefaultForJob(longPeriod);
longPeriod.setInstitutionId(detailId);
longPeriod.setLineId(lineId);
longPeriod.setExecutionCycle(executionCycleForMonth);
longPeriod.setOptimizeDeadline(optimizeDeadline);
midPeriodList.add(longPeriod);
return longPeriod.getId();
}
/**
* 创建中短期优化井口信息
*
* @param midWellheadList 井口中部列表
* @param midPeriodId 中期id
* @param wellheadId 井口id
* @param wellNumber 井号
* @return {@link String}
*/
private String createOptimizeMidWellhead(List<SpaceOptimizeMidWellheadView> midWellheadList, String midPeriodId, String wellheadId, String wellNumber) {
SpaceOptimizeMidWellheadView wellheadView = new SpaceOptimizeMidWellheadView();
BaseUtils.setBaseModelDefaultForJob(wellheadView);
wellheadView.setMidPeriodId(midPeriodId);
wellheadView.setWellheadId(wellheadId);
wellheadView.setWellNumber(wellNumber);
midWellheadList.add(wellheadView);
return wellheadView.getId();
}
/**
* 创建中短期优化井口区间配置信息
*
* @param midDurationList 中期清单
* @param midPeriodId 中期id
* @param recordId 记录id
* @param wellheadId 井口id
* @param generationTypeKey 生成类型密钥
* @param openWellTime 开井时间
* @param endTimeString 结束时间字符串
*/
private void createOptimizeMidDuration(List<SpaceOptimizeMidDurationView> midDurationList, String midPeriodId,
String recordId, String wellheadId, String generationTypeKey, String openWellTime, String endTimeString) {
SpaceOptimizeMidDurationView durationView = new SpaceOptimizeMidDurationView();
BaseUtils.setBaseModelDefaultForJob(durationView);
durationView.setRecordId(recordId);
durationView.setMidPeriodId(midPeriodId);
durationView.setWellheadId(wellheadId);
durationView.setGenerationTypeKey(generationTypeKey);
durationView.setIsOptimize(BusinessConstant.ZERO);
durationView.setOpenWellTime(openWellTime);
durationView.setCloseWellTime(endTimeString);
midDurationList.add(durationView);
}
/**
* 创建原始间开区间
*
* @param unOptimizeDurationList 取消优化工期列表
* @param durationEnt 持续时间ent
* @param midPeriodId 中期id
* @param recordId 记录id
* @param wellheadId 井口id
*/
private void createUnOptimizeMidDuration(List<SpaceOptimizeMidDurationView> unOptimizeDurationList, SpaceInstitutionDurationEnt durationEnt,
String midPeriodId, String recordId, String wellheadId) {
SpaceOptimizeMidDurationView durationViewUnOptimize = new SpaceOptimizeMidDurationView();
BaseUtils.setBaseModelDefaultForJob(durationViewUnOptimize);
durationViewUnOptimize.setRecordId(recordId);
durationViewUnOptimize.setMidPeriodId(midPeriodId);
durationViewUnOptimize.setWellheadId(wellheadId);
durationViewUnOptimize.setIsOptimize(BusinessConstant.ONE);
durationViewUnOptimize.setOpenWellTime(durationEnt.getOpenWellTime());
durationViewUnOptimize.setCloseWellTime(durationEnt.getCloseWellTime());
unOptimizeDurationList.add(durationViewUnOptimize);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment