gunshi-project-ss/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java

642 lines
28 KiB
Java
Raw Normal View History

2025-11-26 15:23:02 +08:00
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.*;
2025-11-26 18:00:57 +08:00
import com.gunshi.project.hsz.util.LocalDateTimeUtils;
2025-11-26 15:23:02 +08:00
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());
}
2025-12-08 16:03:17 +08:00
queryWrapper.orderByDesc(RiceRqWater::getCreateTime);
2025-11-26 15:23:02 +08:00
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;
}
2025-12-03 13:52:10 +08:00
public RiceRqWater queryById(Long id) {
RiceRqWater riceRqWater = this.baseMapper.selectById(id);
if(riceRqWater == null){
return riceRqWater;
}
riceRqWater.setRiceWaterKis(riceWaterKiService.selectByRiceWaterId(riceRqWater.getId()));
//水稻生长系数配置
riceRqWater.setRiceGrowConfig(riceGrowConfigService.selectByRiceWaterId(riceRqWater.getId()));
//按月份
riceRqWater.setRiceWaterForecastMonths(riceWaterForecastMonthService.selectByRiceWaterId(riceRqWater.getId()));
//按生长周期
riceRqWater.setRiceWaterForecastCycles(riceWaterForecastCycleService.selectByRiceWaterId(riceRqWater.getId()));
return riceRqWater;
}
2025-11-26 15:23:02 +08:00
public RiceRqWater saveData(RiceRqWater dto) {
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
List<RiceWaterKi> riceWaterKis = dto.getRiceWaterKis();
List<RiceWaterForecastCycle> riceWaterForecastCycles = dto.getRiceWaterForecastCycles();
List<RiceWaterForecastMonth> riceWaterForecastMonths = dto.getRiceWaterForecastMonths();
2025-12-03 13:52:10 +08:00
dto.setReqWater(riceGrowConfig.getIrrigationUse());
dto.setCreateTime(LocalDateTime.now());
2025-11-26 15:23:02 +08:00
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();
2025-12-08 14:24:49 +08:00
dto.setReqWater(riceGrowConfig.getIrrigationUse());
dto.setCreateTime(LocalDateTime.now());
2025-11-26 15:23:02 +08:00
updateById(dto);
2025-12-08 14:24:49 +08:00
riceWaterKiService.removeByRiceWaterId(dto.getId());
riceGrowConfigService.removeByRiceWaterId(dto.getId());
riceIrrigationUseService.removeByRiceWaterId(dto.getId());
riceWaterForecastCycleService.removeByRiceWaterId(dto.getId());
riceWaterForecastMonthService.removeByRiceWaterId(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());
});
riceGrowConfig.setRiceWaterId(dto.getId());
riceWaterKiService.saveBatch(riceWaterKis);
riceGrowConfigService.save(riceGrowConfig);
riceWaterForecastCycleService.saveBatch(riceWaterForecastCycles);
riceWaterForecastMonthService.saveBatch(riceWaterForecastMonths);
2025-11-26 15:23:02 +08:00
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();
2025-12-03 13:52:10 +08:00
riceGrowConfig.setCycle(LocalDateTimeUtils.getTotalDayByRangeDate(riceWaterKis.getFirst().getStartTime(),riceWaterKis.getLast().getEndTime()));
2025-11-26 15:23:02 +08:00
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;
// 计算泡田期在当前月份的耗水量
2025-11-27 17:59:12 +08:00
/**
*
* 3.30~4.25
* 4·26~5·6
*
*/
2025-11-26 15:23:02 +08:00
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();
// 检查该阶段是否包含这个月份
2025-11-26 18:00:57 +08:00
if (LocalDateTimeUtils.isMonthInPeriod(month, startTime, endTime)) {
2025-11-26 15:23:02 +08:00
// 获取阶段在该月份的天数
2025-11-26 18:00:57 +08:00
int daysInMonth = LocalDateTimeUtils.calculateDaysInMonthForPeriod(startTime, endTime, month);
2025-11-26 15:23:02 +08:00
if (daysInMonth > 0) {
// 判断阶段是否跨月份
2025-11-26 18:00:57 +08:00
List<Integer> monthsInStage = LocalDateTimeUtils.getMonthsInPeriod(startTime, endTime);
2025-11-26 15:23:02 +08:00
if (monthsInStage.size() == 1) {
// 不跨月份:直接使用完整耗水量
totalConsumption = totalConsumption.add(growPeriod.getWaterRqStage());
} else {
// 跨月份:按天数比例分配耗水量
2025-11-27 17:59:12 +08:00
//当前月份对应阶段的耗水量/当前阶段的全天数
/**
*
* 3.30~4.25
* 4·26~5·6
* month4 4
* /11*(ps
*/
2025-11-26 15:23:02 +08:00
BigDecimal dailyConsumption = growPeriod.getWaterRqStage()
.divide(BigDecimal.valueOf(growPeriod.getDays()), 10, RoundingMode.HALF_UP);
2025-11-27 17:59:12 +08:00
//再去乘当前阶段在当前月份的天数
2025-11-26 15:23:02 +08:00
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();
// 检查该阶段是否包含这个月份
2025-11-26 18:00:57 +08:00
if (LocalDateTimeUtils.isMonthInPeriod(month, startTime, endTime)) {
2025-11-26 15:23:02 +08:00
// 使用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) {
2025-12-02 15:44:15 +08:00
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
2025-11-26 15:23:02 +08:00
List<RiceIrrigationUse> riceIrrigationUses = irrigationCaculate(dto);//获取灌区水稻用水量
2025-12-02 15:44:15 +08:00
BigDecimal totalWaterUse = BigDecimal.ZERO;
for (RiceIrrigationUse riceIrrigationUs : riceIrrigationUses) {
totalWaterUse = totalWaterUse.add(riceIrrigationUs.getIrrigationUse());
}
riceGrowConfig.setWaterUse(totalWaterUse);
2025-11-26 15:23:02 +08:00
List<RiceWaterForecastMonth> res = new ArrayList<>();
2025-12-02 15:44:15 +08:00
2025-11-26 15:23:02 +08:00
//灌溉区面积(亩)
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;
// 获取阶段跨越的月份
2025-11-26 18:00:57 +08:00
Set<Integer> months = LocalDateTimeUtils.getMonthsInPeriodSet(stageStartTime, stageEndTime);
2025-11-26 15:23:02 +08:00
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);
// 计算阶段在该月份的实际使用天数
2025-11-26 18:00:57 +08:00
int daysInMonth = LocalDateTimeUtils.calculateDaysInMonthForPeriod(stageStartTime, stageEndTime, month);
int totalDaysInMonth = LocalDateTimeUtils.getTotalDaysInMonth(stageStartTime.getYear(), month);
2025-11-26 15:23:02 +08:00
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) {
//先计算阶段耗水量
2025-12-02 15:44:15 +08:00
RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig();
2025-11-26 15:23:02 +08:00
RiceRqWaterCaculateVo vo = new RiceRqWaterCaculateVo();
List<RiceWaterKi> riceWaterKis = stageCaculate(dto);
dto.setRiceWaterKis(riceWaterKis);
//计算灌区水稻用水量-按月份
List<RiceWaterForecastMonth> riceWaterForecastMonths = irrigationComprehensiveCaculateMonth(dto);
2025-11-28 10:32:24 +08:00
BigDecimal monthTotal = BigDecimal.ZERO;
for (RiceWaterForecastMonth riceWaterForecastMonth : riceWaterForecastMonths) {
monthTotal = monthTotal.add(riceWaterForecastMonth.getIrrigationUse());
}
2025-12-02 15:44:15 +08:00
riceGrowConfig.setIrrigationUse(monthTotal);
2025-11-26 15:23:02 +08:00
//计算灌区水稻用水量-按周期
List<RiceWaterForecastCycle> riceWaterForecastCycles = irrigationComprehensiveCaculateCycle(dto);
2025-11-28 10:32:24 +08:00
BigDecimal cycleTotal = BigDecimal.ZERO;
for (RiceWaterForecastCycle riceWaterForecastCycle : riceWaterForecastCycles) {
cycleTotal = cycleTotal.add(riceWaterForecastCycle.getIrrigationUse());
}
vo.setIrrigationMonthTotalUse(monthTotal);
vo.setIrrigationCycleTotalUse(cycleTotal);
2025-11-26 15:23:02 +08:00
vo.setRiceWaterKis(riceWaterKis);
vo.setRiceWaterForecastMonths(riceWaterForecastMonths);
vo.setRiceWaterForecastCycles(riceWaterForecastCycles);
2025-12-03 13:52:10 +08:00
vo.setRiceGrowConfig(riceGrowConfig);
2025-11-26 15:23:02 +08:00
return vo;
}
}