451 lines
18 KiB
Java
451 lines
18 KiB
Java
package com.gunshi.project.hsz.service;
|
||
|
||
import cn.hutool.core.collection.CollectionUtil;
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||
import com.gunshi.project.hsz.entity.dto.StZqrlBDto;
|
||
import com.gunshi.project.hsz.entity.so.HomeStStbprpBSo;
|
||
import com.gunshi.project.hsz.entity.vo.*;
|
||
import com.gunshi.project.hsz.mapper.OsmoticPressRMapper;
|
||
import com.gunshi.project.hsz.mapper.OsmoticShiftRMapper;
|
||
import com.gunshi.project.hsz.mapper.StStbprpBMapper;
|
||
import com.gunshi.project.hsz.model.StRsvrR;
|
||
import com.gunshi.project.hsz.model.StStbprpB;
|
||
import com.gunshi.project.hsz.model.StZqrlB;
|
||
import com.gunshi.project.hsz.model.StZvarlB;
|
||
import com.gunshi.project.hsz.util.DateUtil;
|
||
import jakarta.annotation.Resource;
|
||
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.io.Serializable;
|
||
import java.math.BigDecimal;
|
||
import java.math.RoundingMode;
|
||
import java.text.SimpleDateFormat;
|
||
import java.time.Duration;
|
||
import java.time.Instant;
|
||
import java.time.LocalDateTime;
|
||
import java.util.*;
|
||
import java.util.stream.Collectors;
|
||
|
||
/**
|
||
* 描述: sttp 以水利标准来
|
||
* author: xusan
|
||
* date: 2024-07-08 17:30:38
|
||
*/
|
||
@Service
|
||
@Slf4j
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public class StStbprpBService extends ServiceImpl<StStbprpBMapper, StStbprpB> {
|
||
@Resource
|
||
private OsmoticPressRMapper pressRMapper;
|
||
|
||
@Resource
|
||
private OsmoticShiftRMapper shiftRMapper;
|
||
|
||
@Autowired
|
||
private StZqrlBService stZqrlBService;
|
||
|
||
@Autowired
|
||
private StZvarlBService stZvarlBService;
|
||
|
||
@Autowired
|
||
private StRsvrRService rsvrRService;
|
||
|
||
public List<HomeStStbprpBVo> rainfallStationDetailsList(HomeStStbprpBSo dto) {
|
||
return baseMapper.rainfallStationDetailsList(dto);
|
||
}
|
||
|
||
public List<HomeStStbprpBVo> reservoirStationDetailsList() {
|
||
return baseMapper.reservoirStationDetailsList();
|
||
}
|
||
|
||
public List<HomeStStbprpBVo> flowStationDetailsList() {
|
||
return baseMapper.flowStationDetailsList();
|
||
}
|
||
|
||
public StStatusListVo statusList() {
|
||
StStatusListVo res = new StStatusListVo();
|
||
//水雨情站超过2小时为离线;渗压,渗流,位移暂定超过24小时为离线
|
||
List<StStatusVo> list = new ArrayList<>();
|
||
List<StStatusVo> onLineList = new ArrayList<>();
|
||
List<StStatusVo> offLineList = new ArrayList<>();
|
||
//雨量站
|
||
List<StStatusVo> rainList = baseMapper.realRainList();
|
||
//水位站
|
||
List<StStatusVo> rzList = baseMapper.rzList();
|
||
//图像站
|
||
List<StStatusVo> imgList = baseMapper.imgList();
|
||
rainList.addAll(rzList);
|
||
rainList.addAll(imgList);
|
||
rainList.stream().collect(Collectors.toMap(obj -> obj.getStcd(), obj -> obj, (obj1, obj2) ->
|
||
DateUtil.convertStringToDate(obj1.getTm()).after(DateUtil.convertStringToDate(obj2.getTm())) ? obj1 : obj2
|
||
)).values().stream().collect(Collectors.toList());
|
||
for (StStatusVo statusVo : rainList) {
|
||
String tm = statusVo.getTm();
|
||
if (StringUtils.isEmpty(tm) || DateUtil.hoursBetweenDate(DateUtil.convertStringToDate(tm), new Date()) > 2) {
|
||
offLineList.add(statusVo);
|
||
} else {
|
||
onLineList.add(statusVo);
|
||
}
|
||
}
|
||
//渗压
|
||
List<OsmoticPressVo> pressList = pressRMapper.listValue();
|
||
list.addAll(pressList.stream().map(o -> {
|
||
StStatusVo vo = new StStatusVo();
|
||
vo.setStnm(o.getStationCode());
|
||
vo.setTm(o.getTm());
|
||
return vo;
|
||
}).collect(Collectors.toList()));
|
||
//渗流
|
||
List<OsmoticPressVo> flowList = pressRMapper.flowListValue();
|
||
list.addAll(flowList.stream().map(o -> {
|
||
StStatusVo vo = new StStatusVo();
|
||
vo.setStnm(o.getStationCode());
|
||
vo.setTm(o.getTm());
|
||
return vo;
|
||
}).collect(Collectors.toList()));
|
||
//位移
|
||
List<OsmoticShiftListVo> shiftList = shiftRMapper.listValue();
|
||
list.addAll(shiftList.stream().map(o -> {
|
||
StStatusVo vo = new StStatusVo();
|
||
vo.setStnm(o.getStationCode());
|
||
vo.setTm(o.getTm());
|
||
return vo;
|
||
}).collect(Collectors.toList()));
|
||
|
||
for (StStatusVo vo : list) {
|
||
String tm = vo.getTm();
|
||
if (StringUtils.isEmpty(tm) || DateUtil.hoursBetweenDate(DateUtil.convertStringToDate(tm), new Date()) > 24) {
|
||
offLineList.add(vo);
|
||
} else {
|
||
onLineList.add(vo);
|
||
}
|
||
}
|
||
res.setOnline(onLineList.stream().sorted(Comparator.comparing(StStatusVo::getTm, Comparator.nullsFirst(String::compareTo)).reversed()).collect(Collectors.toList()));
|
||
res.setOffLine(offLineList.stream().sorted(Comparator.comparing(StStatusVo::getTm, Comparator.nullsFirst(String::compareTo)).reversed()).collect(Collectors.toList()));
|
||
return res;
|
||
}
|
||
|
||
public List<StStatusVo> rainList() {
|
||
return this.baseMapper.rainList();
|
||
}
|
||
|
||
public List<StZqrlBVo> flowList(StZqrlBDto obj) {
|
||
/*
|
||
* 查出时段内的水位列表,按时间升序排,根据水位查水位流量曲线表得到流量
|
||
* 第一条数据的累计溢洪量设为0,第二条累计溢洪量=上一条累计溢洪量+本条溢洪流量*60分*60秒,以此类推
|
||
*/
|
||
|
||
//TODO 这里得确定一下,这个新建的泄洪道水位站是不是从水库历史水位表中查
|
||
//获取水位历史数据
|
||
List<StRsvrR> rsvrList = rsvrRService.lambdaQuery()
|
||
.eq(StRsvrR::getStcd, obj.getStcd())
|
||
.between(StRsvrR::getTm, obj.getDateSo().getStart(), obj.getDateSo().getEnd())
|
||
.orderBy(true, true, StRsvrR::getTm)
|
||
.list();
|
||
//查询水位-流量关系
|
||
List<StZqrlB> zqrlList = stZqrlBService.list();
|
||
zqrlList.sort(Comparator.comparing(StZqrlB::getZ));
|
||
//获取水位-库容关系
|
||
List<StZvarlB> zvarlList = stZvarlBService.list();
|
||
zvarlList.sort(Comparator.comparing(StZvarlB::getRz));
|
||
List<StZqrlBVo> ret = new ArrayList<>();
|
||
|
||
for (int i = 0; i < rsvrList.size(); i++) {
|
||
StRsvrR rsvr = rsvrList.get(i);
|
||
BigDecimal rz = new BigDecimal(rsvr.getRz());
|
||
StZqrlBVo vo = new StZqrlBVo();
|
||
vo.setStcd(rsvr.getStcd());
|
||
vo.setTm(rsvr.getTm());
|
||
vo.setWaterLevel(rz);
|
||
//溢洪流量计算
|
||
//TODO 这里水位->流量 需要计算公式
|
||
BigDecimal q = stZqrlBService.getQByZqrl(zqrlList,rz);//根据水位计算流量
|
||
vo.setFlowNum(q);//计算溢洪量(非累加值)
|
||
BigDecimal w = stZvarlBService.getWByZvarl(zvarlList, rz);//根据水位计算库容
|
||
vo.setBoxNum(w);
|
||
if (i == 0) {
|
||
vo.setQtotal(BigDecimal.ZERO);
|
||
} else {
|
||
StZqrlBVo voPrev = ret.get(i - 1);
|
||
//累计溢洪量 = 上一条数据累计溢洪量 + 本条溢洪流量 * 2条数据之间的间隔
|
||
Instant curInstant = vo.getTm().toInstant();
|
||
Instant preInstant = voPrev.getTm().toInstant();
|
||
long timeDiffSeconds = Duration.between(curInstant, preInstant).getSeconds();
|
||
|
||
BigDecimal qTotal = voPrev.getQtotal().add(vo.getFlowNum().multiply(BigDecimal.valueOf(timeDiffSeconds)));
|
||
vo.setQtotal(qTotal);
|
||
}
|
||
|
||
ret.add(vo);
|
||
}
|
||
//倒序输出
|
||
ret.sort(Comparator.comparing(StZqrlBVo::getTm).reversed());
|
||
return ret;
|
||
}
|
||
|
||
public StZqrlBCountVo count(Serializable stcd) {
|
||
StZqrlBCountVo vo = new StZqrlBCountVo();
|
||
vo.setStcd(stcd.toString());
|
||
|
||
//取出当月的时间 20xx-xx-01 00:00:00
|
||
Calendar calendar = Calendar.getInstance();
|
||
Date now = calendar.getTime();
|
||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||
calendar.set(Calendar.MINUTE, 0);
|
||
calendar.set(Calendar.SECOND, 0);
|
||
calendar.set(Calendar.MILLISECOND, 0);
|
||
Date monthStart = calendar.getTime();
|
||
|
||
//取本年的时间 20xx-01-01 00:00:00
|
||
calendar.set(Calendar.MONTH,0);
|
||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||
calendar.set(Calendar.MINUTE, 0);
|
||
calendar.set(Calendar.SECOND, 0);
|
||
calendar.set(Calendar.MILLISECOND, 0);
|
||
Date yearStart = calendar.getTime();
|
||
|
||
|
||
calendar.setTime(now);
|
||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||
calendar.set(Calendar.MINUTE, 0);
|
||
calendar.set(Calendar.SECOND, 0);
|
||
calendar.set(Calendar.MILLISECOND, 0);
|
||
Date dayStart = calendar.getTime();
|
||
|
||
//查询当年水位数据
|
||
List<StRsvrR> rsvrList = rsvrRService.lambdaQuery()
|
||
.eq(StRsvrR::getStcd, stcd)
|
||
.between(StRsvrR::getTm, yearStart, now)
|
||
.orderByAsc(true, StRsvrR::getTm)
|
||
.list();
|
||
|
||
//获取水位流量关系
|
||
List<StZqrlB> zqrlList = stZqrlBService.list();
|
||
zqrlList.sort(Comparator.comparing(StZqrlB::getZ));
|
||
|
||
List<RsvrComplexVo> complexList = new ArrayList<>();
|
||
int idx = 0;
|
||
for (StRsvrR rsvr : rsvrList) {
|
||
RsvrComplexVo complex = new RsvrComplexVo();
|
||
BigDecimal rz = new BigDecimal(rsvr.getRz());
|
||
complex.setRz(rz);
|
||
complex.setTm(rsvr.getTm());
|
||
|
||
//TODO 这里需要重新计算水位-流量(溢洪量)对应数据
|
||
//BigDecimal q = stZqrlBService.getQFromZqrl(rz, zqrlList);
|
||
BigDecimal q = stZqrlBService.getQByZqrl(zqrlList,rz);
|
||
complex.setQ(q);
|
||
complex.setSv(complex.getQ());
|
||
// if (idx == 0) {
|
||
// complex.setSv(BigDecimal.ZERO);
|
||
// } else {
|
||
// //计算溢洪量
|
||
// RsvrComplexVo complexPrev = complexList.get(idx - 1);
|
||
// complex.setSv(complexPrev.getSv().add(complex.getQ().multiply(BigDecimal.valueOf(60 * 60))));
|
||
// }
|
||
|
||
complexList.add(complex);
|
||
idx++;
|
||
}
|
||
|
||
//当前流量
|
||
vo.setVal(complexList.getLast().getQ());
|
||
vo.setCreateTime(complexList.getLast().getTm());
|
||
|
||
// 今日累计溢洪量(基于时间间隔的积分)
|
||
List<RsvrComplexVo> complexDayList = complexList.stream().filter(complex -> complex.getTm().after(dayStart)).collect(Collectors.toList());
|
||
BigDecimal sumToday = stZqrlBService.getFlowQSum(complexDayList);
|
||
vo.setCurrDayValSum(sumToday);
|
||
|
||
|
||
// 当月累计溢洪量
|
||
List<RsvrComplexVo> complexMonthList = complexList.stream().filter(complex -> (complex.getTm().after(monthStart) || complex.getTm().equals(monthStart))
|
||
&& complex.getTm().before(now) || complex.getTm().equals(now)).collect(Collectors.toList());
|
||
BigDecimal sumMonth = stZqrlBService.getFlowQSum(complexMonthList);
|
||
vo.setCurrMonthSum(sumMonth);
|
||
|
||
|
||
|
||
// 当年累计溢洪量
|
||
BigDecimal sumYear = stZqrlBService.getFlowQSum(complexList);
|
||
vo.setCurrYearSum(sumYear);
|
||
|
||
|
||
// //今日sv的和
|
||
// BigDecimal sumToday = complexList.stream().filter(complex -> complex.getTm().after(dayStart))
|
||
// .map(RsvrComplexVo::getSv)
|
||
// .reduce(BigDecimal.ZERO, BigDecimal::add);
|
||
// vo.setCurrDayValSum(sumToday);
|
||
//
|
||
// // 当月溢洪量总和(筛选本月数据)
|
||
// BigDecimal sumMonth = complexList.stream()
|
||
// .filter(complex -> (complex.getTm().after(monthStart) || complex.getTm().equals(monthStart))
|
||
// && complex.getTm().before(now) || complex.getTm().equals(now))
|
||
// .map(RsvrComplexVo::getSv)
|
||
// .reduce(BigDecimal.ZERO, BigDecimal::add);
|
||
// vo.setCurrMonthSum(sumMonth);
|
||
//
|
||
// // 当年溢洪量总和(所有数据都是当年的,直接求和)
|
||
// BigDecimal sumYear = complexList.stream()
|
||
// .map(RsvrComplexVo::getSv)
|
||
// .reduce(BigDecimal.ZERO, BigDecimal::add);
|
||
// vo.setCurrYearSum(sumYear);
|
||
|
||
|
||
//计算溢洪次数
|
||
// 0 0 0 1 1 0 1 0 1
|
||
int overFlowCount = 0;
|
||
boolean isOverFlow = false;
|
||
//连续的sv > 0 才算一次 溢洪
|
||
for(int i =0;i<complexList.size();i++){
|
||
BigDecimal sv = complexList.get(i).getSv();
|
||
if(sv.compareTo(BigDecimal.ZERO) > 0){
|
||
if(!isOverFlow){
|
||
overFlowCount++;
|
||
isOverFlow = true;
|
||
}
|
||
}else{
|
||
isOverFlow = false;
|
||
}
|
||
}
|
||
vo.setCurrYearCount(Long.valueOf(overFlowCount));
|
||
// 本年单次最大溢洪量
|
||
Optional<RsvrComplexVo> maxOverflowComplex = complexList.stream()
|
||
.max(Comparator.comparing(RsvrComplexVo::getSv));
|
||
if (maxOverflowComplex.isPresent()) {
|
||
RsvrComplexVo maxComplex = maxOverflowComplex.get();
|
||
vo.setCurrYearMaxVal(maxComplex.getSv());
|
||
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss");
|
||
int maxIndex = complexList.indexOf(maxComplex);
|
||
if (maxIndex < complexList.size() - 1) {
|
||
// 可以取前后时间点作为时间段的参考
|
||
Date startTime = complexList.get(maxIndex).getTm();
|
||
Date endTime = complexList.get(maxIndex + 1).getTm();
|
||
String period = sdf.format(startTime) + " ~ " + sdf.format(endTime);
|
||
vo.setMaxOverflowPeriod(period);
|
||
}else{
|
||
Date startTime = complexList.get(maxIndex).getTm();
|
||
String period = sdf.format(startTime) + " ~ " + sdf.format(now);
|
||
vo.setMaxOverflowPeriod(period);
|
||
}
|
||
} else {
|
||
vo.setCurrYearMaxVal(BigDecimal.ZERO);
|
||
vo.setMaxOverflowPeriod("无溢洪记录");
|
||
}
|
||
return vo;
|
||
}
|
||
|
||
public StZqrlBCount24Vo count24(Serializable stcd) {
|
||
StZqrlBCount24Vo vo = new StZqrlBCount24Vo();
|
||
vo.setStcd(stcd.toString());
|
||
|
||
StRsvrR rsvrLatest = rsvrRService.lambdaQuery().eq(StRsvrR::getStcd, stcd).orderByDesc(StRsvrR::getTm).last("limit 1").one();
|
||
if (rsvrLatest == null) {
|
||
return vo;
|
||
}
|
||
BigDecimal rzLatest = new BigDecimal(rsvrLatest.getRz());
|
||
//获取水位-流量数据k
|
||
List<StZqrlB> zqrlBList = stZqrlBService.list();
|
||
//TODO 转换溢洪流量计算
|
||
BigDecimal qLatest = stZqrlBService.getQByZqrl(zqrlBList,rzLatest);
|
||
//BigDecimal qLatest = stZqrlBService.getQFromZqrl(rzLatest);
|
||
vo.setCurrWaterLevel(rzLatest);
|
||
vo.setFlowNum(qLatest);//当前溢洪量 就为 流量
|
||
vo.setCreateTime(rsvrLatest.getTm());
|
||
|
||
LocalDateTime now = LocalDateTime.now();
|
||
LocalDateTime before24 = now.minusHours(24);
|
||
List<StRsvrR> rsvrList = rsvrRService.lambdaQuery().ge(StRsvrR::getTm, before24).le(StRsvrR::getTm, now).orderByAsc(StRsvrR::getTm).list();
|
||
//TODO 这个溢洪流量汇总的计算也需要进行公式计算
|
||
List<RsvrComplexVo> rsvrComplexVos = stZqrlBService.calculateSpilledVolumeList(rsvrList);
|
||
BigDecimal totalSv = rsvrComplexVos.stream().map(RsvrComplexVo::getSv).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||
vo.setSum24(totalSv);
|
||
|
||
return vo;
|
||
}
|
||
|
||
public List<StZqrlB> calculateQtotal(List<StZqrlB> list) {
|
||
if (list == null || list.size() < 2) {
|
||
return list;
|
||
}
|
||
|
||
// 第一条数据设为0或null
|
||
list.get(0).setQtotal(BigDecimal.ZERO);
|
||
|
||
for (int i = 1; i < list.size(); i++) {
|
||
StZqrlB current = list.get(i);
|
||
StZqrlB previous = list.get(i - 1);
|
||
|
||
// 使用Duration计算分钟差(精确到小数)
|
||
Duration duration = Duration.between(previous.getModitimeAsLocalDateTime(), current.getModitimeAsLocalDateTime());
|
||
double minutesDiff = duration.toMillis() / 60000.0; // 毫秒转分钟
|
||
|
||
// 使用BigDecimal的valueOf方法,避免new BigDecimal(double)的精度问题
|
||
BigDecimal minutesDecimal = BigDecimal.valueOf(minutesDiff);
|
||
|
||
// 计算并设置qtotal
|
||
current.setQtotal(current.getQ().multiply(minutesDecimal));
|
||
}
|
||
return list;
|
||
}
|
||
|
||
private List<StZqrlB> getList(String stcd, LocalDateTime start, LocalDateTime end) {
|
||
LambdaQueryWrapper<StZqrlB> qw = new LambdaQueryWrapper();
|
||
List<StZqrlB> list = stZqrlBService.list(qw);
|
||
return list;
|
||
}
|
||
|
||
private BigDecimal sumVal(String stcd, LocalDateTime start, LocalDateTime end) {
|
||
LambdaQueryWrapper<StZqrlB> qw = new LambdaQueryWrapper();
|
||
qw.eq(StZqrlB::getStcd, stcd);
|
||
qw.ge(StZqrlB::getModitime, start);
|
||
qw.le(StZqrlB::getModitime, end);
|
||
List<StZqrlB> list = stZqrlBService.list(qw);
|
||
if (CollectionUtil.isNotEmpty(list)) {
|
||
return list.stream().map(StZqrlB::getQ).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private Long countVal(String stcd, LocalDateTime start, LocalDateTime end) {
|
||
LambdaQueryWrapper<StZqrlB> qw = new LambdaQueryWrapper();
|
||
qw.eq(StZqrlB::getStcd, stcd);
|
||
qw.ge(StZqrlB::getModitime, start);
|
||
qw.le(StZqrlB::getModitime, end);
|
||
List<StZqrlB> list = stZqrlBService.list(qw);
|
||
if (CollectionUtil.isNotEmpty(list)) {
|
||
return list.stream().map(StZqrlB::getQ).filter(Objects::nonNull).filter(q -> q.compareTo(BigDecimal.ZERO) > 0).count();
|
||
}
|
||
return 0l;
|
||
}
|
||
|
||
private BigDecimal maxVal(String stcd, LocalDateTime start, LocalDateTime end) {
|
||
LambdaQueryWrapper<StZqrlB> qw = new LambdaQueryWrapper();
|
||
qw.eq(StZqrlB::getStcd, stcd);
|
||
qw.ge(StZqrlB::getModitime, start);
|
||
qw.le(StZqrlB::getModitime, end);
|
||
List<StZqrlB> list = stZqrlBService.list(qw);
|
||
if (CollectionUtil.isNotEmpty(list)) {
|
||
return list.stream().map(StZqrlB::getQ).filter(Objects::nonNull).max(Comparator.naturalOrder()).orElse(null);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public List<StStbprpB> getPptnStations() {
|
||
return baseMapper.getPptnStations();
|
||
}
|
||
|
||
public List<StStbprpB> getRsvrStations() {
|
||
return baseMapper.getRsvrStations();
|
||
}
|
||
}
|
||
|
||
|