回归修改

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<>();
@ -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累计降雨
@ -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<>();
// 获取配置参数
@ -715,10 +698,10 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @description:
* @param zvarlBS 线
* @param resultVo vo
* @param rz
* @description:
* @return: void
* @auther: cxw
* @date: 2024-10-14, , 09:36:13
@ -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
*/
@ -948,9 +931,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @description:
* @param startDate
* @param endDate
* @description:
* @return: java.util.List<java.util.Date[]>
* @auther: cxw
*/
@ -1011,8 +994,8 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
}
/**
* @param forecastProject
* @description: voList
* @param forecastProject
* @return: void
* @auther: cxw
* @date: 2024-08-07, , 15:52:19
@ -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

@ -104,18 +104,18 @@ public class PaDataTask {
// 获取最新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

@ -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();
}
}