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.time.Duration; 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 { @Resource private OsmoticPressRMapper pressRMapper; @Resource private OsmoticShiftRMapper shiftRMapper; @Autowired private StZqrlBService stZqrlBService; @Autowired private StZvarlBService stZvarlBService; @Autowired private StRsvrRService rsvrRService; public List rainfallStationDetailsList(HomeStStbprpBSo dto) { return baseMapper.rainfallStationDetailsList(dto); } public List reservoirStationDetailsList() { return baseMapper.reservoirStationDetailsList(); } public List flowStationDetailsList() { return baseMapper.flowStationDetailsList(); } public StStatusListVo statusList() { StStatusListVo res = new StStatusListVo(); //水雨情站超过2小时为离线;渗压,渗流,位移暂定超过24小时为离线 List list = new ArrayList<>(); List onLineList = new ArrayList<>(); List offLineList = new ArrayList<>(); //雨量站 List rainList = baseMapper.realRainList(); //水位站 List rzList = baseMapper.rzList(); //图像站 List 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 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 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 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 rainList() { return this.baseMapper.rainList(); } public List flowList(StZqrlBDto obj) { /* * 查出时段内的水位列表,按时间升序排,根据水位查水位流量曲线表得到流量 * 第一条数据的累计溢洪量设为0,第二条累计溢洪量=上一条累计溢洪量+本条溢洪流量*60分*60秒,以此类推 */ List rsvrList = rsvrRService.lambdaQuery() .eq(StRsvrR::getStcd, obj.getStcd()) .between(StRsvrR::getTm, obj.getDateSo().getStart(), obj.getDateSo().getEnd()) .orderBy(true, true, StRsvrR::getTm) .list(); List zqrlList = stZqrlBService.list(); zqrlList.sort(Comparator.comparing(StZqrlB::getZ)); List zvarlList = stZvarlBService.list(); zvarlList.sort(Comparator.comparing(StZvarlB::getRz)); List 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); zqrlList.stream() .filter(zqrl -> zqrl.getZ().equals(new BigDecimal(rsvr.getRz()))) .findFirst() .ifPresentOrElse(zqrl -> { vo.setFlowNum(zqrl.getQ()); }, () -> vo.setFlowNum(BigDecimal.ZERO)); zvarlList.stream() .filter(zvarl -> zvarl.getRz().equals(new BigDecimal(rsvr.getRz()))) .findFirst() .ifPresentOrElse(zvarl -> { vo.setBoxNum(zvarl.getW()); }, () -> vo.setBoxNum(BigDecimal.ZERO)); if (i == 0) { vo.setQtotal(BigDecimal.ZERO); } else { StZqrlBVo voPrev = ret.get(i - 1); BigDecimal qTotal = vo.getFlowNum().multiply(BigDecimal.valueOf(60 * 60)); BigDecimal prevQtotal = voPrev.getQtotal(); qTotal = qTotal.add(prevQtotal); 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()); //取出当月的水位 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); List rsvrList = rsvrRService.lambdaQuery() .eq(StRsvrR::getStcd, stcd) .between(StRsvrR::getTm, calendar.getTime(), now) .orderByAsc(true, StRsvrR::getTm) .list(); List zqrlList = stZqrlBService.list(); List 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()); BigDecimal q = stZqrlBService.getQFromZqrl(rz, zqrlList); complex.setQ(q); if (idx == 0) { complex.setSv(BigDecimal.ZERO); } else { RsvrComplexVo complexPrev = complexList.get(idx - 1); complex.setSv(complexPrev.getSv().add(complexPrev.getQ().multiply(BigDecimal.valueOf(60 * 60)))); } complexList.add(complex); idx++; } //当前流量 vo.setVal(complexList.getLast().getQ()); vo.setCreateTime(complexList.getLast().getTm()); 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 today = calendar.getTime(); //今日sv的和 BigDecimal sumToday = complexList.stream().filter(complex -> complex.getTm().after(today)) .map(RsvrComplexVo::getSv) .reduce(BigDecimal.ZERO, BigDecimal::add); vo.setCurrDayValSum(sumToday); //当月sv的和 BigDecimal sumMonth = complexList.stream().map(RsvrComplexVo::getSv) .reduce(BigDecimal.ZERO, BigDecimal::add); vo.setCurrMonthSum(sumMonth); 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()); 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 rsvrList = rsvrRService.lambdaQuery().ge(StRsvrR::getTm, before24).le(StRsvrR::getTm, now).orderByAsc(StRsvrR::getTm).list(); List rsvrComplexVos = stZqrlBService.calculateSpilledVolumeList(rsvrList); BigDecimal totalSv = rsvrComplexVos.stream().map(RsvrComplexVo::getSv).reduce(BigDecimal.ZERO, BigDecimal::add); vo.setSum24(totalSv); return vo; } public List calculateQtotal(List 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 getList(String stcd, LocalDateTime start, LocalDateTime end) { LambdaQueryWrapper qw = new LambdaQueryWrapper(); List list = stZqrlBService.list(qw); return list; } private BigDecimal sumVal(String stcd, LocalDateTime start, LocalDateTime end) { LambdaQueryWrapper qw = new LambdaQueryWrapper(); qw.eq(StZqrlB::getStcd, stcd); qw.ge(StZqrlB::getModitime, start); qw.le(StZqrlB::getModitime, end); List 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 qw = new LambdaQueryWrapper(); qw.eq(StZqrlB::getStcd, stcd); qw.ge(StZqrlB::getModitime, start); qw.le(StZqrlB::getModitime, end); List 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 qw = new LambdaQueryWrapper(); qw.eq(StZqrlB::getStcd, stcd); qw.ge(StZqrlB::getModitime, start); qw.le(StZqrlB::getModitime, end); List 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 getPptnStations() { return baseMapper.getPptnStations(); } public List getRsvrStations() { return baseMapper.getRsvrStations(); } }