Commit ad59607a authored by ZWT's avatar ZWT

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

1.开发间开优化长期间开优化定时任务,完成并网流程绿电消纳优先策略;
2.开发间开优化长期间开优化定时任务,完成并网流程消峰平谷策略;
3.开发间开优化中短期间开优化定时任务,创建定时任务并添加配置;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent ecb09eed
package pps.core.task.job; package pps.core.task.job;
import pps.cloud.space.service.ISpaceOptimizeMidCloudService;
import pps.core.task.constant.CronConstant; import pps.core.task.constant.CronConstant;
import xstartup.annotation.XService; import xstartup.annotation.XService;
import xstartup.annotation.XText; import xstartup.annotation.XText;
...@@ -27,6 +28,9 @@ public class SpaceOptimizeMidJob implements XJob { ...@@ -27,6 +28,9 @@ public class SpaceOptimizeMidJob implements XJob {
@XCronTrigger(value = CronConstant.EVERY_MONDAY) @XCronTrigger(value = CronConstant.EVERY_MONDAY)
@Override @Override
public XServiceResult execute(XContext xContext) { public XServiceResult execute(XContext xContext) {
ISpaceOptimizeMidCloudService service = xContext.getBean(ISpaceOptimizeMidCloudService.class);
XServiceResult result = service.optimizeLongJob(xContext);
result.throwIfFail();
return XServiceResult.OK; return XServiceResult.OK;
} }
} }
package pps.cloud.space.service;
import xstartup.annotation.XService;
import xstartup.annotation.XText;
import xstartup.base.XContext;
import xstartup.data.XServiceResult;
/**
* 中短期间开优化Cloud模块
*
* @author ZWT
* @date 2023/09/13 14:03
*/
@XService
@XText("中短期间开优化Cloud模块")
public interface ISpaceOptimizeMidCloudService {
/**
* 中短期间开优化Cloud模块--定时任务
*
* @param context 上下文
* @return {@link XServiceResult}
*/
@XText("中短期间开优化Cloud模块--定时任务")
XServiceResult optimizeLongJob(XContext context);
}
\ No newline at end of file
...@@ -7,15 +7,9 @@ import cn.hutool.core.date.DateUnit; ...@@ -7,15 +7,9 @@ import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils; 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_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.GetBasePriceStrategyDetailInput;
import pps.cloud.base.service.data.base_price_strategy_detail.GetBasePriceStrategyDetailOutput; 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;
import pps.cloud.prediction.service.data.plant_predicted_power_data.DynamicQueryPlantPredictedPowerInput; 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.prediction.service.data.plant_predicted_power_data.DynamicQueryPlantPredictedPowerOutput;
import pps.cloud.space.service.ISpaceOptimizeLongCloudService; import pps.cloud.space.service.ISpaceOptimizeLongCloudService;
...@@ -28,7 +22,6 @@ import pps.core.space.mapper.*; ...@@ -28,7 +22,6 @@ import pps.core.space.mapper.*;
import pps.core.space.utils.ServiceUtil; import pps.core.space.utils.ServiceUtil;
import xstartup.annotation.XService; import xstartup.annotation.XService;
import xstartup.base.XContext; import xstartup.base.XContext;
import xstartup.data.XListResult;
import xstartup.data.XServiceResult; import xstartup.data.XServiceResult;
import xstartup.helper.XTransactionHelper; import xstartup.helper.XTransactionHelper;
...@@ -77,9 +70,9 @@ public class SpaceOptimizeLongCloudServiceImpl implements ISpaceOptimizeLongClou ...@@ -77,9 +70,9 @@ public class SpaceOptimizeLongCloudServiceImpl implements ISpaceOptimizeLongClou
//未发现可优化井口 //未发现可优化井口
return XServiceResult.error(context, BusinessError.DidNotFindWellhead); return XServiceResult.error(context, BusinessError.DidNotFindWellhead);
} }
this.setServiceRatingForSpaceWellheadList(context, spaceWellheadList); ServiceUtil.setServiceRatingForSpaceWellheadList(context, spaceWellheadList);
//取线路关联的所有光伏电站ID //取线路关联的所有光伏电站ID
List<DynamicQueryBasePowerLinePlantOutput> plantList = this.getPowerLinePlantListByLineIds(context, lineIds); List<DynamicQueryBasePowerLinePlantOutput> plantList = ServiceUtil.getPowerLinePlantListByLineIds(context, lineIds);
if (CollUtil.isEmpty(plantList)) { if (CollUtil.isEmpty(plantList)) {
//未发现可用光伏电站 //未发现可用光伏电站
return XServiceResult.error(context, BusinessError.DidNotFindPlant); return XServiceResult.error(context, BusinessError.DidNotFindPlant);
...@@ -112,7 +105,7 @@ public class SpaceOptimizeLongCloudServiceImpl implements ISpaceOptimizeLongClou ...@@ -112,7 +105,7 @@ public class SpaceOptimizeLongCloudServiceImpl implements ISpaceOptimizeLongClou
//并网型优化 //并网型优化
case "1": case "1":
//获取当前制度对应的光伏预测数据列表 //获取当前制度对应的光伏预测数据列表
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = this.getAveragePowerGenerationListByPlantIds(context, List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = ServiceUtil.getAveragePowerGenerationListByPlantIds(context,
DynamicQueryPlantPredictedPowerInput.builder() DynamicQueryPlantPredictedPowerInput.builder()
.plantIds( .plantIds(
plantList.stream() plantList.stream()
...@@ -579,67 +572,4 @@ public class SpaceOptimizeLongCloudServiceImpl implements ISpaceOptimizeLongClou ...@@ -579,67 +572,4 @@ public class SpaceOptimizeLongCloudServiceImpl implements ISpaceOptimizeLongClou
durationViewUnOptimize.setCloseWellTime(durationEnt.getCloseWellTime()); durationViewUnOptimize.setCloseWellTime(durationEnt.getCloseWellTime());
unOptimizeDurationList.add(durationViewUnOptimize); unOptimizeDurationList.add(durationViewUnOptimize);
} }
/**
* 条件获取获取光伏预测各时段平均值列表
*
* @param context 上下文
* @param input 输入
* @return {@link List}<{@link DynamicQueryPlantPredictedPowerOutput}>
*/
private List<DynamicQueryPlantPredictedPowerOutput> getAveragePowerGenerationListByPlantIds(XContext context, DynamicQueryPlantPredictedPowerInput input) {
IPlantPredictedPowerCloudService cloudService = context.getBean(IPlantPredictedPowerCloudService.class);
XListResult<DynamicQueryPlantPredictedPowerOutput> result = cloudService.queryAveragePowerGenerationListByParam(context, input);
result.throwIfFail();
return result.getResult();
}
/**
* 按线路ID集合获取电站列表
*
* @param context 上下文
* @param lineIds 线路ID
* @return {@link List}<{@link DynamicQueryBasePowerLinePlantOutput}>
*/
private List<DynamicQueryBasePowerLinePlantOutput> getPowerLinePlantListByLineIds(XContext context, Set<String> lineIds) {
IBasePowerLineCloudService cloudService = context.getBean(IBasePowerLineCloudService.class);
XListResult<DynamicQueryBasePowerLinePlantOutput> result = cloudService.queryPowerLinePlantListByParam(context,
DynamicQueryBasePowerLinePlantInput.builder()
.lineIds(lineIds)
.build()
);
result.throwIfFail();
return result.getResult();
}
/**
* 为间开井口列表设置发电功率
*
* @param context 上下文
* @param spaceWellheadList 空间井口清单
*/
private void setServiceRatingForSpaceWellheadList(XContext context, List<SpaceInstitutionWellheadView> spaceWellheadList) {
IBaseWellheadCloudService cloudService = context.getBean(IBaseWellheadCloudService.class);
XListResult<DynamicQueryBaseWellheadOutput> result = cloudService.queryBaseWellheadListByParam(context,
DynamicQueryBaseWellheadInput.builder()
.wellheadIds(spaceWellheadList.stream()
.map(SpaceInstitutionWellheadView::getWellheadId)
.collect(Collectors.toList())
)
.build());
result.throwIfFail();
List<DynamicQueryBaseWellheadOutput> wellheadOutputList = result.getResult();
if (CollUtil.isEmpty(wellheadOutputList)) {
return;
}
spaceWellheadList.forEach(s -> {
s.setServiceRating(
wellheadOutputList.stream()
.filter(w -> StringUtils.equals(s.getWellheadId(), w.getId()))
.findAny()
.map(DynamicQueryBaseWellheadOutput::getServiceRating)
.orElse(BigDecimal.ZERO)
);
});
}
} }
\ 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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
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.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;
import pps.core.common.constant.BusinessConstant;
import pps.core.common.entity.BaseModel;
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.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.stream.Collectors;
/**
* 中短期间开优化Cloud模块
*
* @author ZWT
* @date 2023/09/18 14:14
*/
@XService
public class SpaceOptimizeMidCloudServiceImpl implements ISpaceOptimizeMidCloudService {
/**
* 中短期间开优化Cloud模块--定时任务
*
* @param context 上下文
* @return {@link XServiceResult}
*/
@Override
public XServiceResult optimizeLongJob(XContext context) {
//取当前时间
DateTime date = DateUtil.date();
String startWeek = date.toString("yyyy-MM-dd");
//取生效中的基础间开
SpaceInstitutionDetailMapper detailMapper = context.getBean(SpaceInstitutionDetailMapper.class);
List<SpaceInstitutionDetailEnt> detailEntList = detailMapper.selectList(new LambdaQueryWrapper<SpaceInstitutionDetailEnt>()
.eq(BaseModel::getIsDeleted, BusinessConstant.ONE)
.eq(SpaceInstitutionDetailEnt::getIsCurrentBasic, BusinessConstant.ZERO)
.le(SpaceInstitutionDetailEnt::getStartInterval, startWeek)
.ge(SpaceInstitutionDetailEnt::getInstitutionEndDate, startWeek)
);
if (CollUtil.isEmpty(detailEntList)) {
//未发现可优化基础间开制度
return XServiceResult.error(context, BusinessError.DidNotFindSpace);
}
Set<String> lineIds = new HashSet<>(32);
Set<String> institutionIds = new HashSet<>(32);
for (SpaceInstitutionDetailEnt spaceInstitutionDetailEnt : detailEntList) {
lineIds.add(spaceInstitutionDetailEnt.getLineId());
institutionIds.add(spaceInstitutionDetailEnt.getId());
}
//取生效中间开的所有井口
SpaceInstitutionWellheadViewMapper wellheadMapper = context.getBean(SpaceInstitutionWellheadViewMapper.class);
List<SpaceInstitutionWellheadView> spaceWellheadList = wellheadMapper.selectListByInstitutionIds(institutionIds);
if (CollUtil.isEmpty(spaceWellheadList)) {
//未发现可优化井口
return XServiceResult.error(context, BusinessError.DidNotFindWellhead);
}
ServiceUtil.setServiceRatingForSpaceWellheadList(context, spaceWellheadList);
//取线路关联的所有光伏电站ID
List<DynamicQueryBasePowerLinePlantOutput> plantList = ServiceUtil.getPowerLinePlantListByLineIds(context, lineIds);
if (CollUtil.isEmpty(plantList)) {
//未发现可用光伏电站
return XServiceResult.error(context, BusinessError.DidNotFindPlant);
}
//下一周
String nextWeek = DateUtil.nextWeek().toString("yyyy-MM-dd");
//月份要加一
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);
String executionCycleForMonth = BaseUtils.getExecutionCycleForMonth(date);
DateTime optimizeDeadline = DateUtil.endOfMonth(date);
//优化
for (SpaceInstitutionDetailEnt detail : detailEntList) {
String detailId = detail.getId();
String lineId = detail.getLineId();
//创建记录
String midPeriodId = this.createOptimizeMidPeriod(midPeriodList, detailId, lineId, executionCycleForMonth, optimizeDeadline);
switch (detail.getGridTypeKey()) {
//并网型优化
case "1":
//获取当前制度对应的光伏预测数据列表
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = ServiceUtil.getAveragePowerGenerationListByPlantIds(context,
DynamicQueryPlantPredictedPowerInput.builder()
.plantIds(
plantList.stream()
.filter(p -> StringUtils.equals(lineId, p.getLineId()))
.map(DynamicQueryBasePowerLinePlantOutput::getPlantId)
.collect(Collectors.toList())
)
.startTime(startWeek)
.endTime(nextWeek)
.build()
);
//取光伏出力峰值
BigDecimal powerMax = avgPowerList.stream()
.map(DynamicQueryPlantPredictedPowerOutput::getPower)
.max(BigDecimal::compareTo)
.orElse(BigDecimal.ZERO);
//取当前制度下井口的总功率
BigDecimal wellheadTotalPower = spaceWellheadList.stream()
.filter(w -> StringUtils.equals(detailId, w.getInstitutionId()))
.map(SpaceInstitutionWellheadView::getServiceRating)
.reduce(BigDecimal.ZERO, BigDecimal::add);
//根据类型过滤井口:大间开,连抽井不优化
List<SpaceInstitutionWellheadView> wellheadViewList = spaceWellheadList.stream()
.filter(w -> StringUtils.equals(detailId, w.getInstitutionId()) &&
StringUtils.equals("INTERVAL", w.getRunTypeKey()) &&
StringUtils.equals("0", w.getIntervalTypeKey()))
.sorted(Comparator.comparing(SpaceInstitutionWellheadView::getStartSeq))
.collect(Collectors.toList());
if (CollUtil.isEmpty(wellheadViewList)) {
continue;
}
//通过间开ID和井口ID查所有井口时段配置
List<SpaceInstitutionDurationEnt> durationList = durationMapper.selectList(new LambdaQueryWrapper<SpaceInstitutionDurationEnt>()
.eq(BaseModel::getIsDeleted, BusinessConstant.ONE)
.eq(SpaceInstitutionDurationEnt::getInstitutionId, detailId)
.orderByAsc(SpaceInstitutionDurationEnt::getOpenWellTime)
);
if (CollUtil.isEmpty(durationList)) {
//没有设置时间段,无法优化
continue;
}
Map<String, List<SpaceInstitutionDurationEnt>> durationMap = durationList.stream()
.collect(Collectors.groupingBy(SpaceInstitutionDurationEnt::getWellheadId));
int compare = powerMax.compareTo(wellheadTotalPower);
//光伏出力峰值大于等于井口总功率:绿电消纳优先策略
if (compare >= BusinessConstant.ZERO) {
//---------------------------------绿电消纳策略---------------------------------
this.greenElectricityConsumptionStrategy(midWellheadList, unOptimizeDurationList, midDurationList,
wellheadViewList, avgPowerList, durationMap, detail, midPeriodId);
} else {
//遍历井口,按发电功率大于等于光伏出力峰值条件分组
Map<Boolean, List<SpaceInstitutionWellheadView>> collect = spaceWellheadList.stream()
.filter(w ->
StringUtils.equals(detailId, w.getInstitutionId())
)
.collect(Collectors.partitioningBy(w -> powerMax.compareTo(w.getServiceRating()) >= BusinessConstant.ZERO));
List<SpaceInstitutionWellheadView> lowWellheadList = collect.get(false);
int size = spaceWellheadList.size();
int lowWellheadListSize = lowWellheadList.size();
//光伏出力峰值<任何一口井的运行功率:消峰平谷策略
if (size == lowWellheadListSize) {
//---------------------------------消峰平谷策略---------------------------------
this.peakEliminationAndValleyLevelingStrategy(context, midWellheadList, unOptimizeDurationList, midDurationList, wellheadViewList,
durationMap, detail, lineId, monthNum, midPeriodId);
}
//光伏出力峰值>=线路哪部分井口运行功率:满足的部分井口采用绿电消纳优先,不满足的井采用消峰平谷
else {
List<SpaceInstitutionWellheadView> highWellheadList = collect.get(true);
this.greenElectricityConsumptionStrategy(midWellheadList, unOptimizeDurationList, midDurationList,
highWellheadList, avgPowerList, durationMap, detail, midPeriodId);
this.peakEliminationAndValleyLevelingStrategy(context, midWellheadList, unOptimizeDurationList, midDurationList, lowWellheadList,
durationMap, detail, lineId, monthNum, midPeriodId);
}
}
break;
//离网型优化
case "0":
break;
default:
//电网类型不存在
}
}
//开启事务
return XTransactionHelper.begin(context, () -> {
int size;
// if (CollUtil.isNotEmpty(longPeriodList)) {
// SpaceOptimizeLongPeriodViewMapper longPeriodViewMapper = context.getBean(SpaceOptimizeLongPeriodViewMapper.class);
// size = longPeriodList.size();
// if (size > BaseUtils.BATCH_SIZE) {
// List<List<SpaceOptimizeLongPeriodView>> subList = BaseUtils.getSubList(longPeriodList);
// subList.forEach(b -> longPeriodViewMapper.batchInsertList(b));
// } else {
// longPeriodViewMapper.batchInsertList(longPeriodList);
// }
// }
// if (CollUtil.isNotEmpty(midWellheadList)) {
// SpaceOptimizeMidWellheadViewMapper longWellheadViewMapper = context.getBean(SpaceOptimizeMidWellheadViewMapper.class);
// size = midWellheadList.size();
// if (size > BaseUtils.BATCH_SIZE) {
// List<List<SpaceOptimizeMidWellheadView>> subList = BaseUtils.getSubList(midWellheadList);
// subList.forEach(b -> longWellheadViewMapper.batchInsertList(b));
// } else {
// longWellheadViewMapper.batchInsertList(midWellheadList);
// }
// }
// if (CollUtil.isNotEmpty(unOptimizeDurationList)) {
// SpaceOptimizeMidDurationViewMapper longDurationViewMapper = context.getBean(SpaceOptimizeMidDurationViewMapper.class);
// size = unOptimizeDurationList.size();
// if (size > BaseUtils.BATCH_SIZE) {
// List<List<SpaceOptimizeMidDurationView>> subList = BaseUtils.getSubList(unOptimizeDurationList);
// subList.forEach(b -> longDurationViewMapper.batchInsertList(b));
// } else {
// longDurationViewMapper.batchInsertList(unOptimizeDurationList);
// }
// }
// if (CollUtil.isNotEmpty(midDurationList)) {
// SpaceOptimizeMidDurationViewMapper longDurationViewMapper = context.getBean(SpaceOptimizeMidDurationViewMapper.class);
// size = midDurationList.size();
// if (size > BaseUtils.BATCH_SIZE) {
// List<List<SpaceOptimizeMidDurationView>> subList = BaseUtils.getSubList(midDurationList);
// subList.forEach(b -> longDurationViewMapper.batchInsertList(b));
// } else {
// longDurationViewMapper.batchInsertList(midDurationList);
// }
// }
return XServiceResult.OK;
});
}
/*-----------------------------------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
...@@ -6,22 +6,32 @@ import cn.hutool.core.date.DateUtil; ...@@ -6,22 +6,32 @@ import cn.hutool.core.date.DateUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import pps.cloud.base.service.IBasePowerLineCloudService; import pps.cloud.base.service.IBasePowerLineCloudService;
import pps.cloud.base.service.IBasePriceStrategyCloudService; import pps.cloud.base.service.IBasePriceStrategyCloudService;
import pps.cloud.base.service.IBaseWellheadCloudService;
import pps.cloud.base.service.data.base_power_line.DynamicQueryBasePowerLineInput; import pps.cloud.base.service.data.base_power_line.DynamicQueryBasePowerLineInput;
import pps.cloud.base.service.data.base_power_line.DynamicQueryBasePowerLineOutput; import pps.cloud.base.service.data.base_power_line.DynamicQueryBasePowerLineOutput;
import pps.cloud.base.service.data.base_power_line.GetBasePowerLineInput; import pps.cloud.base.service.data.base_power_line.GetBasePowerLineInput;
import pps.cloud.base.service.data.base_power_line.GetBasePowerLineViewOutput; import pps.cloud.base.service.data.base_power_line.GetBasePowerLineViewOutput;
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.GetBasePriceStrategyDetailInput;
import pps.cloud.base.service.data.base_price_strategy_detail.GetBasePriceStrategyDetailOutput; 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;
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.system.service.SysOrganizationCloudService; import pps.cloud.system.service.SysOrganizationCloudService;
import pps.cloud.system.service.SystemDictionaryService; import pps.cloud.system.service.SystemDictionaryService;
import pps.cloud.system.service.data.*; import pps.cloud.system.service.data.*;
import pps.core.common.constant.BusinessConstant; import pps.core.common.constant.BusinessConstant;
import pps.core.space.entity.SpaceInstitutionWellheadView;
import pps.core.space.service.data.SpaceOptimizeDateDuration; import pps.core.space.service.data.SpaceOptimizeDateDuration;
import pps.core.space.service.data.SpaceOptimizeDateOutput; import pps.core.space.service.data.SpaceOptimizeDateOutput;
import xstartup.base.XContext; import xstartup.base.XContext;
import xstartup.data.XListResult; import xstartup.data.XListResult;
import xstartup.data.XSingleResult; import xstartup.data.XSingleResult;
import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -142,6 +152,69 @@ public class ServiceUtil { ...@@ -142,6 +152,69 @@ public class ServiceUtil {
return result.getResult(); return result.getResult();
} }
/**
* 按线路ID集合获取电站列表
*
* @param context 上下文
* @param lineIds 线路ID
* @return {@link List}<{@link DynamicQueryBasePowerLinePlantOutput}>
*/
public static List<DynamicQueryBasePowerLinePlantOutput> getPowerLinePlantListByLineIds(XContext context, Set<String> lineIds) {
IBasePowerLineCloudService cloudService = context.getBean(IBasePowerLineCloudService.class);
XListResult<DynamicQueryBasePowerLinePlantOutput> result = cloudService.queryPowerLinePlantListByParam(context,
DynamicQueryBasePowerLinePlantInput.builder()
.lineIds(lineIds)
.build()
);
result.throwIfFail();
return result.getResult();
}
/**
* 为间开井口列表设置发电功率
*
* @param context 上下文
* @param spaceWellheadList 空间井口清单
*/
public static void setServiceRatingForSpaceWellheadList(XContext context, List<SpaceInstitutionWellheadView> spaceWellheadList) {
IBaseWellheadCloudService cloudService = context.getBean(IBaseWellheadCloudService.class);
XListResult<DynamicQueryBaseWellheadOutput> result = cloudService.queryBaseWellheadListByParam(context,
DynamicQueryBaseWellheadInput.builder()
.wellheadIds(spaceWellheadList.stream()
.map(SpaceInstitutionWellheadView::getWellheadId)
.collect(Collectors.toList())
)
.build());
result.throwIfFail();
List<DynamicQueryBaseWellheadOutput> wellheadOutputList = result.getResult();
if (CollUtil.isEmpty(wellheadOutputList)) {
return;
}
spaceWellheadList.forEach(s -> {
s.setServiceRating(
wellheadOutputList.stream()
.filter(w -> StringUtils.equals(s.getWellheadId(), w.getId()))
.findAny()
.map(DynamicQueryBaseWellheadOutput::getServiceRating)
.orElse(BigDecimal.ZERO)
);
});
}
/**
* 条件获取获取光伏预测各时段平均值列表
*
* @param context 上下文
* @param input 输入
* @return {@link List}<{@link DynamicQueryPlantPredictedPowerOutput}>
*/
public static List<DynamicQueryPlantPredictedPowerOutput> getAveragePowerGenerationListByPlantIds(XContext context, DynamicQueryPlantPredictedPowerInput input) {
IPlantPredictedPowerCloudService cloudService = context.getBean(IPlantPredictedPowerCloudService.class);
XListResult<DynamicQueryPlantPredictedPowerOutput> result = cloudService.queryAveragePowerGenerationListByParam(context, input);
result.throwIfFail();
return result.getResult();
}
/** /**
* 获取优化日期列表 * 获取优化日期列表
* *
......
...@@ -31,4 +31,10 @@ public class DynamicQueryPlantPredictedPowerInput { ...@@ -31,4 +31,10 @@ public class DynamicQueryPlantPredictedPowerInput {
@XText("月") @XText("月")
private String monthTime; private String monthTime;
@XText("开始时间")
private String startTime;
@XText("结束时间")
private String endTime;
} }
...@@ -38,6 +38,8 @@ public class PlantPredictedPowerCloudServiceImpl implements IPlantPredictedPower ...@@ -38,6 +38,8 @@ public class PlantPredictedPowerCloudServiceImpl implements IPlantPredictedPower
List<String> plantIds = input.getPlantIds(); List<String> plantIds = input.getPlantIds();
String yearTime = input.getYearTime(); String yearTime = input.getYearTime();
String monthTime = input.getMonthTime(); String monthTime = input.getMonthTime();
String startTime = input.getStartTime();
String endTime = input.getEndTime();
PlantPredictedPowerDataMapper mapper = context.getBean(PlantPredictedPowerDataMapper.class); PlantPredictedPowerDataMapper mapper = context.getBean(PlantPredictedPowerDataMapper.class);
List<PlantPredictedPowerDataEnt> list = mapper.selectList( List<PlantPredictedPowerDataEnt> list = mapper.selectList(
new QueryWrapper<PlantPredictedPowerDataEnt>() new QueryWrapper<PlantPredictedPowerDataEnt>()
...@@ -51,6 +53,7 @@ public class PlantPredictedPowerCloudServiceImpl implements IPlantPredictedPower ...@@ -51,6 +53,7 @@ public class PlantPredictedPowerCloudServiceImpl implements IPlantPredictedPower
.in(CollUtil.isNotEmpty(plantIds), PlantPredictedPowerDataEnt::getPlantId, plantIds) .in(CollUtil.isNotEmpty(plantIds), PlantPredictedPowerDataEnt::getPlantId, plantIds)
.eq(StringUtils.isNotBlank(yearTime), PlantPredictedPowerDataEnt::getYearTime, yearTime) .eq(StringUtils.isNotBlank(yearTime), PlantPredictedPowerDataEnt::getYearTime, yearTime)
.eq(StringUtils.isNotBlank(monthTime), PlantPredictedPowerDataEnt::getMonthTime, monthTime) .eq(StringUtils.isNotBlank(monthTime), PlantPredictedPowerDataEnt::getMonthTime, monthTime)
.between(!StringUtils.isAnyBlank(startTime, endTime), PlantPredictedPowerDataEnt::getDataDate, startTime, endTime)
.groupBy(PlantPredictedPowerDataEnt::getYearTime, .groupBy(PlantPredictedPowerDataEnt::getYearTime,
PlantPredictedPowerDataEnt::getMonthTime, PlantPredictedPowerDataEnt::getMonthTime,
PlantPredictedPowerDataEnt::getHourTime, PlantPredictedPowerDataEnt::getHourTime,
......
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