洪水-调度演算
parent
accdfb627a
commit
c43f3f16af
|
|
@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.gunshi.core.result.R;
|
import com.gunshi.core.result.R;
|
||||||
|
import com.gunshi.project.ss.entity.dto.DispatchResultDto;
|
||||||
import com.gunshi.project.ss.entity.vo.ForecastResultVo;
|
import com.gunshi.project.ss.entity.vo.ForecastResultVo;
|
||||||
import com.gunshi.project.ss.model.*;
|
import com.gunshi.project.ss.model.*;
|
||||||
import com.gunshi.project.ss.service.ForecastProjectService;
|
import com.gunshi.project.ss.service.ForecastProjectService;
|
||||||
|
|
@ -146,16 +147,16 @@ public class ForecastProjectController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "调度计算-闸门开放关闭时间")
|
@Operation(summary = "调度计算-闸门开放关闭时间")
|
||||||
@GetMapping("/caculate/{waterLevel}")
|
@GetMapping("/caculate/{id}/{waterLevel}")
|
||||||
public R<List<ForecastDispatchCommand>> caculate(@PathVariable("waterLevel") String waterLevel) {
|
public R<List<ForecastDispatchCommand>> caculate(@PathVariable("id") String id,@PathVariable("waterLevel") String waterLevel) {
|
||||||
List<ForecastDispatchCommand> res = service.caculate(waterLevel);
|
List<ForecastDispatchCommand> res = service.caculate(id,waterLevel);
|
||||||
return R.ok(res);
|
return R.ok(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "调度计算-调度结果")
|
@Operation(summary = "调度计算-调度结果")
|
||||||
@GetMapping("/dispatch/result")
|
@PostMapping("/dispatch/result")
|
||||||
public R<ForecastDispatchResult> getDispatchResult(){
|
public R<ForecastDispatchResult> getDispatchResult(@RequestBody DispatchResultDto dto){
|
||||||
ForecastDispatchResult result = service.getDispatchResult();
|
ForecastDispatchResult result = service.getDispatchResult(dto);
|
||||||
return R.ok(result);
|
return R.ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.gunshi.project.ss.entity.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import com.gunshi.db.dto.DateTimeRangeSo;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DispatchResultDto {
|
||||||
|
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
private DateTimeRangeSo dateTimeRangeSo;
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
package com.gunshi.project.ss.service;
|
package com.gunshi.project.ss.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.gunshi.db.dto.DateTimeRangeSo;
|
||||||
import com.gunshi.project.ss.common.util.LocalDateTimeConverter;
|
import com.gunshi.project.ss.common.util.LocalDateTimeConverter;
|
||||||
import com.gunshi.project.ss.entity.TimeCapacity;
|
import com.gunshi.project.ss.entity.TimeCapacity;
|
||||||
import com.gunshi.project.ss.entity.TimeNetWater;
|
import com.gunshi.project.ss.entity.TimeNetWater;
|
||||||
|
import com.gunshi.project.ss.entity.dto.DispatchResultDto;
|
||||||
import com.gunshi.project.ss.entity.vo.ForecastResultVo;
|
import com.gunshi.project.ss.entity.vo.ForecastResultVo;
|
||||||
import com.gunshi.project.ss.mapper.ForecastProjectMapper;
|
import com.gunshi.project.ss.mapper.ForecastProjectMapper;
|
||||||
import com.gunshi.project.ss.model.*;
|
import com.gunshi.project.ss.model.*;
|
||||||
|
import com.gunshi.project.ss.service.AttResBaseService;
|
||||||
|
import com.gunshi.project.ss.service.ForecastResultsService;
|
||||||
|
import com.gunshi.project.ss.service.ForecastUseparamService;
|
||||||
|
import com.gunshi.project.ss.service.StZvarlBService;
|
||||||
import com.itextpdf.io.font.PdfEncodings;
|
import com.itextpdf.io.font.PdfEncodings;
|
||||||
import com.itextpdf.kernel.colors.DeviceRgb;
|
import com.itextpdf.kernel.colors.DeviceRgb;
|
||||||
import com.itextpdf.kernel.events.Event;
|
import com.itextpdf.kernel.events.Event;
|
||||||
|
|
@ -41,7 +48,6 @@ import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeFormatterBuilder;
|
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -167,29 +173,15 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ForecastDispatchCommand> caculate(String rz) {
|
public List<ForecastDispatchCommand> caculate(String id, String rz) {
|
||||||
BigDecimal openDoorFlow = new BigDecimal(5);//开闸门放水流量 5立方米/秒
|
BigDecimal openDoorFlow = new BigDecimal("5");//开闸门放水流量 5立方米/秒
|
||||||
|
ForecastProject forecastProjectResults = getForecastProjectResults(id);
|
||||||
ForecastTask forecastTask = new ForecastTask();
|
List<ForecastResultVo> humanForecastResult = forecastProjectResults.getVoList();
|
||||||
// 设置当前时间整点
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
LocalDateTime nowHour = now.withMinute(0).withSecond(0).withNano(0);
|
|
||||||
forecastTask.setNowTime(LocalDateTimeConverter.toDate(nowHour));
|
|
||||||
|
|
||||||
// 设置开始时间(当前时间减去一天)
|
|
||||||
LocalDateTime startTime = nowHour.minusDays(1);
|
|
||||||
forecastTask.setStartTime(LocalDateTimeConverter.toDate(startTime));
|
|
||||||
|
|
||||||
// 设置结束时间(当前时间加上durationHours)
|
|
||||||
LocalDateTime endTime = nowHour.plusHours(24);
|
|
||||||
forecastTask.setEndTime(LocalDateTimeConverter.toDate(endTime));
|
|
||||||
|
|
||||||
forecastTask.setForecastWarm(1);
|
|
||||||
forecastTask.setForecastPeriod(24); // 设置预报时长
|
|
||||||
List<ForecastResultVo> humanForecastResult = forecastResultsService.getHumanForecastResult(forecastTask);
|
|
||||||
if(humanForecastResult.isEmpty()){
|
if(humanForecastResult.isEmpty()){
|
||||||
throw new IllegalArgumentException("对不起,暂无预报数据");
|
throw new IllegalArgumentException("对不起,暂无预报数据");
|
||||||
}
|
}
|
||||||
|
Date forecastTm = forecastProjectResults.getForecastTm();
|
||||||
|
LocalDateTime nowHour = LocalDateTimeConverter.fromDate(forecastTm);
|
||||||
//过滤出大于等于nowHour的数据
|
//过滤出大于等于nowHour的数据
|
||||||
// 获取当前时间的格式化字符串(与tm格式一致)
|
// 获取当前时间的格式化字符串(与tm格式一致)
|
||||||
String nowHourStr = nowHour.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
String nowHourStr = nowHour.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
@ -203,17 +195,25 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
return vo.getTm().compareTo(nowHourStr) >= 0;
|
return vo.getTm().compareTo(nowHourStr) >= 0;
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
// filteredResults.stream().forEach(o ->{
|
|
||||||
// o.setYcRkQValue(new BigDecimal("10"));
|
|
||||||
// o.setYcCkQValue(new BigDecimal("0"));
|
|
||||||
// });
|
|
||||||
ForecastResultVo forecastResultVo = filteredResults.get(0);//a点
|
ForecastResultVo forecastResultVo = filteredResults.get(0);//a点
|
||||||
//b点为filteredResults的最后一条数据
|
//b点为filteredResults的最后一条数据
|
||||||
//c点为waterLevel
|
//c点为waterLevel
|
||||||
BigDecimal waterLevel = new BigDecimal(rz);//c点
|
BigDecimal waterLevel = new BigDecimal(rz);//c点
|
||||||
LocalDateTime start = null;
|
LocalDateTime start = null;
|
||||||
LocalDateTime end = null;
|
LocalDateTime end = null;
|
||||||
List<StZvarlB> stZvarlBList = stZvarlBService.list();
|
List<StZvarlB> stZvarlBList = stZvarlBService.lambdaQuery()
|
||||||
|
.orderByAsc(StZvarlB::getRz)
|
||||||
|
.list();
|
||||||
|
if(rz != null){
|
||||||
|
BigDecimal minRZ = stZvarlBList.get(0).getRz();
|
||||||
|
BigDecimal maxRZ = stZvarlBList.get(stZvarlBList.size() - 1).getRz();
|
||||||
|
BigDecimal curRZ = new BigDecimal(rz);
|
||||||
|
if(curRZ.compareTo(minRZ) < 0){
|
||||||
|
throw new IllegalArgumentException("对不起,水位控制值小于了库容曲线的最小值");
|
||||||
|
}else if(curRZ.compareTo(maxRZ) > 0){
|
||||||
|
throw new IllegalArgumentException("对不起,水位控制值大于了库容曲线的最大值");
|
||||||
|
}
|
||||||
|
}
|
||||||
// 获取配置参数
|
// 获取配置参数
|
||||||
List<ForecastUseparam> paramList = forecastUseparamService.list(new QueryWrapper<ForecastUseparam>().isNotNull("param_code").isNotNull("param_value"));
|
List<ForecastUseparam> paramList = forecastUseparamService.list(new QueryWrapper<ForecastUseparam>().isNotNull("param_code").isNotNull("param_value"));
|
||||||
if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(paramList)) {
|
if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(paramList)) {
|
||||||
|
|
@ -231,8 +231,10 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
timeInterval = new BigDecimal("3600");
|
timeInterval = new BigDecimal("3600");
|
||||||
}
|
}
|
||||||
if(forecastResultVo.getYcSwHValue().compareTo(waterLevel) > 0){
|
if(forecastResultVo.getYcSwHValue().compareTo(waterLevel) > 0){
|
||||||
|
log.info("实际水位大于输入水位哦");
|
||||||
//如果实际水位已经大于了输入的水位的话,那么闸门开门时间就设置为当前时间
|
//如果实际水位已经大于了输入的水位的话,那么闸门开门时间就设置为当前时间
|
||||||
start = nowHour;//
|
start = nowHour;//
|
||||||
|
log.info("开始时间为{}",start);
|
||||||
//计算闸门关门时间
|
//计算闸门关门时间
|
||||||
//计算a点库容
|
//计算a点库容
|
||||||
//库容单位 万m³
|
//库容单位 万m³
|
||||||
|
|
@ -298,6 +300,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(dTime == null){
|
if(dTime == null){
|
||||||
|
log.info("dTime is null");
|
||||||
//如果a~b之间不存在d点,则闸门关闭时间 = a时间点 + [(a~b之间净入库水量) + (aSubC)] /5(先精确时分秒,向上取整,再精确到时分)
|
//如果a~b之间不存在d点,则闸门关闭时间 = a时间点 + [(a~b之间净入库水量) + (aSubC)] /5(先精确时分秒,向上取整,再精确到时分)
|
||||||
//计算净入库水量
|
//计算净入库水量
|
||||||
BigDecimal pureRKWater = BigDecimal.ZERO;//净入库水量
|
BigDecimal pureRKWater = BigDecimal.ZERO;//净入库水量
|
||||||
|
|
@ -311,20 +314,21 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
// aSubC是万m³,需要转换为m³
|
// aSubC是万m³,需要转换为m³
|
||||||
BigDecimal aSubCInM3 = aSubC.multiply(new BigDecimal("10000")); // 转换为m³
|
BigDecimal aSubCInM3 = aSubC.multiply(new BigDecimal("10000")); // 转换为m³
|
||||||
|
log.info("aSubCinM3 {}",aSubCInM3);
|
||||||
// 计算公式:[(a~b之间净入库水量) + (aSubC)] / 5
|
// 计算公式:[(a~b之间净入库水量) + (aSubC)] / 5
|
||||||
// pureRKWater单位已经是m³(因为timeInterval是秒,流量是m³/s)
|
// pureRKWater单位已经是m³(因为timeInterval是秒,流量是m³/s)
|
||||||
BigDecimal totalWater = pureRKWater.add(aSubCInM3); // 总水量 = 净入库水量 + aSubC转换后的水量
|
BigDecimal totalWater = pureRKWater.add(aSubCInM3); // 总水量 = 净入库水量 + aSubC转换后的水量
|
||||||
|
|
||||||
// 除以5(开闸门放水流量5立方米/秒)
|
// 除以5(开闸门放水流量5立方米/秒)
|
||||||
BigDecimal timeSeconds = totalWater.divide(openDoorFlow, 10, BigDecimal.ROUND_HALF_UP);
|
BigDecimal timeSeconds = totalWater.divide(openDoorFlow, 10, BigDecimal.ROUND_HALF_UP);
|
||||||
|
log.info("时间差{}",timeSeconds.toString());
|
||||||
// 先精确时分秒,向上取整
|
// 先精确时分秒,向上取整
|
||||||
long timeSecondsLong = timeSeconds.setScale(0, BigDecimal.ROUND_UP).longValue();
|
long timeSecondsLong = timeSeconds.setScale(0, BigDecimal.ROUND_UP).longValue();
|
||||||
|
|
||||||
// 计算闸门关闭时间 = a时间点 + 计算出的时间
|
// 计算闸门关闭时间 = a时间点 + 计算出的时间
|
||||||
LocalDateTime aTime = LocalDateTime.parse(forecastResultVo.getTm(), formatter);
|
LocalDateTime aTime = LocalDateTime.parse(forecastResultVo.getTm(), formatter);
|
||||||
|
log.info("aTime {}",aTime);
|
||||||
LocalDateTime closeTime = aTime.plusSeconds(timeSecondsLong);
|
LocalDateTime closeTime = aTime.plusSeconds(timeSecondsLong);
|
||||||
|
log.info("closeTime {}",closeTime);
|
||||||
// 如果有秒数或者分钟数有小数部分(即秒数不为0),则分钟向上取整
|
// 如果有秒数或者分钟数有小数部分(即秒数不为0),则分钟向上取整
|
||||||
if (closeTime.getSecond() > 0) {
|
if (closeTime.getSecond() > 0) {
|
||||||
// 分钟加1
|
// 分钟加1
|
||||||
|
|
@ -333,7 +337,9 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
// 再精确到时分(分钟和秒设为0)
|
// 再精确到时分(分钟和秒设为0)
|
||||||
closeTime = closeTime.withSecond(0).withNano(0);
|
closeTime = closeTime.withSecond(0).withNano(0);
|
||||||
end = closeTime;
|
end = closeTime;
|
||||||
|
log.info("结束时间{}",end);
|
||||||
}else{
|
}else{
|
||||||
|
log.info("存在dTime{}",dTime);
|
||||||
/**
|
/**
|
||||||
* 如果存在d点
|
* 如果存在d点
|
||||||
* 那么从d点往前推算要求库容刚好<=c水位值对应的库容的具体时间点e【精确只时分,d点往前倒推时长的计算公式为(ps这个公式是用于计算e点的公式)
|
* 那么从d点往前推算要求库容刚好<=c水位值对应的库容的具体时间点e【精确只时分,d点往前倒推时长的计算公式为(ps这个公式是用于计算e点的公式)
|
||||||
|
|
@ -367,14 +373,11 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
BigDecimal dMinus1CkQ = dMinus1Vo.getYcCkQValue() != null ? dMinus1Vo.getYcCkQValue() : BigDecimal.ZERO;
|
BigDecimal dMinus1CkQ = dMinus1Vo.getYcCkQValue() != null ? dMinus1Vo.getYcCkQValue() : BigDecimal.ZERO;
|
||||||
// 计算:(d-1的出库流量 + 5 - d-1的入库流量)
|
// 计算:(d-1的出库流量 + 5 - d-1的入库流量)
|
||||||
BigDecimal flowRateDiff = dMinus1CkQ.add(openDoorFlow).subtract(dMinus1RkQ); // m³/s
|
BigDecimal flowRateDiff = dMinus1CkQ.add(openDoorFlow).subtract(dMinus1RkQ); // m³/s
|
||||||
// 防止除数为0或负数
|
|
||||||
// if (flowRateDiff.compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
// flowRateDiff = new BigDecimal("0.001"); // 设置一个很小的正数
|
|
||||||
// }
|
|
||||||
// 计算往前倒推的时长:(c水位值对应的库容 - d点库容) / (d-1的出库流量 + 5 - d-1的入库流量)
|
// 计算往前倒推的时长:(c水位值对应的库容 - d点库容) / (d-1的出库流量 + 5 - d-1的入库流量)
|
||||||
BigDecimal backwardSeconds = capacityDiffInM3.divide(flowRateDiff, 10, BigDecimal.ROUND_HALF_UP);
|
BigDecimal backwardSeconds = capacityDiffInM3.divide(flowRateDiff, 10, BigDecimal.ROUND_HALF_UP);
|
||||||
// 不进行四舍五入,若存在小数点则向下取整
|
// 转为分钟,向下取整,再转回秒
|
||||||
long backwardSecondsLong = backwardSeconds.setScale(0, BigDecimal.ROUND_DOWN).longValue();
|
long minutesLong = backwardSeconds.divide(new BigDecimal(60), 0, BigDecimal.ROUND_DOWN).longValue();
|
||||||
|
long backwardSecondsLong = minutesLong * 60;
|
||||||
// 计算e点时间 = d点时间 - 倒推时长
|
// 计算e点时间 = d点时间 - 倒推时长
|
||||||
LocalDateTime eTime = dTime.minusSeconds(backwardSecondsLong);
|
LocalDateTime eTime = dTime.minusSeconds(backwardSecondsLong);
|
||||||
// 检查e点是否在filteredResults集合中存在
|
// 检查e点是否在filteredResults集合中存在
|
||||||
|
|
@ -394,46 +397,41 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
// 2. 计算e~b之间的净入库水量f
|
// 2. 计算e~b之间的净入库水量f
|
||||||
BigDecimal f = BigDecimal.ZERO;
|
BigDecimal f = BigDecimal.ZERO;
|
||||||
|
|
||||||
// 找到e点在filteredResults中的索引
|
//找到eTime之后的第一个整点数据的索引
|
||||||
int eIndex = -1;
|
int firstWholeHourIndex = -1;
|
||||||
|
LocalDateTime firstWholeHourTime = null;
|
||||||
for (int i = 0; i < filteredResults.size(); i++) {
|
for (int i = 0; i < filteredResults.size(); i++) {
|
||||||
LocalDateTime voTime = LocalDateTime.parse(filteredResults.get(i).getTm(), formatter);
|
LocalDateTime voTime = LocalDateTime.parse(filteredResults.get(i).getTm(), formatter);
|
||||||
if (voTime.equals(eTime) || voTime.isBefore(eTime)) { // e点或之后的时间
|
// 找到第一个大于eTime的整点时间(比如eTime=18:48,找19:00)
|
||||||
eIndex = i;
|
if (voTime.isAfter(eTime) && voTime.getMinute() == 0 && voTime.getSecond() == 0) {
|
||||||
}else{
|
firstWholeHourIndex = i;
|
||||||
|
firstWholeHourTime = voTime;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 2.1 计算第一段:eTime 到 第一个整点(比如18:48 ~ 19:00)的净入库水量
|
||||||
|
// 获取第一个整点前的那条数据(18:00的数据,因为流量数据是按整点存储的)
|
||||||
|
ForecastResultVo preVo = filteredResults.get(firstWholeHourIndex - 1);
|
||||||
|
BigDecimal preRkQ = preVo.getYcRkQValue() != null ? preVo.getYcRkQValue() : BigDecimal.ZERO;
|
||||||
|
BigDecimal preCkQ = preVo.getYcCkQValue() != null ? preVo.getYcCkQValue() : BigDecimal.ZERO;
|
||||||
|
BigDecimal preGapQ = preRkQ.subtract(preCkQ);
|
||||||
|
|
||||||
if (eIndex == -1) {
|
// 计算eTime到第一个整点的时间间隔(分钟),向下取整
|
||||||
eIndex = 0; // 如果没找到,从第一个开始
|
long minutesDiffFirst = ChronoUnit.MINUTES.between(eTime, firstWholeHourTime);
|
||||||
}
|
// 累加第一段水量(分钟转为秒)
|
||||||
|
f = f.add(preGapQ.multiply(new BigDecimal(minutesDiffFirst * 60)));
|
||||||
|
|
||||||
// 计算e~b之间的净入库水量
|
// 2.2 计算第二段:第一个整点 到 后续数据的净入库水量(19:00~20:00, 20:00~21:00...)
|
||||||
for (int i = eIndex; i < filteredResults.size() - 1; i++) {
|
for (int i = firstWholeHourIndex; i < filteredResults.size() - 1; i++) {
|
||||||
ForecastResultVo currentVo = filteredResults.get(i);
|
ForecastResultVo currentVo = filteredResults.get(i);
|
||||||
BigDecimal ycRkQValue = currentVo.getYcRkQValue() != null ? currentVo.getYcRkQValue() : BigDecimal.ZERO;
|
BigDecimal currentRkQ = currentVo.getYcRkQValue() != null ? currentVo.getYcRkQValue() : BigDecimal.ZERO;
|
||||||
BigDecimal ycCkQValue = currentVo.getYcCkQValue() != null ? currentVo.getYcCkQValue() : BigDecimal.ZERO;
|
BigDecimal currentCkQ = currentVo.getYcCkQValue() != null ? currentVo.getYcCkQValue() : BigDecimal.ZERO;
|
||||||
|
BigDecimal currentGapQ = currentRkQ.subtract(currentCkQ);
|
||||||
|
|
||||||
// (入库流量 - 出库流量) * 时间间隔
|
// 整点间隔固定为timeInterval(比如1小时)
|
||||||
BigDecimal gapQValue = ycRkQValue.subtract(ycCkQValue);
|
BigDecimal timeSum = currentGapQ.multiply(timeInterval);
|
||||||
|
|
||||||
if (i == eIndex) {
|
|
||||||
// 对于eIndex处的数据,使用eTime与下一条数据的时间间隔
|
|
||||||
ForecastResultVo nextVo = filteredResults.get(i + 1);
|
|
||||||
LocalDateTime nextTime = LocalDateTime.parse(nextVo.getTm(), formatter);
|
|
||||||
|
|
||||||
// 计算eTime到nextTime的时间差(小时)
|
|
||||||
long minutesDiff = ChronoUnit.MINUTES.between(eTime, nextTime);
|
|
||||||
BigDecimal currentTimeInterval = BigDecimal.valueOf(minutesDiff).divide(BigDecimal.valueOf(60), 10, RoundingMode.HALF_UP);
|
|
||||||
|
|
||||||
BigDecimal timeSum = gapQValue.multiply(currentTimeInterval);
|
|
||||||
f = f.add(timeSum);
|
f = f.add(timeSum);
|
||||||
} else {
|
log.info("第" + i + "段水量(" + currentVo.getTm() + "~" + filteredResults.get(i+1).getTm() + "):" + currentGapQ + " * " + timeInterval + " = " + timeSum);
|
||||||
// 其他情况使用固定的timeInterval
|
|
||||||
BigDecimal timeSum = gapQValue.multiply(timeInterval);
|
|
||||||
f = f.add(timeSum);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 计算持续开闸时长g = f / 5
|
// 3. 计算持续开闸时长g = f / 5
|
||||||
|
|
@ -452,6 +450,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
closeTime = closeTime.withSecond(0).withNano(0);
|
closeTime = closeTime.withSecond(0).withNano(0);
|
||||||
end = closeTime;
|
end = closeTime;
|
||||||
|
log.info("关闭时间2",end);
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -474,7 +473,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
BigDecimal ycCkQValue = currentVo.getYcCkQValue() != null ? currentVo.getYcCkQValue() : BigDecimal.ZERO;
|
BigDecimal ycCkQValue = currentVo.getYcCkQValue() != null ? currentVo.getYcCkQValue() : BigDecimal.ZERO;
|
||||||
|
|
||||||
// (入库流量 - 出库流量) * 时间间隔
|
// (入库流量 - 出库流量) * 时间间隔
|
||||||
BigDecimal gapQValue = ycRkQValue.subtract(ycCkQValue).subtract(openDoorFlow);
|
BigDecimal gapQValue = ycRkQValue.subtract(ycCkQValue);
|
||||||
BigDecimal timeSum = gapQValue.multiply(timeInterval);
|
BigDecimal timeSum = gapQValue.multiply(timeInterval);
|
||||||
netInflow = netInflow.add(timeSum);
|
netInflow = netInflow.add(timeSum);
|
||||||
}
|
}
|
||||||
|
|
@ -514,7 +513,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
|
|
||||||
// 计算公式:Vt+1 = Vt + (预测入库流量 - 预测出库流量 - 5) * 时间间隔
|
// 计算公式:Vt+1 = Vt + (预测入库流量 - 预测出库流量 - 5) * 时间间隔
|
||||||
// 注意单位转换:流量是m³/s,库容是万m³,时间间隔是秒
|
// 注意单位转换:流量是m³/s,库容是万m³,时间间隔是秒
|
||||||
BigDecimal flowDiff = ycRkQValue.subtract(ycCkQValue).subtract(openDoorFlow); // m³/s
|
BigDecimal flowDiff = ycRkQValue.subtract(ycCkQValue); // m³/s
|
||||||
BigDecimal volumeChange = flowDiff.multiply(timeInterval); // m³
|
BigDecimal volumeChange = flowDiff.multiply(timeInterval); // m³
|
||||||
|
|
||||||
// 转换为万m³:1万m³ = 10000 m³
|
// 转换为万m³:1万m³ = 10000 m³
|
||||||
|
|
@ -548,6 +547,9 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(tTime == null){
|
||||||
|
tTime = timeCapacities.get(0).getTime();
|
||||||
|
}
|
||||||
if(tTime != null){
|
if(tTime != null){
|
||||||
//计算t0
|
//计算t0
|
||||||
BigDecimal tCapacity = timeCapacities.get(tIndex).getCapacity();
|
BigDecimal tCapacity = timeCapacities.get(tIndex).getCapacity();
|
||||||
|
|
@ -567,7 +569,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
BigDecimal tCkQ = tVo.getYcCkQValue() != null ? tVo.getYcCkQValue() : BigDecimal.ZERO;
|
BigDecimal tCkQ = tVo.getYcCkQValue() != null ? tVo.getYcCkQValue() : BigDecimal.ZERO;
|
||||||
|
|
||||||
// 计算流量差
|
// 计算流量差
|
||||||
BigDecimal flowRateDiff = tRkQ.subtract(tCkQ).subtract(openDoorFlow);
|
BigDecimal flowRateDiff = tRkQ.subtract(tCkQ);
|
||||||
|
|
||||||
// 计算t到t0的持续时长
|
// 计算t到t0的持续时长
|
||||||
BigDecimal durationSeconds = capacityDiffInM3.divide(flowRateDiff, 10, BigDecimal.ROUND_HALF_UP);
|
BigDecimal durationSeconds = capacityDiffInM3.divide(flowRateDiff, 10, BigDecimal.ROUND_HALF_UP);
|
||||||
|
|
@ -739,7 +741,8 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
BigDecimal dtSeconds = maxNetWater.divide(openDoorFlow, 10, BigDecimal.ROUND_HALF_UP);
|
BigDecimal dtSeconds = maxNetWater.divide(openDoorFlow, 10, BigDecimal.ROUND_HALF_UP);
|
||||||
|
|
||||||
// 向上取整
|
// 向上取整
|
||||||
long dtSecondsLong = dtSeconds.setScale(0, BigDecimal.ROUND_UP).longValue();
|
// 转为分钟,向上取整,再转为秒
|
||||||
|
long dtSecondsLong = dtSeconds.divide(new BigDecimal(60), 0, BigDecimal.ROUND_UP).longValue() * 60;
|
||||||
|
|
||||||
// 计算实际开闸时间j = t0 - dt
|
// 计算实际开闸时间j = t0 - dt
|
||||||
LocalDateTime jTime = t0Time.minusSeconds(dtSecondsLong);
|
LocalDateTime jTime = t0Time.minusSeconds(dtSecondsLong);
|
||||||
|
|
@ -927,24 +930,14 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
@Autowired
|
@Autowired
|
||||||
private AttResBaseService attResBaseService;
|
private AttResBaseService attResBaseService;
|
||||||
|
|
||||||
public ForecastDispatchResult getDispatchResult() {
|
public ForecastDispatchResult getDispatchResult(DispatchResultDto dto) {
|
||||||
ForecastTask forecastTask = new ForecastTask();
|
ForecastProject forecastProjectResults = getForecastProjectResults(dto.getProjectId());
|
||||||
// 设置当前时间整点
|
List<ForecastResultVo> humanForecastResult = forecastProjectResults.getVoList();
|
||||||
LocalDateTime now = LocalDateTime.now();
|
if(humanForecastResult.isEmpty()){
|
||||||
LocalDateTime nowHour = now.withMinute(0).withSecond(0).withNano(0);
|
throw new IllegalArgumentException("对不起,暂无预报数据");
|
||||||
forecastTask.setNowTime(LocalDateTimeConverter.toDate(nowHour));
|
}
|
||||||
|
Date forecastTm = forecastProjectResults.getForecastTm();
|
||||||
// 设置开始时间(当前时间减去一天)
|
LocalDateTime nowHour = LocalDateTimeConverter.fromDate(forecastTm);
|
||||||
LocalDateTime startTime = nowHour.minusDays(1);
|
|
||||||
forecastTask.setStartTime(LocalDateTimeConverter.toDate(startTime));
|
|
||||||
|
|
||||||
// 设置结束时间(当前时间加上durationHours)
|
|
||||||
LocalDateTime endTime = nowHour.plusHours(24);
|
|
||||||
forecastTask.setEndTime(LocalDateTimeConverter.toDate(endTime));
|
|
||||||
|
|
||||||
forecastTask.setForecastWarm(1);
|
|
||||||
forecastTask.setForecastPeriod(24); // 设置预报时长
|
|
||||||
List<ForecastResultVo> humanForecastResult = forecastResultsService.getHumanForecastResult(forecastTask);
|
|
||||||
//过滤出大于等于nowHour的数据
|
//过滤出大于等于nowHour的数据
|
||||||
// 获取当前时间的格式化字符串(与tm格式一致)
|
// 获取当前时间的格式化字符串(与tm格式一致)
|
||||||
String nowHourStr = nowHour.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
String nowHourStr = nowHour.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
@ -979,13 +972,6 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
LocalDateTime maxRKDate = null;
|
LocalDateTime maxRKDate = null;
|
||||||
BigDecimal totalRKWater = BigDecimal.ZERO;
|
BigDecimal totalRKWater = BigDecimal.ZERO;
|
||||||
BigDecimal totalCKWater = BigDecimal.ZERO;
|
BigDecimal totalCKWater = BigDecimal.ZERO;
|
||||||
BigDecimal maxRz = BigDecimal.ZERO;
|
|
||||||
LocalDateTime maxRzDate = null;
|
|
||||||
BigDecimal overLimit = BigDecimal.ZERO;
|
|
||||||
LocalDateTime start = null;
|
|
||||||
LocalDateTime end = null;
|
|
||||||
AttResBase attResBase = attResBaseService.list().get(0);
|
|
||||||
BigDecimal flLowLimLev = attResBase.getFlLowLimLev();//汛限水位
|
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
for (int i = 0; i < filteredResults.size(); i++) {
|
for (int i = 0; i < filteredResults.size(); i++) {
|
||||||
ForecastResultVo vo = filteredResults.get(i);
|
ForecastResultVo vo = filteredResults.get(i);
|
||||||
|
|
@ -993,60 +979,68 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
//计算总入库水量和总出库水量
|
//计算总入库水量和总出库水量
|
||||||
BigDecimal ycRkQValue = vo.getYcRkQValue();
|
BigDecimal ycRkQValue = vo.getYcRkQValue();
|
||||||
BigDecimal ycCkQValue = vo.getYcCkQValue();
|
BigDecimal ycCkQValue = vo.getYcCkQValue();
|
||||||
ycRkQValue = ycRkQValue.multiply(timeInterval).divide(new BigDecimal("10000")).setScale(2, BigDecimal.ROUND_HALF_UP);
|
ycRkQValue = ycRkQValue.multiply(timeInterval);
|
||||||
totalRKWater = totalRKWater.add(ycRkQValue);
|
totalRKWater = totalRKWater.add(ycRkQValue);
|
||||||
ycCkQValue = ycCkQValue.multiply(timeInterval).divide(new BigDecimal("10000")).setScale(2, BigDecimal.ROUND_HALF_UP);
|
ycCkQValue = ycCkQValue.multiply(timeInterval);
|
||||||
totalCKWater = totalCKWater.add(ycCkQValue);
|
totalCKWater = totalCKWater.add(ycCkQValue);
|
||||||
}
|
}
|
||||||
//最高库水位
|
|
||||||
if(vo.getYcSwHValue().compareTo(maxRz) > 0){
|
|
||||||
maxRz = vo.getYcSwHValue();
|
|
||||||
maxRzDate = LocalDateTime.parse(vo.getTm(),formatter);
|
|
||||||
}
|
|
||||||
//最大入库流量
|
//最大入库流量
|
||||||
if(vo.getYcRkQValue().compareTo(maxRKQ) >0){
|
if(vo.getYcRkQValue().compareTo(maxRKQ) >0){
|
||||||
maxRKQ = vo.getYcRkQValue();
|
maxRKQ = vo.getYcRkQValue();
|
||||||
maxRKDate = LocalDateTime.parse(vo.getTm(),formatter);
|
maxRKDate = LocalDateTime.parse(vo.getTm(),formatter);
|
||||||
}
|
}
|
||||||
if(start == null){
|
|
||||||
if(vo.getYcSwHValue().compareTo(flLowLimLev) > 0){
|
|
||||||
start = LocalDateTime.parse(vo.getTm(),formatter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(vo.getYcSwHValue().compareTo(flLowLimLev) > 0){
|
|
||||||
//如果预测水位高于汛限水位
|
|
||||||
BigDecimal gap = vo.getYcSwHValue().subtract(flLowLimLev);
|
|
||||||
if(gap.compareTo(overLimit) > 0){
|
|
||||||
overLimit = gap;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if(start != null && end == null){
|
DateTimeRangeSo dateTimeRangeSo = dto.getDateTimeRangeSo();
|
||||||
if(vo.getYcSwHValue().compareTo(flLowLimLev) <= 0){
|
if(dateTimeRangeSo != null){
|
||||||
end = LocalDateTime.parse(vo.getTm(),formatter);
|
Date start = dateTimeRangeSo.getStart();
|
||||||
}
|
Date end = dateTimeRangeSo.getEnd();
|
||||||
}
|
long timeSeconds = (end.getTime() - start.getTime()) / 1000;
|
||||||
|
totalCKWater = totalCKWater.add(new BigDecimal("5").multiply(new BigDecimal(timeSeconds)));
|
||||||
}
|
}
|
||||||
|
result.setTotalOutflowVolume(totalCKWater.divide(new BigDecimal("10000").setScale(2,RoundingMode.HALF_UP)));
|
||||||
|
result.setTotalInflowVolume(totalRKWater.divide(new BigDecimal("10000").setScale(2,RoundingMode.HALF_UP)));
|
||||||
result.setMaxInflow(maxRKQ);
|
result.setMaxInflow(maxRKQ);
|
||||||
if(maxRKQ.compareTo(BigDecimal.ZERO) == 0){
|
if(maxRKQ.compareTo(BigDecimal.ZERO) == 0){
|
||||||
result.setMaxInflowDate(nowHour);
|
result.setMaxInflowDate(nowHour);
|
||||||
}else{
|
}else{
|
||||||
result.setMaxInflowDate(maxRKDate);
|
result.setMaxInflowDate(maxRKDate);
|
||||||
}
|
}
|
||||||
result.setExceedLimitStart(start);
|
return result;
|
||||||
result.setExceedLimitEnd(end);
|
|
||||||
if(start == null && end == null){
|
|
||||||
result.setExceedLimitValue(null);
|
|
||||||
}else{
|
|
||||||
result.setExceedLimitValue(overLimit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.setMaxReservoirLevel(maxRz);
|
public ForecastProject getForecastProjectResults(String projectId) {
|
||||||
result.setMaxReservoirLevelDate(maxRzDate);
|
ForecastProject forecastProject = getById(projectId);
|
||||||
|
if (Objects.isNull(forecastProject)) {
|
||||||
result.setTotalInflowVolume(totalRKWater);
|
throw new IllegalArgumentException("抱歉,该预报方案不存在");
|
||||||
result.setTotalOutflowVolume(totalCKWater);
|
}
|
||||||
return result;
|
List<ForecastResults> resultList = forecastResultsService.list(new QueryWrapper<ForecastResults>().eq("project_id", projectId).orderBy(true, true, "tm"));
|
||||||
|
if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(resultList)) {
|
||||||
|
List<ForecastResultVo> vos = resultList.stream()
|
||||||
|
.map(result -> {
|
||||||
|
ForecastResultVo vo = new ForecastResultVo();
|
||||||
|
vo.setTm(sdf.format(result.getTm()));
|
||||||
|
vo.setYcRkQValue(result.getYcRkQValue());
|
||||||
|
vo.setRealRkQValue(result.getRealRkQValue());
|
||||||
|
vo.setYcCkQValue(result.getYcCkQValue());
|
||||||
|
vo.setRealCkQValue(result.getRealCkQValue());
|
||||||
|
vo.setYcSwHValue(result.getYcSwHValue());
|
||||||
|
vo.setRealSwHValue(result.getRealSwHValue());
|
||||||
|
BigDecimal ycSwHValue = result.getYcSwHValue() == null ? BigDecimal.ZERO : result.getYcSwHValue();
|
||||||
|
BigDecimal realSwHValue = result.getRealSwHValue() == null ? BigDecimal.ZERO : result.getRealSwHValue();
|
||||||
|
vo.setSwHDValue(ycSwHValue.subtract(realSwHValue));// 处理预测与实测水位差
|
||||||
|
vo.setDrp(result.getDrp());
|
||||||
|
vo.setIspreDrp(result.getIspreDrp());
|
||||||
|
vo.setR(result.getR());
|
||||||
|
vo.setFlLowLimLev(result.getFlLowLimLev());
|
||||||
|
vo.setCurrentYdgdyjz(result.getCurrentYdgdyjz());
|
||||||
|
vo.setPa(result.getPa());
|
||||||
|
return vo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
forecastProject.setVoList(vos);
|
||||||
|
forecastResultsService.handleVoList(forecastProject);
|
||||||
|
}
|
||||||
|
return forecastProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页码事件处理器 - 简化版本
|
// 页码事件处理器 - 简化版本
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue