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

307 lines
11 KiB
Java
Raw Normal View History

2025-07-17 15:26:39 +08:00
package com.gunshi.project.hsz.service;
2024-09-24 13:33:32 +08:00
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
2025-07-17 15:26:39 +08:00
import com.gunshi.project.hsz.entity.so.DataQueryCommonSo;
2025-09-03 14:13:30 +08:00
import com.gunshi.project.hsz.entity.vo.*;
2025-07-17 15:26:39 +08:00
import com.gunshi.project.hsz.mapper.AttResBaseMapper;
import com.gunshi.project.hsz.mapper.StZqRMapper;
2025-07-17 15:26:39 +08:00
import com.gunshi.project.hsz.mapper.StZqrlBMapper;
2025-09-03 14:13:30 +08:00
import com.gunshi.project.hsz.model.*;
2025-07-17 15:26:39 +08:00
import com.gunshi.project.hsz.util.DataHandleUtil;
2024-09-24 13:33:32 +08:00
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
2024-09-24 13:33:32 +08:00
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
/**
* Description:
* Created by wanyan on 2024/2/21
*
* @author wanyan
* @version 1.0
*/
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class RiverWaterService {
@Resource
private AttResBaseMapper attRvBaseMapper;
@Resource
private StZqrlBMapper stZqrlBMapper;
@Resource
private RainBasinDivisionService rainBasinDivisionService;
2025-09-03 14:13:30 +08:00
@Resource
private AlarmSetService alarmSetService;
@Resource
private StRiverRRealService stRiverRRealService;
@Resource
private StZqRMapper stZqRMapper;//水位-流量关系
public List<AttRvBaseVo> list() {
List<AttRvBaseVo> attRvBaseVos = attRvBaseMapper.queryWaterListUpAndLow();
if(CollectionUtils.isEmpty(attRvBaseVos)){
return attRvBaseVos;
}
return attRvBaseVos;
}
public List<AttRvBaseVo> get(String stcd) {
2025-09-03 14:13:30 +08:00
List<AttRvBaseVo> attRvBaseVos = attRvBaseMapper.queryWaterListByStcd(stcd);
2024-09-24 13:33:32 +08:00
if(CollectionUtils.isEmpty(attRvBaseVos)){
return attRvBaseVos;
}
return attRvBaseVos;
}
public List<StZqrlB> zqrl(String stcd) {
LambdaQueryWrapper<StZqrlB> queryWrapper = Wrappers.lambdaQuery();
2024-09-30 11:30:31 +08:00
queryWrapper.eq(StZqrlB::getStcd, stcd).orderByAsc(StZqrlB::getPtno);
2024-09-24 13:33:32 +08:00
return stZqrlBMapper.selectList(queryWrapper);
}
public BigDecimal getQByRz(List<StZqR> zqr,BigDecimal rz){
// 1. 参数校验
if (zqr == null || zqr.isEmpty()) {
throw new IllegalArgumentException("水位-流量关系列表不能为空");
}
if (rz == null) {
throw new IllegalArgumentException("水位值不能为空");
}
// 2. 检查边界情况:如果目标水位低于最低水位或高于最高水位
BigDecimal minRz = zqr.get(0).getZ();
BigDecimal maxRz = zqr.get(zqr.size() - 1).getZ();
if (rz.compareTo(minRz) < 0) {
// 低于最低水位返回0流量
return BigDecimal.ZERO;
}
if (rz.compareTo(maxRz) > 0) {
// 高于最高水位返回0流量
return BigDecimal.ZERO;
}
// 3. 二分查找水位区间
int l = 0;
int r = zqr.size() - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
BigDecimal midRz = zqr.get(mid).getZ();
int compareResult = midRz.compareTo(rz);
if (compareResult == 0) {
// 找到完全匹配的水位,直接返回对应的流量
return zqr.get(mid).getQ();
} else if (compareResult < 0) {
l = mid + 1;
} else {
r = mid - 1;
}
}
/**
*
* l rz
* r rz
* r (x1, y1) -
* l (x2, y2) -
*/
if (l >= zqr.size() || r < 0) {
return BigDecimal.ZERO;
}
// 获取前后相邻的两个点
StZqR lowerPoint = zqr.get(r);
StZqR upperPoint = zqr.get(l);
// 使用线性插值计算流量
return linearInterpolation(
lowerPoint.getZ(), lowerPoint.getQ(),
upperPoint.getZ(), upperPoint.getQ(),
rz
).setScale(3, RoundingMode.HALF_UP);
}
/**
* 线
* @param x1 1
* @param y1 1
* @param x2 2
* @param y2 2
* @param x
* @return
*/
private BigDecimal linearInterpolation(BigDecimal x1, BigDecimal y1,
BigDecimal x2, BigDecimal y2,
BigDecimal x) {
// 使用公式: y = y1 + ( (y2 - y1) / (x2 - x1) ) * (x - x1)
// 计算斜率: (y2 - y1) / (x2 - x1)
BigDecimal slope = y2.subtract(y1)
.divide(x2.subtract(x1), 10, RoundingMode.HALF_UP);
// 计算: slope * (x - x1)
BigDecimal xDiff = x.subtract(x1);
BigDecimal product = slope.multiply(xDiff);
// 计算最终结果: y1 + product
return y1.add(product);
}
2024-09-24 13:33:32 +08:00
public List<AttRvMonitorVo> monitorData(DataQueryCommonSo dataQueryCommonSo) {
String stcd = dataQueryCommonSo.getStcd();
//雨量数据
List<AttRvMonitorVo> drpData = attRvBaseMapper.drp(dataQueryCommonSo);
//水位数据
List<AttRvMonitorVo> rzData = attRvBaseMapper.rz(dataQueryCommonSo);
//获取水位流量关系,算出转换流量
//List<StZqrlB> zqrl = zqrl(stcd);
List<StZqR> zqr = zqr(stcd);
if(CollectionUtils.isNotEmpty(zqr)){
rzData.stream().forEach(o->{
o.setQ(getQByRz(zqr,o.getZ()));
});
2024-09-24 13:33:32 +08:00
}
//根据监测时间合并雨量和水位数据
return bindData(stcd,drpData,rzData);
}
private List<AttRvMonitorVo> bindData(String stcd, List<AttRvMonitorVo> drpData, List<AttRvMonitorVo> rzData) {
HashSet<Date> strings = new HashSet<>();
drpData.stream().forEach(v1 -> strings.add(v1.getTm()));
rzData.stream().forEach(v1 -> strings.add(v1.getTm()));
ArrayList<AttRvMonitorVo> result = new ArrayList<>();
strings.stream().forEach(v1 -> result.add(AttRvMonitorVo.builder().stcd(stcd).tm(v1).build()));
List<AttRvMonitorVo> list = result.stream().map(v1 -> {
drpData.stream().filter(v2 -> v1.getTm().equals(v2.getTm())).forEach(v2 -> {
v1.setDrp(v2.getDrp());
});
rzData.stream().filter(v2 -> v1.getTm().equals(v2.getTm())).forEach(v2 -> {
v1.setZ(v2.getZ());
v1.setQ(v2.getQ());
v1.setTq(v2.getTq());
});
return v1;
}).collect(Collectors.toList());
return list.stream().sorted(Comparator.comparing(AttRvMonitorVo::getTm).reversed()).collect(Collectors.toList());
}
private void calcTqData(List<AttRvMonitorVo> rzData, List<StZqrlB> zqrl) {
BigDecimal maxRz = zqrl.stream().max(Comparator.comparing(StZqrlB::getZ)).get().getZ();
BigDecimal minRz = zqrl.stream().min(Comparator.comparing(StZqrlB::getZ)).get().getZ();
Map<BigDecimal, BigDecimal> map = zqrl.stream().collect(Collectors.toMap(StZqrlB::getZ, StZqrlB::getQ));
List<BigDecimal> list = zqrl.stream().map(StZqrlB::getZ).collect(Collectors.toList());
for(AttRvMonitorVo vo : rzData){
BigDecimal rz = vo.getZ();
if(rz.compareTo(minRz) < 0 || rz.compareTo(maxRz) > 0){
continue;
}
vo.setTq(DataHandleUtil.calcData(rz,map,list));
}
}
public AttRvMonitorDetailVo detail(String stcd) {
AttRvMonitorDetailVo vo = new AttRvMonitorDetailVo();
StPptnDetailsVo stPptnDetailsVo = rainBasinDivisionService.queryStPptnDetailsByStcd(stcd);
BeanUtils.copyProperties(stPptnDetailsVo,vo,AttRvMonitorDetailVo.class);
//最新水位
2024-09-24 15:23:38 +08:00
AttRvMonitorVo monitorVo = attRvBaseMapper.newRz(stcd);
2024-09-24 13:33:32 +08:00
if(monitorVo == null){
return vo;
}
Date tm = monitorVo.getTm();
BigDecimal rz = monitorVo.getZ();
//最新水位时间往前推24小时水位
LocalDateTime now = LocalDateTime.ofInstant(tm.toInstant(), ZoneId.systemDefault());
LocalDateTime dateTime = now.minusDays(1);
2024-11-01 11:05:19 +08:00
BigDecimal oldRz = attRvBaseMapper.oldRz(stcd,1,Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant()));
2024-09-24 13:33:32 +08:00
2024-11-01 11:05:19 +08:00
if(oldRz != null){
2025-10-13 10:01:13 +08:00
//设置水位涨跌情况
2024-11-01 11:05:19 +08:00
vo.setRzDiff(rz.subtract(oldRz));
2024-09-24 13:33:32 +08:00
}
//本年最高水位
BigDecimal maxYearRz = queryYearRzByStcdAndTime(stcd);
vo.setMaxRz(maxYearRz);
return vo;
}
private BigDecimal queryYearRzByStcdAndTime(String stcd) {
LocalDateTime now = LocalDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault());
LocalDateTime startTime;
LocalDateTime endTime;
if (now.getHour() >= 8 || (now.getHour() < 8 && now.getMonthValue() > 1) || (now.getHour() < 8 && now.getMonthValue() == 1 && now.getDayOfMonth() >= 1)){
startTime = LocalDateTime.of(
now.getYear(),
1,
1,
8,
0,
0
);
endTime = now;
2024-11-01 11:05:19 +08:00
return attRvBaseMapper.queryRiverMaxRz(stcd,Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()), Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));
2024-09-24 13:33:32 +08:00
}
return new BigDecimal(0);
}
2025-09-03 14:13:30 +08:00
public AttRiverNowDataVo nowData(String stcd) {
AttRiverNowDataVo vo = new AttRiverNowDataVo();
LambdaQueryWrapper<AlarmSet> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AlarmSet::getStcd,stcd);
AlarmSet alarmSet = alarmSetService.getBaseMapper().selectOne(queryWrapper);//查询该站点的警告水位配置信息
if(alarmSet == null){
vo.setWaterAlarm(BigDecimal.ZERO);
vo.setWaterPromise(BigDecimal.ZERO);
}else{
vo.setWaterAlarm(alarmSet.getWarnWaterLevel());
vo.setWaterPromise(alarmSet.getPromiseWaterLevel());
}
StPptnRReal stPptnRReal = rainBasinDivisionService.queryStPptnRealByStcd(stcd);//查询该站点的实时降雨
BeanUtils.copyProperties(stPptnRReal,vo);
//查询该站点实时水位
StRiverRReal stRiverRReal = stRiverRRealService.getBaseMapper().queryQByStcd(stcd);
if(stRiverRReal == null){
2025-09-11 14:47:57 +08:00
return vo;
2025-09-03 14:13:30 +08:00
}
BigDecimal z = stRiverRReal.getZ() == null ? BigDecimal.ZERO : stRiverRReal.getZ();
2025-10-13 10:01:13 +08:00
vo.setRz(z);
2025-09-03 14:13:30 +08:00
vo.setWaterAlarmGap(z.subtract(vo.getWaterAlarm()));
vo.setWaterPromiseGap(z.subtract(vo.getWaterPromise()));
2025-09-03 14:13:30 +08:00
return vo;
}
public List<StZqR> zqr(String stcd){
LambdaQueryWrapper<StZqR> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(StZqR::getStcd, stcd).orderByAsc(StZqR::getZ);
return stZqRMapper.selectList(queryWrapper);
}
2024-09-24 13:33:32 +08:00
}