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

235 lines
8.6 KiB
Java
Raw Normal View History

2025-07-17 15:26:39 +08:00
package com.gunshi.project.hsz.service;
2024-07-08 17:47:02 +08:00
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
2025-07-17 15:26:39 +08:00
import com.gunshi.project.hsz.entity.vo.RsvrComplexVo;
import com.gunshi.project.hsz.mapper.StZqrlBMapper;
import com.gunshi.project.hsz.model.StRsvrR;
import com.gunshi.project.hsz.model.StZqrlB;
2024-07-08 17:47:02 +08:00
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;
2024-07-08 17:47:02 +08:00
/**
* : 线
* author: xusan
* date: 2024-07-08 17:30:38
*/
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class StZqrlBService extends ServiceImpl<StZqrlBMapper, StZqrlB> {
/**
*
*
* @param rz
* @param seconds
* @param zqrlList 线
* @return
* @author lyf
*/
public BigDecimal calculateSpilledVolume(BigDecimal rz, long seconds, List<StZqrlB> zqrlList) {
return getQFromZqrl(rz, zqrlList).multiply(BigDecimal.valueOf(seconds));
}
/**
*
*
* @param rz
* @param seconds
* @return
* @author lyf
*/
public BigDecimal calculateSpilledVolume(BigDecimal rz, long seconds) {
return calculateSpilledVolume(rz, seconds, list());
}
/**
*
*
* @param rsvrList
* @param zqrlList 线
* @return
* @author lyf
*/
public List<RsvrComplexVo> calculateSpilledVolumeList(List<StRsvrR> rsvrList, List<StZqrlB> zqrlList) {
rsvrList.sort(Comparator.comparing(StRsvrR::getTm).reversed());
List<RsvrComplexVo> ret = new ArrayList<>();
for (int i = 0; i < rsvrList.size(); i++) {
StRsvrR rsvr = rsvrList.get(i);
BigDecimal rz = new BigDecimal(rsvr.getRz());
Date tm = rsvr.getTm();
RsvrComplexVo vo = RsvrComplexVo.of(rz, tm);
BigDecimal q = getQFromZqrl(rz, zqrlList);
//TODO 这个需要公式进行对水位->流量的转换
if (i == 0) {
vo.setQ(getQFromZqrl(rz, zqrlList));
vo.setSv(BigDecimal.ZERO);
} else {
StRsvrR rsvrPrev = rsvrList.get(i - 1);
Date tmPrev = rsvrPrev.getTm();
long seconds = tm.getTime() - tmPrev.getTime();
vo.setQ(getQFromZqrl(rz, zqrlList));
//TODO 这里有个函数调用,记得到时候也替换一下计算公式
vo.setSv(calculateSpilledVolume(rz, seconds));
}
ret.add(vo);
}
return ret;
}
/**
*
*
* @param rsvrList
* @return
* @author lyf
*/
public List<RsvrComplexVo> calculateSpilledVolumeList(List<StRsvrR> rsvrList) {
return calculateSpilledVolumeList(rsvrList, list());
}
/**
*
*
* @param rz
* @return
* @author lyf
*/
public BigDecimal getQFromZqrl(BigDecimal rz) {
return getQFromZqrl(rz, list());
}
/**
*
*
* @param rz
* @param zqrlList 线
* @return
* @author lyf
*/
public BigDecimal getQFromZqrl(BigDecimal rz, List<StZqrlB> zqrlList) {
return toMap(zqrlList).getOrDefault(rz.setScale(3, RoundingMode.DOWN), BigDecimal.ZERO);
}
/**
* 线BigDecimal
*
* @param zqrlList 线
* @return 线
* @author lyf
*/
private Map<BigDecimal, BigDecimal> toMap(List<StZqrlB> zqrlList) {
return zqrlList.stream()
.map(item -> Map.entry(item.getZ().setScale(3, RoundingMode.DOWN), item.getQ()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
2024-07-08 17:47:02 +08:00
public BigDecimal getQByZqrl(List<StZqrlB> zqrlBList, BigDecimal rz) {
int l =0;
int r = zqrlBList.size() - 1;
if(rz.compareTo(zqrlBList.get(0).getZ()) < 0){
return BigDecimal.ZERO;
}
//使用二分法,来获取 避免On的查询时间复杂度
while(l < r){
int mid = l + (r - l) / 2;
if(zqrlBList.get(mid).getZ().compareTo(rz) ==0){
return zqrlBList.get(mid).getQ();
}else if(zqrlBList.get(mid).getZ().compareTo(rz) >0){
r = mid - 1;
}else{
l = mid + 1;
}
}
// 现在 l 是最接近的索引,但需要比较前后三个值
int closestIndex = l;
// 处理边界情况
if (l == 0) {
// 只有第一个元素,或者比较第一个和第二个哪个更接近
if (zqrlBList.size() > 1) {
BigDecimal diff1 = rz.subtract(zqrlBList.get(0).getZ()).abs();
BigDecimal diff2 = rz.subtract(zqrlBList.get(1).getZ()).abs();
closestIndex = diff1.compareTo(diff2) <= 0 ? 0 : 1;
}
//TODO 这里找到最接近的值后,仍然要通过公式,计算出真正的流量
return zqrlBList.get(closestIndex).getQ();
}
if (l == zqrlBList.size() - 1) {
// 只有最后一个元素,或者比较最后两个哪个更接近
if (zqrlBList.size() > 1) {
BigDecimal diff1 = rz.subtract(zqrlBList.get(l - 1).getZ()).abs();
BigDecimal diff2 = rz.subtract(zqrlBList.get(l).getZ()).abs();
closestIndex = diff1.compareTo(diff2) <= 0 ? l - 1 : l;
}
//TODO 这里找到最接近的值后,仍然要通过公式,计算出真正的流量
return zqrlBList.get(closestIndex).getQ();
}
// 正常情况:比较前一个、当前、后一个三个值,找到最接近的
BigDecimal preVal = zqrlBList.get(l - 1).getZ();
BigDecimal curVal = zqrlBList.get(l).getZ();
BigDecimal nextVal = zqrlBList.get(l + 1).getZ();
//计算他们与目标的插值
BigDecimal diffPre = rz.subtract(preVal).abs();
BigDecimal diffCur = rz.subtract(curVal).abs();
BigDecimal diffNext = rz.subtract(nextVal).abs();
// 找到最小的差值
if (diffPre.compareTo(diffCur) <= 0 && diffPre.compareTo(diffNext) <= 0) {
closestIndex = l - 1;
} else if (diffCur.compareTo(diffPre) <= 0 && diffCur.compareTo(diffNext) <= 0) {
closestIndex = l;
} else {
closestIndex = l + 1;
}
//TODO 这里找到最接近的值后,仍然要通过公式,计算出真正的流量
return zqrlBList.get(closestIndex).getQ();
}
/**
*
* @param complexList
* @return
*/
public BigDecimal getFlowQSum(List<RsvrComplexVo> complexList) {
BigDecimal sum = BigDecimal.ZERO;
for (int i = 0; i < complexList.size(); i++) {
RsvrComplexVo current = complexList.get(i);
if (i == 0) {
// 第一条数据累计量为0
sum = BigDecimal.ZERO;
} else {
RsvrComplexVo previous = complexList.get(i - 1);
// 计算时间间隔(秒)
long timeDiffSeconds = Duration.between(previous.getTm().toInstant(),
current.getTm().toInstant()).getSeconds();
if (timeDiffSeconds > 0) {
// 使用梯形法则计算这段时间内的溢洪量:(上一个流量 + 当前流量) / 2 * 时间间隔
BigDecimal avgFlow = previous.getSv().add(current.getSv())
.divide(BigDecimal.valueOf(2), 10, RoundingMode.HALF_UP);
BigDecimal increment = avgFlow.multiply(BigDecimal.valueOf(timeDiffSeconds));
sum = sum.add(increment);
}
}
}
return sum;
}
2024-07-08 17:47:02 +08:00
}