供需平衡分析
parent
75162d9e33
commit
b278261480
|
|
@ -48,7 +48,7 @@ public class RiceSupportBalanceController {
|
||||||
return R.ok(true);
|
return R.ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "来水预测-分页查询,供需平衡板")
|
@Operation(summary = "来水预测-分页查询,供需平衡版")
|
||||||
@PostMapping("/icpage")
|
@PostMapping("/icpage")
|
||||||
public R<Page<IcWaterForecast>> icPage(@RequestBody RiceSupportBalanceCaculatePageSo pageSo){
|
public R<Page<IcWaterForecast>> icPage(@RequestBody RiceSupportBalanceCaculatePageSo pageSo){
|
||||||
Page<IcWaterForecast> page = riceSupportBalanceService.icPage(pageSo);
|
Page<IcWaterForecast> page = riceSupportBalanceService.icPage(pageSo);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.gunshi.project.hsz.entity.dto;
|
package com.gunshi.project.hsz.entity.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -13,8 +14,10 @@ public class RiceSupportBalanceCaculateDto {
|
||||||
|
|
||||||
private String planName;//方案名称
|
private String planName;//方案名称
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private LocalDateTime startTime;//开始时间
|
private LocalDateTime startTime;//开始时间
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private LocalDateTime endTime;//结束时间
|
private LocalDateTime endTime;//结束时间
|
||||||
|
|
||||||
private Long icId;//来水方案Id
|
private Long icId;//来水方案Id
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
List<StZvarlB> list = stZvarlBService.lambdaQuery().orderByAsc(StZvarlB::getRz).list();
|
List<StZvarlB> list = stZvarlBService.lambdaQuery().orderByAsc(StZvarlB::getRz).list();
|
||||||
BigDecimal w = stZvarlBService.getWByZvarl(list, stRsvrRReal.getRz());//获取库容
|
BigDecimal w = stZvarlBService.getWByZvarl(list, stRsvrRReal.getRz());//获取库容
|
||||||
BigDecimal deadW = stZvarlBService.getWByZvarl(list, deadLev);//死水位库容
|
BigDecimal deadW = stZvarlBService.getWByZvarl(list, deadLev);//死水位库容
|
||||||
Integer year = icWaterForecast.getYear();//获取相似年
|
Integer year = riceRqWater.getRiceGrowConfig().getYear();//获取相似年
|
||||||
if(dto.getStartTime().isAfter(today)){
|
if(dto.getStartTime().isAfter(today)){
|
||||||
// 总来水量 = 当前~开始时间这一段时间的来水量 + 来回方案来水
|
// 总来水量 = 当前~开始时间这一段时间的来水量 + 来回方案来水
|
||||||
//方案来水量的时间范围 今天1号,开始时间4号,需要计算1-3号共3天
|
//方案来水量的时间范围 今天1号,开始时间4号,需要计算1-3号共3天
|
||||||
|
|
@ -118,13 +118,13 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 总来水量 = 当前到开始时间的降雨来水量 + 方案来水
|
// 总来水量 = 当前到开始时间的降雨来水量 + 方案来水(长期预测为万m³,短期预测为m³ 所以如果为短期,则需要进行÷10000
|
||||||
BigDecimal currentToStartWater = totalRainfallWater; // 这里假设totalRainfallWater就是需要的来水量
|
BigDecimal currentToStartWater = totalRainfallWater; // 这里假设totalRainfallWater就是需要的来水量
|
||||||
totalIcWater = totalIcWater.add(currentToStartWater).add(icWaterForecast.getForecastWater()); // 将当前到开始时间的来水量加入总来水量
|
totalIcWater = totalIcWater.add(currentToStartWater).add(icWaterForecast.getType() == 0? icWaterForecast.getForecastWater(): icWaterForecast.getForecastWater().divide(new BigDecimal("10000"))); // 将当前到开始时间的来水量加入总来水量
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// 总来水量 = 当前蓄水量 + 来水方案中的来水
|
// 总来水量 = 当前蓄水量 + 来水方案中的来水
|
||||||
BigDecimal forecastWater = icWaterForecast.getForecastWater();
|
BigDecimal forecastWater = icWaterForecast.getType() == 0? icWaterForecast.getForecastWater(): icWaterForecast.getForecastWater().divide(new BigDecimal("10000"));
|
||||||
totalIcWater = w.add(forecastWater);
|
totalIcWater = w.add(forecastWater);
|
||||||
}
|
}
|
||||||
BigDecimal totalNeedWater = BigDecimal.ZERO;
|
BigDecimal totalNeedWater = BigDecimal.ZERO;
|
||||||
|
|
@ -181,7 +181,7 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
// 计算灌溉用水的缩放比例
|
// 计算灌溉用水的缩放比例
|
||||||
BigDecimal irrigationRatio;
|
BigDecimal irrigationRatio;
|
||||||
if (totalIrrigationNeed.compareTo(BigDecimal.ZERO) > 0) {
|
if (totalIrrigationNeed.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
irrigationRatio = totalWaterForIrrigation.divide(totalIrrigationNeed, 4, BigDecimal.ROUND_HALF_UP);
|
irrigationRatio = totalIcWater.divide(totalNeedWater, 4, BigDecimal.ROUND_HALF_UP);
|
||||||
} else {
|
} else {
|
||||||
irrigationRatio = BigDecimal.ZERO;
|
irrigationRatio = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
|
|
@ -193,10 +193,11 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
riceSupportBalance.setEndTime(dto.getEndTime());
|
riceSupportBalance.setEndTime(dto.getEndTime());
|
||||||
riceSupportBalance.setCreateTime(LocalDateTime.now());
|
riceSupportBalance.setCreateTime(LocalDateTime.now());
|
||||||
riceSupportBalance.setTotalSupport(totalPlan);
|
riceSupportBalance.setTotalSupport(totalPlan);
|
||||||
riceSupportBalance.setTotalCost(totalIrrigationNeed);
|
riceSupportBalance.setTotalCost(totalNeedWater);
|
||||||
riceSupportBalance.setCreateName(dto.getCreateName());
|
riceSupportBalance.setCreateName(dto.getCreateName());
|
||||||
riceSupportBalance.setStatus(0);
|
riceSupportBalance.setStatus(0);
|
||||||
this.save(riceSupportBalance);
|
riceSupportBalance.setPlanName(dto.getPlanName());
|
||||||
|
boolean save = this.save(riceSupportBalance);
|
||||||
// 创建final或effectively final的局部变量副本
|
// 创建final或effectively final的局部变量副本
|
||||||
final Long mainId = riceSupportBalance.getId();
|
final Long mainId = riceSupportBalance.getId();
|
||||||
final BigDecimal finalDailyEcoWaterUse = dailyEcoWaterUse;
|
final BigDecimal finalDailyEcoWaterUse = dailyEcoWaterUse;
|
||||||
|
|
@ -205,10 +206,10 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
final List<RiceSupportMidCaculate> finalRiceSupportMidCaculates = new ArrayList<>(riceSupportMidCaculates);
|
final List<RiceSupportMidCaculate> finalRiceSupportMidCaculates = new ArrayList<>(riceSupportMidCaculates);
|
||||||
|
|
||||||
// 在新线程中执行计算和保存
|
// 在新线程中执行计算和保存
|
||||||
|
//TODO 这样做会有事务问题(如果明细数据计算失败,那么会导致 只有主表数据,没有明细数据(当然也可以保持同步计算逻辑)
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
List<RiceSupportBalanceDetail> saveDetails = new ArrayList<>();
|
List<RiceSupportBalanceDetail> saveDetails = new ArrayList<>();
|
||||||
|
|
||||||
for (LocalDateTime localDateTime : finalAllDays) {
|
for (LocalDateTime localDateTime : finalAllDays) {
|
||||||
RiceSupportBalanceDetail entity = new RiceSupportBalanceDetail();
|
RiceSupportBalanceDetail entity = new RiceSupportBalanceDetail();
|
||||||
entity.setTm(localDateTime);
|
entity.setTm(localDateTime);
|
||||||
|
|
@ -216,11 +217,38 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
// 查找当前日期属于哪个生长周期,计算灌溉需水量
|
// 查找当前日期属于哪个生长周期,计算灌溉需水量
|
||||||
BigDecimal dailyIrrigationNeed = BigDecimal.ZERO; // 灌溉需水量
|
BigDecimal dailyIrrigationNeed = BigDecimal.ZERO; // 灌溉需水量
|
||||||
for (RiceSupportMidCaculate caculate : finalRiceSupportMidCaculates) {
|
for (RiceSupportMidCaculate caculate : finalRiceSupportMidCaculates) {
|
||||||
if (!localDateTime.isBefore(caculate.getStartTime()) &&
|
// 提取月份和日,忽略年份
|
||||||
!localDateTime.isAfter(caculate.getEndTime())) {
|
int currentMonth = localDateTime.getMonthValue();
|
||||||
|
int currentDay = localDateTime.getDayOfMonth();
|
||||||
|
|
||||||
|
int startMonth = caculate.getStartTime().getMonthValue();
|
||||||
|
int startDay = caculate.getStartTime().getDayOfMonth();
|
||||||
|
|
||||||
|
int endMonth = caculate.getEndTime().getMonthValue();
|
||||||
|
int endDay = caculate.getEndTime().getDayOfMonth();
|
||||||
|
|
||||||
|
// 判断日期是否在周期内(只比较月日)
|
||||||
|
boolean isInCycle = false;
|
||||||
|
|
||||||
|
if (startMonth < endMonth || (startMonth == endMonth && startDay <= endDay)) {
|
||||||
|
// 正常情况:开始月日 <= 结束月日(不跨年)
|
||||||
|
if ((currentMonth > startMonth || (currentMonth == startMonth && currentDay >= startDay)) &&
|
||||||
|
(currentMonth < endMonth || (currentMonth == endMonth && currentDay <= endDay))) {
|
||||||
|
isInCycle = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 跨年情况:开始月日 > 结束月日(如11月到次年2月)
|
||||||
|
if ((currentMonth > startMonth || (currentMonth == startMonth && currentDay >= startDay)) ||
|
||||||
|
(currentMonth < endMonth || (currentMonth == endMonth && currentDay <= endDay))) {
|
||||||
|
isInCycle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInCycle) {
|
||||||
// 计算该生长周期的天数
|
// 计算该生长周期的天数
|
||||||
int daysInCycle = LocalDateTimeUtils.getTotalDayByRangeDate(
|
int daysInCycle = LocalDateTimeUtils.calculateDaysIgnoringYear(
|
||||||
caculate.getStartTime(), caculate.getEndTime()
|
caculate.getStartTime(),
|
||||||
|
caculate.getEndTime()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (daysInCycle > 0 && caculate.getIrrigationUse() != null) {
|
if (daysInCycle > 0 && caculate.getIrrigationUse() != null) {
|
||||||
|
|
@ -259,14 +287,14 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
||||||
updateById(riceSupportBalance);
|
updateById(riceSupportBalance);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("保存水稻平衡供水明细失败", e);
|
log.error("保存水稻平衡供水明细失败", e);
|
||||||
// 这里可以添加异常处理,比如记录日志、发送通知等
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
// 主线程立即返回,不等待明细计算完成
|
||||||
// 主线程立即返回,不等待明细计算完成
|
|
||||||
log.info("水稻平衡供水主表已保存,明细计算正在异步执行");
|
log.info("水稻平衡供水主表已保存,明细计算正在异步执行");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Page<IcWaterForecast> icPage(RiceSupportBalanceCaculatePageSo pageSo) {
|
public Page<IcWaterForecast> icPage(RiceSupportBalanceCaculatePageSo pageSo) {
|
||||||
LambdaQueryWrapper<IcWaterForecast> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<IcWaterForecast> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.le(IcWaterForecast::getStartTime,pageSo.getStartTime());
|
queryWrapper.le(IcWaterForecast::getStartTime,pageSo.getStartTime());
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,72 @@ public class LocalDateTimeUtils {
|
||||||
return (int) days;
|
return (int) days;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算忽略年份的时间范围内的天数(用于年循环的周期,如生长周期)
|
||||||
|
* 处理跨年情况,如11月15日到次年3月15日
|
||||||
|
*
|
||||||
|
* @param startTime 开始时间
|
||||||
|
* @param endTime 结束时间
|
||||||
|
* @return 天数(假设为同一年计算)
|
||||||
|
*/
|
||||||
|
public static int calculateDaysIgnoringYear(LocalDateTime startTime, LocalDateTime endTime) {
|
||||||
|
if (startTime == null || endTime == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将开始和结束时间调整为同一年(比如都调整为2020年)
|
||||||
|
int baseYear = 2020; // 选择一个基准年
|
||||||
|
|
||||||
|
LocalDateTime adjustedStart = startTime.withYear(baseYear);
|
||||||
|
LocalDateTime adjustedEnd = endTime.withYear(baseYear);
|
||||||
|
|
||||||
|
// 如果调整后开始时间在结束时间之后,说明是跨年周期
|
||||||
|
// 如:11月15日(2020年)到3月15日(2020年)实际上应该是11月15日到次年3月15日
|
||||||
|
if (adjustedStart.isAfter(adjustedEnd)) {
|
||||||
|
adjustedEnd = adjustedEnd.plusYears(1); // 结束时间加一年
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算天数
|
||||||
|
return getTotalDayByRangeDate(adjustedStart, adjustedEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断日期是否在忽略年份的时间范围内
|
||||||
|
*
|
||||||
|
* @param checkDate 检查日期
|
||||||
|
* @param startTime 周期开始时间
|
||||||
|
* @param endTime 周期结束时间
|
||||||
|
* @return 是否在周期内
|
||||||
|
*/
|
||||||
|
public static boolean isDateInCycleIgnoringYear(LocalDateTime checkDate,
|
||||||
|
LocalDateTime startTime,
|
||||||
|
LocalDateTime endTime) {
|
||||||
|
if (checkDate == null || startTime == null || endTime == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取月日
|
||||||
|
int checkMonth = checkDate.getMonthValue();
|
||||||
|
int checkDay = checkDate.getDayOfMonth();
|
||||||
|
|
||||||
|
int startMonth = startTime.getMonthValue();
|
||||||
|
int startDay = startTime.getDayOfMonth();
|
||||||
|
|
||||||
|
int endMonth = endTime.getMonthValue();
|
||||||
|
int endDay = endTime.getDayOfMonth();
|
||||||
|
|
||||||
|
// 判断日期是否在周期内
|
||||||
|
if (startMonth < endMonth || (startMonth == endMonth && startDay <= endDay)) {
|
||||||
|
// 不跨年情况
|
||||||
|
return (checkMonth > startMonth || (checkMonth == startMonth && checkDay >= startDay)) &&
|
||||||
|
(checkMonth < endMonth || (checkMonth == endMonth && checkDay <= endDay));
|
||||||
|
} else {
|
||||||
|
// 跨年情况
|
||||||
|
return (checkMonth > startMonth || (checkMonth == startMonth && checkDay >= startDay)) ||
|
||||||
|
(checkMonth < endMonth || (checkMonth == endMonth && checkDay <= endDay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue