新增预警规则
parent
fcd21e42fb
commit
b895f42e7d
|
|
@ -1,77 +1,211 @@
|
|||
package com.gunshi;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import com.gunshi.project.hsz.common.model.vo.OsmoticPressDetailVo;
|
||||
import com.gunshi.project.hsz.model.RegressionEquation;
|
||||
import com.gunshi.project.hsz.util.ProjectCalculateUtil;
|
||||
import com.gunshi.project.hsz.util.RegressionAnalysis;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.Format;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class Tests extends Thread {
|
||||
|
||||
static Queue<Integer> queue = new LinkedList<>();
|
||||
static int maxSize = 10;
|
||||
public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Tests tc = new Tests();
|
||||
// // 创建生产者线程
|
||||
// Thread producer = new Thread(() -> {
|
||||
// try {
|
||||
// int value = 0;
|
||||
// while (true) {
|
||||
// tc.produce();
|
||||
// Thread.sleep(2000); // 模拟生产耗时
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// Thread.currentThread().interrupt();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // 创建消费者线程
|
||||
// Thread consumer = new Thread(() -> {
|
||||
// try {
|
||||
// while (true) {
|
||||
// tc.customer();
|
||||
// Thread.sleep(1500); // 模拟消费耗时
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// Thread.currentThread().interrupt();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// producer.start();
|
||||
// consumer.start();
|
||||
CountDownLatch countDownLatch = new CountDownLatch(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
new Thread(() -> {
|
||||
System.out.println("执行任务中。。。");
|
||||
List<OsmoticPressDetailVo> res = new ArrayList<>();
|
||||
OsmoticPressDetailVo o1 = new OsmoticPressDetailVo();
|
||||
o1.setRz(new BigDecimal("119.19"));
|
||||
o1.setValue(new BigDecimal("99.65"));
|
||||
|
||||
OsmoticPressDetailVo o2 = new OsmoticPressDetailVo();
|
||||
o2.setRz(new BigDecimal("119.19"));
|
||||
o2.setValue(new BigDecimal("99.655"));
|
||||
|
||||
OsmoticPressDetailVo o3 = new OsmoticPressDetailVo();
|
||||
o3.setRz(new BigDecimal("119.2"));
|
||||
o3.setValue(new BigDecimal("99.665"));
|
||||
|
||||
OsmoticPressDetailVo o4 = new OsmoticPressDetailVo();
|
||||
o4.setRz(new BigDecimal("119.22"));
|
||||
o4.setValue(new BigDecimal("99.675"));
|
||||
|
||||
OsmoticPressDetailVo o5 = new OsmoticPressDetailVo();
|
||||
o5.setRz(new BigDecimal("119.23"));
|
||||
o5.setValue(new BigDecimal("99.645"));
|
||||
res.add(o1);
|
||||
res.add(o2);
|
||||
res.add(o5);
|
||||
res.add(o3);
|
||||
res.add(o4);
|
||||
RegressionEquation first = RegressionAnalysis.calculateLinear(res);
|
||||
System.out.println(first.toString());
|
||||
BigDecimal decimal = calculateRegressionValue(first.toString(), new BigDecimal("119.19"));
|
||||
System.out.println(decimal.toString());
|
||||
RegressionEquation second = RegressionAnalysis.calculateQuadratic(res);
|
||||
BigDecimal decimal1 = calculateRegressionValue(second.toString(), new BigDecimal("119.19"));
|
||||
System.out.println(decimal1.toString());
|
||||
System.out.println(second.toString());
|
||||
RegressionEquation three = RegressionAnalysis.calculateCubic(res);
|
||||
System.out.println(calculateRegressionValue(three.toString(), new BigDecimal("119.19")));
|
||||
System.out.println(three.toString());
|
||||
RegressionEquation four = RegressionAnalysis.calculateQuartic(res);
|
||||
// System.out.println(calculateRegressionValue(four.toString(), new BigDecimal("119.19")));
|
||||
System.out.println(four.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据回归方程计算y值
|
||||
* @param equation 回归方程字符串
|
||||
* @param x 自变量x的值
|
||||
* @return 计算得到的y值
|
||||
*/
|
||||
private static BigDecimal calculateRegressionValue(String equation, BigDecimal x) {
|
||||
if (equation == null || equation.trim().isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 清理方程字符串,移除空格和y=
|
||||
String cleanEquation = equation.replace("y =", "").replace(" ", "").toLowerCase();
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
countDownLatch.countDown();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
BigDecimal result;
|
||||
// 根据方程的形式判断阶数并计算
|
||||
if (cleanEquation.contains("x^4")) {
|
||||
result = calculateFourthOrder(cleanEquation, x);
|
||||
} else if (cleanEquation.contains("x^3")) {
|
||||
result = calculateThirdOrder(cleanEquation, x);
|
||||
} else if (cleanEquation.contains("x^2")) {
|
||||
result = calculateSecondOrder(cleanEquation, x);
|
||||
} else {
|
||||
result = calculateFirstOrder(cleanEquation, x);
|
||||
}
|
||||
}).start();
|
||||
// 四舍五入保留两位小数
|
||||
return result.setScale(2, RoundingMode.HALF_UP);
|
||||
} catch (Exception e) {
|
||||
// 计算异常时返回0
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
countDownLatch.await();
|
||||
System.out.println("所有任务执行完毕");
|
||||
}
|
||||
|
||||
public synchronized void produce() throws Exception{
|
||||
while (queue.size() == maxSize){
|
||||
System.out.println("队列已满,生产者等待...");
|
||||
wait();
|
||||
}
|
||||
queue.offer(0);
|
||||
System.out.println("生产者生产。。" + "队列大小为:" + queue.size());
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
|
||||
public synchronized void customer() throws Exception{
|
||||
while(queue.size() == 0){
|
||||
System.out.println("队列无数据,等待生产者生产");
|
||||
wait();
|
||||
/**
|
||||
* 计算一阶线性方程 y = ax + b
|
||||
*/
|
||||
private static BigDecimal calculateFirstOrder(String equation, BigDecimal x) {
|
||||
// 解析方程系数,格式如:0.0455x+94.2395
|
||||
String[] parts = equation.split("x");
|
||||
if (parts.length < 2) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
queue.poll();
|
||||
System.out.println("消费者消费。。" + "队列大小为:" + queue.size());
|
||||
notifyAll();
|
||||
|
||||
BigDecimal a = parseCoefficient(parts[0]);
|
||||
BigDecimal b = parseCoefficient(parts[1]);
|
||||
|
||||
return a.multiply(x).add(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算二阶方程 y = ax^2 + bx + c
|
||||
*/
|
||||
private static BigDecimal calculateSecondOrder(String equation, BigDecimal x) {
|
||||
// 解析方程系数,格式如:-68.4211x^2+16312.8684x-972224.1397
|
||||
String[] parts = equation.split("x");
|
||||
if (parts.length < 3) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
BigDecimal a = parseCoefficient(parts[0]);
|
||||
BigDecimal b = parseCoefficient(parts[1].replace("^2", ""));
|
||||
BigDecimal c = parseCoefficient(parts[2]);
|
||||
|
||||
BigDecimal x2 = x.multiply(x); // x^2
|
||||
return a.multiply(x2).add(b.multiply(x)).add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算三阶方程 y = ax^3 + bx^2 + cx + d
|
||||
*/
|
||||
private static BigDecimal calculateThirdOrder(String equation, BigDecimal x) {
|
||||
// 解析方程系数,格式如:-2291.6667x^3+819497.9167x^2-97683901.8750x+3881297151.1650
|
||||
String[] parts = equation.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 d = parseCoefficient(parts[3]);
|
||||
|
||||
BigDecimal x2 = x.multiply(x); // x^2
|
||||
BigDecimal x3 = x2.multiply(x); // x^3
|
||||
|
||||
return a.multiply(x3).add(b.multiply(x2)).add(c.multiply(x)).add(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算四阶方程 y = ax^4 + bx^3 + cx^2 + dx + e
|
||||
*/
|
||||
private static BigDecimal calculateFourthOrder(String equation, BigDecimal x) {
|
||||
// 解析方程系数,格式如:-5.9039x^4+523.5482x^3+316095.2736x^2-57676816.2672x+2688986002.6804
|
||||
String[] parts = equation.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 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
|
||||
|
||||
return a.multiply(x4).add(b.multiply(x3)).add(c.multiply(x2)).add(d.multiply(x)).add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析系数,处理正负号和数字格式
|
||||
*/
|
||||
private static BigDecimal parseCoefficient(String coeffStr) {
|
||||
if (coeffStr == null || coeffStr.isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 处理空字符串情况
|
||||
if (coeffStr.equals("+") || coeffStr.equals("-")) {
|
||||
coeffStr += "1";
|
||||
}
|
||||
|
||||
// 处理没有显式数字的情况,如:x^2+x+1 中的第一个x系数为1
|
||||
if (coeffStr.equals("")) {
|
||||
return BigDecimal.ONE;
|
||||
}
|
||||
|
||||
try {
|
||||
return new BigDecimal(coeffStr);
|
||||
} catch (NumberFormatException e) {
|
||||
// 如果解析失败,尝试处理特殊情况
|
||||
if (coeffStr.equals("+")) {
|
||||
return BigDecimal.ONE;
|
||||
} else if (coeffStr.equals("-")) {
|
||||
return BigDecimal.ONE.negate();
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 描述: 预报_预测结果表
|
||||
|
|
@ -97,6 +99,18 @@ public class ForecastResultsController {
|
|||
if (CollectionUtils.isNotEmpty(voList)) {
|
||||
service.handleVoList(forecastProject);
|
||||
}
|
||||
|
||||
//收集实际数据和
|
||||
List<ForecastResultVo> collect = voList.stream().filter(o -> {
|
||||
return o.getYcRkQValue() != null;
|
||||
}).collect(Collectors.toList());
|
||||
BigDecimal rkVValue = BigDecimal.ZERO;
|
||||
for (ForecastResultVo entity : collect) {
|
||||
rkVValue = rkVValue.add(entity.getRealRkQValue().multiply(new BigDecimal("3600")));
|
||||
}
|
||||
// 转换为万m³
|
||||
rkVValue = rkVValue.divide(new BigDecimal("10000"), 2, BigDecimal.ROUND_HALF_UP);
|
||||
forecastProject.setRkVValue(rkVValue);
|
||||
return R.ok(forecastProject);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.gunshi.project.hsz.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gunshi.core.result.R;
|
||||
import com.gunshi.project.hsz.entity.so.TermiteSurveyPageSo;
|
||||
import com.gunshi.project.hsz.entity.so.WarningRulePageSo;
|
||||
import com.gunshi.project.hsz.model.TermiteSurvey;
|
||||
import com.gunshi.project.hsz.model.WarningRule;
|
||||
import com.gunshi.project.hsz.service.WarningRuleService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "预警规则")
|
||||
@RestController
|
||||
@RequestMapping(value="/warn/rule")
|
||||
public class WarningRuleController {
|
||||
|
||||
@Autowired
|
||||
private WarningRuleService warningRuleService;
|
||||
|
||||
|
||||
@Operation(summary = "分页")
|
||||
@PostMapping("/page")
|
||||
public R<Page<WarningRule>> page(@RequestBody @Validated WarningRulePageSo page) {
|
||||
return R.ok(warningRuleService.pageQuery(page));
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "新增")
|
||||
@PostMapping("/insert")
|
||||
public R<WarningRule> insert(@RequestBody @Validated WarningRule dto) {
|
||||
return R.ok(warningRuleService.saveData(dto));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.gunshi.project.hsz.entity.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum IndicatorTypeEnum {
|
||||
|
||||
REAL_WATER_LEVEL("REAL_WATER_LEVEL", "实时水位"),
|
||||
PEAK_FLOW("PEAK_FLOW", "预报洪峰流量"),
|
||||
RAINFALL("RAINFALL", "降雨量"),
|
||||
WATER_STORAGE("WATER_STORAGE", "蓄水量"),
|
||||
FORECAST_RAINFALL("FORECAST_RAINFALL", "预报降雨量");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
IndicatorTypeEnum(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public static IndicatorTypeEnum getByCode(String code) {
|
||||
for (IndicatorTypeEnum type : values()) {
|
||||
if (type.getCode().equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.gunshi.project.hsz.entity.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum OperatorEnum {
|
||||
|
||||
GREATER_THAN(">", "大于"),
|
||||
GREATER_EQUAL(">=", "大于等于"),
|
||||
LESS_THAN("<", "小于"),
|
||||
LESS_EQUAL("<=", "小于等于");
|
||||
|
||||
private final String symbol;
|
||||
private final String description;
|
||||
|
||||
OperatorEnum(String symbol, String description) {
|
||||
this.symbol = symbol;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public static OperatorEnum getBySymbol(String symbol) {
|
||||
for (OperatorEnum operator : values()) {
|
||||
if (operator.getSymbol().equals(symbol)) {
|
||||
return operator;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.gunshi.project.hsz.entity.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum RelationTypeEnum {
|
||||
|
||||
AND("AND", "且"),
|
||||
OR("OR", "或");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
RelationTypeEnum(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public static RelationTypeEnum getByCode(String code) {
|
||||
for (RelationTypeEnum type : values()) {
|
||||
if (type.getCode().equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.gunshi.project.hsz.entity.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum WarningTypeEnum {
|
||||
|
||||
FLOOD("FLOOD", "洪水预警"),
|
||||
DROUGHT("DROUGHT", "干旱预警");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
WarningTypeEnum(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public static WarningTypeEnum getByCode(String code) {
|
||||
for (WarningTypeEnum type : values()) {
|
||||
if (type.getCode().equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.gunshi.project.hsz.entity.so;
|
||||
|
||||
|
||||
import com.gunshi.db.dto.PageSo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class WarningRulePageSo {
|
||||
|
||||
@NotNull(message = "分页参数不能为空")
|
||||
@Schema(description = "分页参数")
|
||||
private PageSo pageSo;
|
||||
|
||||
private String ruleName;
|
||||
|
||||
private String warningType;
|
||||
}
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
package com.gunshi.project.hsz.mapper;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gunshi.project.hsz.model.SyRegressionData;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SyRegressionDataMapper extends BaseMapper<SyRegressionData> {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.gunshi.project.hsz.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gunshi.project.hsz.model.WarningCondition;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface WarningConditionMapper extends BaseMapper<WarningCondition> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.gunshi.project.hsz.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import com.gunshi.project.hsz.model.WarningRule;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface WarningRuleMapper extends BaseMapper<WarningRule> {
|
||||
}
|
||||
|
|
@ -177,4 +177,11 @@ public class ForecastProject extends GenericPageParams implements Serializable {
|
|||
@Schema(description = "预报洪水总量(万m³)")
|
||||
@TableField(exist = false)
|
||||
private BigDecimal ycSumFlood;
|
||||
|
||||
/**
|
||||
* 预报洪水总量(万m³)
|
||||
*/
|
||||
@Schema(description = "入库水量(m³)")
|
||||
@TableField(exist = false)
|
||||
private BigDecimal rkVValue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import jakarta.validation.constraints.Size;
|
|||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
|
|
@ -81,4 +82,9 @@ public class SyRegressionData implements Serializable {
|
|||
@Schema(description = "排序(一阶-四阶)")
|
||||
private Integer order;
|
||||
|
||||
|
||||
@TableField(value = "create_time")
|
||||
@JsonFormat(pattern = DateFormatString.YYYY_MM_DD_HH_MM_SS, timezone = "GMT+8")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.gunshi.project.hsz.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 预警规则-预警指标表
|
||||
*/
|
||||
@Data
|
||||
@TableName("warning_condition")
|
||||
public class WarningCondition {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 规则ID
|
||||
*/
|
||||
@TableField("rule_id")
|
||||
private Long ruleId;
|
||||
|
||||
/**
|
||||
* 条件排序字段
|
||||
*/
|
||||
@TableField("_order")
|
||||
private Integer order;
|
||||
|
||||
/**
|
||||
* 预警指标类型
|
||||
*/
|
||||
@TableField("indicator_type")
|
||||
private String indicatorType;
|
||||
|
||||
/**
|
||||
* 测点编码
|
||||
*/
|
||||
@TableField("stcd")
|
||||
private String stcd;
|
||||
|
||||
/**
|
||||
* 比较运算符
|
||||
*/
|
||||
@TableField("_operator")
|
||||
private String operator;
|
||||
|
||||
/**
|
||||
* 阈值
|
||||
*/
|
||||
@TableField("threshold_value")
|
||||
private BigDecimal thresholdValue;
|
||||
|
||||
/**
|
||||
* 时长/时段(小时)
|
||||
*/
|
||||
@TableField("duration_hours")
|
||||
private Integer durationHours;
|
||||
|
||||
/**
|
||||
* 与前一个条件的关系:AND-且,OR-或(最后一个条件为空)
|
||||
*/
|
||||
@TableField("relation_type")
|
||||
private String relationType;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.gunshi.project.hsz.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 预警规则主表
|
||||
*/
|
||||
@Data
|
||||
@TableName("warning_rule")
|
||||
public class WarningRule {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 规则名称
|
||||
*/
|
||||
@TableField("rule_name")
|
||||
private String ruleName;
|
||||
|
||||
/**
|
||||
* 预警类型:FLOOD-洪水预警,DROUGHT-干旱预警
|
||||
*/
|
||||
@TableField("warning_type")
|
||||
private String warningType;
|
||||
|
||||
/**
|
||||
* 状态:0-未启用,1-启用
|
||||
*/
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField("create_name")
|
||||
private String createName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 预警条件列表
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<WarningCondition> conditions;
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ 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.util.*;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
|
@ -65,6 +66,9 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
|
|||
@Autowired
|
||||
private JcskSyREightAmMapper jcskSyREightAmMapper;
|
||||
|
||||
@Autowired
|
||||
private SyRegressionDataService syRegressionDataService;
|
||||
|
||||
|
||||
|
||||
public Page<JcskSyR> pageQuery(JcskSyRPageSo page) {
|
||||
|
|
@ -835,23 +839,58 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
|
|||
if(data.isEmpty()){
|
||||
return res;
|
||||
}
|
||||
List<SyRegressionData> saves = new ArrayList<>();
|
||||
RegressionEquation first = RegressionAnalysis.calculateLinear(data);
|
||||
LocalDateTime createTime = LocalDateTime.now();
|
||||
if(first != null){
|
||||
res.setOne(first.toString());
|
||||
SyRegressionData syRegressionData = new SyRegressionData();
|
||||
syRegressionData.setOrder(1);
|
||||
syRegressionData.setRegressionEquation(first.toString());
|
||||
syRegressionData.setDvcd(dto.getDvcd());
|
||||
syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart());
|
||||
syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd());
|
||||
syRegressionData.setCreateTime(createTime);
|
||||
saves.add(syRegressionData);
|
||||
}
|
||||
RegressionEquation second = RegressionAnalysis.calculateQuadratic(data);
|
||||
if(second != null){
|
||||
res.setTwo(second.toString());
|
||||
SyRegressionData syRegressionData = new SyRegressionData();
|
||||
syRegressionData.setOrder(2);
|
||||
syRegressionData.setRegressionEquation(second.toString());
|
||||
syRegressionData.setDvcd(dto.getDvcd());
|
||||
syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart());
|
||||
syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd());
|
||||
syRegressionData.setCreateTime(createTime);
|
||||
saves.add(syRegressionData);
|
||||
}
|
||||
RegressionEquation three = RegressionAnalysis.calculateCubic(data);
|
||||
if(three != null){
|
||||
res.setThree(three.toString());
|
||||
SyRegressionData syRegressionData = new SyRegressionData();
|
||||
syRegressionData.setOrder(3);
|
||||
syRegressionData.setRegressionEquation(three.toString());
|
||||
syRegressionData.setDvcd(dto.getDvcd());
|
||||
syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart());
|
||||
syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd());
|
||||
syRegressionData.setCreateTime(createTime);
|
||||
saves.add(syRegressionData);
|
||||
}
|
||||
RegressionEquation four = RegressionAnalysis.calculateQuartic(data);
|
||||
if(four != null){
|
||||
res.setFour(four.toString());
|
||||
SyRegressionData syRegressionData = new SyRegressionData();
|
||||
syRegressionData.setOrder(4);
|
||||
syRegressionData.setRegressionEquation(four.toString());
|
||||
syRegressionData.setDvcd(dto.getDvcd());
|
||||
syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart());
|
||||
syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd());
|
||||
syRegressionData.setCreateTime(createTime);
|
||||
saves.add(syRegressionData);
|
||||
}
|
||||
res.setDatas(data);
|
||||
syRegressionDataService.saveBatch(saves);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package com.gunshi.project.hsz.service;
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gunshi.project.hsz.mapper.StZvarlBMapper;
|
||||
|
||||
import com.gunshi.project.hsz.mapper.SyRegressionDataMapper;
|
||||
import com.gunshi.project.hsz.model.StZvarlB;
|
||||
import com.gunshi.project.hsz.model.SyRegressionData;
|
||||
|
|
@ -27,6 +28,8 @@ public class SyRegressionDataService extends ServiceImpl<SyRegressionDataMapper,
|
|||
if(dto.getOrder() != null){
|
||||
queryWrapper.eq(SyRegressionData::getOrder, dto.getOrder());
|
||||
}
|
||||
queryWrapper.orderByDesc(SyRegressionData::getCreateTime)
|
||||
.last("limit 1");
|
||||
List<SyRegressionData> syRegressionData = this.baseMapper.selectList(queryWrapper);
|
||||
return syRegressionData;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.gunshi.project.hsz.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gunshi.project.hsz.mapper.WarningConditionMapper;
|
||||
import com.gunshi.project.hsz.mapper.WarningRuleMapper;
|
||||
import com.gunshi.project.hsz.model.WarningCondition;
|
||||
import com.gunshi.project.hsz.model.WarningRule;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class WarningConditionService extends ServiceImpl<WarningConditionMapper, WarningCondition> {
|
||||
|
||||
|
||||
|
||||
public List<WarningCondition> getListByRuleId(Serializable id){
|
||||
LambdaQueryWrapper<WarningCondition> queryWrapper = new LambdaQueryWrapper<WarningCondition>();
|
||||
queryWrapper.eq(WarningCondition::getRuleId,id);
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.gunshi.project.hsz.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gunshi.project.hsz.entity.so.WarningRulePageSo;
|
||||
import com.gunshi.project.hsz.mapper.TermiteSurveyMapper;
|
||||
import com.gunshi.project.hsz.mapper.WarningRuleMapper;
|
||||
import com.gunshi.project.hsz.model.TermiteSurvey;
|
||||
import com.gunshi.project.hsz.model.WarningCondition;
|
||||
import com.gunshi.project.hsz.model.WarningRule;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class WarningRuleService extends ServiceImpl<WarningRuleMapper, WarningRule> {
|
||||
|
||||
@Autowired
|
||||
private WarningConditionService warningConditionService;
|
||||
|
||||
public Page<WarningRule> pageQuery(WarningRulePageSo page) {
|
||||
LambdaQueryWrapper<WarningRule> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if(!StringUtils.isBlank(page.getRuleName())){
|
||||
queryWrapper.like(WarningRule::getRuleName, page.getRuleName());
|
||||
}
|
||||
if(!StringUtils.isBlank(page.getRuleName())){
|
||||
queryWrapper.eq(WarningRule::getWarningType, page.getWarningType());
|
||||
}
|
||||
Page<WarningRule> warningRulePage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper);
|
||||
|
||||
for (WarningRule record : warningRulePage.getRecords()) {
|
||||
List<WarningCondition> listByRuleId = warningConditionService.getListByRuleId(record.getId());
|
||||
record.setConditions(listByRuleId);
|
||||
}
|
||||
return warningRulePage;
|
||||
}
|
||||
|
||||
public WarningRule saveData(WarningRule dto) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,16 @@ public class RegressionAnalysis {
|
|||
|
||||
n = validData.size();
|
||||
|
||||
// 检查所有x值是否相同
|
||||
boolean allXSame = checkAllXSame(validData);
|
||||
if (allXSame) {
|
||||
// 所有x值相同,返回常数函数(y = 平均值)
|
||||
BigDecimal meanY = calculateMeanY(validData);
|
||||
List<BigDecimal> collect = List.of(meanY);
|
||||
BigDecimal rSquareds = BigDecimal.ZERO; // 这种情况下R²为0
|
||||
return new RegressionEquation(1, collect, rSquareds, n);
|
||||
}
|
||||
|
||||
BigDecimal sumX = BigDecimal.ZERO;
|
||||
BigDecimal sumY = BigDecimal.ZERO;
|
||||
BigDecimal sumXY = BigDecimal.ZERO;
|
||||
|
|
@ -93,6 +103,16 @@ public class RegressionAnalysis {
|
|||
|
||||
n = validData.size();
|
||||
|
||||
// 检查所有x值是否相同
|
||||
boolean allXSame = checkAllXSame(validData);
|
||||
if (allXSame) {
|
||||
// 所有x值相同,返回常数函数
|
||||
BigDecimal meanY = calculateMeanY(validData);
|
||||
List<BigDecimal> collect = List.of(meanY);
|
||||
BigDecimal rSquaredsame = BigDecimal.ZERO;
|
||||
return new RegressionEquation(2, collect, rSquaredsame, n);
|
||||
}
|
||||
|
||||
// 计算各项和
|
||||
BigDecimal sumX = BigDecimal.ZERO, sumY = BigDecimal.ZERO;
|
||||
BigDecimal sumX2 = BigDecimal.ZERO, sumX3 = BigDecimal.ZERO, sumX4 = BigDecimal.ZERO;
|
||||
|
|
@ -437,21 +457,29 @@ public class RegressionAnalysis {
|
|||
|
||||
|
||||
/**
|
||||
* 计算四次回归方程(4阶)
|
||||
* 计算四次回归方程(4阶)- 与三阶保持一致精度,失败时自动降级为三阶
|
||||
*/
|
||||
public static RegressionEquation calculateQuartic(List<OsmoticPressDetailVo> data) {
|
||||
int n = 0;
|
||||
List<BigDecimal> coeffsList = null;
|
||||
BigDecimal rSquared = null;
|
||||
try {
|
||||
List<OsmoticPressDetailVo> validData = filterValidData(data);
|
||||
if (validData.size() < 5) {
|
||||
throw new IllegalArgumentException("四次回归至少需要5个数据点");
|
||||
// 数据点不足5个,尝试三阶
|
||||
return calculateCubic(data);
|
||||
}
|
||||
|
||||
n = validData.size();
|
||||
int n = validData.size();
|
||||
|
||||
// 计算各项和:sumX, sumY, sumX2, sumX3, sumX4, sumX5, sumX6, sumX7, sumX8, sumXY, sumX2Y, sumX3Y, sumX4Y
|
||||
// 检查所有x值是否相同
|
||||
boolean allXSame = checkAllXSame(validData);
|
||||
if (allXSame) {
|
||||
BigDecimal meanY = calculateMeanY(validData);
|
||||
return new RegressionEquation(1, List.of(meanY), BigDecimal.ZERO, n);
|
||||
}
|
||||
|
||||
// 与三阶保持一致的200位精度
|
||||
MathContext mc = new MathContext(200, RoundingMode.HALF_UP);
|
||||
|
||||
// 计算各项和(高精度)
|
||||
BigDecimal sumX = BigDecimal.ZERO, sumY = BigDecimal.ZERO;
|
||||
BigDecimal sumX2 = BigDecimal.ZERO, sumX3 = BigDecimal.ZERO, sumX4 = BigDecimal.ZERO;
|
||||
BigDecimal sumX5 = BigDecimal.ZERO, sumX6 = BigDecimal.ZERO, sumX7 = BigDecimal.ZERO, sumX8 = BigDecimal.ZERO;
|
||||
|
|
@ -461,58 +489,135 @@ public class RegressionAnalysis {
|
|||
BigDecimal x = vo.getRz();
|
||||
BigDecimal y = vo.getValue();
|
||||
|
||||
BigDecimal x2 = x.multiply(x);
|
||||
BigDecimal x3 = x2.multiply(x);
|
||||
BigDecimal x4 = x3.multiply(x);
|
||||
BigDecimal x5 = x4.multiply(x);
|
||||
BigDecimal x6 = x5.multiply(x);
|
||||
BigDecimal x7 = x6.multiply(x);
|
||||
BigDecimal x8 = x7.multiply(x);
|
||||
BigDecimal x2 = x.multiply(x, mc);
|
||||
BigDecimal x3 = x2.multiply(x, mc);
|
||||
BigDecimal x4 = x3.multiply(x, mc);
|
||||
BigDecimal x5 = x4.multiply(x, mc);
|
||||
BigDecimal x6 = x5.multiply(x, mc);
|
||||
BigDecimal x7 = x6.multiply(x, mc);
|
||||
BigDecimal x8 = x7.multiply(x, mc);
|
||||
|
||||
sumX = sumX.add(x);
|
||||
sumY = sumY.add(y);
|
||||
sumX2 = sumX2.add(x2);
|
||||
sumX3 = sumX3.add(x3);
|
||||
sumX4 = sumX4.add(x4);
|
||||
sumX5 = sumX5.add(x5);
|
||||
sumX6 = sumX6.add(x6);
|
||||
sumX7 = sumX7.add(x7);
|
||||
sumX8 = sumX8.add(x8);
|
||||
sumXY = sumXY.add(x.multiply(y));
|
||||
sumX2Y = sumX2Y.add(x2.multiply(y));
|
||||
sumX3Y = sumX3Y.add(x3.multiply(y));
|
||||
sumX4Y = sumX4Y.add(x4.multiply(y));
|
||||
sumX = sumX.add(x, mc);
|
||||
sumY = sumY.add(y, mc);
|
||||
sumX2 = sumX2.add(x2, mc);
|
||||
sumX3 = sumX3.add(x3, mc);
|
||||
sumX4 = sumX4.add(x4, mc);
|
||||
sumX5 = sumX5.add(x5, mc);
|
||||
sumX6 = sumX6.add(x6, mc);
|
||||
sumX7 = sumX7.add(x7, mc);
|
||||
sumX8 = sumX8.add(x8, mc);
|
||||
sumXY = sumXY.add(x.multiply(y, mc), mc);
|
||||
sumX2Y = sumX2Y.add(x2.multiply(y, mc), mc);
|
||||
sumX3Y = sumX3Y.add(x3.multiply(y, mc), mc);
|
||||
sumX4Y = sumX4Y.add(x4.multiply(y, mc), mc);
|
||||
}
|
||||
|
||||
BigDecimal nBig = new BigDecimal(n);
|
||||
|
||||
// 构建正规方程组的系数矩阵
|
||||
// 中心化处理(与三阶逻辑一致,提高稳定性)
|
||||
BigDecimal meanX = sumX.divide(nBig, mc);
|
||||
|
||||
// 计算中心化后的各阶矩
|
||||
BigDecimal m2 = BigDecimal.ZERO, m3 = BigDecimal.ZERO, m4 = BigDecimal.ZERO, m5 = BigDecimal.ZERO, m6 = BigDecimal.ZERO, m7 = BigDecimal.ZERO, m8 = BigDecimal.ZERO;
|
||||
BigDecimal m1y = BigDecimal.ZERO, m2y = BigDecimal.ZERO, m3y = BigDecimal.ZERO, m4y = BigDecimal.ZERO;
|
||||
|
||||
for (OsmoticPressDetailVo vo : validData) {
|
||||
BigDecimal xCentered = vo.getRz().subtract(meanX, mc);
|
||||
BigDecimal y = vo.getValue();
|
||||
|
||||
BigDecimal x2 = xCentered.multiply(xCentered, mc);
|
||||
BigDecimal x3 = x2.multiply(xCentered, mc);
|
||||
BigDecimal x4 = x3.multiply(xCentered, mc);
|
||||
BigDecimal x5 = x4.multiply(xCentered, mc);
|
||||
BigDecimal x6 = x5.multiply(xCentered, mc);
|
||||
BigDecimal x7 = x6.multiply(xCentered, mc);
|
||||
BigDecimal x8 = x7.multiply(xCentered, mc);
|
||||
|
||||
m2 = m2.add(x2, mc);
|
||||
m3 = m3.add(x3, mc);
|
||||
m4 = m4.add(x4, mc);
|
||||
m5 = m5.add(x5, mc);
|
||||
m6 = m6.add(x6, mc);
|
||||
m7 = m7.add(x7, mc);
|
||||
m8 = m8.add(x8, mc);
|
||||
m1y = m1y.add(xCentered.multiply(y, mc), mc);
|
||||
m2y = m2y.add(x2.multiply(y, mc), mc);
|
||||
m3y = m3y.add(x3.multiply(y, mc), mc);
|
||||
m4y = m4y.add(x4.multiply(y, mc), mc);
|
||||
}
|
||||
|
||||
// 中心化后的正规方程组
|
||||
BigDecimal[][] matrix = {
|
||||
{nBig, sumX, sumX2, sumX3, sumX4}, // 第1行
|
||||
{sumX, sumX2, sumX3, sumX4, sumX5}, // 第2行
|
||||
{sumX2, sumX3, sumX4, sumX5, sumX6}, // 第3行
|
||||
{sumX3, sumX4, sumX5, sumX6, sumX7}, // 第4行
|
||||
{sumX4, sumX5, sumX6, sumX7, sumX8} // 第5行
|
||||
{nBig, BigDecimal.ZERO, m2, m3, m4},
|
||||
{BigDecimal.ZERO, m2, m3, m4, m5},
|
||||
{m2, m3, m4, m5, m6},
|
||||
{m3, m4, m5, m6, m7},
|
||||
{m4, m5, m6, m7, m8}
|
||||
};
|
||||
|
||||
// 构建右侧向量
|
||||
BigDecimal[] vector = {sumY, sumXY, sumX2Y, sumX3Y, sumX4Y};
|
||||
BigDecimal[] vector = {
|
||||
sumY, // 常数项
|
||||
m1y, // 一次项
|
||||
m2y, // 二次项
|
||||
m3y, // 三次项
|
||||
m4y // 四次项
|
||||
};
|
||||
|
||||
// 使用改进的高斯消元法求解系数 [a, b, c, d, e]
|
||||
BigDecimal[] coefficients = solveLinearSystemImproved(matrix, vector);
|
||||
if (coefficients == null) {
|
||||
throw new IllegalArgumentException("无法求解四次回归方程(矩阵奇异)");
|
||||
// 高精度求解四阶方程
|
||||
BigDecimal[] centeredCoefficients = solveLinearSystemHighPrecision(matrix, vector, mc);
|
||||
if (centeredCoefficients == null) {
|
||||
// 四阶求解失败,自动降级为三阶
|
||||
return calculateCubic(data);
|
||||
}
|
||||
|
||||
// 将中心化系数转换回原始坐标
|
||||
BigDecimal[] originalCoefficients = convertCenteredToOriginalQuartic(centeredCoefficients, meanX, mc);
|
||||
|
||||
// 计算R²
|
||||
BigDecimal meanY = sumY.divide(nBig, MathContext.DECIMAL128);
|
||||
coeffsList = Arrays.asList(coefficients);
|
||||
rSquared = calculateRSquared(validData, coeffsList, meanY);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
BigDecimal meanY = sumY.divide(nBig, mc);
|
||||
List<BigDecimal> coefficientsList = Arrays.asList(originalCoefficients);
|
||||
BigDecimal rSquared = calculateRSquared(validData, coefficientsList, meanY);
|
||||
|
||||
return new RegressionEquation(4, coeffsList, rSquared, n);
|
||||
return new RegressionEquation(4, coefficientsList, rSquared, n);
|
||||
} catch (Exception e) {
|
||||
// 任何异常都降级为三阶
|
||||
return calculateCubic(data);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 将中心化四次系数转换回原始坐标
|
||||
*/
|
||||
private static BigDecimal[] convertCenteredToOriginalQuartic(BigDecimal[] centeredCoeffs, BigDecimal mean, MathContext mc) {
|
||||
// centered: y = a + b(x-μ) + c(x-μ)² + d(x-μ)³ + e(x-μ)⁴
|
||||
// original: y = A + Bx + Cx² + Dx³ + Ex⁴
|
||||
BigDecimal a = centeredCoeffs[0];
|
||||
BigDecimal b = centeredCoeffs[1];
|
||||
BigDecimal c = centeredCoeffs[2];
|
||||
BigDecimal d = centeredCoeffs[3];
|
||||
BigDecimal e = centeredCoeffs[4];
|
||||
|
||||
BigDecimal mu = mean;
|
||||
BigDecimal mu2 = mu.multiply(mu, mc);
|
||||
BigDecimal mu3 = mu2.multiply(mu, mc);
|
||||
BigDecimal mu4 = mu3.multiply(mu, mc);
|
||||
|
||||
BigDecimal A = a.subtract(b.multiply(mu, mc), mc)
|
||||
.add(c.multiply(mu2, mc), mc)
|
||||
.subtract(d.multiply(mu3, mc), mc)
|
||||
.add(e.multiply(mu4, mc), mc);
|
||||
|
||||
BigDecimal B = b.subtract(BigDecimal.valueOf(2).multiply(c, mc).multiply(mu, mc), mc)
|
||||
.add(BigDecimal.valueOf(3).multiply(d, mc).multiply(mu2, mc), mc)
|
||||
.subtract(BigDecimal.valueOf(4).multiply(e, mc).multiply(mu3, mc), mc);
|
||||
|
||||
BigDecimal C = c.subtract(BigDecimal.valueOf(3).multiply(d, mc).multiply(mu, mc), mc)
|
||||
.add(BigDecimal.valueOf(6).multiply(e, mc).multiply(mu2, mc), mc);
|
||||
|
||||
BigDecimal D = d.subtract(BigDecimal.valueOf(4).multiply(e, mc).multiply(mu, mc), mc);
|
||||
|
||||
BigDecimal E = e;
|
||||
|
||||
return new BigDecimal[]{A, B, C, D, E};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -583,19 +688,6 @@ public class RegressionAnalysis {
|
|||
return x;
|
||||
}
|
||||
|
||||
// ========== 辅助方法(已存在,无需修改) ==========
|
||||
|
||||
/**
|
||||
* 计算均值(高精度)
|
||||
*/
|
||||
private static BigDecimal calculateMean(List<OsmoticPressDetailVo> data,
|
||||
java.util.function.Function<OsmoticPressDetailVo, BigDecimal> extractor) {
|
||||
BigDecimal sum = BigDecimal.ZERO;
|
||||
for (OsmoticPressDetailVo vo : data) {
|
||||
sum = sum.add(extractor.apply(vo));
|
||||
}
|
||||
return sum.divide(new BigDecimal(data.size()), MathContext.DECIMAL128);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -626,4 +718,30 @@ public class RegressionAnalysis {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查所有数据点的x值是否相同
|
||||
*/
|
||||
private static boolean checkAllXSame(List<OsmoticPressDetailVo> data) {
|
||||
if (data.isEmpty()) return false;
|
||||
|
||||
BigDecimal firstX = data.get(0).getRz();
|
||||
for (OsmoticPressDetailVo vo : data) {
|
||||
if (vo.getRz().compareTo(firstX) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算y值的平均值
|
||||
*/
|
||||
private static BigDecimal calculateMeanY(List<OsmoticPressDetailVo> data) {
|
||||
BigDecimal sum = BigDecimal.ZERO;
|
||||
for (OsmoticPressDetailVo vo : data) {
|
||||
sum = sum.add(vo.getValue());
|
||||
}
|
||||
return sum.divide(new BigDecimal(data.size()), MathContext.DECIMAL128);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue