Commit 2d669ebf authored by ZWT's avatar ZWT

feat(零碳): 长庆

1.修改极短期间开预测定时任务逻辑,解决优化后部分优化结果时间段过短问题;
2.修改心知天气气象数据获取及接收定时任务,解决天气数据通过邮件下载后,部分数据精度丢失问题;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent f4bb3ff8
......@@ -247,394 +247,16 @@ public class SpaceOptimizeShortPeriodService extends SpaceOptimizeBaseService {
serviceRating = serviceRating.add(wellhead.getServiceRating());
//计算权重
List<SpaceOptimizeWeight> weightList = this.calculateWeightList(serviceRating, rangeToList, powerList, strategyList);
//每日开井时长
int dayOpenMinute = wellhead.getRunDuration()
.multiply(BusinessConstant.SIXTY)
.intValue();
//每日最小开井时长(分钟)
int minOpenMinute = wellhead.getMinOpen()
.multiply(BusinessConstant.SIXTY)
.intValue();
//每日最大开井时长(分钟)
int maxOpenMinute = wellhead.getMaxOpen()
.multiply(BusinessConstant.SIXTY)
.intValue();
//每日最小关井时长(分钟)
int minCloseMinute = wellhead.getMinClose()
.multiply(BusinessConstant.SIXTY)
.intValue();
//每日最大关井时长(分钟)
int maxCloseMinute = wellhead.getMaxClose()
.multiply(BusinessConstant.SIXTY)
.intValue();
SpaceOptimizeWeight weight;
//分级取时间段
List<SpaceOptimizeWeightDuration> weightDurationList = this.weightListProcessing(ladder, weightList, minOpenMinute);
//时间段优化
List<SpaceOptimizeDurationDTO> optimizeDurationDTOList = new ArrayList<>(12);
//总开井时间
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 (0 == i && 0 == i1) {
firstOpenWellTime = weightDuration.getOpenTime();
}
//偏移其他井口开井时间,并修改时间间隔
if (0 == openTime.compareTo(firstOpenWellTime) && i > 0 && 0 == i1) {
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 += minOpenMinute;
closeTimeNew = openTime.offsetNew(DateField.MINUTE, minOpenMinute);
duration = duration - minOpenMinute - 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 += minOpenMinute;
openTimeNew = closeTime.offsetNew(DateField.MINUTE, -minOpenMinute);
duration = duration - minOpenMinute - 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 (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 : 没法补时间
}
}
firstOpenWellTime = this.timePeriodOptimization(optimizeDurationDTOList, weightDurationList, firstOpenWellTime, i,
startInterval, minOpenMinute, wellhead, weightList);
//创建优化后的间开区间
if (CollUtil.isNotEmpty(optimizeDurationDTOList)) {
//重新按开井时间排序
......@@ -803,6 +425,9 @@ public class SpaceOptimizeShortPeriodService extends SpaceOptimizeBaseService {
} else {
//todo 不需要补时间,需要优化计算
List<SpaceOptimizeDurationDTO> optimizeDurationDTOList = new ArrayList<>(12);
this.timePeriodOptimization(optimizeDurationDTOList, weightDurationList, firstOpenWellTime, wellheadList.size(),
startInterval, minOpenMinute, tundraStrategyWellhead, weightList);
}
System.out.println();
}
......@@ -853,6 +478,404 @@ public class SpaceOptimizeShortPeriodService extends SpaceOptimizeBaseService {
}
/**
* 时间段优化
*
* @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.SIXTY)
.intValue();
//每日最大开井时长(分钟)
int maxOpenMinute = wellhead.getMaxOpen()
.multiply(BusinessConstant.SIXTY)
.intValue();
//每日最小关井时长(分钟)
int minCloseMinute = wellhead.getMinClose()
.multiply(BusinessConstant.SIXTY)
.intValue();
//每日最大关井时长(分钟)
int maxCloseMinute = wellhead.getMaxClose()
.multiply(BusinessConstant.SIXTY)
.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 (0 == i && 0 == i1) {
firstOpenWellTime = weightDuration.getOpenTime();
}
//偏移其他井口开井时间,并修改时间间隔
if (0 == openTime.compareTo(firstOpenWellTime) && i > 0 && 0 == i1) {
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 += minOpenMinute;
closeTimeNew = openTime.offsetNew(DateField.MINUTE, minOpenMinute);
duration = duration - minOpenMinute - 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 += minOpenMinute;
openTimeNew = closeTime.offsetNew(DateField.MINUTE, -minOpenMinute);
duration = duration - minOpenMinute - 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 (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;
}
/**
* 计算权重列表
*
......
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