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

246 lines
8.2 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;
2025-11-06 11:35:41 +08:00
import com.gunshi.project.hsz.common.model.StRsvrR;
2025-07-17 15:26:39 +08:00
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));
List<RsvrComplexVo> ret = new ArrayList<>();
BigDecimal sum = BigDecimal.ZERO;
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 = getQByZqrl(zqrlList,rz);
//TODO 这个需要公式进行对水位->流量的转换
vo.setQ(q);
if (i == 0) {
vo.setTotalSv(BigDecimal.ZERO);
sum = BigDecimal.ZERO;
} else {
StRsvrR rsvrPrev = rsvrList.get(i - 1);
Date tmPrev = rsvrPrev.getTm();
long seconds = tm.getTime() - tmPrev.getTime();
sum = sum.add(vo.getQ().multiply(BigDecimal.valueOf(60 * 60)));
vo.setTotalSv(sum);
}
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) {
2025-10-13 10:01:13 +08:00
// 1. 参数校验
if (zqrlBList == null || zqrlBList.isEmpty()) {
throw new IllegalArgumentException("水位-流量关系列表不能为空");
}
if (rz == null) {
throw new IllegalArgumentException("水位值不能为空");
}
// 2. 检查边界情况:如果目标水位低于最低水位或高于最高水位
BigDecimal minRz = zqrlBList.get(0).getZ();
BigDecimal maxRz = zqrlBList.get(zqrlBList.size() - 1).getZ();
if (rz.compareTo(minRz) < 0) {
// 低于最低水位返回0流量
return BigDecimal.ZERO;
}
if (rz.compareTo(maxRz) > 0) {
// 高于最高水位返回0流量
return BigDecimal.ZERO;
}
2025-10-13 10:01:13 +08:00
// 3. 二分查找水位区间
int l = 0;
int r = zqrlBList.size() - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
2025-10-13 10:01:13 +08:00
BigDecimal midRz = zqrlBList.get(mid).getZ();
int compareResult = midRz.compareTo(rz);
if (compareResult == 0) {
// 找到完全匹配的水位,直接返回对应的流量
return zqrlBList.get(mid).getQ();
2025-10-13 10:01:13 +08:00
} else if (compareResult < 0) {
l = mid + 1;
2025-10-13 10:01:13 +08:00
} else {
r = mid - 1;
}
}
2025-10-13 10:01:13 +08:00
/**
*
* l rz
* r rz
* r (x1, y1) -
* l (x2, y2) -
*/
if (l >= zqrlBList.size() || r < 0) {
return BigDecimal.ZERO;
}
2025-10-13 10:01:13 +08:00
// 获取前后相邻的两个点
StZqrlB lowerPoint = zqrlBList.get(r);
StZqrlB upperPoint = zqrlBList.get(l);
2025-10-13 10:01:13 +08:00
// 使用线性插值计算流量
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);
2025-10-13 10:01:13 +08:00
// 计算: slope * (x - x1)
BigDecimal xDiff = x.subtract(x1);
BigDecimal product = slope.multiply(xDiff);
2025-10-13 10:01:13 +08:00
// 计算最终结果: y1 + product
return y1.add(product);
}
/**
*
* @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 {
BigDecimal multiply = current.getQ().multiply(new BigDecimal(60 * 60));
sum = sum.add(multiply);
}
}
return sum;
}
2024-07-08 17:47:02 +08:00
}