Commit 5e29c267 authored by ZWT's avatar ZWT

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

1.开发间开优化定期校准定时任务,配置表达式修改定时任务配置文件,创建cloud模块方法;
2.开发间开优化定期校准定时任务,完成业务逻辑开发;
3.修改间开制度管理模块定期校准新增功能,增加初始化校准历史业务逻辑;
4.开发间开优化短期间开优化定时任务,配置表达式修改定时任务配置文件,创建cloud模块方法;
5.修改长期间开优化定时任务,添加离网型线路数据处理逻辑;
6.创建储能预测电量数据(模拟数据测试用)表,生成对应代码,添加条件查询各时段储能预测数据Cloud模块接口;
7.修改长期间开优化定时任务,增加离网型算法计算储能可用时长逻辑;
8.修改长期间开优化定时任务,优化部分sql查询语句查询逻辑,优化代码结构;
9.光伏预测Cloud模块查询预测发电量接口修改,增加查询长期发电量逻辑;
10.修改中短期间开优化定时任务,添加离网型优化逻辑;
11.修改长期/中短期间开优化定时任务,优化代码结构;
12.修改基础间开配置模块设为基础间开制度及重新优化接口,增加并网型优化逻辑;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent 1c8db3fa
......@@ -90,6 +90,11 @@ public class BusinessConstant {
*/
public static final String END_OF_DAY_TIME = "23:59";
/**
* 一天开始时间
*/
public static final String START_OF_DAY_TIME = "00:00";
/**
* 日期标志
*/
......
......@@ -117,308 +117,109 @@ public class SpaceOptimizeBaseService {
}
/**
* 条件获取获取光伏预测各时段平均值列表
*
* @param context 上下文
* @param input 输入
* @return {@link List}<{@link DynamicQueryPlantPredictedPowerOutput}>
*/
public 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();
}
/**
* 条件查询时段储能电量平均值(模拟测试用)
* todo: 模拟测试用,后续替换
* 并网优化
*
* @param context 上下文
* @param input 输入
* @return {@link List}<{@link DynamicQueryStoragePredictedPowerOutput}>
*/
public List<DynamicQueryStoragePredictedPowerOutput> getAverageEnergyStorageListByParam(XContext context, DynamicQueryStoragePredictedPowerInput input) {
IStoragePredictedPowerCloudService cloudService = context.getBean(IStoragePredictedPowerCloudService.class);
XListResult<DynamicQueryStoragePredictedPowerOutput> result = cloudService.queryAverageEnergyStorageListByParam(context, input);
result.throwIfFail();
return result.getResult();
}
/**
* 获得最大功率
*
* @param avgPowerList 平均功率列表
* @return {@link BigDecimal}
*/
public BigDecimal getPowerMax(List<DynamicQueryPlantPredictedPowerOutput> avgPowerList) {
return avgPowerList.stream()
.map(DynamicQueryPlantPredictedPowerOutput::getPower)
.max(BigDecimal::compareTo)
.orElse(BigDecimal.ZERO);
}
/**
* 获取井口总功率
*
* @param wellheadDTOList 井口dtolist
* @param durationDTOList 持续时间dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param spaceWellheadList 空间井口清单
* @param detailId 详细信息id
* @return {@link BigDecimal}
* @param detail 细节
* @param monthNum 月份
* @param periodId 期间id
* @param plantPowerInput 电厂功率输入
*/
public BigDecimal getWellheadTotalPower(List<SpaceInstitutionWellheadView> spaceWellheadList, String detailId) {
return spaceWellheadList.stream()
.filter(w -> StringUtils.equals(detailId, w.getInstitutionId()))
.map(SpaceInstitutionWellheadView::getServiceRating)
.reduce(BigDecimal.ZERO, BigDecimal::add);
public void gridConnectedOptimization(XContext context, List<SpaceOptimizeWellheadDTO> wellheadDTOList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
List<SpaceInstitutionWellheadView> spaceWellheadList,
SpaceInstitutionDetailEnt detail, int monthNum, String periodId,
DynamicQueryPlantPredictedPowerInput plantPowerInput) {
//获取当前制度对应的光伏预测数据列表
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = this.getAveragePowerGenerationListByPlantIds(context, plantPowerInput);
if (CollUtil.isEmpty(avgPowerList)) {
return;
}
/**
* 获取当前制度关联的井口按照是否可优化分组
*
* @param spaceWellheadList 空间井口清单
* @param detailId 详细信息id
* @return {@link Map}<{@link Boolean}, {@link List}<{@link SpaceInstitutionWellheadView}>>
*/
public Map<Boolean, List<SpaceInstitutionWellheadView>> getWellheadViewList(List<SpaceInstitutionWellheadView> spaceWellheadList, String detailId) {
return spaceWellheadList.stream()
.sorted(Comparator.comparing(SpaceInstitutionWellheadView::getStartSeq))
.collect(
Collectors.partitioningBy(w -> StringUtils.equals(detailId, w.getInstitutionId()) &&
StringUtils.equals("INTERVAL", w.getRunTypeKey()) &&
StringUtils.equals("0", w.getIntervalTypeKey())
)
);
//取光伏出力峰值
BigDecimal powerMax = this.getPowerMax(avgPowerList);
//取当前制度下井口的总功率
BigDecimal wellheadTotalPower = this.getWellheadTotalPower(spaceWellheadList, detail.getId());
//根据类型过滤井口:大间开,连抽井不优化
Map<Boolean, List<SpaceInstitutionWellheadView>> wellheadViewMap = this.getWellheadViewList(spaceWellheadList, detail.getId());
List<SpaceInstitutionWellheadView> wellheadViewList = wellheadViewMap.get(true);
if (CollUtil.isEmpty(wellheadViewList)) {
return;
}
/**
* 获取井口间开时间段
*
* @param context 上下文
* @param detailId 详细信息id
* @return {@link Map}<{@link String}, {@link List}<{@link SpaceInstitutionDurationEnt}>>
*/
public Map<String, List<SpaceInstitutionDurationEnt>> getDurationMap(XContext context, String detailId) {
SpaceInstitutionDurationMapper durationMapper = context.getBean(SpaceInstitutionDurationMapper.class);
//通过间开ID和井口ID查所有井口时段配置
List<SpaceInstitutionDurationEnt> durationList = durationMapper.selectList(new QueryWrapper<SpaceInstitutionDurationEnt>()
.select("*",
"STR_TO_DATE( CONCAT( open_well_time, ':00' ), '%H:%i:%s' ) AS openTime",
"STR_TO_DATE( CONCAT( close_well_time, ':00' ), '%H:%i:%s' ) AS closeTime"
)
.lambda()
.eq(BaseModel::getIsDeleted, BusinessConstant.ONE)
.eq(SpaceInstitutionDurationEnt::getInstitutionId, detailId)
.orderByAsc(SpaceInstitutionDurationEnt::getOpenWellTime)
);
if (CollUtil.isEmpty(durationList)) {
Map<String, List<SpaceInstitutionDurationEnt>> durationMap = this.getDurationMap(context, detail.getId());
if (CollUtil.isEmpty(durationMap)) {
//没有设置时间段,无法优化
return null;
}
return durationList.stream()
.collect(
Collectors.groupingBy(SpaceInstitutionDurationEnt::getWellheadId)
);
return;
}
/*-----------------------------------private-----------------------------------*/
/**
* 获取井口Map通过最大功率区分
*
* @param wellheadViewList 井口视图列表
* @param powerMax 最大功率
* @return {@link Map}<{@link Boolean}, {@link List}<{@link SpaceInstitutionWellheadView}>>
*/
private Map<Boolean, List<SpaceInstitutionWellheadView>> getWellheadViewMapByPower(List<SpaceInstitutionWellheadView> wellheadViewList, BigDecimal powerMax) {
return wellheadViewList.stream()
.collect(
Collectors.partitioningBy(w -> powerMax.compareTo(w.getServiceRating()) >= BusinessConstant.ZERO)
);
//光伏出力峰值大于等于井口总功率:绿电消纳优先策略
if (powerMax.compareTo(wellheadTotalPower) >= BusinessConstant.ZERO) {
//---------------------------------绿电消纳策略---------------------------------
this.greenElectricityConsumptionStrategy(wellheadDTOList, unOptimizeDurationList, durationDTOList,
wellheadViewList, avgPowerList, durationMap, detail, periodId);
} else {
//遍历井口,按发电功率大于等于光伏出力峰值条件分组
Map<Boolean, List<SpaceInstitutionWellheadView>> collect = this.getWellheadViewMapByPower(wellheadViewList, powerMax);
List<SpaceInstitutionWellheadView> lowWellheadList = collect.get(false);
int size = spaceWellheadList.size();
int lowWellheadListSize = lowWellheadList.size();
//光伏出力峰值<任何一口井的运行功率:消峰平谷策略
if (size == lowWellheadListSize) {
//---------------------------------消峰平谷策略---------------------------------
this.peakEliminationAndValleyLevelingStrategy(context, wellheadDTOList, unOptimizeDurationList, durationDTOList, wellheadViewList,
durationMap, detail, monthNum, periodId);
}
/**
* 按线路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();
//光伏出力峰值>=线路哪部分井口运行功率:满足的部分井口采用绿电消纳优先,不满足的井采用消峰平谷
else {
List<SpaceInstitutionWellheadView> highWellheadList = collect.get(true);
this.greenElectricityConsumptionStrategy(wellheadDTOList, unOptimizeDurationList, durationDTOList,
highWellheadList, avgPowerList, durationMap, detail, periodId);
this.peakEliminationAndValleyLevelingStrategy(context, wellheadDTOList, unOptimizeDurationList, durationDTOList,
lowWellheadList, durationMap, detail, monthNum, periodId);
}
/**
* 条件查询线路关联储能设备参数平均值
*
* @param context 上下文
* @param lineIds 线路ID
* @return {@link Map}<{@link String}, {@link List}<{@link DynamicQueryBasePowerLineStorageViewOutput}>>
*/
private Map<String, List<DynamicQueryBasePowerLineStorageViewOutput>> getPowerLineStorageListByLineIds(XContext context, Set<String> lineIds) {
IBasePowerLineCloudService cloudService = context.getBean(IBasePowerLineCloudService.class);
XListResult<DynamicQueryBasePowerLineStorageViewOutput> result = cloudService.queryPowerLineStorageListByLineIds(context,
DynamicQueryBasePowerLineStorageInput.builder()
.lineIds(lineIds)
.build()
);
result.throwIfFail();
List<DynamicQueryBasePowerLineStorageViewOutput> list = result.getResult();
Map<String, List<DynamicQueryBasePowerLineStorageViewOutput>> collect;
if (CollUtil.isEmpty(list)) {
collect = new HashMap<>(0);
} else {
collect = list.stream()
.collect(Collectors.groupingBy(DynamicQueryBasePowerLineStorageViewOutput::getLineId));
}
return collect;
//保存不需要优化的井口
this.setUnOptimizeWellheadConfig(wellheadDTOList, unOptimizeDurationList, durationDTOList,
wellheadViewMap.get(false), durationMap, periodId);
}
/**
* 为间开井口列表设置发电功率
* 离网优化
*
* @param context 上下文
* @param wellheadDTOList 井口dtolist
* @param durationDTOList 持续时间dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param spaceWellheadList 空间井口清单
* @param storageAvgMap 存储平均值映射
* @param detail 细节
* @param periodId 期间id
* @param input 输入
* @param plantPowerInput 电厂功率输入
*/
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)) {
public void offGridOptimization(XContext context, List<SpaceOptimizeWellheadDTO> wellheadDTOList, List<SpaceOptimizeDurationDTO> durationDTOList,
List<SpaceOptimizeDurationDTO> unOptimizeDurationList, List<SpaceInstitutionWellheadView> spaceWellheadList,
Map<String, List<DynamicQueryBasePowerLineStorageViewOutput>> storageAvgMap, SpaceInstitutionDetailEnt detail, String periodId,
DynamicQueryStoragePredictedPowerInput input, DynamicQueryPlantPredictedPowerInput plantPowerInput) {
//获取当前制度对应的光伏预测数据列表
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = this.getAveragePowerGenerationListByPlantIds(context, plantPowerInput);
if (CollUtil.isEmpty(avgPowerList)) {
return;
}
spaceWellheadList.forEach(s -> {
s.setServiceRating(
wellheadOutputList.stream()
.filter(w -> StringUtils.equals(s.getWellheadId(), w.getId()))
.findAny()
.map(DynamicQueryBaseWellheadOutput::getServiceRating)
.orElse(BigDecimal.ZERO)
);
});
//根据类型过滤井口:大间开,连抽井不优化
Map<Boolean, List<SpaceInstitutionWellheadView>> wellheadViewMap = this.getWellheadViewList(spaceWellheadList, detail.getId());
List<SpaceInstitutionWellheadView> wellheadViewList = wellheadViewMap.get(true);
if (CollUtil.isEmpty(wellheadViewList)) {
return;
}
/**
* 创建间开优化信息
*
* @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.setOptimizeState(BusinessConstant.ZERO);
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);
//获取井口间开时间段
Map<String, List<SpaceInstitutionDurationEnt>> durationMap = this.getDurationMap(context, detail.getId());
if (CollUtil.isEmpty(durationMap)) {
//没有设置时间段,无法优化
return;
}
/**
* 绿电消纳策略
*
* @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;
//启动间隔累积
......@@ -427,8 +228,12 @@ public class SpaceOptimizeBaseService {
boolean isFirstWellhead;
//第一口井启动时间
DateTime firstStartTime = null;
//第一口井开井时间
int firstIndex = 0;
//井口累积运行总功率
BigDecimal totalOperatingPower = BigDecimal.ZERO;
//离网时间段
List<SpaceOptimizeDurationDTO> offGridPeriodList = new ArrayList<>(32);
for (int w = 0, wellheadSize = wellheadViewList.size(); w < wellheadSize; w++) {
SpaceInstitutionWellheadView wellhead = wellheadViewList.get(w);
String wellheadId = wellhead.getWellheadId();
......@@ -444,46 +249,40 @@ public class SpaceOptimizeBaseService {
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
}
//累加
totalOperatingPower = totalOperatingPower.add(serviceRating);
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);
DateTime startTime = DateUtil.date(duration.getOpenTime());
DateTime endTime = DateUtil.date(duration.getCloseTime());
//第一次启动
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;
firstIndex = a;
break;
}
}
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
String startTimeString = start.getHourTime() + start.getMinTime();
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(firstIndex);
DateTime startTimeOptimize = DateUtil.date(start.getCreateTime());
//计算第一次关井时间,按照间开时间段顺延
int startDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
DateTime endTimeOptimize = startTime.offset(DateField.MINUTE, startDuration);
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
StringUtils.substringBeforeLast(startTimeString, BusinessConstant.INITIALIZATION_SECOND), endTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT)
);
//计算时间偏移
DateTime startTimeOptimize = DateUtil.parse(startTimeString, BusinessConstant.TIME_FORMAT);
//取时间间隔(分钟)
this.createDurationOffGridPeriod(offGridPeriodList, wellheadId, startTimeOptimize, endTimeOptimize);
//计算时间偏移,取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(startTimeOptimize, startTime);
}
//其它井口的第一次启动时间
......@@ -492,8 +291,7 @@ public class SpaceOptimizeBaseService {
int startIndex = -1;
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 (DateUtil.date(predictedPower.getCreateTime()).compareTo(startTimeOffset) >= 0) {
//判断第一口井启动时间+启动间隔时日平均光伏出力-前两口井的运行功率是否为正数
if (predictedPower.getPower().compareTo(totalOperatingPower) >= 0) {
//确定第二口井第一次开井时间为第一口井启动时间+启动间隔
......@@ -504,13 +302,11 @@ public class SpaceOptimizeBaseService {
}
if (startIndex > -1) {
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
DateTime startTimeOptimize = DateUtil.parse(start.getHourTime() + start.getMinTime(), BusinessConstant.TIME_FORMAT);
DateTime startTimeOptimize = DateUtil.date(start.getCreateTime());
//计算未优化启动间隔
int openDuration = (int) startTime.between(endTime, DateUnit.MINUTE);
DateTime endTimeOptimize = startTimeOptimize.offset(DateField.MINUTE, openDuration);
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
startTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT), BaseUtils.getEndTimeString(endTimeOptimize)
);
this.createDurationOffGridPeriod(offGridPeriodList, wellheadId, startTimeOptimize, endTimeOptimize);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(endTimeOptimize, endTime);
} else {
......@@ -524,250 +320,151 @@ public class SpaceOptimizeBaseService {
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))
this.createDurationOffGridPeriod(offGridPeriodList, wellheadId, offset,
DateUtil.date(duration.getCloseTime()).offset(DateField.MINUTE, between)
);
}
}
}
//离网优化
if (CollUtil.isNotEmpty(offGridPeriodList)) {
if (!storageAvgMap.containsKey(detail.getLineId())) {
//没有储能设备,无法计算
return;
}
/**
* 消峰平谷策略
*
* @param context 上下文
* @param wellheadDTOList 井口dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param durationDTOList 持续时间dtolist
* @param wellheadViewList 井口视图列表
* @param durationMap 持续时间图
* @param detail 细节
* @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,
int monthNum, String periodId) {
//通过线路ID和月份获取市电峰谷策略明细配置
List<GetBasePriceStrategyDetailOutput> strategyDetailList = ServiceUtil.getStrategyDetailList(context,
GetBasePriceStrategyDetailInput.builder()
.lineId(detail.getLineId())
.strategyMonth(String.valueOf(monthNum))
.build()
);
if (CollUtil.isEmpty(strategyDetailList)) {
//没有配置,不优化
//截取从第一次开井时间往后的时间段
List<DynamicQueryPlantPredictedPowerOutput> subAvgPowerList = CollUtil.sub(avgPowerList, firstIndex + 1, avgPowerList.size());
if (CollUtil.isEmpty(subAvgPowerList)) {
//没有时间段,无法计算
return;
}
//获取第一段谷电阶段的开始时间为第一口井的开井时间
Optional<GetBasePriceStrategyDetailOutput> low = strategyDetailList.stream()
.filter(s -> !StringUtils.isAnyBlank(s.getEndTime(), s.getStartTime()) && StringUtils.equals("LOW", s.getPeriodTypeKey()))
.findFirst();
if (!low.isPresent()) {
//没有谷电,不优化
//查获取前一个月该时间点储能剩余电量,求平均数
List<DynamicQueryStoragePredictedPowerOutput> averageEnergyStorageList = this.getAverageEnergyStorageListByParam(context, input);
if (CollUtil.isEmpty(averageEnergyStorageList)) {
//没有储能发电量,无法计算
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, periodId, wellheadId, wellhead.getWellNumber());
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellheadId);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
//取储能计算参数
List<DynamicQueryBasePowerLineStorageViewOutput> avgStorageViewList = storageAvgMap.get(detail.getLineId());
DynamicQueryBasePowerLineStorageViewOutput avgStorageView = avgStorageViewList.get(0);
//平均额定放电效率(%)
BigDecimal avgRatedDischargeEfficiency = avgStorageView.getRatedDischargeEfficiency();
//平均额定放电深度(%)
BigDecimal avgRatedDischargeDepth = avgStorageView.getRatedDischargeDepth();
//平均额定放电功率(KW)
BigDecimal avgRatedDischargePower = avgStorageView.getRatedDischargePower();
//逐15分钟计算光伏出力-井场运行功率之和,获得光伏出力不足时间段,并计算储能可用时长
Iterator<DynamicQueryStoragePredictedPowerOutput> iterator = averageEnergyStorageList.iterator();
for (DynamicQueryPlantPredictedPowerOutput avg : subAvgPowerList) {
if (avg.getPower().compareTo(totalOperatingPower) >= 0) {
//电量不足,计算储能可用时长
avg.setBatteryLowFlag(false);
String hourTime = avg.getHourTime();
String minTime = avg.getMinTime();
while (iterator.hasNext()) {
DynamicQueryStoragePredictedPowerOutput storagePredicted = iterator.next();
if (StringUtils.equals(hourTime, storagePredicted.getHourTime()) && StringUtils.equals(minTime, storagePredicted.getMinTime())) {
//计算储能可供电时长:(储能剩余容量*放电深度*放电效率)/额定放电功率
avg.setPowerDuration(
storagePredicted.getPower()
.multiply(avgRatedDischargeDepth)
.multiply(avgRatedDischargeEfficiency)
.divide(avgRatedDischargePower)
.setScale(BusinessConstant.ZERO, RoundingMode.DOWN)
.intValueExact()
);
break;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
//删除计算过的时间段
iterator.remove();
}
if (w == 0) {
//第一个井口
isFirstWellhead = true;
} else {
//计算启动间隔
startInterval = startInterval + detail.getStartInterval();
isFirstWellhead = false;
avg.setBatteryLowFlag(true);
}
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, periodId, 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, periodId, 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;
//拆分时间段
for (SpaceOptimizeDurationDTO durationDTO : offGridPeriodList) {
Date openTime = durationDTO.getOpenTime();
Date closeTime = durationDTO.getCloseTime();
if (closeTime.compareTo(BusinessConstant.DATE_FLAG) > 0) {
closeTime = DateUtil.endOfDay(DateUtil.date());
}
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)
)
//匹配时间
for (int i = 0, size = subAvgPowerList.size(); i < size; i++) {
DynamicQueryPlantPredictedPowerOutput avg = subAvgPowerList.get(i);
DateTime createTime = DateUtil.date(avg.getCreateTime());
//计算时间范围:大于等于开始时间,小于等于结束时间
if (openTime.compareTo(createTime) >= 0 && closeTime.compareTo(createTime) <= 0) {
String endString = createTime.offset(DateField.MINUTE, 15).toString(BusinessConstant.MINUTES_FORMAT);
String startString = createTime.toString(BusinessConstant.MINUTES_FORMAT);
//电量满足跳过
if (avg.getBatteryLowFlag()) {
//创建光伏
this.createOptimizeDuration(durationDTOList, periodId, durationDTO.getRecordId(), durationDTO.getWellheadId(), BusinessConstant.PHOTOVOLTAIC,
startString, endString
);
} else {
int powerDuration = avg.getPowerDuration();
String offset = createTime.offset(DateField.MINUTE, powerDuration).toString(BusinessConstant.MINUTES_FORMAT);
//储能发电时长
this.createOptimizeDuration(durationDTOList, periodId, durationDTO.getRecordId(), durationDTO.getWellheadId(), BusinessConstant.STORED_ENERGY,
startString, offset
);
//柴发发电时长
this.createOptimizeDuration(durationDTOList, periodId, durationDTO.getRecordId(), durationDTO.getWellheadId(), BusinessConstant.DIESEL_POWER,
offset, endString
);
}
}
}
}
}
//保存不需要优化的井口
this.setUnOptimizeWellheadConfig(wellheadDTOList, unOptimizeDurationList, durationDTOList,
wellheadViewMap.get(false), durationMap, periodId);
}
/**
* 并网优化
* 创建间开优化信息
*
* @param context 上下文
* @param wellheadDTOList 井口dtolist
* @param durationDTOList 持续时间dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param spaceWellheadList 空间井口清单
* @param detail 细节
* @param monthNum 月份
* @param periodId 期间id
* @param plantPowerInput 电厂功率输入
* @param periodDTOList 时期数据主义者
* @param detailId 详细信息id
* @param lineId 线路id
* @param executionCycleForMonth 月执行周期
* @param optimizeDeadline 优化截止日期
* @return {@link String}
*/
public void gridConnectedOptimization(XContext context, List<SpaceOptimizeWellheadDTO> wellheadDTOList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
List<SpaceInstitutionWellheadView> spaceWellheadList,
SpaceInstitutionDetailEnt detail, int monthNum, String periodId,
DynamicQueryPlantPredictedPowerInput plantPowerInput) {
//获取当前制度对应的光伏预测数据列表
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = this.getAveragePowerGenerationListByPlantIds(context, plantPowerInput);
if (CollUtil.isEmpty(avgPowerList)) {
return;
}
//取光伏出力峰值
BigDecimal powerMax = this.getPowerMax(avgPowerList);
//取当前制度下井口的总功率
BigDecimal wellheadTotalPower = this.getWellheadTotalPower(spaceWellheadList, detail.getId());
//根据类型过滤井口:大间开,连抽井不优化
Map<Boolean, List<SpaceInstitutionWellheadView>> wellheadViewMap = this.getWellheadViewList(spaceWellheadList, detail.getId());
List<SpaceInstitutionWellheadView> wellheadViewList = wellheadViewMap.get(true);
if (CollUtil.isEmpty(wellheadViewList)) {
return;
}
Map<String, List<SpaceInstitutionDurationEnt>> durationMap = this.getDurationMap(context, detail.getId());
if (CollUtil.isEmpty(durationMap)) {
//没有设置时间段,无法优化
return;
}
//光伏出力峰值大于等于井口总功率:绿电消纳优先策略
if (powerMax.compareTo(wellheadTotalPower) >= BusinessConstant.ZERO) {
//---------------------------------绿电消纳策略---------------------------------
this.greenElectricityConsumptionStrategy(wellheadDTOList, unOptimizeDurationList, durationDTOList,
wellheadViewList, avgPowerList, durationMap, detail, periodId);
} else {
//遍历井口,按发电功率大于等于光伏出力峰值条件分组
Map<Boolean, List<SpaceInstitutionWellheadView>> collect = this.getWellheadViewMapByPower(wellheadViewList, powerMax);
List<SpaceInstitutionWellheadView> lowWellheadList = collect.get(false);
int size = spaceWellheadList.size();
int lowWellheadListSize = lowWellheadList.size();
//光伏出力峰值<任何一口井的运行功率:消峰平谷策略
if (size == lowWellheadListSize) {
//---------------------------------消峰平谷策略---------------------------------
this.peakEliminationAndValleyLevelingStrategy(context, wellheadDTOList, unOptimizeDurationList, durationDTOList, wellheadViewList,
durationMap, detail, monthNum, periodId);
}
//光伏出力峰值>=线路哪部分井口运行功率:满足的部分井口采用绿电消纳优先,不满足的井采用消峰平谷
else {
List<SpaceInstitutionWellheadView> highWellheadList = collect.get(true);
this.greenElectricityConsumptionStrategy(wellheadDTOList, unOptimizeDurationList, durationDTOList,
highWellheadList, avgPowerList, durationMap, detail, periodId);
this.peakEliminationAndValleyLevelingStrategy(context, wellheadDTOList, unOptimizeDurationList, durationDTOList,
lowWellheadList, durationMap, detail, monthNum, periodId);
}
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.setOptimizeState(BusinessConstant.ZERO);
periodDTO.setOptimizeDeadline(optimizeDeadline);
periodDTOList.add(periodDTO);
return periodDTO.getId();
}
//保存不需要优化的井口
List<SpaceInstitutionWellheadView> unOptimizeWellheadList = wellheadViewMap.get(false);
if (CollUtil.isEmpty(unOptimizeWellheadList)) {
return;
}
for (SpaceInstitutionWellheadView unOptimizeWellhead : unOptimizeWellheadList) {
String wellheadId = unOptimizeWellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, periodId, wellheadId, unOptimizeWellhead.getWellNumber());
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellheadId);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
}
}
}
/*-----------------------------------private-----------------------------------*/
/**
* 离网优化
* 绿电消纳策略
*
* @param context 上下文
* @param wellheadDTOList 井口dtolist
* @param durationDTOList 持续时间dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param spaceWellheadList 空间井口清单
* @param storageAvgMap 存储平均值映射
* @param durationDTOList 持续时间dtolist
* @param wellheadViewList 井口视图列表
* @param avgPowerList 平均功率列表
* @param durationMap 持续时间图
* @param detail 细节
* @param periodId 期间id
* @param input 输入
* @param plantPowerInput 电厂功率输入
*/
public void offGridOptimization(XContext context, List<SpaceOptimizeWellheadDTO> wellheadDTOList, List<SpaceOptimizeDurationDTO> durationDTOList,
List<SpaceOptimizeDurationDTO> unOptimizeDurationList, List<SpaceInstitutionWellheadView> spaceWellheadList,
Map<String, List<DynamicQueryBasePowerLineStorageViewOutput>> storageAvgMap, SpaceInstitutionDetailEnt detail, String periodId,
DynamicQueryStoragePredictedPowerInput input, DynamicQueryPlantPredictedPowerInput plantPowerInput) {
//获取当前制度对应的光伏预测数据列表
List<DynamicQueryPlantPredictedPowerOutput> avgPowerList = this.getAveragePowerGenerationListByPlantIds(context, plantPowerInput);
if (CollUtil.isEmpty(avgPowerList)) {
return;
}
//根据类型过滤井口:大间开,连抽井不优化
Map<Boolean, List<SpaceInstitutionWellheadView>> wellheadViewMap = this.getWellheadViewList(spaceWellheadList, detail.getId());
List<SpaceInstitutionWellheadView> wellheadViewList = wellheadViewMap.get(true);
if (CollUtil.isEmpty(wellheadViewList)) {
return;
}
//获取井口间开时间段
Map<String, List<SpaceInstitutionDurationEnt>> durationMap = this.getDurationMap(context, detail.getId());
if (CollUtil.isEmpty(durationMap)) {
//没有设置时间段,无法优化
return;
}
private 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;
//启动间隔累积
......@@ -776,12 +473,8 @@ public class SpaceOptimizeBaseService {
boolean isFirstWellhead;
//第一口井启动时间
DateTime firstStartTime = null;
//第一口井开井时间
int firstIndex = 0;
//井口累积运行总功率
BigDecimal totalOperatingPower = BigDecimal.ZERO;
//离网时间段
List<SpaceOptimizeDurationDTO> offGridPeriodList = new ArrayList<>(32);
for (int w = 0, wellheadSize = wellheadViewList.size(); w < wellheadSize; w++) {
SpaceInstitutionWellheadView wellhead = wellheadViewList.get(w);
String wellheadId = wellhead.getWellheadId();
......@@ -797,40 +490,46 @@ public class SpaceOptimizeBaseService {
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
}
//累加
totalOperatingPower = totalOperatingPower.add(serviceRating);
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);
DateTime startTime = DateUtil.date(duration.getOpenTime());
DateTime endTime = DateUtil.date(duration.getCloseTime());
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) {
firstIndex = a;
startIndex = a;
break;
}
}
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(firstIndex);
DateTime startTimeOptimize = DateUtil.date(start.getCreateTime());
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.createDurationOffGridPeriod(offGridPeriodList, wellheadId, startTimeOptimize, endTimeOptimize);
//计算时间偏移,取时间间隔(分钟)
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
StringUtils.substringBeforeLast(startTimeString, BusinessConstant.INITIALIZATION_SECOND), endTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT)
);
//计算时间偏移
DateTime startTimeOptimize = DateUtil.parse(startTimeString, BusinessConstant.TIME_FORMAT);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(startTimeOptimize, startTime);
}
//其它井口的第一次启动时间
......@@ -839,7 +538,8 @@ public class SpaceOptimizeBaseService {
int startIndex = -1;
for (int a = 0, avgPowerSize = avgPowerList.size(); a < avgPowerSize; a++) {
DynamicQueryPlantPredictedPowerOutput predictedPower = avgPowerList.get(a);
if (DateUtil.date(predictedPower.getCreateTime()).compareTo(startTimeOffset) >= 0) {
if (DateUtil.parse(predictedPower.getHourTime() + predictedPower.getMinTime(), BusinessConstant.TIME_FORMAT)
.compareTo(startTimeOffset) >= 0) {
//判断第一口井启动时间+启动间隔时日平均光伏出力-前两口井的运行功率是否为正数
if (predictedPower.getPower().compareTo(totalOperatingPower) >= 0) {
//确定第二口井第一次开井时间为第一口井启动时间+启动间隔
......@@ -850,11 +550,13 @@ public class SpaceOptimizeBaseService {
}
if (startIndex > -1) {
DynamicQueryPlantPredictedPowerOutput start = avgPowerList.get(startIndex);
DateTime startTimeOptimize = DateUtil.date(start.getCreateTime());
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.createDurationOffGridPeriod(offGridPeriodList, wellheadId, startTimeOptimize, endTimeOptimize);
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
startTimeOptimize.toString(BusinessConstant.MINUTES_FORMAT), BaseUtils.getEndTimeString(endTimeOptimize)
);
//取时间间隔(分钟)
between = BaseUtils.getTimeDifferenceMinute(endTimeOptimize, endTime);
} else {
......@@ -868,105 +570,426 @@ public class SpaceOptimizeBaseService {
continue;
}
//计算偏移
this.createDurationOffGridPeriod(offGridPeriodList, wellheadId, offset,
DateUtil.date(duration.getCloseTime()).offset(DateField.MINUTE, between)
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))
);
}
}
}
//离网优化
if (CollUtil.isNotEmpty(offGridPeriodList)) {
if (!storageAvgMap.containsKey(detail.getLineId())) {
//没有储能设备,无法计算
return;
}
//截取从第一次开井时间往后的时间段
List<DynamicQueryPlantPredictedPowerOutput> subAvgPowerList = CollUtil.sub(avgPowerList, firstIndex + 1, avgPowerList.size());
if (CollUtil.isEmpty(subAvgPowerList)) {
//没有时间段,无法计算
return;
}
//查获取前一个月该时间点储能剩余电量,求平均数
List<DynamicQueryStoragePredictedPowerOutput> averageEnergyStorageList = this.getAverageEnergyStorageListByParam(context, input);
if (CollUtil.isEmpty(averageEnergyStorageList)) {
//没有储能发电量,无法计算
return;
}
//取储能计算参数
List<DynamicQueryBasePowerLineStorageViewOutput> avgStorageViewList = storageAvgMap.get(detail.getLineId());
DynamicQueryBasePowerLineStorageViewOutput avgStorageView = avgStorageViewList.get(0);
//平均额定放电效率(%)
BigDecimal avgRatedDischargeEfficiency = avgStorageView.getRatedDischargeEfficiency();
//平均额定放电深度(%)
BigDecimal avgRatedDischargeDepth = avgStorageView.getRatedDischargeDepth();
//平均额定放电功率(KW)
BigDecimal avgRatedDischargePower = avgStorageView.getRatedDischargePower();
//逐15分钟计算光伏出力-井场运行功率之和,获得光伏出力不足时间段,并计算储能可用时长
Iterator<DynamicQueryStoragePredictedPowerOutput> iterator = averageEnergyStorageList.iterator();
for (DynamicQueryPlantPredictedPowerOutput avg : subAvgPowerList) {
if (avg.getPower().compareTo(totalOperatingPower) >= 0) {
//电量不足,计算储能可用时长
avg.setBatteryLowFlag(false);
String hourTime = avg.getHourTime();
String minTime = avg.getMinTime();
while (iterator.hasNext()) {
DynamicQueryStoragePredictedPowerOutput storagePredicted = iterator.next();
if (StringUtils.equals(hourTime, storagePredicted.getHourTime()) && StringUtils.equals(minTime, storagePredicted.getMinTime())) {
//计算储能可供电时长:(储能剩余容量*放电深度*放电效率)/额定放电功率
avg.setPowerDuration(
storagePredicted.getPower()
.multiply(avgRatedDischargeDepth)
.multiply(avgRatedDischargeEfficiency)
.divide(avgRatedDischargePower)
.setScale(BusinessConstant.ZERO, RoundingMode.DOWN)
.intValueExact()
/**
* 消峰平谷策略
*
* @param context 上下文
* @param wellheadDTOList 井口dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param durationDTOList 持续时间dtolist
* @param wellheadViewList 井口视图列表
* @param durationMap 持续时间图
* @param detail 细节
* @param monthNum 月份
* @param periodId id
*/
private void peakEliminationAndValleyLevelingStrategy(XContext context, List<SpaceOptimizeWellheadDTO> wellheadDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceInstitutionWellheadView> wellheadViewList,
Map<String, List<SpaceInstitutionDurationEnt>> durationMap, SpaceInstitutionDetailEnt detail,
int monthNum, String periodId) {
//通过线路ID和月份获取市电峰谷策略明细配置
List<GetBasePriceStrategyDetailOutput> strategyDetailList = ServiceUtil.getStrategyDetailList(context,
GetBasePriceStrategyDetailInput.builder()
.lineId(detail.getLineId())
.strategyMonth(String.valueOf(monthNum))
.build()
);
break;
if (CollUtil.isEmpty(strategyDetailList)) {
//没有配置,不优化
return;
}
//删除计算过的时间段
iterator.remove();
//获取第一段谷电阶段的开始时间为第一口井的开井时间
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, periodId, wellheadId, wellhead.getWellNumber());
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellheadId);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
//保存原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
}
if (w == 0) {
//第一个井口
isFirstWellhead = true;
} else {
avg.setBatteryLowFlag(true);
//计算启动间隔
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, periodId, 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, periodId, recordId, wellheadId, null,
startTimeOffset.toString(BusinessConstant.MINUTES_FORMAT), endTimeOffset.toString(BusinessConstant.MINUTES_FORMAT)
);
}
//拆分时间段
for (SpaceOptimizeDurationDTO durationDTO : offGridPeriodList) {
Date openTime = durationDTO.getOpenTime();
Date closeTime = durationDTO.getCloseTime();
if (closeTime.compareTo(BusinessConstant.DATE_FLAG) > 0) {
closeTime = DateUtil.endOfDay(DateUtil.date());
} else {
//计算偏移
DateTime offset = startTime.offset(DateField.MINUTE, between);
if (offset.compareTo(BusinessConstant.DATE_FLAG) > 0) {
//如果时间超过当天,舍弃
continue;
}
//匹配时间
for (int i = 0, size = subAvgPowerList.size(); i < size; i++) {
DynamicQueryPlantPredictedPowerOutput avg = subAvgPowerList.get(i);
DateTime createTime = DateUtil.date(avg.getCreateTime());
//计算时间范围:大于等于开始时间,小于等于结束时间
if (openTime.compareTo(createTime) >= 0 && closeTime.compareTo(createTime) <= 0) {
String endString = createTime.offset(DateField.MINUTE, 15).toString(BusinessConstant.MINUTES_FORMAT);
String startString = createTime.toString(BusinessConstant.MINUTES_FORMAT);
//电量满足跳过
if (avg.getBatteryLowFlag()) {
//创建光伏
this.createOptimizeDuration(durationDTOList, periodId, durationDTO.getRecordId(), durationDTO.getWellheadId(), BusinessConstant.PHOTOVOLTAIC,
startString, endString
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 avgPowerList 平均功率列表
* @return {@link BigDecimal}
*/
private BigDecimal getPowerMax(List<DynamicQueryPlantPredictedPowerOutput> avgPowerList) {
return avgPowerList.stream()
.map(DynamicQueryPlantPredictedPowerOutput::getPower)
.max(BigDecimal::compareTo)
.orElse(BigDecimal.ZERO);
}
/**
* 获取井口总功率
*
* @param spaceWellheadList 空间井口清单
* @param detailId 详细信息id
* @return {@link BigDecimal}
*/
private BigDecimal getWellheadTotalPower(List<SpaceInstitutionWellheadView> spaceWellheadList, String detailId) {
return spaceWellheadList.stream()
.filter(w -> StringUtils.equals(detailId, w.getInstitutionId()))
.map(SpaceInstitutionWellheadView::getServiceRating)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* 获取当前制度关联的井口按照是否可优化分组
*
* @param spaceWellheadList 空间井口清单
* @param detailId 详细信息id
* @return {@link Map}<{@link Boolean}, {@link List}<{@link SpaceInstitutionWellheadView}>>
*/
private Map<Boolean, List<SpaceInstitutionWellheadView>> getWellheadViewList(List<SpaceInstitutionWellheadView> spaceWellheadList, String detailId) {
return spaceWellheadList.stream()
.sorted(Comparator.comparing(SpaceInstitutionWellheadView::getStartSeq))
.collect(
Collectors.partitioningBy(w -> StringUtils.equals(detailId, w.getInstitutionId()) &&
StringUtils.equals("INTERVAL", w.getRunTypeKey()) &&
StringUtils.equals("0", w.getIntervalTypeKey())
)
);
}
/**
* 获取井口间开时间段
*
* @param context 上下文
* @param detailId 详细信息id
* @return {@link Map}<{@link String}, {@link List}<{@link SpaceInstitutionDurationEnt}>>
*/
private Map<String, List<SpaceInstitutionDurationEnt>> getDurationMap(XContext context, String detailId) {
SpaceInstitutionDurationMapper durationMapper = context.getBean(SpaceInstitutionDurationMapper.class);
//通过间开ID和井口ID查所有井口时段配置
List<SpaceInstitutionDurationEnt> durationList = durationMapper.selectList(new QueryWrapper<SpaceInstitutionDurationEnt>()
.select("*",
"STR_TO_DATE( CONCAT( open_well_time, ':00' ), '%H:%i:%s' ) AS openTime",
"STR_TO_DATE( CONCAT( close_well_time, ':00' ), '%H:%i:%s' ) AS closeTime"
)
.lambda()
.eq(BaseModel::getIsDeleted, BusinessConstant.ONE)
.eq(SpaceInstitutionDurationEnt::getInstitutionId, detailId)
.orderByAsc(SpaceInstitutionDurationEnt::getOpenWellTime)
);
if (CollUtil.isEmpty(durationList)) {
//没有设置时间段,无法优化
return null;
}
return durationList.stream()
.collect(
Collectors.groupingBy(SpaceInstitutionDurationEnt::getWellheadId)
);
}
/**
* 按线路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 lineIds 线路ID
* @return {@link Map}<{@link String}, {@link List}<{@link DynamicQueryBasePowerLineStorageViewOutput}>>
*/
private Map<String, List<DynamicQueryBasePowerLineStorageViewOutput>> getPowerLineStorageListByLineIds(XContext context, Set<String> lineIds) {
IBasePowerLineCloudService cloudService = context.getBean(IBasePowerLineCloudService.class);
XListResult<DynamicQueryBasePowerLineStorageViewOutput> result = cloudService.queryPowerLineStorageListByLineIds(context,
DynamicQueryBasePowerLineStorageInput.builder()
.lineIds(lineIds)
.build()
);
result.throwIfFail();
List<DynamicQueryBasePowerLineStorageViewOutput> list = result.getResult();
Map<String, List<DynamicQueryBasePowerLineStorageViewOutput>> collect;
if (CollUtil.isEmpty(list)) {
collect = new HashMap<>(0);
} else {
int powerDuration = avg.getPowerDuration();
String offset = createTime.offset(DateField.MINUTE, powerDuration).toString(BusinessConstant.MINUTES_FORMAT);
//储能发电时长
this.createOptimizeDuration(durationDTOList, periodId, durationDTO.getRecordId(), durationDTO.getWellheadId(), BusinessConstant.STORED_ENERGY,
startString, offset
collect = list.stream()
.collect(Collectors.groupingBy(DynamicQueryBasePowerLineStorageViewOutput::getLineId));
}
return collect;
}
/**
* 为间开井口列表设置发电功率
*
* @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)
);
//柴发发电时长
this.createOptimizeDuration(durationDTOList, periodId, durationDTO.getRecordId(), durationDTO.getWellheadId(), BusinessConstant.DIESEL_POWER,
offset, endString
});
}
/**
* 条件获取获取光伏预测各时段平均值列表
*
* @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();
}
/**
* 条件查询时段储能电量平均值(模拟测试用)
* todo: 模拟测试用,后续替换
*
* @param context 上下文
* @param input 输入
* @return {@link List}<{@link DynamicQueryStoragePredictedPowerOutput}>
*/
private List<DynamicQueryStoragePredictedPowerOutput> getAverageEnergyStorageListByParam(XContext context, DynamicQueryStoragePredictedPowerInput input) {
IStoragePredictedPowerCloudService cloudService = context.getBean(IStoragePredictedPowerCloudService.class);
XListResult<DynamicQueryStoragePredictedPowerOutput> result = cloudService.queryAverageEnergyStorageListByParam(context, input);
result.throwIfFail();
return result.getResult();
}
/**
* 获取井口Map通过最大功率区分
*
* @param wellheadViewList 井口视图列表
* @param powerMax 最大功率
* @return {@link Map}<{@link Boolean}, {@link List}<{@link SpaceInstitutionWellheadView}>>
*/
private Map<Boolean, List<SpaceInstitutionWellheadView>> getWellheadViewMapByPower(List<SpaceInstitutionWellheadView> wellheadViewList, BigDecimal powerMax) {
return wellheadViewList.stream()
.collect(
Collectors.partitioningBy(w -> powerMax.compareTo(w.getServiceRating()) >= BusinessConstant.ZERO)
);
}
/**
* 设置不需要优化的井口配置
*
* @param wellheadDTOList 井口dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param durationDTOList 持续时间dtolist
* @param unOptimizeWellheadList 取消优化井口列表
* @param durationMap 持续时间图
* @param periodId 期间id
*/
private void setUnOptimizeWellheadConfig(List<SpaceOptimizeWellheadDTO> wellheadDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceInstitutionWellheadView> unOptimizeWellheadList,
Map<String, List<SpaceInstitutionDurationEnt>> durationMap, String periodId) {
//保存不需要优化的井口
if (CollUtil.isEmpty(unOptimizeWellheadList)) {
return;
}
for (SpaceInstitutionWellheadView unOptimizeWellhead : unOptimizeWellheadList) {
String wellheadId = unOptimizeWellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, periodId, wellheadId, unOptimizeWellhead.getWellNumber());
List<SpaceInstitutionDurationEnt> durationConfigList = durationMap.get(wellheadId);
if (CollUtil.isEmpty(durationConfigList)) {
//没有设置时间段,无法优化
continue;
}
for (SpaceInstitutionDurationEnt durationEnt : durationConfigList) {
//保存原始记录
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId);
//存未优化结果
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
BusinessConstant.START_OF_DAY_TIME, BusinessConstant.END_OF_DAY_TIME
);
}
}
}
/**
* 创建间开优化井口信息
*
* @param wellheadDTOList 井口dtolist
* @param periodId 期间id
* @param wellheadId 井口id
* @param wellNumber 井号
* @return {@link String}
*/
private 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 结束时间字符串
*/
private 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
*/
private 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);
}
/**
......
......@@ -144,6 +144,4 @@ public class SpaceOptimizeLongCloudServiceImpl extends SpaceOptimizeBaseService
return XServiceResult.OK;
});
}
/*-----------------------------------private-----------------------------------*/
}
\ 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