572 lines
24 KiB
Java
572 lines
24 KiB
Java
package com.gunshi.project.hsz.service;
|
||
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||
import com.gunshi.project.hsz.entity.dto.RiceWaterCaculateDto;
|
||
import com.gunshi.project.hsz.entity.so.RiceRqWaterPageSo;
|
||
import com.gunshi.project.hsz.entity.vo.RiceRqWaterCaculateVo;
|
||
import com.gunshi.project.hsz.entity.vo.TyYearRainfallVo;
|
||
import com.gunshi.project.hsz.mapper.RiceRqWaterMapper;
|
||
import com.gunshi.project.hsz.model.*;
|
||
import com.gunshi.project.hsz.util.LocalDateTimeUtils;
|
||
import com.ruoyi.common.utils.StringUtils;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
|
||
import java.math.BigDecimal;
|
||
import java.math.RoundingMode;
|
||
import java.time.LocalDate;
|
||
import java.time.LocalDateTime;
|
||
import java.time.YearMonth;
|
||
import java.util.*;
|
||
import java.util.stream.Collectors;
|
||
|
||
/**
|
||
* 描述: 水稻需水主表
|
||
* author: xusan
|
||
* date: 2024-09-04 13:42:40
|
||
*/
|
||
@Service
|
||
@Slf4j
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public class RiceRqWaterService extends ServiceImpl<RiceRqWaterMapper, RiceRqWater> {
|
||
|
||
|
||
@Autowired
|
||
private RiceGrowConfigService riceGrowConfigService;
|
||
|
||
@Autowired
|
||
private RiceIrrigationUseService riceIrrigationUseService;
|
||
|
||
@Autowired
|
||
private RiceWaterForecastCycleService riceWaterForecastCycleService;
|
||
|
||
@Autowired
|
||
private RiceWaterForecastMonthService riceWaterForecastMonthService;
|
||
|
||
@Autowired
|
||
private RiceWaterKiService riceWaterKiService;
|
||
|
||
public Page<RiceRqWater> pageQuery(RiceRqWaterPageSo page) {
|
||
LambdaQueryWrapper<RiceRqWater> queryWrapper = new LambdaQueryWrapper<>();
|
||
if(page.getYear() != null){
|
||
queryWrapper.eq(RiceRqWater::getYear,page.getYear());
|
||
}
|
||
|
||
if(!StringUtils.isBlank(page.getPlanName())){
|
||
queryWrapper.like(RiceRqWater::getPlanName,page.getPlanName());
|
||
}
|
||
Page<RiceRqWater> riceRqWaterPage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper);
|
||
List<RiceRqWater> records = riceRqWaterPage.getRecords();
|
||
for (RiceRqWater record : records) {
|
||
//灌水定额配置
|
||
record.setRiceWaterKis(riceWaterKiService.selectByRiceWaterId(record.getId()));
|
||
//水稻生长系数配置
|
||
record.setRiceGrowConfig(riceGrowConfigService.selectByRiceWaterId(record.getId()));
|
||
//按月份
|
||
record.setRiceWaterForecastMonths(riceWaterForecastMonthService.selectByRiceWaterId(record.getId()));
|
||
//按生长周期
|
||
record.setRiceWaterForecastCycles(riceWaterForecastCycleService.selectByRiceWaterId(record.getId()));
|
||
}
|
||
return riceRqWaterPage;
|
||
}
|
||
|
||
public RiceRqWater saveData(RiceRqWater dto) {
|
||
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
|
||
List<RiceWaterKi> riceWaterKis = dto.getRiceWaterKis();
|
||
List<RiceWaterForecastCycle> riceWaterForecastCycles = dto.getRiceWaterForecastCycles();
|
||
List<RiceWaterForecastMonth> riceWaterForecastMonths = dto.getRiceWaterForecastMonths();
|
||
save(dto);
|
||
riceGrowConfig.setRiceWaterId(dto.getId());
|
||
riceWaterKis.stream().forEach(o ->{
|
||
o.setRiceWaterId(dto.getId());
|
||
});
|
||
riceWaterForecastCycles.stream().forEach(o ->{
|
||
o.setRiceWaterId(dto.getId());
|
||
});
|
||
riceWaterForecastMonths.stream().forEach(o ->{
|
||
o.setRiceWaterId(dto.getId());
|
||
});
|
||
riceWaterKiService.saveBatch(riceWaterKis);
|
||
riceGrowConfigService.save(riceGrowConfig);
|
||
riceWaterForecastCycleService.saveBatch(riceWaterForecastCycles);
|
||
riceWaterForecastMonthService.saveBatch(riceWaterForecastMonths);
|
||
return dto;
|
||
}
|
||
|
||
public RiceRqWater updateData(RiceRqWater dto) {
|
||
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
|
||
List<RiceWaterKi> riceWaterKis = dto.getRiceWaterKis();
|
||
List<RiceWaterForecastCycle> riceWaterForecastCycles = dto.getRiceWaterForecastCycles();
|
||
List<RiceWaterForecastMonth> riceWaterForecastMonths = dto.getRiceWaterForecastMonths();
|
||
updateById(dto);
|
||
riceWaterKiService.updateBatchById(riceWaterKis);
|
||
riceWaterForecastCycleService.updateBatchById(riceWaterForecastCycles);
|
||
riceWaterForecastMonthService.updateBatchById(riceWaterForecastMonths);
|
||
riceGrowConfigService.updateById(riceGrowConfig);
|
||
return dto;
|
||
}
|
||
|
||
public Boolean delData(Long id) {
|
||
removeById(id);
|
||
riceWaterKiService.removeByRiceWaterId(id);
|
||
riceGrowConfigService.removeByRiceWaterId(id);
|
||
riceIrrigationUseService.removeByRiceWaterId(id);
|
||
riceWaterForecastCycleService.removeByRiceWaterId(id);
|
||
riceWaterForecastMonthService.removeByRiceWaterId(id);
|
||
return true;
|
||
}
|
||
|
||
public List<RiceWaterKi> stageCaculate(RiceWaterCaculateDto dto) {
|
||
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
|
||
List<RiceWaterKi> riceWaterKis = dto.getRiceWaterKis();
|
||
orderByStartTimeAsc(riceWaterKis);
|
||
// 早稻需水系数
|
||
BigDecimal α1 = riceGrowConfig.getΑ1();
|
||
if(α1 == null){
|
||
throw new IllegalArgumentException("早稻需水系数不能为空");
|
||
}
|
||
// 渗漏强度
|
||
BigDecimal lkIntensity = riceGrowConfig.getLkIntensity();
|
||
if(lkIntensity == null){
|
||
throw new IllegalArgumentException("渗漏强度不能为空");
|
||
}
|
||
// 生长期水面蒸发量(mm)
|
||
BigDecimal ed1 = riceGrowConfig.getEd1();
|
||
if(ed1 == null){
|
||
throw new IllegalArgumentException("生长期水面蒸发量不能为空");
|
||
}
|
||
for (RiceWaterKi riceWaterKi : riceWaterKis) {
|
||
// 计算阶段耗水量
|
||
if(riceWaterKi.getRiceGrowStage().contains("泡田")){
|
||
riceWaterKi.setKi(riceGrowConfig.getΑ1());//需水系数
|
||
riceWaterKi.setWaterRqStage(riceGrowConfig.getKaQuota());//泡田定额
|
||
continue;
|
||
}
|
||
BigDecimal waterRqStage = calculateWaterRqStage(riceWaterKi, α1, ed1, lkIntensity);
|
||
riceWaterKi.setWaterRqStage(waterRqStage.setScale(1,RoundingMode.UP));
|
||
}
|
||
|
||
return riceWaterKis;
|
||
}
|
||
|
||
/**
|
||
* 计算阶段耗水量
|
||
* 公式:ki * α1 * ed1 + days * lkIntensity
|
||
*/
|
||
private BigDecimal calculateWaterRqStage(RiceWaterKi riceWaterKi, BigDecimal α1,
|
||
BigDecimal ed1, BigDecimal lkIntensity) {
|
||
// 获取需水模系数
|
||
BigDecimal ki = riceWaterKi.getKi();
|
||
if(ki == null){
|
||
throw new IllegalArgumentException("需水模型系数不能为空");
|
||
}
|
||
// 计算天数(如果days为空,则根据开始结束日期计算)
|
||
Integer days = riceWaterKi.getDays();
|
||
if (days == null && riceWaterKi.getStartTime() != null && riceWaterKi.getEndTime() != null) {
|
||
days = calculateDaysBetween(riceWaterKi.getStartTime(), riceWaterKi.getEndTime());
|
||
riceWaterKi.setDays(days); // 同时设置回实体中
|
||
}
|
||
if (days == null) {
|
||
days = 0;
|
||
}
|
||
|
||
|
||
// 计算公式:ki * α1 * ed1 + days * lkIntensity
|
||
BigDecimal part1 = ki.multiply(α1).multiply(ed1);
|
||
BigDecimal part2 = new BigDecimal(days).multiply(lkIntensity);
|
||
|
||
return part1.add(part2);
|
||
}
|
||
|
||
/**
|
||
* 计算两个LocalDateTime之间的天数(包含开始和结束日期)
|
||
* 例如:2025-04-26 ~ 2025-05-06 = 11天
|
||
*/
|
||
private Integer calculateDaysBetween(LocalDateTime startTime, LocalDateTime endTime) {
|
||
if (startTime == null || endTime == null) {
|
||
return 0;
|
||
}
|
||
|
||
// 使用LocalDate来计算天数,忽略时间部分
|
||
long days = java.time.temporal.ChronoUnit.DAYS.between(
|
||
startTime.toLocalDate(),
|
||
endTime.toLocalDate()
|
||
);
|
||
|
||
// 因为包含开始和结束日期,所以需要+1
|
||
return (int) days + 1;
|
||
}
|
||
|
||
@Autowired
|
||
private TyYearRainfallService tyYearRainfallService;
|
||
|
||
public List<RiceIrrigationUse> irrigationCaculate(RiceWaterCaculateDto dto) {
|
||
List<RiceWaterKi> riceWaterKis = dto.getRiceWaterKis();
|
||
List<RiceIrrigationUse> res = new ArrayList<>();
|
||
orderByStartTimeAsc(riceWaterKis);
|
||
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
|
||
Integer year = riceGrowConfig.getYear();//相似年
|
||
List<TyYearRainfallVo> tyYearRainfallVos = tyYearRainfallService.queryList();
|
||
List<TyYearRainfallVo> collect = tyYearRainfallVos.stream().filter(o -> {
|
||
return o.getYear().equals(year);
|
||
}).collect(Collectors.toList());
|
||
if(collect == null || collect.isEmpty()){
|
||
throw new IllegalArgumentException("对不起,没有该年份的降雨资料");
|
||
}
|
||
TyYearRainfallVo tyYearRainfallVo = collect.get(0);
|
||
List<TyYearRainfall> list = tyYearRainfallVo.getList();//获取月份的降雨资料
|
||
//泡田定额
|
||
BigDecimal kaQuota = riceGrowConfig.getKaQuota();
|
||
|
||
// 泡田期是第一个元素
|
||
RiceWaterKi kaPeriod = riceWaterKis.get(0);
|
||
LocalDateTime kaStartTime = kaPeriod.getStartTime();
|
||
LocalDateTime kaEndTime = kaPeriod.getEndTime();
|
||
int totalKaDays = calculateTotalKaDays(kaStartTime, kaEndTime);
|
||
|
||
// 生育期数据(排除泡田期)
|
||
List<RiceWaterKi> growPeriods = riceWaterKis.subList(1, riceWaterKis.size());
|
||
|
||
// 用于存储去重后的月份(1-12)
|
||
Set<Integer> monthSet = new HashSet<>();
|
||
|
||
// 添加泡田期的月份
|
||
monthSet.add(kaStartTime.getMonthValue());
|
||
monthSet.add(kaEndTime.getMonthValue());
|
||
|
||
// 遍历集合,提取每个元素的 startTime 和 endTime 对应的月份
|
||
for (RiceWaterKi riceWaterKi : riceWaterKis) {
|
||
LocalDateTime start = riceWaterKi.getStartTime();
|
||
LocalDateTime end = riceWaterKi.getEndTime();
|
||
|
||
if (start != null) {
|
||
monthSet.add(start.getMonthValue());
|
||
}
|
||
if (end != null) {
|
||
monthSet.add(end.getMonthValue());
|
||
}
|
||
}
|
||
|
||
// 将去重后的月份转为列表并按从小到大排序
|
||
List<Integer> sortedMonths = monthSet.stream()
|
||
.sorted()
|
||
.collect(Collectors.toList());
|
||
|
||
for (Integer sortedMonth : sortedMonths) {
|
||
RiceIrrigationUse riceIrrigationUse = new RiceIrrigationUse();
|
||
riceIrrigationUse.setMonth(sortedMonth);
|
||
|
||
BigDecimal irrigationVolume = BigDecimal.ZERO;
|
||
|
||
// 计算泡田期在当前月份的耗水量
|
||
if (isMonthInKaPeriod(sortedMonth, kaStartTime, kaEndTime)) {
|
||
int kaDaysInMonth = calculateKaDaysInMonth(kaStartTime, kaEndTime, sortedMonth);
|
||
BigDecimal kaConsumption = kaQuota.divide(BigDecimal.valueOf(totalKaDays), 100, RoundingMode.HALF_UP)
|
||
.multiply(BigDecimal.valueOf(kaDaysInMonth));
|
||
irrigationVolume = irrigationVolume.add(kaConsumption);
|
||
}
|
||
|
||
// 修正:计算生育期在当前月份的总耗水量(按Excel逻辑)
|
||
BigDecimal growConsumption = calculateGrowConsumptionForMonth(sortedMonth, growPeriods);
|
||
irrigationVolume = irrigationVolume.add(growConsumption);
|
||
|
||
// 计算该月份所有生育阶段的总有效降雨量
|
||
BigDecimal monthlyRainfall = calculateTotalEffectiveRainfallForMonth(sortedMonth, growPeriods, list);
|
||
irrigationVolume = irrigationVolume.subtract(monthlyRainfall);
|
||
|
||
|
||
// 如果计算结果是负数,则设为0
|
||
// if (irrigationVolume.compareTo(BigDecimal.ZERO) < 0) {
|
||
// irrigationVolume = BigDecimal.ZERO;
|
||
// }
|
||
|
||
// 保留1位小数
|
||
irrigationVolume = irrigationVolume.setScale(2, RoundingMode.HALF_UP);
|
||
|
||
riceIrrigationUse.setIrrigationUse(irrigationVolume);
|
||
res.add(riceIrrigationUse);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
|
||
/**
|
||
* 计算指定月份生育期的总耗水量(按Excel逻辑)
|
||
*/
|
||
private BigDecimal calculateGrowConsumptionForMonth(int month, List<RiceWaterKi> growPeriods) {
|
||
BigDecimal totalConsumption = BigDecimal.ZERO;
|
||
|
||
for (RiceWaterKi growPeriod : growPeriods) {
|
||
LocalDateTime startTime = growPeriod.getStartTime();
|
||
LocalDateTime endTime = growPeriod.getEndTime();
|
||
|
||
// 检查该阶段是否包含这个月份
|
||
if (LocalDateTimeUtils.isMonthInPeriod(month, startTime, endTime)) {
|
||
// 获取阶段在该月份的天数
|
||
int daysInMonth = LocalDateTimeUtils.calculateDaysInMonthForPeriod(startTime, endTime, month);
|
||
|
||
if (daysInMonth > 0) {
|
||
// 判断阶段是否跨月份
|
||
List<Integer> monthsInStage = LocalDateTimeUtils.getMonthsInPeriod(startTime, endTime);
|
||
|
||
if (monthsInStage.size() == 1) {
|
||
// 不跨月份:直接使用完整耗水量
|
||
totalConsumption = totalConsumption.add(growPeriod.getWaterRqStage());
|
||
} else {
|
||
// 跨月份:按天数比例分配耗水量
|
||
BigDecimal dailyConsumption = growPeriod.getWaterRqStage()
|
||
.divide(BigDecimal.valueOf(growPeriod.getDays()), 10, RoundingMode.HALF_UP);
|
||
BigDecimal monthlyConsumption = dailyConsumption.multiply(BigDecimal.valueOf(daysInMonth));
|
||
totalConsumption = totalConsumption.add(monthlyConsumption);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return totalConsumption;
|
||
}
|
||
|
||
/**
|
||
* 计算指定月份所有生育阶段的总有效降雨量
|
||
*/
|
||
private BigDecimal calculateTotalEffectiveRainfallForMonth(int month, List<RiceWaterKi> growPeriods,
|
||
List<TyYearRainfall> rainfallList) {
|
||
BigDecimal totalRainfall = BigDecimal.ZERO;
|
||
|
||
for (RiceWaterKi growPeriod : growPeriods) {
|
||
LocalDateTime startTime = growPeriod.getStartTime();
|
||
LocalDateTime endTime = growPeriod.getEndTime();
|
||
|
||
// 检查该阶段是否包含这个月份
|
||
if (LocalDateTimeUtils.isMonthInPeriod(month, startTime, endTime)) {
|
||
// 使用getMonthlyRainfall方法计算该阶段在该月份的有效降雨量
|
||
BigDecimal stageRainfall = getMonthlyRainfall(rainfallList, month, startTime, endTime);
|
||
totalRainfall = totalRainfall.add(stageRainfall);
|
||
}
|
||
}
|
||
|
||
return totalRainfall.setScale(1, RoundingMode.HALF_UP);
|
||
}
|
||
|
||
|
||
/**
|
||
* 判断月份是否在泡田期内
|
||
*/
|
||
private boolean isMonthInKaPeriod(int month, LocalDateTime kaStart, LocalDateTime kaEnd) {
|
||
int startMonth = kaStart.getMonthValue();
|
||
int endMonth = kaEnd.getMonthValue();
|
||
return month >= startMonth && month <= endMonth;
|
||
}
|
||
|
||
/**
|
||
* 计算泡田期在当前月份的天数
|
||
*/
|
||
private int calculateKaDaysInMonth(LocalDateTime kaStart, LocalDateTime kaEnd, int targetMonth) {
|
||
int startMonth = kaStart.getMonthValue();
|
||
int endMonth = kaEnd.getMonthValue();
|
||
|
||
// 如果整个泡田期都在目标月份内
|
||
if (startMonth == targetMonth && endMonth == targetMonth) {
|
||
return (int) java.time.temporal.ChronoUnit.DAYS.between(kaStart.toLocalDate(), kaEnd.toLocalDate()) + 1;
|
||
}
|
||
|
||
// 如果泡田期开始时间在目标月份,结束时间在下个月
|
||
if (startMonth == targetMonth && endMonth > targetMonth) {
|
||
LocalDate lastDayOfMonth = kaStart.toLocalDate().withDayOfMonth(kaStart.toLocalDate().lengthOfMonth());
|
||
return (int) java.time.temporal.ChronoUnit.DAYS.between(kaStart.toLocalDate(), lastDayOfMonth) + 1;
|
||
}
|
||
|
||
// 如果泡田期结束时间在目标月份,开始时间在上个月
|
||
if (endMonth == targetMonth && startMonth < targetMonth) {
|
||
LocalDate firstDayOfMonth = kaEnd.toLocalDate().withDayOfMonth(1);
|
||
return (int) java.time.temporal.ChronoUnit.DAYS.between(firstDayOfMonth, kaEnd.toLocalDate()) + 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* 计算泡田期总天数
|
||
*/
|
||
private int calculateTotalKaDays(LocalDateTime kaStart, LocalDateTime kaEnd) {
|
||
return (int) java.time.temporal.ChronoUnit.DAYS.between(kaStart.toLocalDate(), kaEnd.toLocalDate()) + 1;
|
||
}
|
||
|
||
/**
|
||
* 将ki的数据按照月份从小到大排序
|
||
*/
|
||
private void orderByStartTimeAsc(List<RiceWaterKi> riceWaterKis) {
|
||
Collections.sort(riceWaterKis, (ki1, ki2) -> {
|
||
LocalDateTime time1 = ki1.getStartTime();
|
||
LocalDateTime time2 = ki2.getStartTime();
|
||
if (time1 == null) return -1;
|
||
if (time2 == null) return 1;
|
||
return time1.compareTo(time2);
|
||
});
|
||
}
|
||
|
||
public List<RiceWaterForecastMonth> irrigationComprehensiveCaculateMonth(RiceWaterCaculateDto dto) {
|
||
List<RiceIrrigationUse> riceIrrigationUses = irrigationCaculate(dto);//获取灌区水稻用水量
|
||
List<RiceWaterForecastMonth> res = new ArrayList<>();
|
||
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
|
||
//灌溉区面积(亩)
|
||
BigDecimal sArea = riceGrowConfig.getArea();
|
||
|
||
for (RiceIrrigationUse riceIrrigationUse : riceIrrigationUses) {
|
||
RiceWaterForecastMonth entity = new RiceWaterForecastMonth();
|
||
entity.setMonth(riceIrrigationUse.getMonth());
|
||
|
||
BigDecimal irrigationUse = riceIrrigationUse.getIrrigationUse();
|
||
// 计算公式:2/3 * irrigationUse * sArea / 10000
|
||
BigDecimal value = new BigDecimal("2")
|
||
.divide(new BigDecimal("3"), 10, RoundingMode.HALF_UP) // 2/3,保留10位小数
|
||
.multiply(irrigationUse)
|
||
.multiply(sArea)
|
||
.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP); // 除以10000,保留2位小数
|
||
|
||
entity.setIrrigationUse(value);
|
||
res.add(entity);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
public List<RiceWaterForecastCycle> irrigationComprehensiveCaculateCycle(RiceWaterCaculateDto dto) {
|
||
List<RiceWaterKi> riceWaterKis = dto.getRiceWaterKis();
|
||
orderByStartTimeAsc(riceWaterKis);
|
||
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
|
||
BigDecimal kaQuota = riceGrowConfig.getKaQuota();//泡田定额
|
||
Integer year = riceGrowConfig.getYear();//相似年
|
||
BigDecimal sArea = riceGrowConfig.getArea();
|
||
List<TyYearRainfallVo> tyYearRainfallVos = tyYearRainfallService.queryList();
|
||
List<TyYearRainfallVo> collect = tyYearRainfallVos.stream().filter(o -> {
|
||
return o.getYear().equals(year);
|
||
}).collect(Collectors.toList());
|
||
if(collect == null || collect.isEmpty()){
|
||
throw new IllegalArgumentException("对不起,没有该年份的降雨资料");
|
||
}
|
||
TyYearRainfallVo tyYearRainfallVo = collect.get(0);
|
||
List<TyYearRainfall> rainfallList = tyYearRainfallVo.getList();//获取月份的降雨资料
|
||
List<RiceWaterForecastCycle> res = new ArrayList<>();
|
||
|
||
for (int i = 0; i < riceWaterKis.size(); i++) {
|
||
RiceWaterKi riceWaterKi = riceWaterKis.get(i);
|
||
RiceWaterForecastCycle data = new RiceWaterForecastCycle();
|
||
data.setRiceGrowStage(riceWaterKi.getRiceGrowStage());
|
||
data.setOrder(i + 1);
|
||
|
||
//泡田期为定值,泡田定额
|
||
if(riceWaterKi.getRiceGrowStage().contains("泡田")){
|
||
data.setIrrigationUse(kaQuota);
|
||
data.setRiceGrowStage("泡田期");
|
||
res.add(data);
|
||
} else {
|
||
LocalDateTime startTime = riceWaterKi.getStartTime();
|
||
LocalDateTime endTime = riceWaterKi.getEndTime();
|
||
BigDecimal irrigationUse = calculateIrrigationUse(riceWaterKi, rainfallList, startTime, endTime);
|
||
data.setIrrigationUse(irrigationUse.setScale(2,RoundingMode.UP));
|
||
res.add(data);
|
||
}
|
||
}
|
||
|
||
for (RiceWaterForecastCycle re : res) {
|
||
BigDecimal irrigationUse = re.getIrrigationUse();
|
||
|
||
BigDecimal value = new BigDecimal("2")
|
||
.divide(new BigDecimal("3"), 10, RoundingMode.HALF_UP) // 2/3,保留10位小数
|
||
.multiply(irrigationUse)
|
||
.multiply(sArea)
|
||
.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP); // 除以10000,保留2位小数
|
||
re.setIrrigationUse(value);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
/**
|
||
* 计算非泡田期的灌溉用水量
|
||
*/
|
||
private BigDecimal calculateIrrigationUse(RiceWaterKi riceWaterKi, List<TyYearRainfall> rainfallList,
|
||
LocalDateTime startTime, LocalDateTime endTime) {
|
||
// 阶段用水量(从waterRqStage获取)
|
||
BigDecimal stageWaterUse = riceWaterKi.getWaterRqStage();
|
||
if (stageWaterUse == null) {
|
||
stageWaterUse = BigDecimal.ZERO;
|
||
}
|
||
|
||
// 计算有效降雨量
|
||
BigDecimal effectiveRainfall = calculateEffectiveRainfall(rainfallList, startTime, endTime);
|
||
|
||
// 灌溉用水量 = 阶段用水量 - 有效降雨量
|
||
BigDecimal irrigationUse = stageWaterUse.subtract(effectiveRainfall);
|
||
|
||
// 确保不会出现负值
|
||
return irrigationUse.compareTo(BigDecimal.ZERO) > 0 ? irrigationUse : BigDecimal.ZERO;
|
||
}
|
||
|
||
/**
|
||
* 计算阶段内的有效降雨量
|
||
*/
|
||
private BigDecimal calculateEffectiveRainfall(List<TyYearRainfall> rainfallList,
|
||
LocalDateTime stageStartTime, LocalDateTime stageEndTime) {
|
||
BigDecimal totalEffectiveRainfall = BigDecimal.ZERO;
|
||
|
||
// 获取阶段跨越的月份
|
||
Set<Integer> months = LocalDateTimeUtils.getMonthsInPeriodSet(stageStartTime, stageEndTime);
|
||
|
||
for (Integer month : months) {
|
||
BigDecimal monthlyRainfall = getMonthlyRainfall(rainfallList, month, stageStartTime, stageEndTime);
|
||
totalEffectiveRainfall = totalEffectiveRainfall.add(monthlyRainfall);
|
||
}
|
||
|
||
return totalEffectiveRainfall;
|
||
}
|
||
|
||
/**
|
||
* 从降雨资料中获取指定月份的降雨量,并根据阶段实际使用天数进行调整
|
||
*/
|
||
private BigDecimal getMonthlyRainfall(List<TyYearRainfall> rainfallList, int month,
|
||
LocalDateTime stageStartTime, LocalDateTime stageEndTime) {
|
||
if (rainfallList == null || stageStartTime == null || stageEndTime == null) {
|
||
return BigDecimal.ZERO;
|
||
}
|
||
|
||
// 获取原始月降雨量
|
||
BigDecimal originalRainfall = rainfallList.stream()
|
||
.filter(rainfall -> rainfall.getMonth() != null && rainfall.getMonth() == month)
|
||
.findFirst()
|
||
.map(TyYearRainfall::getDrp)
|
||
.orElse(BigDecimal.ZERO);
|
||
|
||
// 计算阶段在该月份的实际使用天数
|
||
int daysInMonth = LocalDateTimeUtils.calculateDaysInMonthForPeriod(stageStartTime, stageEndTime, month);
|
||
int totalDaysInMonth = LocalDateTimeUtils.getTotalDaysInMonth(stageStartTime.getYear(), month);
|
||
|
||
if (daysInMonth > 0 && totalDaysInMonth > 0) {
|
||
// 按实际使用天数比例计算有效降雨量
|
||
return originalRainfall
|
||
.multiply(BigDecimal.valueOf(daysInMonth))
|
||
.divide(BigDecimal.valueOf(totalDaysInMonth), 10, RoundingMode.HALF_UP);
|
||
}
|
||
|
||
return BigDecimal.ZERO;
|
||
}
|
||
|
||
public RiceRqWaterCaculateVo caculate(RiceWaterCaculateDto dto) {
|
||
//先计算阶段耗水量
|
||
RiceRqWaterCaculateVo vo = new RiceRqWaterCaculateVo();
|
||
List<RiceWaterKi> riceWaterKis = stageCaculate(dto);
|
||
dto.setRiceWaterKis(riceWaterKis);
|
||
//计算灌区水稻用水量-按月份
|
||
List<RiceWaterForecastMonth> riceWaterForecastMonths = irrigationComprehensiveCaculateMonth(dto);
|
||
//计算灌区水稻用水量-按周期
|
||
List<RiceWaterForecastCycle> riceWaterForecastCycles = irrigationComprehensiveCaculateCycle(dto);
|
||
vo.setRiceWaterKis(riceWaterKis);
|
||
vo.setRiceWaterForecastMonths(riceWaterForecastMonths);
|
||
vo.setRiceWaterForecastCycles(riceWaterForecastCycles);
|
||
return vo;
|
||
|
||
}
|
||
} |