新增预警规则

master
yangzhe123 2025-11-18 10:53:17 +08:00
parent fcd21e42fb
commit b895f42e7d
20 changed files with 843 additions and 126 deletions

View File

@ -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("执行任务中。。。");
try {
Thread.sleep(1000);
countDownLatch.countDown();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
countDownLatch.await();
System.out.println("所有任务执行完毕");
}
List<OsmoticPressDetailVo> res = new ArrayList<>();
OsmoticPressDetailVo o1 = new OsmoticPressDetailVo();
o1.setRz(new BigDecimal("119.19"));
o1.setValue(new BigDecimal("99.65"));
public synchronized void produce() throws Exception{
while (queue.size() == maxSize){
System.out.println("队列已满,生产者等待...");
wait();
}
queue.offer(0);
System.out.println("生产者生产。。" + "队列大小为:" + queue.size());
notifyAll();
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());
}
public synchronized void customer() throws Exception{
while(queue.size() == 0){
System.out.println("队列无数据,等待生产者生产");
wait();
/**
* 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 {
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);
}
// 四舍五入保留两位小数
return result.setScale(2, RoundingMode.HALF_UP);
} catch (Exception e) {
// 计算异常时返回0
return BigDecimal.ZERO;
}
queue.poll();
System.out.println("消费者消费。。" + "队列大小为:" + queue.size());
notifyAll();
}
/**
* 线 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;
}
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;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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> {
}

View File

@ -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> {
}

View File

@ -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> {
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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[][] 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行
};
// 中心化处理(与三阶逻辑一致,提高稳定性)
BigDecimal meanX = sumX.divide(nBig, mc);
// 构建右侧向量
BigDecimal[] vector = {sumY, sumXY, sumX2Y, sumX3Y, sumX4Y};
// 计算中心化后的各阶矩
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;
// 使用改进的高斯消元法求解系数 [a, b, c, d, e]
BigDecimal[] coefficients = solveLinearSystemImproved(matrix, vector);
if (coefficients == null) {
throw new IllegalArgumentException("无法求解四次回归方程(矩阵奇异)");
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);
}
// 计算R²
BigDecimal meanY = sumY.divide(nBig, MathContext.DECIMAL128);
coeffsList = Arrays.asList(coefficients);
rSquared = calculateRSquared(validData, coeffsList, meanY);
} catch (IllegalArgumentException e) {
return null;
}
// 中心化后的正规方程组
BigDecimal[][] matrix = {
{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}
};
return new RegressionEquation(4, coeffsList, rSquared, n);
BigDecimal[] vector = {
sumY, // 常数项
m1y, // 一次项
m2y, // 二次项
m3y, // 三次项
m4y // 四次项
};
// 高精度求解四阶方程
BigDecimal[] centeredCoefficients = solveLinearSystemHighPrecision(matrix, vector, mc);
if (centeredCoefficients == null) {
// 四阶求解失败,自动降级为三阶
return calculateCubic(data);
}
// 将中心化系数转换回原始坐标
BigDecimal[] originalCoefficients = convertCenteredToOriginalQuartic(centeredCoefficients, meanX, mc);
// 计算R²
BigDecimal meanY = sumY.divide(nBig, mc);
List<BigDecimal> coefficientsList = Arrays.asList(originalCoefficients);
BigDecimal rSquared = calculateRSquared(validData, coefficientsList, meanY);
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);
}
}