diff --git a/src/main/java/com/gunshi/Tests.java b/src/main/java/com/gunshi/Tests.java index abb2ecd..104c472 100644 --- a/src/main/java/com/gunshi/Tests.java +++ b/src/main/java/com/gunshi/Tests.java @@ -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 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 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; + } + } + } diff --git a/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java b/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java index e4cd1c7..2df35d7 100644 --- a/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java +++ b/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java @@ -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 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); } } diff --git a/src/main/java/com/gunshi/project/hsz/controller/WarningRuleController.java b/src/main/java/com/gunshi/project/hsz/controller/WarningRuleController.java new file mode 100644 index 0000000..8aeafdf --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/controller/WarningRuleController.java @@ -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(@RequestBody @Validated WarningRulePageSo page) { + return R.ok(warningRuleService.pageQuery(page)); + } + + + @Operation(summary = "新增") + @PostMapping("/insert") + public R insert(@RequestBody @Validated WarningRule dto) { + return R.ok(warningRuleService.saveData(dto)); + } +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/enums/IndicatorTypeEnum.java b/src/main/java/com/gunshi/project/hsz/entity/enums/IndicatorTypeEnum.java new file mode 100644 index 0000000..5cd9651 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/enums/IndicatorTypeEnum.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/entity/enums/OperatorEnum.java b/src/main/java/com/gunshi/project/hsz/entity/enums/OperatorEnum.java new file mode 100644 index 0000000..414b1bc --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/enums/OperatorEnum.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/entity/enums/RelationTypeEnum.java b/src/main/java/com/gunshi/project/hsz/entity/enums/RelationTypeEnum.java new file mode 100644 index 0000000..b1630e0 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/enums/RelationTypeEnum.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/entity/enums/WarningTypeEnum.java b/src/main/java/com/gunshi/project/hsz/entity/enums/WarningTypeEnum.java new file mode 100644 index 0000000..97b9f95 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/enums/WarningTypeEnum.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/entity/so/WarningRulePageSo.java b/src/main/java/com/gunshi/project/hsz/entity/so/WarningRulePageSo.java new file mode 100644 index 0000000..3729097 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/so/WarningRulePageSo.java @@ -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; +} diff --git a/src/main/java/com/gunshi/project/hsz/mapper/SyRegressionDataMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/SyRegressionDataMapper.java index 582ede1..fe82efa 100644 --- a/src/main/java/com/gunshi/project/hsz/mapper/SyRegressionDataMapper.java +++ b/src/main/java/com/gunshi/project/hsz/mapper/SyRegressionDataMapper.java @@ -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 { - } diff --git a/src/main/java/com/gunshi/project/hsz/mapper/WarningConditionMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/WarningConditionMapper.java new file mode 100644 index 0000000..f893597 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/WarningConditionMapper.java @@ -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 { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/WarningRuleMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/WarningRuleMapper.java new file mode 100644 index 0000000..673d644 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/WarningRuleMapper.java @@ -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 { +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/ForecastProject.java b/src/main/java/com/gunshi/project/hsz/model/ForecastProject.java index 6d6c366..98e06d3 100644 --- a/src/main/java/com/gunshi/project/hsz/model/ForecastProject.java +++ b/src/main/java/com/gunshi/project/hsz/model/ForecastProject.java @@ -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; } diff --git a/src/main/java/com/gunshi/project/hsz/model/SyRegressionData.java b/src/main/java/com/gunshi/project/hsz/model/SyRegressionData.java index 23ac86a..60b0bf7 100644 --- a/src/main/java/com/gunshi/project/hsz/model/SyRegressionData.java +++ b/src/main/java/com/gunshi/project/hsz/model/SyRegressionData.java @@ -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; + } \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/WarningCondition.java b/src/main/java/com/gunshi/project/hsz/model/WarningCondition.java new file mode 100644 index 0000000..d33ab33 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/WarningCondition.java @@ -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; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/WarningRule.java b/src/main/java/com/gunshi/project/hsz/model/WarningRule.java new file mode 100644 index 0000000..71ce078 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/WarningRule.java @@ -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 conditions; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/JcskSyRService.java b/src/main/java/com/gunshi/project/hsz/service/JcskSyRService.java index fc4025f..060ec8b 100644 --- a/src/main/java/com/gunshi/project/hsz/service/JcskSyRService.java +++ b/src/main/java/com/gunshi/project/hsz/service/JcskSyRService.java @@ -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 { @Autowired private JcskSyREightAmMapper jcskSyREightAmMapper; + @Autowired + private SyRegressionDataService syRegressionDataService; + public Page pageQuery(JcskSyRPageSo page) { @@ -835,23 +839,58 @@ public class JcskSyRService extends ServiceImpl { if(data.isEmpty()){ return res; } + List 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; } diff --git a/src/main/java/com/gunshi/project/hsz/service/SyRegressionDataService.java b/src/main/java/com/gunshi/project/hsz/service/SyRegressionDataService.java index b1aeb50..405d1a1 100644 --- a/src/main/java/com/gunshi/project/hsz/service/SyRegressionDataService.java +++ b/src/main/java/com/gunshi/project/hsz/service/SyRegressionDataService.java @@ -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 syRegressionData = this.baseMapper.selectList(queryWrapper); return syRegressionData; } diff --git a/src/main/java/com/gunshi/project/hsz/service/WarningConditionService.java b/src/main/java/com/gunshi/project/hsz/service/WarningConditionService.java new file mode 100644 index 0000000..9ce0964 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/WarningConditionService.java @@ -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 { + + + + public List getListByRuleId(Serializable id){ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); + queryWrapper.eq(WarningCondition::getRuleId,id); + return this.list(queryWrapper); + } +} diff --git a/src/main/java/com/gunshi/project/hsz/service/WarningRuleService.java b/src/main/java/com/gunshi/project/hsz/service/WarningRuleService.java new file mode 100644 index 0000000..f3eb551 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/WarningRuleService.java @@ -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 { + + @Autowired + private WarningConditionService warningConditionService; + + public Page pageQuery(WarningRulePageSo page) { + LambdaQueryWrapper 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 warningRulePage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper); + + for (WarningRule record : warningRulePage.getRecords()) { + List listByRuleId = warningConditionService.getListByRuleId(record.getId()); + record.setConditions(listByRuleId); + } + return warningRulePage; + } + + public WarningRule saveData(WarningRule dto) { + return null; + } +} diff --git a/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java b/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java index d94b0cf..5843835 100644 --- a/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java +++ b/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java @@ -34,6 +34,16 @@ public class RegressionAnalysis { n = validData.size(); + // 检查所有x值是否相同 + boolean allXSame = checkAllXSame(validData); + if (allXSame) { + // 所有x值相同,返回常数函数(y = 平均值) + BigDecimal meanY = calculateMeanY(validData); + List 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 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 data) { - int n = 0; - List coeffsList = null; - BigDecimal rSquared = null; try { List 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 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 data, - java.util.function.Function 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 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 data) { + BigDecimal sum = BigDecimal.ZERO; + for (OsmoticPressDetailVo vo : data) { + sum = sum.add(vo.getValue()); + } + return sum.divide(new BigDecimal(data.size()), MathContext.DECIMAL128); + } + } \ No newline at end of file