Commit dcccdfc9 authored by ZWT's avatar ZWT

feat(零碳): 长庆演示系统新增功能

1.修改第三方日累计数据推送表表结构,增加日累计储能放电量字段,同时修改代码对应实体及mapper文件,修改相关接口增加储能日累计放电量接收逻辑;
2.修改首页井场收益分析模块接口,修改获取储能累计放电量逻辑;
3.设计并创建井口日用电趋势表,生成对应实体类及mapper文件;
4.统计分析模块,新增本月累计节电经济效益查询接口,添加线上接口文档并完成接口冒烟测试;
5.统计分析模块,新增本月累计减碳量查询接口,添加线上接口文档并完成接口冒烟测试;
6.统计分析模块,新增光伏发电趋势查询接口,添加线上接口文档并完成接口冒烟测试;
7.统计分析模块,新增月度总览查询接口,添加线上接口文档并完成接口冒烟测试;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent a178739e
......@@ -5,14 +5,20 @@ 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 cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import pps.cloud.base.service.IBasePowerLineCloudService;
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.DynamicQueryBasePowerLineOutput;
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.DynamicQueryBasePowerLinePlantViewOutput;
import pps.cloud.base.service.data.base_power_line_storage.DynamicQueryBasePowerLineStorageInput;
import pps.cloud.base.service.data.base_power_line_storage.DynamicQueryBasePowerLineStorageOutput;
import pps.cloud.base.service.data.base_power_line_storage.DynamicQueryBasePowerLineStorageViewOutput;
......@@ -32,8 +38,7 @@ import pps.core.common.utils.BaseUtils;
import pps.core.space.entity.*;
import pps.core.space.enums.BusinessError;
import pps.core.space.mapper.*;
import pps.core.space.service.data.SpaceOptimizeDateDuration;
import pps.core.space.service.data.SpaceOptimizeLineRelation;
import pps.core.space.service.data.*;
import pps.core.space.service.data.space_optimize_period.GetSpaceOptimizePeriodInput;
import pps.core.space.service.data.space_optimize_period.GetSpaceOptimizePeriodOutput;
import pps.core.space.service.data.space_optimize_period.GetSpaceOptimizeWellheadOutput;
......@@ -45,6 +50,7 @@ import xstartup.data.XListResult;
import xstartup.error.XError;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
......@@ -111,6 +117,490 @@ public class SpaceOptimizeBaseService {
return output;
}
/**
* 动态优化
*
* @param context 上下文
* @param periodDTOList 时期数据学家
* @param wellheadDTOList 井口dtolist
* @param durationDTOList 持续时间dtolist
* @param unOptimizeDurationList 取消优化工期列表
* @param dateType 日期类型
* @param flag 旗帜
* @param offset 抵消
*/
public void dynamicOptimize(XContext context, List<SpaceOptimizePeriodDTO> periodDTOList, List<SpaceOptimizeWellheadDTO> wellheadDTOList,
List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceOptimizeDurationDTO> unOptimizeDurationList,
Integer dateType, Integer flag, Integer offset) {
//取当前时间
DateTime startDate = DateUtil.beginOfDay(DateTime.now());
//取生效中的基础间开
List<SpaceInstitutionDetailEnt> detailEntList = this.getEffectiveSpaceInstitution(context, startDate.toString());
//取线路ID和制度ID
List<String> lineIds = new ArrayList<>(32);
List<String> institutionIds = new ArrayList<>(32);
detailEntList.forEach(detail -> {
lineIds.add(detail.getLineId());
institutionIds.add(detail.getId());
});
//取间开的所有井口
SpaceInstitutionWellheadViewMapper wellheadMapper = context.getBean(SpaceInstitutionWellheadViewMapper.class);
List<SpaceInstitutionWellheadView> spaceWellheadList = wellheadMapper.selectWellheadsByInstitutionIds(institutionIds);
if (CollUtil.isEmpty(spaceWellheadList)) {
throw new XServiceException(BusinessError.DidNotFindWellhead);
}
//取间开对应的线路
IBasePowerLineCloudService lineCloudService = context.getBean(IBasePowerLineCloudService.class);
XListResult<DynamicQueryBasePowerLineOutput> lineResult = lineCloudService.getBasePowerLineList(context, DynamicQueryBasePowerLineInput.builder()
.lineIds(lineIds)
.build());
lineResult.throwIfFail();
//查线路下所有电站
XListResult<DynamicQueryBasePowerLinePlantViewOutput> linePlantResult = lineCloudService.getPowerLinePlantViewList(context, DynamicQueryBasePowerLinePlantInput.builder()
.lineIds(lineIds)
.build());
linePlantResult.throwIfFail();
//取当前月
int month = startDate.monthBaseOne();
//查市电峰谷
IBasePriceStrategyCloudService strategyCloudService = context.getBean(IBasePriceStrategyCloudService.class);
XListResult<GetBasePriceStrategyDetailOutput> strategyResult = strategyCloudService.queryStrategyDetailList(context, GetBasePriceStrategyDetailInput.builder()
.strategyMonth(String.valueOf(month))
.build());
strategyResult.throwIfFail();
//查井口配置时间段
SpaceInstitutionDurationMapper durationMapper = context.getBean(SpaceInstitutionDurationMapper.class);
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)
.in(SpaceInstitutionDurationEnt::getWellheadId, spaceWellheadList.stream().map(SpaceInstitutionWellheadView::getWellheadId).collect(Collectors.toList()))
.orderByAsc(SpaceInstitutionDurationEnt::getOpenWellTime)
);
if (CollUtil.isEmpty(durationList)) {
throw new XServiceException(BusinessError.DidNotFindCalibration);
}
//间开制度ID/井口LIST Map
Map<String, List<SpaceInstitutionWellheadView>> wellheadMap = spaceWellheadList.stream()
.collect(Collectors.groupingBy(SpaceInstitutionWellheadView::getInstitutionId));
//线路ID/峰谷策略ID Map
Map<String, String> lineMap = lineResult.getResult().stream()
.collect(Collectors.toMap(DynamicQueryBasePowerLineOutput::getId, DynamicQueryBasePowerLineOutput::getStrategyId));
//线路ID/电站ID LIST Map
Map<String, List<String>> plantIdsMap = linePlantResult.getResult().stream()
.collect(Collectors.groupingBy(DynamicQueryBasePowerLinePlantViewOutput::getLineId,
Collectors.mapping(DynamicQueryBasePowerLinePlantViewOutput::getPlantId, Collectors.toList())));
//峰谷策略ID/峰谷策略LIST Map
Map<String, List<GetBasePriceStrategyDetailOutput>> strategyMap = strategyResult.getResult().stream()
.collect(Collectors.groupingBy(GetBasePriceStrategyDetailOutput::getStrategyId));
//间开制度ID/区间配置Map Map
Map<String, Map<String, List<SpaceInstitutionDurationEnt>>> durationMap = durationList.stream()
.collect(Collectors.groupingBy(SpaceInstitutionDurationEnt::getInstitutionId,
Collectors.groupingBy(SpaceInstitutionDurationEnt::getWellheadId)));
//初始化时间轴
List<DateTime> rangeToList = DateUtil.rangeToList(DateUtil.offsetDay(BusinessConstant.DATE_FLAG, -1), BusinessConstant.DATE_FLAG, DateField.MINUTE, 30);
//初始化时间轴(5分钟间隔)
List<DateTime> timerShaft_5 = DateUtil.rangeToList(DateUtil.offsetDay(BusinessConstant.DATE_FLAG, -1), BusinessConstant.DATE_FLAG, DateField.MINUTE, 5);
//遍历
List<DynamicQueryPlantPredictedPowerOutput> powerList;
List<GetBasePriceStrategyDetailOutput> strategyList;
List<SpaceInstitutionWellheadView> wellheadList;
String periodId;
Map<Boolean, List<SpaceInstitutionWellheadView>> collect;
//权重数组
int[] ladder = {10, 5, 3, 1};
//时间间隔
Integer startInterval;
Date institutionEndDate;
DateTime optimizeDeadline;
//取优化截至日期
DateTime optimizeDate;
DateTime begin;
for (SpaceInstitutionDetailEnt detail : detailEntList) {
//查最新间开历史
if (this.isOptimize(context, detail.getId(), flag, startDate)) {
continue;
}
//制度结束时间
institutionEndDate = detail.getInstitutionEndDate();
optimizeDeadline = DateUtil.offsetDay(startDate, offset);
if (optimizeDeadline.compareTo(institutionEndDate) > 0) {
optimizeDeadline = DateUtil.endOfDay(institutionEndDate);
}
//创建记录
periodId = this.createOptimizePeriod(periodDTOList, detail.getId(), detail.getLineId(),
BaseUtils.getExecutionCycleForCalibration(startDate, DateUtil.offsetDay(optimizeDeadline, -1)), optimizeDeadline);
for (int d = 0; d < offset; d++) {
begin = DateUtil.offsetDay(startDate, d);
optimizeDate = DateUtil.offsetDay(startDate, d + 1);
//查预测光伏出力
powerList = this.getAveragePowerHalfHour(context, DynamicQueryPlantPredictedPowerInput.builder()
.plantIds(plantIdsMap.get(detail.getLineId()))
.startTime(begin.toString(BusinessConstant.DATE_FORMAT_DAY))
.endTime(optimizeDate.toString(BusinessConstant.DATE_FORMAT_DAY))
.dateType(BusinessConstant.ONE)
.build());
//取峰谷策略
strategyList = strategyMap.get(lineMap.get(detail.getLineId()));
//按是否需要优化分组
collect = wellheadMap.get(detail.getId()).stream()
.sorted(Comparator.comparing(SpaceInstitutionWellheadView::getStartSeq))
.collect(
Collectors.partitioningBy(w ->
CharSequenceUtil.equals(BusinessConstant.INTERVAL_PUMPING_WELL, w.getRunTypeKey()) &&
CharSequenceUtil.equals("0", w.getIntervalTypeKey())
)
);
//保存不需要优化的井口
List<SpaceInstitutionWellheadView> unOptimizeWellhead = collect.get(Boolean.FALSE);
this.setUnOptimizeWellheadConfig(durationDTOList, unOptimizeDurationList, wellheadDTOList,
unOptimizeWellhead, durationMap.get(detail.getId()), periodId, optimizeDate);
//取待优化井口并遍历
wellheadList = collect.get(Boolean.TRUE);
//防冻堵策略(一口井就全开不走优化)
SpaceInstitutionWellheadView tundraStrategyWellhead = null;
List<SpaceOptimizeDurationDTO> tundraStrategyList = new ArrayList<>(32);
Integer tundraStrategy = detail.getTundraStrategy();
//防冻堵条件:不存在常开井(不需要优化的井)&&需要优化的井口不能为空&&开启防冻堵
boolean isTundraStrategy = CollUtil.isEmpty(unOptimizeWellhead) && CollUtil.isNotEmpty(wellheadList) && ObjectUtil.isNotNull(tundraStrategy) && tundraStrategy.equals(0);
if (isTundraStrategy) {
int removeIndex = 0;
BigDecimal serviceRating = wellheadList.get(0).getServiceRating();
if (wellheadList.size() == 1) {
SpaceInstitutionWellheadView wellhead = wellheadList.get(0);
String wellheadId = wellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, periodId, wellheadId, wellhead.getWellNumber(), wellhead.getStartSeq(), optimizeDate, BusinessConstant.ZERO);
//保存间开原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationMap.get(detail.getId()).get(wellheadId)) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId, optimizeDate);
}
//设置间开优化24小时全开
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
BusinessConstant.START_OF_DAY_TIME,
BusinessConstant.END_OF_DAY_TIME,
BusinessConstant.ZERO, optimizeDate
);
} else {
for (int i = 1; i < wellheadList.size(); i++) {
//找运行功率最小的井口(功率都一样取启动顺序最晚的)
if (serviceRating.compareTo(wellheadList.get(i).getServiceRating()) >= 0) {
removeIndex = i;
}
}
//取出防冻井
tundraStrategyWellhead = wellheadList.get(removeIndex);
}
//排除防冻井
wellheadList.remove(removeIndex);
}
BigDecimal serviceRating = BigDecimal.ZERO;
SpaceInstitutionWellheadView wellhead;
//记录第一次开井时间
DateTime firstOpenWellTime = null;
/* [第一次开井时间优化]
int offset = detail.getStartInterval();*/
startInterval = detail.getStartInterval();
if (CollUtil.isNotEmpty(wellheadList)) {
for (int i = 0; i < wellheadList.size(); i++) {
wellhead = wellheadList.get(i);
String wellheadId = wellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, periodId, wellheadId, wellhead.getWellNumber(), wellhead.getStartSeq(), optimizeDate, BusinessConstant.ONE);
//保存间开原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationMap.get(detail.getId()).get(wellheadId)) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId, optimizeDate);
}
//累加运行功率
serviceRating = serviceRating.add(wellhead.getServiceRating());
//计算权重
List<SpaceOptimizeWeight> weightList = this.calculateWeightList(serviceRating, rangeToList, powerList, strategyList);
//每日最小开井时长(分钟)
int minOpenMinute = wellhead.getMinOpen()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
//分级取时间段
List<SpaceOptimizeWeightDuration> weightDurationList = this.weightListProcessing(ladder, weightList, minOpenMinute);
//时间段优化
List<SpaceOptimizeDurationDTO> optimizeDurationDTOList = new ArrayList<>(12);
firstOpenWellTime = this.timePeriodOptimization(optimizeDurationDTOList, weightDurationList, firstOpenWellTime, i,
startInterval, minOpenMinute, wellhead, weightList);
//创建优化后的间开区间
this.addOptimizeDuration(optimizeDurationDTOList, durationDTOList, tundraStrategyList, periodId, recordId, wellheadId, optimizeDate);
}
//防冻井
if (ObjectUtil.isNotNull(tundraStrategyWellhead) && CollUtil.isNotEmpty(tundraStrategyList)) {
List<SpaceOptimizeDurationDTO> closeList = new ArrayList<>(32);
long totalOpenTime = 0;
if (tundraStrategyList.size() == 1) {
//记录第一段开始时间之前的关井时间
if (BusinessConstant.DATE_FLAG_BEGIN.compareTo(tundraStrategyList.get(0).getOpenTime()) != 0) {
long between = DateUtil.between(BusinessConstant.DATE_FLAG_BEGIN, tundraStrategyList.get(0).getOpenTime(), DateUnit.MINUTE);
totalOpenTime += between;
closeList.add(
SpaceOptimizeDurationDTO.builder()
.openTime(BusinessConstant.DATE_FLAG_BEGIN)
.closeTime(tundraStrategyList.get(0).getOpenTime())
.duration(between)
.build()
);
}
//记录最后一段停井时间之后的关井时间
if (BusinessConstant.DATE_FLAG.compareTo(tundraStrategyList.get(0).getCloseTime()) != 0) {
long between = DateUtil.between(tundraStrategyList.get(0).getCloseTime(), BusinessConstant.DATE_FLAG, DateUnit.MINUTE);
totalOpenTime += between;
closeList.add(
SpaceOptimizeDurationDTO.builder()
.openTime(tundraStrategyList.get(0).getCloseTime())
.closeTime(BusinessConstant.DATE_FLAG)
.duration(between)
.build()
);
}
} else {
//初始化时间轴
List<SpaceOptimizeTundraStrategy> axis = new ArrayList<>(timerShaft_5.size());
for (DateTime dateTime : timerShaft_5) {
axis.add(
SpaceOptimizeTundraStrategy.builder()
.timestamp(dateTime)
.beUsing(Boolean.FALSE)
.build()
);
}
//先按开井时间再按关井时间排序
tundraStrategyList.sort(Comparator.comparing(SpaceOptimizeDurationDTO::getOpenTime).thenComparing(SpaceOptimizeDurationDTO::getCloseTime));
//渲染时间轴
int nextBegin = 0;
for (SpaceOptimizeDurationDTO durationDTO : tundraStrategyList) {
Date openTime = durationDTO.getOpenTime();
Date closeTime = durationDTO.getCloseTime();
for (int i = nextBegin; i < axis.size(); i++) {
SpaceOptimizeTundraStrategy z = axis.get(i);
if (DateUtil.isIn(z.getTimestamp(), openTime, closeTime)) {
z.setBeUsing(Boolean.TRUE);
}
//记录下一次开始位置
if (z.getTimestamp().compareTo(closeTime) > 0) {
nextBegin = i;
break;
}
}
}
//取关井时间段
int beginIndex = 0;
boolean isClose = Boolean.FALSE;
for (int i = 0; i < axis.size(); i++) {
SpaceOptimizeTundraStrategy z = axis.get(i);
Boolean beUsing = z.getBeUsing();
if (isClose && beUsing) {
long between = DateUtil.between(axis.get(beginIndex).getTimestamp(), axis.get(i).getTimestamp(), DateUnit.MINUTE);
totalOpenTime += between;
//存时间段,重置状态
closeList.add(
SpaceOptimizeDurationDTO.builder()
.openTime(axis.get(beginIndex).getTimestamp())
.closeTime(axis.get(i).getTimestamp())
.duration(between)
.build()
);
isClose = Boolean.FALSE;
} else if (!isClose && !beUsing) {
//确定开始位置
if (i > 0) {
beginIndex = i - 1;
}
isClose = Boolean.TRUE;
}
}
//补充最后一段
if (isClose) {
long between = DateUtil.between(axis.get(beginIndex).getTimestamp(), axis.get(axis.size() - 1).getTimestamp(), DateUnit.MINUTE);
totalOpenTime += between;
closeList.add(
SpaceOptimizeDurationDTO.builder()
.openTime(axis.get(beginIndex).getTimestamp())
.closeTime(axis.get(axis.size() - 1).getTimestamp())
.duration(between)
.build()
);
}
}
//计算权重时间轴
//每日最小开井时长(分钟)
int minOpenMinute = tundraStrategyWellhead.getMinOpen()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
serviceRating = serviceRating.add(tundraStrategyWellhead.getServiceRating());
List<SpaceOptimizeWeight> weightList = this.calculateWeightList(serviceRating, rangeToList, powerList, strategyList);
List<SpaceOptimizeWeightDuration> weightDurationList = this.weightListProcessing(ladder, weightList, minOpenMinute);
//创建优化记录
String wellheadId = tundraStrategyWellhead.getWellheadId();
String recordId = this.createOptimizeWellhead(wellheadDTOList, periodId, wellheadId, tundraStrategyWellhead.getWellNumber(), tundraStrategyWellhead.getStartSeq(), optimizeDate, BusinessConstant.ZERO);
//保存间开原始记录
for (SpaceInstitutionDurationEnt durationEnt : durationMap.get(detail.getId()).get(wellheadId)) {
this.createUnOptimizeDuration(unOptimizeDurationList, durationEnt, periodId, recordId, wellheadId, optimizeDate);
}
//关井时间优化
if (CollUtil.isNotEmpty(closeList)) {
//每日开井时长
int dayOpenMinute = tundraStrategyWellhead.getRunDuration()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
//计算需要补的时间
long supplementaryTime = dayOpenMinute - totalOpenTime;
//补时间
for (SpaceOptimizeWeightDuration weightDuration : weightDurationList) {
if (supplementaryTime <= 0) {
break;
}
DateTime openTimeWeight = weightDuration.getOpenTime();
DateTime closeTimeWeight = weightDuration.getCloseTime();
//计算排除次数
int exceptSize = 0;
for (int i = 0; i < closeList.size(); i++) {
SpaceOptimizeDurationDTO close = closeList.get(i);
Date openTime = close.getOpenTime();
Date closeTime = close.getCloseTime();
if (DateUtil.compare(openTime, openTimeWeight) >= 0 && DateUtil.compare(closeTimeWeight, closeTime) >= 0) {
//可优化时间段在开井范围内
if (i > 0) {
//判断开井时间是否小于上一段关井时间
if (DateUtil.compare(openTimeWeight, closeList.get(i - 1).getCloseTime()) < 0) {
//如果小于上一段关井时间,修改当前开井时间
openTimeWeight = DateUtil.date(closeList.get(i - 1).getCloseTime());
}
}
//取后一位
if (i + 1 < closeList.size()) {
//判断关井时间是否大于下一段开井时间
if (DateUtil.compare(closeTimeWeight, closeList.get(i + 1).getOpenTime()) > 0) {
//如果大于下一段开井时间,修改当前关井时间
closeTimeWeight = DateUtil.date(closeList.get(i + 1).getOpenTime());
}
}
//这里需要把时长补回去再计算
supplementaryTime += close.getDuration();
//重新计算结束时间及总开井时长
long between = DateUtil.between(openTimeWeight, closeTimeWeight, DateUnit.MINUTE);
if (between >= supplementaryTime) {
//从后往前计算开井时间
close.setDuration(supplementaryTime);
supplementaryTime = 0;
} else {
close.setDuration(between);
supplementaryTime -= between;
}
close.setOpenTime(openTimeWeight);
close.setCloseTime(closeTimeWeight);
break;
}
if (DateUtil.compare(openTime, closeTimeWeight) >= 0 || DateUtil.compare(closeTime, openTimeWeight) <= 0) {
//判断时间段是否在开井范围之外
exceptSize++;
continue;
}
//从后往前算
if (DateUtil.isIn(openTime, openTimeWeight, closeTimeWeight)) {
//取前一位
if (i > 0) {
//判断开井时间是否小于上一段关井时间
if (DateUtil.compare(openTimeWeight, closeList.get(i - 1).getCloseTime()) < 0) {
//如果小于上一段关井时间,修改当前开井时间
openTimeWeight = DateUtil.date(closeList.get(i - 1).getCloseTime());
}
}
//这里需要把时长补回去再计算
supplementaryTime += close.getDuration();
//重新计算结束时间及总开井时长
long between = DateUtil.between(openTimeWeight, closeTime, DateUnit.MINUTE);
if (between >= supplementaryTime) {
//从后往前计算开井时间
close.setOpenTime(DateUtil.offsetMinute(closeTime, -(int) supplementaryTime));
close.setDuration(supplementaryTime);
supplementaryTime = 0;
break;
} else {
close.setOpenTime(openTimeWeight);
close.setDuration(between);
supplementaryTime -= between;
}
}
//从前往后算
if (DateUtil.isIn(closeTime, openTimeWeight, closeTimeWeight)) {
//取后一位
if (i + 1 < closeList.size()) {
//判断关井时间是否大于下一段开井时间
if (DateUtil.compare(closeTimeWeight, closeList.get(i + 1).getOpenTime()) > 0) {
//如果大于下一段开井时间,修改当前关井时间
closeTimeWeight = DateUtil.date(closeList.get(i + 1).getOpenTime());
}
}
//这里需要把时长补回去再计算
supplementaryTime += close.getDuration();
//重新计算开始时间及总开井时长
long between = DateUtil.between(openTime, closeTimeWeight, DateUnit.MINUTE);
if (between >= supplementaryTime) {
//从后往前计算开井时间
close.setCloseTime(DateUtil.offsetMinute(openTime, (int) supplementaryTime));
close.setDuration(supplementaryTime);
supplementaryTime = 0;
break;
} else {
close.setCloseTime(closeTimeWeight);
close.setDuration(between);
supplementaryTime -= between;
}
}
}
//添加时段,处理开井时长
if (exceptSize == closeList.size()) {
long duration = weightDuration.getDuration();
if (duration >= supplementaryTime) {
//计算关井时间
closeTimeWeight = DateUtil.offsetMinute(openTimeWeight, (int) supplementaryTime);
duration = supplementaryTime;
supplementaryTime = 0;
} else {
supplementaryTime -= duration;
}
closeList.add(
SpaceOptimizeDurationDTO.builder()
.openTime(openTimeWeight)
.closeTime(closeTimeWeight)
.duration(duration)
.build()
);
}
}
//时间段合并优化
closeList.sort(Comparator.comparing(SpaceOptimizeDurationDTO::getOpenTime));
List<SpaceOptimizeDurationDTO> optimizeDurationDTOList = new ArrayList<>(closeList.size());
optimizeDurationDTOList.add(closeList.get(0));
for (int i = 1; i < closeList.size(); i++) {
SpaceOptimizeDurationDTO nowOne = closeList.get(i);
SpaceOptimizeDurationDTO lastOne = optimizeDurationDTOList.get(optimizeDurationDTOList.size() - 1);
if (0 == DateUtil.compare(lastOne.getCloseTime(), nowOne.getOpenTime())) {
lastOne.setCloseTime(nowOne.getCloseTime());
} else {
optimizeDurationDTOList.add(nowOne);
}
}
closeList = optimizeDurationDTOList;
} else {
//不需要补时间,需要优化计算
this.timePeriodOptimization(closeList, weightDurationList, firstOpenWellTime, wellheadList.size(),
startInterval, minOpenMinute, tundraStrategyWellhead, weightList);
}
//创建优化后的间开区间
this.addOptimizeDuration(closeList, durationDTOList, tundraStrategyList, periodId, recordId, wellheadId, optimizeDate);
}
}
}
}
}
/**
* 进行优化
*
......@@ -1642,4 +2132,663 @@ public class SpaceOptimizeBaseService {
return false;
}
}
/**
* 加时
*
* @param durationDTO 持续时间dto
* @param endTime 结束时间
* @param minute 分钟
*/
private void overtime(SpaceOptimizeDurationDTO durationDTO, DateTime endTime, int minute) {
//判断向前补还是向后补
if (DateUtil.compare(durationDTO.getOpenTime(), endTime) == 0) {
//向前补
durationDTO.setOpenTime(DateUtil.offsetMinute(durationDTO.getOpenTime(), -minute));
} else {
//向后补
durationDTO.setCloseTime(DateUtil.offsetMinute(durationDTO.getCloseTime(), minute));
}
}
/**
* 通过时段类型获取权重
*
* @param periodTypeKey 周期类型键
* @return int
*/
private int getWeightByPeriodTypeKey(String periodTypeKey) {
switch (periodTypeKey) {
case "LOW":
return 5;
case "PEACE":
return 3;
case "PEAK":
return 1;
case "RUSH":
default:
return 0;
}
}
/**
* 计算权重列表
*
* @param serviceRating 服务等级
* @param rangeToList 要列出范围
* @param powerList 电源列表
* @param strategyList 策略列表
* @return {@link List}<{@link SpaceOptimizeWeight}>
*/
private List<SpaceOptimizeWeight> calculateWeightList(BigDecimal serviceRating, List<DateTime> rangeToList, List<DynamicQueryPlantPredictedPowerOutput> powerList, List<GetBasePriceStrategyDetailOutput> strategyList) {
int rangeListSize = rangeToList.size();
int powerListSize = powerList.size();
int strategyListSize = strategyList.size();
int rangeIndex = 0;
int powerIndex = 0;
int strategyIndex = 0;
List<SpaceOptimizeWeight> weightList = new ArrayList<>(rangeListSize);
DynamicQueryPlantPredictedPowerOutput firstPower;
DynamicQueryPlantPredictedPowerOutput lastPower;
GetBasePriceStrategyDetailOutput firstStrategy;
GetBasePriceStrategyDetailOutput lastStrategy;
while (rangeListSize > 0 && rangeListSize > rangeIndex && powerListSize > powerIndex) {
boolean powerFlag = false;
SpaceOptimizeWeight firstWeight = new SpaceOptimizeWeight();
DateTime firstTime = rangeToList.get(rangeIndex);
firstWeight.setTimestamp(firstTime);
firstWeight.setSort(rangeIndex);
firstPower = powerList.get(powerIndex);
if (0 == firstTime.compareTo(firstPower.getCreateTime())) {
firstWeight.setPower(firstPower.getPower());
//判断发电量是否满足运行功率
powerFlag = firstPower.getPower().compareTo(serviceRating) >= 0;
if (powerFlag) {
firstWeight.setWeight(10);
}
powerIndex++;
}
firstStrategy = strategyList.get(strategyIndex);
Date closeTime = ObjectUtil.isEmpty(firstStrategy.getCloseTime()) && CharSequenceUtil.equals(BusinessConstant.END_OF_DAY_TIME, firstStrategy.getStartTime()) ? BusinessConstant.DATE_FLAG : firstStrategy.getCloseTime();
//在市电峰谷时段内,且未满足运行功率,设置权重
if (DateUtil.isIn(firstTime, firstStrategy.getOpenTime(), closeTime)) {
if (CharSequenceUtil.equals(firstStrategy.getPeriodTypeKey(), "RUSH")) {
//尖峰时段要停井
firstWeight.setWeight(0);
} else if (!powerFlag) {
firstWeight.setWeight(this.getWeightByPeriodTypeKey(firstStrategy.getPeriodTypeKey()));
}
}
if (firstTime.compareTo(firstStrategy.getCloseTime()) >= 0) {
strategyIndex++;
}
weightList.add(firstWeight);
rangeIndex++;
rangeListSize--;
//防止重复插入
if (rangeIndex >= rangeListSize) {
continue;
}
/*----------------------------------------------------*/
powerFlag = false;
SpaceOptimizeWeight lastWeight = new SpaceOptimizeWeight();
DateTime lastTime = rangeToList.get(rangeListSize);
lastWeight.setTimestamp(lastTime);
lastWeight.setSort(rangeListSize);
lastPower = powerList.get(powerListSize - 1);
if (0 == lastTime.compareTo(lastPower.getCreateTime())) {
lastWeight.setPower(lastPower.getPower());
//判断发电量是否满足运行功率
powerFlag = lastPower.getPower().compareTo(serviceRating) >= 0;
if (powerFlag) {
lastWeight.setWeight(10);
}
powerListSize--;
}
lastStrategy = strategyList.get(strategyListSize - 1);
closeTime = ObjectUtil.isEmpty(lastStrategy.getCloseTime()) && CharSequenceUtil.equals(BusinessConstant.END_OF_DAY_TIME, lastStrategy.getEndTime()) ? BusinessConstant.DATE_FLAG : lastStrategy.getCloseTime();
//在市电峰谷时段内,且未满足运行功率,设置权重
if (DateUtil.isIn(lastTime, lastStrategy.getOpenTime(), closeTime)) {
if (CharSequenceUtil.equals(lastStrategy.getPeriodTypeKey(), "RUSH")) {
//尖峰时段要停井
lastWeight.setWeight(0);
} else if (!powerFlag) {
lastWeight.setWeight(this.getWeightByPeriodTypeKey(lastStrategy.getPeriodTypeKey()));
}
}
if (lastTime.compareTo(lastStrategy.getOpenTime()) <= 0) {
strategyListSize--;
}
weightList.add(lastWeight);
}
//排序
weightList.sort(Comparator.comparing(SpaceOptimizeWeight::getSort));
return weightList;
}
/**
* 权重时间处理
*
* @param ladder 梯子
* @param weightList 重量清单
* @param minOpenMinute 最小开放分钟
* @return {@link List}<{@link SpaceOptimizeWeightDuration}>
*/
private List<SpaceOptimizeWeightDuration> weightListProcessing(int[] ladder, List<SpaceOptimizeWeight> weightList, int minOpenMinute) {
SpaceOptimizeWeight weight;
//分级取时间段
List<SpaceOptimizeWeightDuration> weightDurationList = new ArrayList<>(32);
long between;
for (int i1 = 0; i1 < ladder.length; i1++) {
int begin = -1;
//取每级时间
for (int i2 = 0; i2 < weightList.size(); i2++) {
weight = weightList.get(i2);
//过滤条件:权重相同
if (ladder[i1] == weight.getWeight()) {
//确定开始时间位置
if (begin == -1) {
begin = i2;
}
} else if (begin != -1) {
//如果开井时间不满足最小开井时间则舍弃
between = DateUtil.between(weightList.get(begin).getTimestamp(), weightList.get(i2).getTimestamp(), DateUnit.MINUTE);
if (minOpenMinute <= between) {
//创建区间
weightDurationList.add(
SpaceOptimizeWeightDuration.builder()
.openTime(weightList.get(begin).getTimestamp())
.closeTime(weightList.get(i2).getTimestamp())
.openIndex(begin)
.closeIndex(i2)
.duration(between)
.weight(ladder[i1])
.build()
);
}
begin = -1;
}
}
}
//时间处理并排序(处理后第一次开井时间的索引位置为0)
weightDurationList.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
return weightDurationList;
}
/**
* 时间段优化
*
* @param optimizeDurationDTOList 优化工期dtolist
* @param weightDurationList 重量持续时间列表
* @param firstOpenWellTime 首次开井时间
* @param i 我
* @param startInterval 开始间隔
* @param minOpenMinute 最小开放分钟
* @param wellhead 井口
* @param weightList 重量清单
* @return {@link DateTime}
*/
private DateTime timePeriodOptimization(List<SpaceOptimizeDurationDTO> optimizeDurationDTOList, List<SpaceOptimizeWeightDuration> weightDurationList, DateTime firstOpenWellTime,
int i, Integer startInterval, int minOpenMinute, SpaceInstitutionWellheadView wellhead, List<SpaceOptimizeWeight> weightList) {
//每日开井时长
int dayOpenMinute = wellhead.getRunDuration()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
//每日最大开井时长(分钟)
int maxOpenMinute = wellhead.getMaxOpen()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
//每日最小关井时长(分钟)
int minCloseMinute = wellhead.getMinClose()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
//每日最大关井时长(分钟)
int maxCloseMinute = wellhead.getMaxClose()
.multiply(BusinessConstant.BIG_DECIMAL_60)
.intValue();
//总开井时间
long sumOpenTime = 0;
/* //中断标识 [第一次开井时间优化]
boolean breakFlag = false;
//重新计算标识
boolean againFlag = false;*/
for (int i1 = 0; i1 < weightDurationList.size(); i1++) {
SpaceOptimizeWeightDuration weightDuration = weightDurationList.get(i1);
long duration = weightDuration.getDuration();
DateTime openTime = weightDuration.getOpenTime();
//偏移其他井口开井时间,并修改时间间隔
if (i > 0 && 0 == i1 && 0 >= openTime.compareTo(firstOpenWellTime)) {
duration -= (long) startInterval * i;
openTime = DateUtil.offsetMinute(openTime, startInterval * i);
}
DateTime closeTime = weightDuration.getCloseTime();
//正向标识
boolean forwardFlag = true;
//偏移开/关井时间
if (CollUtil.isNotEmpty(optimizeDurationDTOList)) {
SpaceOptimizeDurationDTO durationDTO = optimizeDurationDTOList.get(optimizeDurationDTOList.size() - 1);
Date firstOpenTime = optimizeDurationDTOList.get(0).getOpenTime();
Date lastCloseTime = durationDTO.getCloseTime();
long l;
//如果关井时间在第一次开井时间之前,判断是否需要偏移关井时间
if (DateUtil.compare(firstOpenTime, closeTime) >= 0) {
forwardFlag = false;
l = closeTime.between(firstOpenTime, DateUnit.MINUTE);
long l1 = l - minCloseMinute;
//小于0,说明不满足最小停井时间,需要补
if (l1 < 0) {
//偏移关井时间
closeTime = closeTime.offsetNew(DateField.MINUTE, (int) l1);
duration += l1;
if (duration < minOpenMinute) {
continue;
}
} else if (l1 > 0) {
//判断时间间隔是否超过最大停井时间
if (l > maxCloseMinute) {
//调整当前权重
if (i1 > 0) {
//计算出本次应该的开/关井时间
closeTime = DateUtil.offsetMinute(closeTime, (int) l - maxCloseMinute);
openTime = DateUtil.offsetMinute(openTime, (int) l - maxCloseMinute);
}
}
}
} else {
//计算当前开井时间和上一次关井时间的时间间隔
l = openTime.between(lastCloseTime, DateUnit.MINUTE);
//比较时间
if (DateUtil.compare(lastCloseTime, openTime) > 0) {
//时间间隔-(超出部分时间+最小关井时长)
duration -= (l + minCloseMinute);
if (duration >= minOpenMinute) {
//如果剩余时长能满足最小开井时长,则计算开井时间(用关井时间往前推)
openTime = closeTime.offsetNew(DateField.MINUTE, (int) -duration);
} else {
continue;
}
} else {
long l1 = l - minCloseMinute;
//小于0,说明不满足最小停井时间,需要补
if (l1 < 0) {
openTime = openTime.offsetNew(DateField.MINUTE, (int) -l1);
//偏移启动时间,判断时间区间是否满足最小开井时长
duration += l1;
if (duration < minOpenMinute) {
continue;
}
} else if (l1 > 0) {
//判断时间间隔是否超过最大停井时间
if (l > maxCloseMinute) {
//调整当前权重
if (i1 > 0) {
//计算出本次应该的开井时间
openTime = DateUtil.offsetMinute(lastCloseTime, maxCloseMinute);
//修改本次区间的开始时间及时间间隔
duration = DateUtil.between(openTime, weightDuration.getCloseTime(), DateUnit.MINUTE);
}
}
}
}
}
}
//判断时间间隔是否能满足最大开井时间
if (duration >= maxOpenMinute) {
//满足,判断能满足几次(最大开井时间)
//todo : 能力有限,只能用(最大开井时间+最小停井时间)固定范围,求不了最优排布
int div = (int) NumberUtil.div(duration, maxOpenMinute, 0, RoundingMode.UP);
if (forwardFlag) {
//正向拆分
for (int i2 = 1; i2 <= div; i2++) {
DateTime closeTimeNew;
if (duration >= maxOpenMinute) {
sumOpenTime += maxOpenMinute;
closeTimeNew = openTime.offsetNew(DateField.MINUTE, maxOpenMinute);
duration = duration - maxOpenMinute - minCloseMinute;
} else if (duration >= minOpenMinute) {
sumOpenTime += duration;
closeTimeNew = openTime.offsetNew(DateField.MINUTE, (int) duration);
duration = -minCloseMinute;
} else {
//时间不够,舍弃
continue;
}
optimizeDurationDTOList.add(SpaceOptimizeDurationDTO.builder()
.openTime(openTime)
.closeTime(closeTimeNew)
.build());
//下次启动时间为本次关井时间向后移动最小关井时间
openTime = closeTimeNew.offsetNew(DateField.MINUTE, minCloseMinute);
}
} else {
//反向拆分
for (int i2 = 1; i2 <= div; i2++) {
DateTime openTimeNew;
if (duration >= maxOpenMinute) {
sumOpenTime += maxOpenMinute;
openTimeNew = closeTime.offsetNew(DateField.MINUTE, -maxOpenMinute);
duration = duration - maxOpenMinute - minCloseMinute;
} else if (duration >= minOpenMinute) {
sumOpenTime += duration;
openTimeNew = closeTime.offsetNew(DateField.MINUTE, -(int) duration);
duration = -minCloseMinute;
} else {
//时间不够,舍弃
continue;
}
optimizeDurationDTOList.add(SpaceOptimizeDurationDTO.builder()
.openTime(openTimeNew)
.closeTime(closeTime)
.build());
//下次启动时间为本次关井时间向后移动最小关井时间
closeTime = openTimeNew.offsetNew(DateField.MINUTE, -minCloseMinute);
}
}
} else {
//不满足,取全部
optimizeDurationDTOList.add(SpaceOptimizeDurationDTO.builder()
.openTime(openTime)
.closeTime(closeTime)
.build());
sumOpenTime += duration;
}
//判断开井总时间是否大于每日最大开井时间
if (sumOpenTime >= dayOpenMinute) {
long outdo = sumOpenTime - dayOpenMinute;
if (outdo > 0) {
SpaceOptimizeDurationDTO durationDTO = optimizeDurationDTOList.get(optimizeDurationDTOList.size() - 1);
if (forwardFlag) {
DateTime closeTimeNew = DateUtil.offsetMinute(durationDTO.getCloseTime(), (int) -outdo);
int compare = closeTimeNew.compareTo(durationDTO.getOpenTime());
if (compare <= 0) {
optimizeDurationDTOList.remove(optimizeDurationDTOList.size() - 1);
sumOpenTime -= outdo;
} else {
if (DateUtil.between(durationDTO.getOpenTime(), closeTimeNew, DateUnit.MINUTE) < minOpenMinute) {
//如果缩短后时间间隔不满足最小开井时长则删除
sumOpenTime -= DateUtil.between(durationDTO.getOpenTime(), durationDTO.getCloseTime(), DateUnit.MINUTE);
optimizeDurationDTOList.remove(optimizeDurationDTOList.size() - 1);
} else {
//需要补时间,下面统一补
durationDTO.setCloseTime(closeTimeNew);
}
}
} else {
DateTime openTimeNew = DateUtil.offsetMinute(durationDTO.getOpenTime(), (int) outdo);
int compare = openTimeNew.compareTo(durationDTO.getCloseTime());
if (compare >= 0) {
optimizeDurationDTOList.remove(optimizeDurationDTOList.size() - 1);
sumOpenTime -= outdo;
} else {
if (DateUtil.between(openTimeNew, durationDTO.getCloseTime(), DateUnit.MINUTE) < minOpenMinute) {
//如果缩短后时间间隔不满足最小开井时长则删除
sumOpenTime -= DateUtil.between(durationDTO.getOpenTime(), durationDTO.getCloseTime(), DateUnit.MINUTE);
optimizeDurationDTOList.remove(optimizeDurationDTOList.size() - 1);
} else {
//需要补时间,下面统一补
durationDTO.setOpenTime(openTimeNew);
}
}
}
}
break;
/* //结束循环 [第一次开井时间优化]
breakFlag = true;*/
}
//重新按开井时间排序
optimizeDurationDTOList.sort(Comparator.comparing(SpaceOptimizeDurationDTO::getOpenTime));
/* //判断第一次开井时间 [第一次开井时间优化]
if (breakFlag || i1 == (weightDurationList.size() - 1)) {
Date checkOpenTime = optimizeDurationDTOList.get(0).getOpenTime();
int check = firstOpenWellTime.compareTo(checkOpenTime);
if (check > 0) {
//如果第一次开井时间大于当前开井时间,修改第一次开井时间
firstOpenWellTime = DateUtil.date(checkOpenTime);
if (breakFlag) {
break;
}
} else if (check == 0) {
if (againFlag) {
break;
}
againFlag = true;
if (0 == i) {
//第一口井跳过
continue;
}
//如果第一次开井时间等于当前开井时间,重置优化结果,偏移启动间隔,重新计算
SpaceOptimizeWeightDuration spaceOptimizeWeightDuration = weightDurationList.get(0);
spaceOptimizeWeightDuration.setOpenTime(
DateUtil.offsetMinute(spaceOptimizeWeightDuration.getOpenTime(), offset)
);
spaceOptimizeWeightDuration.setDuration(
spaceOptimizeWeightDuration.getDuration() - offset
);
offset += detail.getStartInterval();
//信息重置
i1 = -1;
sumOpenTime = 0;
optimizeDurationDTOList = new ArrayList<>(12);
breakFlag = false;
} else {
break;
}
}*/
//记录上一次第一次开井时间
if (0 == i1) {
firstOpenWellTime = DateUtil.date(optimizeDurationDTOList.get(0).getOpenTime());
}
}
//判断是否需要补时间
if (sumOpenTime < dayOpenMinute) {
//创建需要补时间的时间范围
List<SpaceOptimizeWeightDuration> replenishList = new ArrayList<>(12);
//得到开始时间时间戳
DateTime beginTime = weightList.get(0).getTimestamp();
for (int i1 = 0; i1 < optimizeDurationDTOList.size() - 1; i1++) {
//取相邻两段时间
SpaceOptimizeDurationDTO first = optimizeDurationDTOList.get(i1);
SpaceOptimizeDurationDTO second = optimizeDurationDTOList.get(i1 + 1);
Date firstOpenTime = first.getOpenTime();
Date firstCloseTime = first.getCloseTime();
Date secondOpenTime = second.getOpenTime();
Date secondCloseTime = second.getCloseTime();
long closeMinute = DateUtil.between(firstCloseTime, secondOpenTime, DateUnit.MINUTE);
//判断关井时长是否满足条件
if (closeMinute == minCloseMinute) {
continue;
}
//计算可优化时长
int optimizeMinute = (int) (closeMinute - minCloseMinute);
//判断是否小于最大开井时长
long firstOpenMinute = DateUtil.between(firstOpenTime, firstCloseTime, DateUnit.MINUTE);
if (firstOpenMinute < maxOpenMinute) {
//找索引开始/结束位置
int firstBeginIndex = (int) DateUtil.between(beginTime, firstCloseTime, DateUnit.MINUTE) / 30;
int firstEndIndex = (int) DateUtil.between(beginTime, DateUtil.offsetMinute(firstCloseTime, optimizeMinute), DateUnit.MINUTE) / 30;
//累加权重
int weightSum = 0;
int endIndex = firstBeginIndex;
//取时间段
SpaceOptimizeWeight optimizeWeight;
//从前往后推
for (int i2 = firstBeginIndex; i2 <= firstEndIndex; i2++) {
optimizeWeight = weightList.get(i2);
if (0 == optimizeWeight.getWeight()) {
break;
}
weightSum += optimizeWeight.getWeight();
endIndex = i2;
}
//添加优化区间
if (endIndex > firstBeginIndex) {
replenishList.add(
SpaceOptimizeWeightDuration.builder()
.openIndex(firstBeginIndex)
.closeIndex(endIndex)
.weight(weightSum)
.optimizeIndex(i1)
.build()
);
}
}
/*---------------------------- 计算下一段 -------------------------------*/
long secondOpenMinute = DateUtil.between(secondOpenTime, secondCloseTime, DateUnit.MINUTE);
if (secondOpenMinute < maxOpenMinute) {
//找索引开始/结束位置
int secondBeginIndex = (int) DateUtil.between(beginTime, DateUtil.offsetMinute(secondOpenTime, -optimizeMinute), DateUnit.MINUTE) / 30;
int secondEndIndex = (int) DateUtil.between(beginTime, secondOpenTime, DateUnit.MINUTE) / 30;
//累加权重
int weightSum = 0;
int beginIndex = secondEndIndex;
//取时间段
SpaceOptimizeWeight optimizeWeight;
//从后往前推
for (int i2 = secondEndIndex; i2 > secondBeginIndex; i2--) {
optimizeWeight = weightList.get(i2);
if (0 == optimizeWeight.getWeight()) {
break;
}
weightSum += optimizeWeight.getWeight();
beginIndex = i2;
}
//添加优化区间
if (beginIndex < secondEndIndex) {
replenishList.add(
SpaceOptimizeWeightDuration.builder()
.openIndex(beginIndex)
.closeIndex(secondEndIndex)
.weight(weightSum)
.optimizeIndex(i1 + 1)
.build()
);
}
}
}
//按权重优先级排序补时间
if (CollUtil.isNotEmpty(replenishList)) {
//计算需要补的时长
long subMinute = dayOpenMinute - sumOpenTime;
//按照权重降序排序
replenishList.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
//遍历,补时间
for (SpaceOptimizeWeightDuration replenish : replenishList) {
if (subMinute <= 0) {
break;
}
//取需要优化的时间段
SpaceOptimizeDurationDTO durationDTO = optimizeDurationDTOList.get(replenish.getOptimizeIndex());
//计算剩余可开井时长
long remainOpenMinute = maxOpenMinute - DateUtil.between(durationDTO.getOpenTime(), durationDTO.getCloseTime(), DateUnit.MINUTE);
//取可优化时间段
DateTime startTime = weightList.get(replenish.getOpenIndex()).getTimestamp();
DateTime endTime = weightList.get(replenish.getCloseIndex()).getTimestamp();
//计算可优化时间
long replenishDuration = DateUtil.between(startTime, endTime, DateUnit.MINUTE);
//判断是否可以满足全部优化
if (replenishDuration >= subMinute) {
//可开井时间大于等于需要优化时长
if (remainOpenMinute >= subMinute) {
this.overtime(durationDTO, endTime, (int) subMinute);
break;
} else {
this.overtime(durationDTO, endTime, (int) remainOpenMinute);
subMinute -= remainOpenMinute;
}
} else {
//可开井时间大于等于可优化时长
if (remainOpenMinute >= replenishDuration) {
this.overtime(durationDTO, endTime, (int) replenishDuration);
subMinute -= replenishDuration;
} else {
this.overtime(durationDTO, endTime, (int) remainOpenMinute);
subMinute -= remainOpenMinute;
}
}
}
} else {
//todo : 没法补时间
}
}
return firstOpenWellTime;
}
/**
* 添加优化结果
*
* @param optimizeDurationDTOList 优化工期dtolist
* @param durationDTOList 持续时间dtolist
* @param tundraStrategyList 苔原战略清单
* @param periodId 期间id
* @param recordId 记录id
* @param wellheadId 井口id
* @param startDate 开始日期
*/
private void addOptimizeDuration(List<SpaceOptimizeDurationDTO> optimizeDurationDTOList, List<SpaceOptimizeDurationDTO> durationDTOList, List<SpaceOptimizeDurationDTO> tundraStrategyList,
String periodId, String recordId, String wellheadId, DateTime startDate) {
if (CollUtil.isNotEmpty(optimizeDurationDTOList)) {
//重新按开井时间排序
optimizeDurationDTOList.sort(Comparator.comparing(SpaceOptimizeDurationDTO::getOpenTime));
SpaceOptimizeDurationDTO durationDTO;
for (int i1 = 0; i1 < optimizeDurationDTOList.size(); i1++) {
durationDTO = optimizeDurationDTOList.get(i1);
DateTime startOffset = DateUtil.date(durationDTO.getOpenTime());
DateTime endOffset = DateUtil.date(durationDTO.getCloseTime());
if (startOffset.compareTo(BusinessConstant.DATE_FLAG) < 0 && endOffset.compareTo(BusinessConstant.DATE_FLAG) > 0) {
//如果时间超过当天,舍弃
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
startOffset.toString(BusinessConstant.MINUTES_FORMAT),
BusinessConstant.END_OF_DAY_TIME,
BusinessConstant.ONE, startDate
);
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
BusinessConstant.START_OF_DAY_TIME,
endOffset.toString(BusinessConstant.MINUTES_FORMAT),
BusinessConstant.ONE, startDate
);
tundraStrategyList.add(
SpaceOptimizeDurationDTO.builder()
.wellheadId(wellheadId)
.openTime(startOffset)
.closeTime(BusinessConstant.DATE_FLAG)
.build()
);
tundraStrategyList.add(
SpaceOptimizeDurationDTO.builder()
.wellheadId(wellheadId)
.openTime(BusinessConstant.DATE_FLAG_BEGIN)
.closeTime(endOffset)
.build()
);
} else if (endOffset.compareTo(BusinessConstant.DATE_FLAG) == 0) {
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
startOffset.toString(BusinessConstant.MINUTES_FORMAT),
BusinessConstant.END_OF_DAY_TIME,
BusinessConstant.ONE, startDate
);
tundraStrategyList.add(
SpaceOptimizeDurationDTO.builder()
.wellheadId(wellheadId)
.openTime(startOffset)
.closeTime(BusinessConstant.DATE_FLAG)
.build()
);
} else {
//计算偏移
this.createOptimizeDuration(durationDTOList, periodId, recordId, wellheadId, null,
startOffset.toString(BusinessConstant.MINUTES_FORMAT),
endOffset.toString(BusinessConstant.MINUTES_FORMAT),
BusinessConstant.ONE, startDate
);
tundraStrategyList.add(
SpaceOptimizeDurationDTO.builder()
.wellheadId(wellheadId)
.openTime(startOffset)
.closeTime(endOffset)
.build()
);
}
}
}
}
}
\ 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