Просмотр исходного кода

feat(utils): 添加告警等级计算工具类

- 实现了基于偏差率的告警等级计算功能
- 提供实际值与正常范围比较的偏差率计算方法
- 支持将偏差率映射到1-4级告警等级(1级最高)
- 添加了等级名称获取功能
- 包含完整的参数校验和边界情况处理
- 实现了偏差率百分比的精确计算和范围限制
林仔 1 неделя назад
Родитель
Сommit
abfff6457b
1 измененных файлов с 144 добавлено и 0 удалено
  1. 144 0
      zk-api-service/src/main/java/com/zksy/api/utils/AlarmLevelUtil.java

+ 144 - 0
zk-api-service/src/main/java/com/zksy/api/utils/AlarmLevelUtil.java

@@ -0,0 +1,144 @@
+package com.zksy.api.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 告警等级计算工具类
+ * 采用"偏离正常范围的偏差率"来定级
+ * 1级最高,4级最低
+ */
+public class AlarmLevelUtil {
+
+    private static final BigDecimal HUNDRED = new BigDecimal("100");
+    private static final BigDecimal TEN = new BigDecimal("10");
+    private static final BigDecimal THIRTY = new BigDecimal("30");
+    private static final BigDecimal SIXTY = new BigDecimal("60");
+
+    /**
+     * 计算告警等级
+     *
+     * @param actual 实际值
+     * @param min    最小值
+     * @param max    最大值
+     * @return 告警等级 1-4,1级最高,4级最低;若参数无效返回4级
+     */
+    public static int calculateLevel(BigDecimal actual, BigDecimal min, BigDecimal max) {
+        BigDecimal deviationRatio = calculateDeviationRatio(actual, min, max);
+        return mapToLevel(deviationRatio);
+    }
+
+    /**
+     * 计算偏差率(百分比,范围0-100)
+     *
+     * @param actual 实际值
+     * @param min    最小值
+     * @param max    最大值
+     * @return 偏差率百分比,例如返回 25 表示 25%
+     */
+    public static BigDecimal calculateDeviationRatio(BigDecimal actual, BigDecimal min, BigDecimal max) {
+        // 参数校验
+        if (actual == null || min == null || max == null) {
+            return BigDecimal.ZERO;
+        }
+
+        BigDecimal deviation;
+        BigDecimal denominator;
+
+        // 计算偏差
+        if (actual.compareTo(min) < 0) {
+            // 低于下限:偏差 = min - actual
+            deviation = min.subtract(actual);
+        } else if (actual.compareTo(max) > 0) {
+            // 高于上限:偏差 = actual - max
+            deviation = actual.subtract(max);
+        } else {
+            // 在正常范围内,无偏差
+            return BigDecimal.ZERO;
+        }
+
+        // 计算分母
+        BigDecimal range = max.subtract(min);
+        if (range.compareTo(BigDecimal.ZERO) != 0) {
+            denominator = range;
+        } else {
+            // 特殊兜底:max - min 为 0 或无效
+            BigDecimal maxAbs = max.abs();
+            BigDecimal minAbs = min.abs();
+            if (maxAbs.compareTo(BigDecimal.ZERO) > 0) {
+                denominator = maxAbs;
+            } else if (minAbs.compareTo(BigDecimal.ZERO) > 0) {
+                denominator = minAbs;
+            } else {
+                // 都为 0,偏差率视为 100%
+                return HUNDRED;
+            }
+        }
+
+        // 计算偏差率 = (偏差 / 分母) * 100
+        if (denominator.compareTo(BigDecimal.ZERO) == 0) {
+            return HUNDRED;
+        }
+
+        BigDecimal ratio = deviation.divide(denominator, 4, RoundingMode.HALF_UP)
+                .multiply(HUNDRED);
+
+        // 限制在 0-100 范围内
+        if (ratio.compareTo(BigDecimal.ZERO) < 0) {
+            return BigDecimal.ZERO;
+        }
+        if (ratio.compareTo(HUNDRED) > 0) {
+            return HUNDRED;
+        }
+
+        return ratio;
+    }
+
+    /**
+     * 将偏差率映射到告警等级
+     *
+     * @param deviationRatio 偏差率(百分比)
+     * @return 告警等级 1-4
+     */
+    private static int mapToLevel(BigDecimal deviationRatio) {
+        if (deviationRatio == null) {
+            return 4;
+        }
+
+        // 偏差率 < 10% → 4级
+        if (deviationRatio.compareTo(TEN) < 0) {
+            return 4;
+        }
+        // 偏差率 >= 10% 且 < 30% → 3级
+        if (deviationRatio.compareTo(THIRTY) < 0) {
+            return 3;
+        }
+        // 偏差率 >= 30% 且 < 60% → 2级
+        if (deviationRatio.compareTo(SIXTY) < 0) {
+            return 2;
+        }
+        // 偏差率 >= 60% → 1级
+        return 1;
+    }
+
+    /**
+     * 获取等级名称
+     *
+     * @param level 告警等级
+     * @return 等级名称
+     */
+    public static String getLevelName(int level) {
+        switch (level) {
+            case 1:
+                return "1级(紧急)";
+            case 2:
+                return "2级(高危)";
+            case 3:
+                return "3级(警告)";
+            case 4:
+                return "4级(提醒)";
+            default:
+                return "未知等级";
+        }
+    }
+}