回归修改

master
yangzhe123 2025-11-18 16:26:32 +08:00
parent 1af30dc3e9
commit 29f4658d91
8 changed files with 219 additions and 180 deletions

View File

@ -11,12 +11,12 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@MapperScan({
"com.gunshi.project.hsz.datasync.mapper",
"com.gunshi.project.hsz.datasync.mapper.jcsk",
"com.gunshi.project.hsz.datasync.rsvrWaterLevel",
"com.gunshi.project.hsz.datasync.config",
"com.gunshi.project.hsz.datasync.flow",
"com.gunshi.project.hsz.datasync.gnss",
"com.gunshi.project.hsz.datasync.rainfall",
"com.gunshi.project.hsz.datasync.gate",
"com.gunshi.project.hsz.datasync.riverWaterLevel",
"com.gunshi.project.hsz.datasync.seepage",
"com.gunshi.project.hsz.datasync.waterLevel",
})
public class Main {

View File

@ -102,7 +102,7 @@ public class ForecastResultsController {
//收集实际数据和
List<ForecastResultVo> collect = voList.stream().filter(o -> {
return o.getYcRkQValue() != null;
return o.getRealRkQValue() != null;
}).collect(Collectors.toList());
BigDecimal rkVValue = BigDecimal.ZERO;
for (ForecastResultVo entity : collect) {

View File

@ -3,6 +3,7 @@ package com.gunshi.project.hsz.model;
import lombok.Data;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
/**
@ -45,7 +46,7 @@ public class RegressionEquation {
}
/**
*
* 使
*/
private String generateEquationString() {
StringBuilder sb = new StringBuilder("y = ");
@ -64,18 +65,19 @@ public class RegressionEquation {
coeff = coeff.abs();
}
// 系数和变量
// 系数和变量 - 保留至少20位小数
if (i == 0) {
// 常数项
sb.append(String.format("%.4f", coeff));
// 常数项 - 保留至少20位小数
sb.append(coeff.setScale(20, RoundingMode.HALF_UP).toPlainString());
} else {
// 非常数项
// 非常数项 - 保留至少20位小数
if (coeff.compareTo(BigDecimal.ONE) != 0 && coeff.compareTo(BigDecimal.ONE.negate()) != 0) {
sb.append(String.format("%.4f", coeff));
sb.append(coeff.setScale(20, RoundingMode.HALF_UP).toPlainString());
}
sb.append("x");
if (i > 1) {
sb.append("^").append(i);
// 使用Unicode上标数字
sb.append(getSuperscript(i));
}
}
}
@ -83,6 +85,30 @@ public class RegressionEquation {
return sb.toString();
}
/**
* Unicode
*/
private String getSuperscript(int number) {
String numStr = String.valueOf(number);
StringBuilder superscript = new StringBuilder();
for (char c : numStr.toCharArray()) {
switch (c) {
case '0': superscript.append('⁰'); break;
case '1': superscript.append('¹'); break;
case '2': superscript.append('²'); break;
case '3': superscript.append('³'); break;
case '4': superscript.append('⁴'); break;
case '5': superscript.append('⁵'); break;
case '6': superscript.append('⁶'); break;
case '7': superscript.append('⁷'); break;
case '8': superscript.append('⁸'); break;
case '9': superscript.append('⁹'); break;
default: superscript.append(c);
}
}
return superscript.toString();
}
/**
* xy
*/

View File

@ -28,8 +28,6 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -42,7 +40,8 @@ import java.util.stream.Collectors;
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, ForecastResults> {
public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, ForecastResults>
{
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@ -86,8 +85,8 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
/**
* @param forecastTask
* @description:
* @param forecastTask
* @return: java.util.List<com.gunshi.model.vo.FloodAlgorithemVo>
* @auther: cxw
* @date: 2024-07-30, , 14:40:45
@ -99,8 +98,8 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @param forecastTask
* @description:
* @param forecastTask
* @return: java.util.List<com.gunshi.project.xyt.entity.vo.ForecastResultVo>
* @auther: cxw
* @date: 2024-07-31, , 11:09:24
@ -124,19 +123,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
return voList;
}
private Date addMinites(Date date, Integer minite) {
Instant instant = date.toInstant().plus(minite, ChronoUnit.MINUTES);
return Date.from(instant);
}
private Date deleteMinites(Date date, Integer minite) {
Instant instant = date.toInstant().minus(minite, ChronoUnit.MINUTES);
return Date.from(instant);
}
/**
* @param forecastTask
* @description: ForecastResultVo
* @param forecastTask
* @return: java.util.List<com.gunshi.project.xyt.entity.vo.ForecastResultVo>
* @auther: cxw
* @date: 2024-08-05, , 17:14:52
@ -160,8 +149,6 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
Date nowHourTime = forecastTask.getNowTime();
Date startTime = forecastTask.getStartTime();
Date endTime = forecastTask.getEndTime();
//TODO 由于endTime为整点数据而监测时间为整点数据过五分
endTime = addMinites(endTime, 5);
// 获取整个时间线的降雨数据
List<StPptnR> pptnRAllList = new ArrayList<>();
List<StPptnR> pptnRFutureList = new ArrayList<>();
@ -196,7 +183,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 获取预报数据
try {
pptnRFutureList = getForecastDrpData(nowHourTime, attResBase.getStcd());
if (CollectionUtils.isEmpty(pptnRFutureList)) {
if(CollectionUtils.isEmpty(pptnRFutureList)) {
isHaveFuturePPtn = false;
log.error("该时间无预报数据");
}
@ -270,11 +257,6 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
List<StZvarlB> zvarlBS = stZvarlBService.list(new QueryWrapper<StZvarlB>().eq("stcd", attResBase.getStcd()).orderBy(true, true, "rz"));
// 水位历史数据
List<StRsvrR> rsvrRRealList = stRsvrRService.list(new QueryWrapper<StRsvrR>().eq("stcd", attResBase.getStcd()).ge("tm", startTime).le("tm", endTime));
//TODO 将过五分数据转为整点数据
rsvrRRealList.stream().forEach(o -> {
// 转换为 Instant 操作后再转回 Date
o.setTm(deleteMinites(o.getTm(), 5));
});
List<StRsvrR> resultList = reorganizeRsvrRData(rsvrRRealList, dt);
List<Date[]> periods = splitByDay8To8(startTime, endTime);
// v累计降雨
@ -334,14 +316,14 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
for (int i = voList.size() - 1; i >= 0; i--) {
int index = lastRArr.size() - 1 - (voList.size() - 1 - i);
lastRArr.set(index, voList.get(i).getR().doubleValue());
if (index <= 0) {
if(index <= 0){
break;
}
}
// 预测执行
List<FloodAlgorithemVo> forecastVoList = RrainfallForecast.getData(sdf.format(period[0]), forecastPa.getK().doubleValue(), forecastPa.getPa0().doubleValue(), Wm, forecastPa.getPt0().doubleValue(), H1, dt,
forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr);
forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr);
if (CollectionUtils.isNotEmpty(forecastVoList)) {
// 筛选同时段的真实水位数据
List<StRsvrR> realRsvrList = resultList.stream().filter(item -> item.getTm().compareTo(period[0]) >= 0 && item.getTm().compareTo(period[1]) <= 0).collect(Collectors.toList());
@ -422,6 +404,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
private List<Map<String, Object>> excuteForecastDebug(ForecastTask forecastTask) throws Exception {
List<ForecastResultVo> voList = new ArrayList<>();
// 获取配置参数
@ -475,7 +458,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 获取预报数据
try {
pptnRFutureList = getForecastDrpData(nowHourTime, attResBase.getStcd());
if (CollectionUtils.isEmpty(pptnRFutureList)) {
if(CollectionUtils.isEmpty(pptnRFutureList)) {
isHaveFuturePPtn = false;
log.error("该时间无预报数据");
}
@ -609,13 +592,13 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
for (int i = voList.size() - 1; i >= 0; i--) {
int index = lastRArr.size() - 1 - (voList.size() - 1 - i);
lastRArr.set(index, voList.get(i).getR().doubleValue());
if (index <= 0) {
if(index <= 0){
break;
}
}
// 预测执行
Map<String, Object> map = new HashMap<>();
Map<String,Object> map = new HashMap<>();
map.put("in period" + k, sdf.format(period[0]));
map.put("in K" + k, forecastPa.getK().doubleValue());
map.put("in pa0" + k, forecastPa.getPa0().doubleValue());
@ -632,7 +615,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
map.put("in Rsum" + k, Rsum.doubleValue());
map.put("in lastRArr" + k, lastRArr);
List<FloodAlgorithemVo> forecastVoList = RrainfallForecast.getData(sdf.format(period[0]), forecastPa.getK().doubleValue(), forecastPa.getPa0().doubleValue(), Wm, forecastPa.getPt0().doubleValue(), H1, dt,
forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr);
forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr);
map.put("out res" + k, forecastVoList);
res.add(map);
if (CollectionUtils.isNotEmpty(forecastVoList)) {
@ -715,24 +698,24 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @param zvarlBS 线
* @param resultVo vo
* @param rz
* @description:
* @param zvarlBS 线
* @param resultVo vo
* @param rz
* @return: void
* @auther: cxw
* @date: 2024-10-14, , 09:36:13
*/
private void calculateCap(List<StZvarlB> zvarlBS, ForecastResultVo resultVo, BigDecimal rz) {
if (CollectionUtils.isNotEmpty(zvarlBS)) {
private void calculateCap(List<StZvarlB> zvarlBS, ForecastResultVo resultVo, BigDecimal rz){
if(CollectionUtils.isNotEmpty(zvarlBS)){
BigDecimal maxRz = zvarlBS.stream().max(Comparator.comparing(StZvarlB::getRz)).get().getRz();
BigDecimal minRz = zvarlBS.stream().min(Comparator.comparing(StZvarlB::getRz)).get().getRz();
if (rz.compareTo(minRz) < 0 || rz.compareTo(maxRz) > 0) {
if(rz.compareTo(minRz) < 0 || rz.compareTo(maxRz) > 0){
return;
}
Map<BigDecimal, BigDecimal> stZvalMap = zvarlBS.stream().collect(Collectors.toMap(StZvarlB::getRz, StZvarlB::getW, (existing, replacement) -> existing));
List<BigDecimal> list = zvarlBS.stream().map(StZvarlB::getRz).sorted().collect(Collectors.toList());
resultVo.setNowCap(DataHandleUtil.calcData(rz, stZvalMap, list));
resultVo.setNowCap(DataHandleUtil.calcData(rz,stZvalMap,list));
}
}
@ -764,7 +747,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
tm = tm.replaceAll(" ", "").replaceAll("-", "");
List<RainGrib2Layer> gribList = forecastService.getGribData(tm, false);
if (CollectionUtils.isEmpty(gribList)) {
if(CollectionUtils.isEmpty(gribList)){
return pptnRFutureList;
}
//24小时每个网格的总量
@ -797,9 +780,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @description: T
* @param rsvrRRealList
* @param dt
* @description: T
* @return: java.util.List<com.gunshi.project.xyt.model.StRsvrR>
* @auther: cxw
*/
@ -854,13 +837,13 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @description: T
* @param filterList
* @param dt
* @param startTm
* @param endTm
* @param nowHourTime
* @param isHaveFuturePPtn
* @description: T
* @return: java.util.List<com.gunshi.project.xyt.model.StPptnR>
* @auther: cxw
*/
@ -868,9 +851,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 目前dt适配0.5和1
// 只保留整小时的数据
filterList = filterList.stream().filter(entity -> {
Date date = entity.getTm();
return date.getMinutes() == 0 && date.getSeconds() == 0;
}).collect(Collectors.toMap(
Date date = entity.getTm();
return date.getMinutes() == 0 && date.getSeconds() == 0;
}).collect(Collectors.toMap(
e -> e.getStcd() + "_" + e.getTm(), // 使用属性组合作为键
Function.identity(),
(existing, replacement) -> existing // 如果有冲突,保留现有的
@ -886,7 +869,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 使用时间一直往后加时间
while (dataTm.compareTo(endTm) < 0) {
// 当数据时间超过实时数据的最大时间并且没有预测雨量数据时,跳出
if (dataTm.compareTo(nowHourTime) >= 0 && !isHaveFuturePPtn) {
if(dataTm.compareTo(nowHourTime) >= 0 && !isHaveFuturePPtn){
break;
}
// 时间加1小时得到应该拆数据的时间后面往前推
@ -925,7 +908,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
calendar.add(Calendar.MINUTE, -(int) (dt * 60));
stPptnRHalfForecast.setTm(calendar.getTime());
stPptnRHalfReal.setTm(calendar.getTime());
if (BigDecimal.ONE.compareTo(BigDecimal.valueOf(dt)) != 0) {
if(BigDecimal.ONE.compareTo(BigDecimal.valueOf(dt)) != 0){
// 存半小时数据
stPptnRHalfForecast.setDrp("0.00");
listForForecast.add(stPptnRHalfForecast);
@ -948,10 +931,10 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @description:
* @param startDate
* @param endDate
* @description:
* @return: java.util.List<java.util.Date [ ]>
* @return: java.util.List<java.util.Date[]>
* @auther: cxw
*/
public static List<Date[]> splitByDay8To8(Date startDate, Date endDate) {
@ -1011,21 +994,21 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @param forecastProject
* @description: voList
* @param forecastProject
* @return: void
* @auther: cxw
* @date: 2024-08-07, , 15:52:19
*/
public void handleVoList(ForecastProject forecastProject) {
Map<String, Object> paramMap = forecastUseparamService.getMap(new QueryWrapper<ForecastUseparam>().eq("param_code", "dt"));
if (paramMap != null) {
if(paramMap != null){
BigDecimal dt = new BigDecimal(paramMap.get("param_value").toString());// 时间间隔小时h
BigDecimal ycMaxSwH = BigDecimal.ZERO;// 预报最高调洪水位
BigDecimal ycMaxRkQ = BigDecimal.ZERO;// 预报最大入库流量
BigDecimal ycMaxCkQ = BigDecimal.ZERO;// 预报最大下泄流量
BigDecimal ycSumRkQ = BigDecimal.ZERO;// 预报入库流量累计和
for (ForecastResultVo vo : forecastProject.getVoList()) {
for (ForecastResultVo vo : forecastProject.getVoList()){
BigDecimal ycSwHValue = vo.getYcSwHValue();
if (ycSwHValue.compareTo(ycMaxSwH) > 0) {
ycMaxSwH = ycSwHValue;
@ -1053,7 +1036,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// x1,y1和x2,y2的间隔必须要大于网格的最小长宽才能相交
BigDecimal dh = layer.getDh();// 单位高度
BigDecimal dw = layer.getDw();// 单位宽度
if (dw.compareTo(BigDecimal.valueOf(x2 - x1)) > 0 || dh.compareTo(BigDecimal.valueOf(y2 - y1)) > 0) {
if(dw.compareTo(BigDecimal.valueOf(x2 - x1)) > 0 || dh.compareTo(BigDecimal.valueOf(y2 - y1)) > 0){
throw new IllegalArgumentException("Geom参数区域范围不足预测降雨网格最小单位");
}
// 校验数据是否在最大允许范围(预测降雨所划定区域)
@ -1203,12 +1186,12 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
try {
BigDecimal result;
// 根据方程的形式判断阶数并计算
if (cleanEquation.contains("x^4")) {
// 根据方程的形式判断阶数并计算(支持数学符号和传统符号)
if (cleanEquation.contains("x⁴") || cleanEquation.contains("x^4")) {
result = calculateFourthOrder(cleanEquation, x);
} else if (cleanEquation.contains("x^3")) {
} else if (cleanEquation.contains("x³") || cleanEquation.contains("x^3")) {
result = calculateThirdOrder(cleanEquation, x);
} else if (cleanEquation.contains("x^2")) {
} else if (cleanEquation.contains("x²") || cleanEquation.contains("x^2")) {
result = calculateSecondOrder(cleanEquation, x);
} else {
result = calculateFirstOrder(cleanEquation, x);
@ -1221,7 +1204,6 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
}
/**
* 线 y = ax + b
*/
@ -1239,63 +1221,69 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* y = ax^2 + bx + c
* y = ax² + bx + c
*/
private BigDecimal calculateSecondOrder(String equation, BigDecimal x) {
// 解析方程系数,格式如:-68.4211x^2+16312.8684x-972224.1397
String[] parts = equation.split("x");
// 解析方程系数,格式如:-68.4211x²+16312.8684x-972224.1397
// 支持两种格式x² 和 x^2
String normalizedEquation = equation.replace("x^2", "x²");
String[] parts = normalizedEquation.split("x");
if (parts.length < 3) {
return BigDecimal.ZERO;
}
BigDecimal a = parseCoefficient(parts[0]);
BigDecimal b = parseCoefficient(parts[1].replace("^2", ""));
BigDecimal b = parseCoefficient(parts[1].replace("²", ""));
BigDecimal c = parseCoefficient(parts[2]);
BigDecimal x2 = x.multiply(x); // x^2
BigDecimal x2 = x.multiply(x); // x²
return a.multiply(x2).add(b.multiply(x)).add(c);
}
/**
* y = ax^3 + bx^2 + cx + d
* y = ax³ + bx² + cx + d
*/
private BigDecimal calculateThirdOrder(String equation, BigDecimal x) {
// 解析方程系数,格式如:-2291.6667x^3+819497.9167x^2-97683901.8750x+3881297151.1650
String[] parts = equation.split("x");
// 解析方程系数,格式如:-2291.6667x³+819497.9167x²-97683901.8750x+3881297151.1650
// 支持两种格式x³ 和 x^3, x² 和 x^2
String normalizedEquation = equation.replace("x^3", "x³").replace("x^2", "x²");
String[] parts = normalizedEquation.split("x");
if (parts.length < 4) {
return BigDecimal.ZERO;
}
BigDecimal a = parseCoefficient(parts[0]);
BigDecimal b = parseCoefficient(parts[1].replace("^3", "").replace("^2", ""));
BigDecimal c = parseCoefficient(parts[2].replace("^2", ""));
BigDecimal b = parseCoefficient(parts[1].replace("³", "").replace(", ""));
BigDecimal c = parseCoefficient(parts[2].replace("²", ""));
BigDecimal d = parseCoefficient(parts[3]);
BigDecimal x2 = x.multiply(x); // x^2
BigDecimal x3 = x2.multiply(x); // x^3
BigDecimal x2 = x.multiply(x); // x²
BigDecimal x3 = x2.multiply(x); // x³
return a.multiply(x3).add(b.multiply(x2)).add(c.multiply(x)).add(d);
}
/**
* y = ax^4 + bx^3 + cx^2 + dx + e
* y = ax + bx³ + cx² + dx + e
*/
private BigDecimal calculateFourthOrder(String equation, BigDecimal x) {
// 解析方程系数,格式如:-5.9039x^4+523.5482x^3+316095.2736x^2-57676816.2672x+2688986002.6804
String[] parts = equation.split("x");
// 解析方程系数,格式如:-5.9039x⁴+523.5482x³+316095.2736x²-57676816.2672x+2688986002.6804
// 支持两种格式x⁴ 和 x^4, x³ 和 x^3, x² 和 x^2
String normalizedEquation = equation.replace("x^4", "x⁴").replace("x^3", "x³").replace("x^2", "x²");
String[] parts = normalizedEquation.split("x");
if (parts.length < 5) {
return BigDecimal.ZERO;
}
BigDecimal a = parseCoefficient(parts[0]);
BigDecimal b = parseCoefficient(parts[1].replace("^4", "").replace("^3", ""));
BigDecimal c = parseCoefficient(parts[2].replace("^3", "").replace("^2", ""));
BigDecimal d = parseCoefficient(parts[3].replace("^2", ""));
BigDecimal b = parseCoefficient(parts[1].replace("⁴", "").replace(", ""));
BigDecimal c = parseCoefficient(parts[2].replace("³", "").replace(", ""));
BigDecimal d = parseCoefficient(parts[3].replace("²", ""));
BigDecimal e = parseCoefficient(parts[4]);
BigDecimal x2 = x.multiply(x); // x^2
BigDecimal x3 = x2.multiply(x); // x^3
BigDecimal x4 = x3.multiply(x); // x^4
BigDecimal x2 = x.multiply(x); // x²
BigDecimal x3 = x2.multiply(x); // x³
BigDecimal x4 = x3.multiply(x); // x
return a.multiply(x4).add(b.multiply(x3)).add(c.multiply(x2)).add(d.multiply(x)).add(e);
}
@ -1313,7 +1301,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
coeffStr += "1";
}
// 处理没有显式数字的情况x^2+x+1 中的第一个x系数为1
// 处理没有显式数字的情况x²+x+1 中的第一个x系数为1
if (coeffStr.equals("")) {
return BigDecimal.ONE;
}

View File

@ -19,10 +19,7 @@ import com.gunshi.project.hsz.common.mapper.JcskSlBMapper;
import com.gunshi.project.hsz.mapper.JcskSyREightAmMapper;
import com.gunshi.project.hsz.common.mapper.JcskSyRMapper;
import com.gunshi.project.hsz.common.model.JcskSyB;
import com.gunshi.project.hsz.model.AttResBase;
import com.gunshi.project.hsz.model.JcskSyREightAm;
import com.gunshi.project.hsz.model.RegressionEquation;
import com.gunshi.project.hsz.model.SyRegressionData;
import com.gunshi.project.hsz.model.*;
import com.gunshi.project.hsz.util.*;
import com.ruoyi.common.utils.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
@ -69,6 +66,9 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
@Autowired
private SyRegressionDataService syRegressionDataService;
@Autowired
private SyDataCheckRuleService syDataCheckRuleService;
public Page<JcskSyR> pageQuery(JcskSyRPageSo page) {
@ -824,6 +824,9 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
//组合成为 时间 库水位 管道水位的数据
List<OsmoticPressDetailVo> data = new ArrayList<>();
for (JcskSyREightAm eightAm : jcskSyREightAms) {
if(eightAm.getMstm() == null || eightAm.getSpprwl() == null){
continue;
}
OsmoticPressDetailVo detailVo = new OsmoticPressDetailVo();
// 设置监测时间和监测值(管道水位)
@ -833,7 +836,23 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
// 查找对应的库水位
BigDecimal rzValue = findClosestRzValue(rzMap, mstmStr);
if(rzValue == null){
continue;
}
detailVo.setRz(rzValue);
//获取数据清洗规则
SyDataCheckRule rule = syDataCheckRuleService.getByDvcd(dto.getDvcd());
if(rule != null && rule.getIsAvailable() == 1){
//校验这条数据是否符合规则
if(rzValue.compareTo(rule.getRz()) >=0){
//如果当前库水位大于等于设置库水位,则跳过这条数据
continue;
}
if(eightAm.getSpprwl().compareTo(rule.getSyValue()) <=0){
//如果当前监测值小于等于设置值,则跳过这套数据
continue;
}
}
data.add(detailVo);
}
if(data.isEmpty()){

View File

@ -51,4 +51,10 @@ public class SyDataCheckRuleService extends ServiceImpl<SyDataCheckRuleMapper, S
boolean flag = updateById(dto);
return flag;
}
public SyDataCheckRule getByDvcd(String dvcd) {
LambdaQueryWrapper<SyDataCheckRule> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SyDataCheckRule::getDvcd,dvcd);
return this.baseMapper.selectOne(queryWrapper);
}
}

View File

@ -103,19 +103,19 @@ public class PaDataTask {
forecastPaService.remove(new QueryWrapper<ForecastPa>().eq("tm", sdfDay.format(nowTime)).eq("stcd", attResBase.getResCode()));
// 获取最新pa
ForecastPa forecastPaLast = forecastPaService.getOne(new QueryWrapper<ForecastPa>().eq("stcd", skStcd).orderBy(true, false, "tm").last("limit 1"));
// 补数据时解开
// if(ObjectUtils.isEmpty(forecastPaLast)){
// forecastPaLast = new ForecastPa();
// forecastPaLast.setStcd(skStcd);
// forecastPaLast.setTm("2024-01-01");
// forecastPaLast.setK(new BigDecimal(0.97));
// forecastPaLast.setPa0(BigDecimal.ZERO);
// forecastPaLast.setIm(new BigDecimal(120));
// forecastPaLast.setPt0(BigDecimal.ZERO);
// forecastPaLast.setPa(BigDecimal.ZERO);
// forecastPaLast.setChtm(new Date());
//
// }
// 补数据时解开
if(ObjectUtils.isEmpty(forecastPaLast)){
forecastPaLast = new ForecastPa();
forecastPaLast.setStcd(skStcd);
forecastPaLast.setTm("2024-01-01");
forecastPaLast.setK(new BigDecimal(0.97));
forecastPaLast.setPa0(BigDecimal.ZERO);
forecastPaLast.setIm(new BigDecimal(120));
forecastPaLast.setPt0(BigDecimal.ZERO);
forecastPaLast.setPa(BigDecimal.ZERO);
forecastPaLast.setChtm(new Date());
}
if (CollectionUtils.isNotEmpty(paramList) && CollectionUtils.isNotEmpty(kList) && ObjectUtils.isNotEmpty(forecastPaLast) && !forecastPaLast.getTm().equals(sdfDay.format(nowTime))) {
Calendar calendar2 = Calendar.getInstance();
calendar2.setTime(sdfDay.parse(forecastPaLast.getTm()));

View File

@ -435,8 +435,8 @@ public class RegressionAnalysis {
}
private static BigDecimal calculateDeterminant3x3(BigDecimal a11, BigDecimal a12, BigDecimal a13,
BigDecimal a21, BigDecimal a22, BigDecimal a23,
BigDecimal a31, BigDecimal a32, BigDecimal a33) {
BigDecimal a21, BigDecimal a22, BigDecimal a23,
BigDecimal a31, BigDecimal a32, BigDecimal a33) {
return a11.multiply(a22.multiply(a33).subtract(a23.multiply(a32)))
.subtract(a12.multiply(a21.multiply(a33).subtract(a23.multiply(a31))))
.add(a13.multiply(a21.multiply(a32).subtract(a22.multiply(a31))));
@ -584,6 +584,7 @@ public class RegressionAnalysis {
return calculateCubic(data);
}
}
/**
*
*/
@ -620,75 +621,6 @@ public class RegressionAnalysis {
return new BigDecimal[]{A, B, C, D, E};
}
/**
* 线
* n Ax = b
*/
private static BigDecimal[] solveLinearSystemImproved(BigDecimal[][] matrix, BigDecimal[] vector) {
int n = vector.length;
// 复制矩阵和向量(避免修改原数据)
BigDecimal[][] a = new BigDecimal[n][n];
BigDecimal[] b = new BigDecimal[n];
for (int i = 0; i < n; i++) {
a[i] = matrix[i].clone();
b[i] = vector[i];
}
// 部分主元高斯消元:逐行处理,选择当前列的最大绝对值元素作为主元
for (int k = 0; k < n; k++) {
// 找到当前列k列中绝对值最大的行maxRow
int maxRow = k;
BigDecimal maxVal = a[k][k].abs(); // 初始为当前对角线元素
for (int i = k + 1; i < n; i++) {
BigDecimal current = a[i][k].abs();
if (current.compareTo(maxVal) > 0) {
maxVal = current;
maxRow = i;
}
}
// 交换行将最大主元所在行交换到当前行k
if (maxRow != k) {
BigDecimal[] tempRow = a[k];
a[k] = a[maxRow];
a[maxRow] = tempRow;
BigDecimal tempB = b[k];
b[k] = b[maxRow];
b[maxRow] = tempB;
}
// 检查主元是否为0矩阵奇异
if (a[k][k].compareTo(BigDecimal.ZERO) == 0) {
return null;
}
// 消元将第k列下方的元素消为0
for (int i = k + 1; i < n; i++) {
BigDecimal factor = a[i][k].divide(a[k][k], MathContext.DECIMAL128); // 除法保留高精度
for (int j = k; j < n; j++) {
a[i][j] = a[i][j].subtract(factor.multiply(a[k][j], MathContext.DECIMAL128), MathContext.DECIMAL128);
}
b[i] = b[i].subtract(factor.multiply(b[k], MathContext.DECIMAL128), MathContext.DECIMAL128);
}
}
// 回代:从最后一行开始,依次求解每个变量
BigDecimal[] x = new BigDecimal[n];
for (int i = n - 1; i >= 0; i--) {
BigDecimal sum = BigDecimal.ZERO;
for (int j = i + 1; j < n; j++) {
sum = sum.add(a[i][j].multiply(x[j], MathContext.DECIMAL128), MathContext.DECIMAL128);
}
x[i] = b[i].subtract(sum, MathContext.DECIMAL128)
.divide(a[i][i], MathContext.DECIMAL128); // 除法保留高精度
}
return x;
}
/**
* R²
@ -717,7 +649,6 @@ public class RegressionAnalysis {
return BigDecimal.ONE.subtract(ssRes.divide(ssTot, MathContext.DECIMAL128), MathContext.DECIMAL128);
}
/**
* x
*/
@ -744,4 +675,73 @@ public class RegressionAnalysis {
return sum.divide(new BigDecimal(data.size()), MathContext.DECIMAL128);
}
/**
* 使
*/
public static String generateEquationString(int order, List<BigDecimal> coefficients) {
StringBuilder sb = new StringBuilder("y = ");
for (int i = 0; i < coefficients.size(); i++) {
BigDecimal coeff = coefficients.get(i);
if (coeff.compareTo(BigDecimal.ZERO) == 0) {
continue;
}
// 处理符号
if (i > 0) {
if (coeff.compareTo(BigDecimal.ZERO) > 0) {
sb.append(" + ");
} else {
sb.append(" - ");
coeff = coeff.abs();
}
}
// 处理系数
if (i == 0 || coeff.compareTo(BigDecimal.ONE) != 0) {
// 格式化系数,避免科学计数法
String coeffStr = coeff.toPlainString();
// 去除不必要的尾随零
if (coeffStr.contains(".")) {
coeffStr = coeffStr.replaceAll("0+$", "").replaceAll("\\.$", "");
}
sb.append(coeffStr);
}
// 处理x的幂次
if (i > 0) {
sb.append("x");
if (i > 1) {
// 使用Unicode上标数字
sb.append(getSuperscript(i));
}
}
}
return sb.toString();
}
/**
* Unicode
*/
private static String getSuperscript(int number) {
String numStr = String.valueOf(number);
StringBuilder superscript = new StringBuilder();
for (char c : numStr.toCharArray()) {
switch (c) {
case '0': superscript.append('⁰'); break;
case '1': superscript.append('¹'); break;
case '2': superscript.append('²'); break;
case '3': superscript.append('³'); break;
case '4': superscript.append('⁴'); break;
case '5': superscript.append('⁵'); break;
case '6': superscript.append('⁶'); break;
case '7': superscript.append('⁷'); break;
case '8': superscript.append('⁸'); break;
case '9': superscript.append('⁹'); break;
default: superscript.append(c);
}
}
return superscript.toString();
}
}