回归修改

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 @SpringBootApplication
@EnableScheduling @EnableScheduling
@MapperScan({ @MapperScan({
"com.gunshi.project.hsz.datasync.mapper", "com.gunshi.project.hsz.datasync.config",
"com.gunshi.project.hsz.datasync.mapper.jcsk", "com.gunshi.project.hsz.datasync.flow",
"com.gunshi.project.hsz.datasync.rsvrWaterLevel", "com.gunshi.project.hsz.datasync.gnss",
"com.gunshi.project.hsz.datasync.rainfall", "com.gunshi.project.hsz.datasync.rainfall",
"com.gunshi.project.hsz.datasync.gate", "com.gunshi.project.hsz.datasync.seepage",
"com.gunshi.project.hsz.datasync.riverWaterLevel", "com.gunshi.project.hsz.datasync.waterLevel",
}) })
public class Main { public class Main {

View File

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

View File

@ -3,6 +3,7 @@ package com.gunshi.project.hsz.model;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List; import java.util.List;
/** /**
@ -45,7 +46,7 @@ public class RegressionEquation {
} }
/** /**
* * 使
*/ */
private String generateEquationString() { private String generateEquationString() {
StringBuilder sb = new StringBuilder("y = "); StringBuilder sb = new StringBuilder("y = ");
@ -64,18 +65,19 @@ public class RegressionEquation {
coeff = coeff.abs(); coeff = coeff.abs();
} }
// 系数和变量 // 系数和变量 - 保留至少20位小数
if (i == 0) { if (i == 0) {
// 常数项 // 常数项 - 保留至少20位小数
sb.append(String.format("%.4f", coeff)); sb.append(coeff.setScale(20, RoundingMode.HALF_UP).toPlainString());
} else { } else {
// 非常数项 // 非常数项 - 保留至少20位小数
if (coeff.compareTo(BigDecimal.ONE) != 0 && coeff.compareTo(BigDecimal.ONE.negate()) != 0) { 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"); sb.append("x");
if (i > 1) { if (i > 1) {
sb.append("^").append(i); // 使用Unicode上标数字
sb.append(getSuperscript(i));
} }
} }
} }
@ -83,6 +85,30 @@ public class RegressionEquation {
return sb.toString(); 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 * xy
*/ */

View File

@ -28,8 +28,6 @@ import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -42,7 +40,8 @@ import java.util.stream.Collectors;
@Service @Service
@Slf4j @Slf4j
@Transactional(rollbackFor = Exception.class) @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"); 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: * @description:
* @param forecastTask
* @return: java.util.List<com.gunshi.model.vo.FloodAlgorithemVo> * @return: java.util.List<com.gunshi.model.vo.FloodAlgorithemVo>
* @auther: cxw * @auther: cxw
* @date: 2024-07-30, , 14:40:45 * @date: 2024-07-30, , 14:40:45
@ -99,8 +98,8 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
/** /**
* @param forecastTask
* @description: * @description:
* @param forecastTask
* @return: java.util.List<com.gunshi.project.xyt.entity.vo.ForecastResultVo> * @return: java.util.List<com.gunshi.project.xyt.entity.vo.ForecastResultVo>
* @auther: cxw * @auther: cxw
* @date: 2024-07-31, , 11:09:24 * @date: 2024-07-31, , 11:09:24
@ -124,19 +123,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
return voList; 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 * @description: ForecastResultVo
* @param forecastTask
* @return: java.util.List<com.gunshi.project.xyt.entity.vo.ForecastResultVo> * @return: java.util.List<com.gunshi.project.xyt.entity.vo.ForecastResultVo>
* @auther: cxw * @auther: cxw
* @date: 2024-08-05, , 17:14:52 * @date: 2024-08-05, , 17:14:52
@ -160,8 +149,6 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
Date nowHourTime = forecastTask.getNowTime(); Date nowHourTime = forecastTask.getNowTime();
Date startTime = forecastTask.getStartTime(); Date startTime = forecastTask.getStartTime();
Date endTime = forecastTask.getEndTime(); Date endTime = forecastTask.getEndTime();
//TODO 由于endTime为整点数据而监测时间为整点数据过五分
endTime = addMinites(endTime, 5);
// 获取整个时间线的降雨数据 // 获取整个时间线的降雨数据
List<StPptnR> pptnRAllList = new ArrayList<>(); List<StPptnR> pptnRAllList = new ArrayList<>();
List<StPptnR> pptnRFutureList = new ArrayList<>(); List<StPptnR> pptnRFutureList = new ArrayList<>();
@ -196,7 +183,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 获取预报数据 // 获取预报数据
try { try {
pptnRFutureList = getForecastDrpData(nowHourTime, attResBase.getStcd()); pptnRFutureList = getForecastDrpData(nowHourTime, attResBase.getStcd());
if (CollectionUtils.isEmpty(pptnRFutureList)) { if(CollectionUtils.isEmpty(pptnRFutureList)) {
isHaveFuturePPtn = false; isHaveFuturePPtn = false;
log.error("该时间无预报数据"); 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<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)); 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<StRsvrR> resultList = reorganizeRsvrRData(rsvrRRealList, dt);
List<Date[]> periods = splitByDay8To8(startTime, endTime); List<Date[]> periods = splitByDay8To8(startTime, endTime);
// v累计降雨 // v累计降雨
@ -334,14 +316,14 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
for (int i = voList.size() - 1; i >= 0; i--) { for (int i = voList.size() - 1; i >= 0; i--) {
int index = lastRArr.size() - 1 - (voList.size() - 1 - i); int index = lastRArr.size() - 1 - (voList.size() - 1 - i);
lastRArr.set(index, voList.get(i).getR().doubleValue()); lastRArr.set(index, voList.get(i).getR().doubleValue());
if (index <= 0) { if(index <= 0){
break; break;
} }
} }
// 预测执行 // 预测执行
List<FloodAlgorithemVo> forecastVoList = RrainfallForecast.getData(sdf.format(period[0]), forecastPa.getK().doubleValue(), forecastPa.getPa0().doubleValue(), Wm, forecastPa.getPt0().doubleValue(), H1, dt, 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)) { 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()); 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 { private List<Map<String, Object>> excuteForecastDebug(ForecastTask forecastTask) throws Exception {
List<ForecastResultVo> voList = new ArrayList<>(); List<ForecastResultVo> voList = new ArrayList<>();
// 获取配置参数 // 获取配置参数
@ -475,7 +458,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 获取预报数据 // 获取预报数据
try { try {
pptnRFutureList = getForecastDrpData(nowHourTime, attResBase.getStcd()); pptnRFutureList = getForecastDrpData(nowHourTime, attResBase.getStcd());
if (CollectionUtils.isEmpty(pptnRFutureList)) { if(CollectionUtils.isEmpty(pptnRFutureList)) {
isHaveFuturePPtn = false; isHaveFuturePPtn = false;
log.error("该时间无预报数据"); log.error("该时间无预报数据");
} }
@ -609,13 +592,13 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
for (int i = voList.size() - 1; i >= 0; i--) { for (int i = voList.size() - 1; i >= 0; i--) {
int index = lastRArr.size() - 1 - (voList.size() - 1 - i); int index = lastRArr.size() - 1 - (voList.size() - 1 - i);
lastRArr.set(index, voList.get(i).getR().doubleValue()); lastRArr.set(index, voList.get(i).getR().doubleValue());
if (index <= 0) { if(index <= 0){
break; 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 period" + k, sdf.format(period[0]));
map.put("in K" + k, forecastPa.getK().doubleValue()); map.put("in K" + k, forecastPa.getK().doubleValue());
map.put("in pa0" + k, forecastPa.getPa0().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 Rsum" + k, Rsum.doubleValue());
map.put("in lastRArr" + k, lastRArr); 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, 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); map.put("out res" + k, forecastVoList);
res.add(map); res.add(map);
if (CollectionUtils.isNotEmpty(forecastVoList)) { if (CollectionUtils.isNotEmpty(forecastVoList)) {
@ -715,24 +698,24 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
/** /**
* @param zvarlBS 线
* @param resultVo vo
* @param rz
* @description: * @description:
* @param zvarlBS 线
* @param resultVo vo
* @param rz
* @return: void * @return: void
* @auther: cxw * @auther: cxw
* @date: 2024-10-14, , 09:36:13 * @date: 2024-10-14, , 09:36:13
*/ */
private void calculateCap(List<StZvarlB> zvarlBS, ForecastResultVo resultVo, BigDecimal rz) { private void calculateCap(List<StZvarlB> zvarlBS, ForecastResultVo resultVo, BigDecimal rz){
if (CollectionUtils.isNotEmpty(zvarlBS)) { if(CollectionUtils.isNotEmpty(zvarlBS)){
BigDecimal maxRz = zvarlBS.stream().max(Comparator.comparing(StZvarlB::getRz)).get().getRz(); BigDecimal maxRz = zvarlBS.stream().max(Comparator.comparing(StZvarlB::getRz)).get().getRz();
BigDecimal minRz = zvarlBS.stream().min(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; return;
} }
Map<BigDecimal, BigDecimal> stZvalMap = zvarlBS.stream().collect(Collectors.toMap(StZvarlB::getRz, StZvarlB::getW, (existing, replacement) -> existing)); 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()); 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("-", ""); tm = tm.replaceAll(" ", "").replaceAll("-", "");
List<RainGrib2Layer> gribList = forecastService.getGribData(tm, false); List<RainGrib2Layer> gribList = forecastService.getGribData(tm, false);
if (CollectionUtils.isEmpty(gribList)) { if(CollectionUtils.isEmpty(gribList)){
return pptnRFutureList; return pptnRFutureList;
} }
//24小时每个网格的总量 //24小时每个网格的总量
@ -797,9 +780,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
/** /**
* @description: T
* @param rsvrRRealList * @param rsvrRRealList
* @param dt * @param dt
* @description: T
* @return: java.util.List<com.gunshi.project.xyt.model.StRsvrR> * @return: java.util.List<com.gunshi.project.xyt.model.StRsvrR>
* @auther: cxw * @auther: cxw
*/ */
@ -854,13 +837,13 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
/** /**
* @description: T
* @param filterList * @param filterList
* @param dt * @param dt
* @param startTm * @param startTm
* @param endTm * @param endTm
* @param nowHourTime * @param nowHourTime
* @param isHaveFuturePPtn * @param isHaveFuturePPtn
* @description: T
* @return: java.util.List<com.gunshi.project.xyt.model.StPptnR> * @return: java.util.List<com.gunshi.project.xyt.model.StPptnR>
* @auther: cxw * @auther: cxw
*/ */
@ -868,9 +851,9 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 目前dt适配0.5和1 // 目前dt适配0.5和1
// 只保留整小时的数据 // 只保留整小时的数据
filterList = filterList.stream().filter(entity -> { filterList = filterList.stream().filter(entity -> {
Date date = entity.getTm(); Date date = entity.getTm();
return date.getMinutes() == 0 && date.getSeconds() == 0; return date.getMinutes() == 0 && date.getSeconds() == 0;
}).collect(Collectors.toMap( }).collect(Collectors.toMap(
e -> e.getStcd() + "_" + e.getTm(), // 使用属性组合作为键 e -> e.getStcd() + "_" + e.getTm(), // 使用属性组合作为键
Function.identity(), Function.identity(),
(existing, replacement) -> existing // 如果有冲突,保留现有的 (existing, replacement) -> existing // 如果有冲突,保留现有的
@ -886,7 +869,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// 使用时间一直往后加时间 // 使用时间一直往后加时间
while (dataTm.compareTo(endTm) < 0) { while (dataTm.compareTo(endTm) < 0) {
// 当数据时间超过实时数据的最大时间并且没有预测雨量数据时,跳出 // 当数据时间超过实时数据的最大时间并且没有预测雨量数据时,跳出
if (dataTm.compareTo(nowHourTime) >= 0 && !isHaveFuturePPtn) { if(dataTm.compareTo(nowHourTime) >= 0 && !isHaveFuturePPtn){
break; break;
} }
// 时间加1小时得到应该拆数据的时间后面往前推 // 时间加1小时得到应该拆数据的时间后面往前推
@ -925,7 +908,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
calendar.add(Calendar.MINUTE, -(int) (dt * 60)); calendar.add(Calendar.MINUTE, -(int) (dt * 60));
stPptnRHalfForecast.setTm(calendar.getTime()); stPptnRHalfForecast.setTm(calendar.getTime());
stPptnRHalfReal.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"); stPptnRHalfForecast.setDrp("0.00");
listForForecast.add(stPptnRHalfForecast); listForForecast.add(stPptnRHalfForecast);
@ -948,10 +931,10 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
/** /**
* @description:
* @param startDate * @param startDate
* @param endDate * @param endDate
* @description: * @return: java.util.List<java.util.Date[]>
* @return: java.util.List<java.util.Date [ ]>
* @auther: cxw * @auther: cxw
*/ */
public static List<Date[]> splitByDay8To8(Date startDate, Date endDate) { public static List<Date[]> splitByDay8To8(Date startDate, Date endDate) {
@ -1011,21 +994,21 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
/** /**
* @param forecastProject
* @description: voList * @description: voList
* @param forecastProject
* @return: void * @return: void
* @auther: cxw * @auther: cxw
* @date: 2024-08-07, , 15:52:19 * @date: 2024-08-07, , 15:52:19
*/ */
public void handleVoList(ForecastProject forecastProject) { public void handleVoList(ForecastProject forecastProject) {
Map<String, Object> paramMap = forecastUseparamService.getMap(new QueryWrapper<ForecastUseparam>().eq("param_code", "dt")); 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 dt = new BigDecimal(paramMap.get("param_value").toString());// 时间间隔小时h
BigDecimal ycMaxSwH = BigDecimal.ZERO;// 预报最高调洪水位 BigDecimal ycMaxSwH = BigDecimal.ZERO;// 预报最高调洪水位
BigDecimal ycMaxRkQ = BigDecimal.ZERO;// 预报最大入库流量 BigDecimal ycMaxRkQ = BigDecimal.ZERO;// 预报最大入库流量
BigDecimal ycMaxCkQ = BigDecimal.ZERO;// 预报最大下泄流量 BigDecimal ycMaxCkQ = BigDecimal.ZERO;// 预报最大下泄流量
BigDecimal ycSumRkQ = BigDecimal.ZERO;// 预报入库流量累计和 BigDecimal ycSumRkQ = BigDecimal.ZERO;// 预报入库流量累计和
for (ForecastResultVo vo : forecastProject.getVoList()) { for (ForecastResultVo vo : forecastProject.getVoList()){
BigDecimal ycSwHValue = vo.getYcSwHValue(); BigDecimal ycSwHValue = vo.getYcSwHValue();
if (ycSwHValue.compareTo(ycMaxSwH) > 0) { if (ycSwHValue.compareTo(ycMaxSwH) > 0) {
ycMaxSwH = ycSwHValue; ycMaxSwH = ycSwHValue;
@ -1053,7 +1036,7 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
// x1,y1和x2,y2的间隔必须要大于网格的最小长宽才能相交 // x1,y1和x2,y2的间隔必须要大于网格的最小长宽才能相交
BigDecimal dh = layer.getDh();// 单位高度 BigDecimal dh = layer.getDh();// 单位高度
BigDecimal dw = layer.getDw();// 单位宽度 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参数区域范围不足预测降雨网格最小单位"); throw new IllegalArgumentException("Geom参数区域范围不足预测降雨网格最小单位");
} }
// 校验数据是否在最大允许范围(预测降雨所划定区域) // 校验数据是否在最大允许范围(预测降雨所划定区域)
@ -1203,12 +1186,12 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
try { try {
BigDecimal result; BigDecimal result;
// 根据方程的形式判断阶数并计算 // 根据方程的形式判断阶数并计算(支持数学符号和传统符号)
if (cleanEquation.contains("x^4")) { if (cleanEquation.contains("x⁴") || cleanEquation.contains("x^4")) {
result = calculateFourthOrder(cleanEquation, x); result = calculateFourthOrder(cleanEquation, x);
} else if (cleanEquation.contains("x^3")) { } else if (cleanEquation.contains("x³") || cleanEquation.contains("x^3")) {
result = calculateThirdOrder(cleanEquation, x); result = calculateThirdOrder(cleanEquation, x);
} else if (cleanEquation.contains("x^2")) { } else if (cleanEquation.contains("x²") || cleanEquation.contains("x^2")) {
result = calculateSecondOrder(cleanEquation, x); result = calculateSecondOrder(cleanEquation, x);
} else { } else {
result = calculateFirstOrder(cleanEquation, x); result = calculateFirstOrder(cleanEquation, x);
@ -1221,7 +1204,6 @@ public class ForecastResultsService extends ServiceImpl<ForecastResultsMapper, F
} }
} }
/** /**
* 线 y = ax + b * 线 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) { private BigDecimal calculateSecondOrder(String equation, BigDecimal x) {
// 解析方程系数,格式如:-68.4211x^2+16312.8684x-972224.1397 // 解析方程系数,格式如:-68.4211x²+16312.8684x-972224.1397
String[] parts = equation.split("x"); // 支持两种格式x² 和 x^2
String normalizedEquation = equation.replace("x^2", "x²");
String[] parts = normalizedEquation.split("x");
if (parts.length < 3) { if (parts.length < 3) {
return BigDecimal.ZERO; return BigDecimal.ZERO;
} }
BigDecimal a = parseCoefficient(parts[0]); BigDecimal a = parseCoefficient(parts[0]);
BigDecimal b = parseCoefficient(parts[1].replace("^2", "")); BigDecimal b = parseCoefficient(parts[1].replace("²", ""));
BigDecimal c = parseCoefficient(parts[2]); 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); 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) { private BigDecimal calculateThirdOrder(String equation, BigDecimal x) {
// 解析方程系数,格式如:-2291.6667x^3+819497.9167x^2-97683901.8750x+3881297151.1650 // 解析方程系数,格式如:-2291.6667x³+819497.9167x²-97683901.8750x+3881297151.1650
String[] parts = equation.split("x"); // 支持两种格式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) { if (parts.length < 4) {
return BigDecimal.ZERO; return BigDecimal.ZERO;
} }
BigDecimal a = parseCoefficient(parts[0]); BigDecimal a = parseCoefficient(parts[0]);
BigDecimal b = parseCoefficient(parts[1].replace("^3", "").replace("^2", "")); BigDecimal b = parseCoefficient(parts[1].replace("³", "").replace(", ""));
BigDecimal c = parseCoefficient(parts[2].replace("^2", "")); BigDecimal c = parseCoefficient(parts[2].replace("²", ""));
BigDecimal d = parseCoefficient(parts[3]); BigDecimal d = parseCoefficient(parts[3]);
BigDecimal x2 = x.multiply(x); // x^2 BigDecimal x2 = x.multiply(x); // x²
BigDecimal x3 = x2.multiply(x); // x^3 BigDecimal x3 = x2.multiply(x); // x³
return a.multiply(x3).add(b.multiply(x2)).add(c.multiply(x)).add(d); 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) { private BigDecimal calculateFourthOrder(String equation, BigDecimal x) {
// 解析方程系数,格式如:-5.9039x^4+523.5482x^3+316095.2736x^2-57676816.2672x+2688986002.6804 // 解析方程系数,格式如:-5.9039x⁴+523.5482x³+316095.2736x²-57676816.2672x+2688986002.6804
String[] parts = equation.split("x"); // 支持两种格式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) { if (parts.length < 5) {
return BigDecimal.ZERO; return BigDecimal.ZERO;
} }
BigDecimal a = parseCoefficient(parts[0]); BigDecimal a = parseCoefficient(parts[0]);
BigDecimal b = parseCoefficient(parts[1].replace("^4", "").replace("^3", "")); BigDecimal b = parseCoefficient(parts[1].replace("⁴", "").replace(", ""));
BigDecimal c = parseCoefficient(parts[2].replace("^3", "").replace("^2", "")); BigDecimal c = parseCoefficient(parts[2].replace("³", "").replace(", ""));
BigDecimal d = parseCoefficient(parts[3].replace("^2", "")); BigDecimal d = parseCoefficient(parts[3].replace("²", ""));
BigDecimal e = parseCoefficient(parts[4]); BigDecimal e = parseCoefficient(parts[4]);
BigDecimal x2 = x.multiply(x); // x^2 BigDecimal x2 = x.multiply(x); // x²
BigDecimal x3 = x2.multiply(x); // x^3 BigDecimal x3 = x2.multiply(x); // x³
BigDecimal x4 = x3.multiply(x); // x^4 BigDecimal x4 = x3.multiply(x); // x
return a.multiply(x4).add(b.multiply(x3)).add(c.multiply(x2)).add(d.multiply(x)).add(e); 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"; coeffStr += "1";
} }
// 处理没有显式数字的情况x^2+x+1 中的第一个x系数为1 // 处理没有显式数字的情况x²+x+1 中的第一个x系数为1
if (coeffStr.equals("")) { if (coeffStr.equals("")) {
return BigDecimal.ONE; 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.mapper.JcskSyREightAmMapper;
import com.gunshi.project.hsz.common.mapper.JcskSyRMapper; import com.gunshi.project.hsz.common.mapper.JcskSyRMapper;
import com.gunshi.project.hsz.common.model.JcskSyB; import com.gunshi.project.hsz.common.model.JcskSyB;
import com.gunshi.project.hsz.model.AttResBase; import com.gunshi.project.hsz.model.*;
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.util.*; import com.gunshi.project.hsz.util.*;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
@ -69,6 +66,9 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
@Autowired @Autowired
private SyRegressionDataService syRegressionDataService; private SyRegressionDataService syRegressionDataService;
@Autowired
private SyDataCheckRuleService syDataCheckRuleService;
public Page<JcskSyR> pageQuery(JcskSyRPageSo page) { public Page<JcskSyR> pageQuery(JcskSyRPageSo page) {
@ -824,6 +824,9 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
//组合成为 时间 库水位 管道水位的数据 //组合成为 时间 库水位 管道水位的数据
List<OsmoticPressDetailVo> data = new ArrayList<>(); List<OsmoticPressDetailVo> data = new ArrayList<>();
for (JcskSyREightAm eightAm : jcskSyREightAms) { for (JcskSyREightAm eightAm : jcskSyREightAms) {
if(eightAm.getMstm() == null || eightAm.getSpprwl() == null){
continue;
}
OsmoticPressDetailVo detailVo = new OsmoticPressDetailVo(); OsmoticPressDetailVo detailVo = new OsmoticPressDetailVo();
// 设置监测时间和监测值(管道水位) // 设置监测时间和监测值(管道水位)
@ -833,7 +836,23 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
// 查找对应的库水位 // 查找对应的库水位
BigDecimal rzValue = findClosestRzValue(rzMap, mstmStr); BigDecimal rzValue = findClosestRzValue(rzMap, mstmStr);
if(rzValue == null){
continue;
}
detailVo.setRz(rzValue); 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); data.add(detailVo);
} }
if(data.isEmpty()){ if(data.isEmpty()){

View File

@ -51,4 +51,10 @@ public class SyDataCheckRuleService extends ServiceImpl<SyDataCheckRuleMapper, S
boolean flag = updateById(dto); boolean flag = updateById(dto);
return flag; 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())); forecastPaService.remove(new QueryWrapper<ForecastPa>().eq("tm", sdfDay.format(nowTime)).eq("stcd", attResBase.getResCode()));
// 获取最新pa // 获取最新pa
ForecastPa forecastPaLast = forecastPaService.getOne(new QueryWrapper<ForecastPa>().eq("stcd", skStcd).orderBy(true, false, "tm").last("limit 1")); ForecastPa forecastPaLast = forecastPaService.getOne(new QueryWrapper<ForecastPa>().eq("stcd", skStcd).orderBy(true, false, "tm").last("limit 1"));
// 补数据时解开 // 补数据时解开
// if(ObjectUtils.isEmpty(forecastPaLast)){ if(ObjectUtils.isEmpty(forecastPaLast)){
// forecastPaLast = new ForecastPa(); forecastPaLast = new ForecastPa();
// forecastPaLast.setStcd(skStcd); forecastPaLast.setStcd(skStcd);
// forecastPaLast.setTm("2024-01-01"); forecastPaLast.setTm("2024-01-01");
// forecastPaLast.setK(new BigDecimal(0.97)); forecastPaLast.setK(new BigDecimal(0.97));
// forecastPaLast.setPa0(BigDecimal.ZERO); forecastPaLast.setPa0(BigDecimal.ZERO);
// forecastPaLast.setIm(new BigDecimal(120)); forecastPaLast.setIm(new BigDecimal(120));
// forecastPaLast.setPt0(BigDecimal.ZERO); forecastPaLast.setPt0(BigDecimal.ZERO);
// forecastPaLast.setPa(BigDecimal.ZERO); forecastPaLast.setPa(BigDecimal.ZERO);
// forecastPaLast.setChtm(new Date()); forecastPaLast.setChtm(new Date());
//
// } }
if (CollectionUtils.isNotEmpty(paramList) && CollectionUtils.isNotEmpty(kList) && ObjectUtils.isNotEmpty(forecastPaLast) && !forecastPaLast.getTm().equals(sdfDay.format(nowTime))) { if (CollectionUtils.isNotEmpty(paramList) && CollectionUtils.isNotEmpty(kList) && ObjectUtils.isNotEmpty(forecastPaLast) && !forecastPaLast.getTm().equals(sdfDay.format(nowTime))) {
Calendar calendar2 = Calendar.getInstance(); Calendar calendar2 = Calendar.getInstance();
calendar2.setTime(sdfDay.parse(forecastPaLast.getTm())); 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, private static BigDecimal calculateDeterminant3x3(BigDecimal a11, BigDecimal a12, BigDecimal a13,
BigDecimal a21, BigDecimal a22, BigDecimal a23, BigDecimal a21, BigDecimal a22, BigDecimal a23,
BigDecimal a31, BigDecimal a32, BigDecimal a33) { BigDecimal a31, BigDecimal a32, BigDecimal a33) {
return a11.multiply(a22.multiply(a33).subtract(a23.multiply(a32))) return a11.multiply(a22.multiply(a33).subtract(a23.multiply(a32)))
.subtract(a12.multiply(a21.multiply(a33).subtract(a23.multiply(a31)))) .subtract(a12.multiply(a21.multiply(a33).subtract(a23.multiply(a31))))
.add(a13.multiply(a21.multiply(a32).subtract(a22.multiply(a31)))); .add(a13.multiply(a21.multiply(a32).subtract(a22.multiply(a31))));
@ -584,6 +584,7 @@ public class RegressionAnalysis {
return calculateCubic(data); return calculateCubic(data);
} }
} }
/** /**
* *
*/ */
@ -620,75 +621,6 @@ public class RegressionAnalysis {
return new BigDecimal[]{A, B, C, D, E}; 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² * R²
@ -717,7 +649,6 @@ public class RegressionAnalysis {
return BigDecimal.ONE.subtract(ssRes.divide(ssTot, MathContext.DECIMAL128), MathContext.DECIMAL128); return BigDecimal.ONE.subtract(ssRes.divide(ssTot, MathContext.DECIMAL128), MathContext.DECIMAL128);
} }
/** /**
* x * x
*/ */
@ -744,4 +675,73 @@ public class RegressionAnalysis {
return sum.divide(new BigDecimal(data.size()), MathContext.DECIMAL128); 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();
}
} }