Browse Source

no message

DFS_Shuo_Chen 1 month ago
parent
commit
8bd20dcb93

+ 8 - 1
EasyTemplate.Blazor.Web/appsettings.json

@@ -5,5 +5,12 @@
       "Microsoft.AspNetCore": "Warning"
     }
   },
-  "AllowedHosts": "*"
+  "AllowedHosts": "*",
+  "VRRules": {
+    "RefReachCount": false,
+    "RefCount": 5,
+    "RefPrewarningIndex": 20,
+    "RefPrewarningIndexAlert": 50,
+    "BCountAllDay": false
+  }
 }

+ 164 - 41
EasyTemplate.Service/WarningService.cs

@@ -168,55 +168,178 @@ namespace EasyTemplate.Service
         }
 
         /// <summary>
-        /// 计算累计统计数据(核心业务逻辑)
-        /// 规则:从当前日期往前找,直到累计笔数>=5 或达到 35 天上限
+        /// 计算累计统计数据(核心业务逻辑 - 按 C++ update_warning 实现
+        /// 规则:从最早日期正向迭代到当前日期,累加统计并在满足条件时清零
         /// </summary>
         private void CalculateAccumulatedStatistics(List<TPrewarning> sortedData, int currentIndex, WarningStatistics stats)
         {
-            int accumulatedTotal = 0;
-            int accumulatedOverproof = 0;
-            int accumulatedOverproofAlert = 0;
-            int accumulatedOverproof2 = 0;
-            int accumulatedDays = 0;
-
-            // 从当前日期往前累加,直到满足条件或达到 35 天
-            for (int i = currentIndex; i >= 0 && (currentIndex - i) < 35; i--)
+            // 累加器初始化(对应 C++ acc_over, acc_over_alert, acc_total, acc_over_2)
+            int acc_over = 0;           // 累计超标记录
+            int acc_over_alert = 0;     // 累计严重超标记录
+            int acc_total = 0;          // 累计总数
+            int acc_over_2 = 0;         // 累计二级超标记录(广东中石化)
+            
+            // 连续天数计数器
+            int continue_days = 0;
+            int continue_days_2 = 0;
+            int continue_days_alert = 0;
+            
+            // 最后计算的超标率
+            int last_rate = 0;
+            int last_rate_2 = 0;
+            int last_rate_alert = 0;
+
+            // 获取区域规则配置
+            bool isBeijingMode = VRRules.RefReachCount; // 北京模式:ref_reach_count
+            int refCount = VRRules.RefCount; // 标准模式阈值(通常 5)
+            int refPrewarningIndex = VRRules.RefPrewarningIndex; // 超标率阈值
+            int refPrewarningIndexAlert = VRRules.RefPrewarningIndexAlert; // 严重超标率阈值
+            bool isZhejiangSpecial = VRRules.BCountAllDay; // 浙江中石化特殊逻辑
+
+            // 正向迭代:从第 0 天到当前天(对应 C++ mapDayWarning.begin() 到 end)
+            for (int i = 0; i <= currentIndex && i < sortedData.Count; i++)
             {
                 var day = sortedData[i];
-                accumulatedTotal += day.total;
-                accumulatedOverproof += day.overproof;
-                accumulatedOverproofAlert += day.overproof_alert;
-                accumulatedOverproof2 += day.overproof_2;
-                accumulatedDays++;
-
-                // 如果累计笔数>=5,停止累加
-                if (accumulatedTotal >= 5)
+                
+                // 累加数据
+                acc_over += day.overproof;
+                acc_over_alert += day.overproof_alert;
+                acc_total += day.total;
+                acc_over_2 += day.overproof_2;
+                
+                // 计算累计超标率(避免除以 0)
+                last_rate = acc_total == 0 ? 0 : (acc_over * 100) / acc_total;
+                last_rate_2 = acc_total == 0 ? 0 : (acc_over_2 * 100) / acc_total;
+                last_rate_alert = acc_total == 0 ? 0 : (acc_over_alert * 100) / acc_total;
+                
+                // 更新警告对象中的累计值(用于显示)
+                // 注意:这里不直接设置 stats,因为可能还需要清零
+                
+                if (isBeijingMode)
                 {
-                    break;
+                    // === 北京模式(ref_reach_count)===
+                    // 规则:超标率>=阈值 且 总笔数>=5 时,连续天数 +1
+                    
+                    // 普通超标判断
+                    if (last_rate >= refPrewarningIndex)
+                    {
+                        if (acc_total >= 5)
+                        {
+                            continue_days++;
+                        }
+                    }
+                    else
+                    {
+                        if (acc_total >= 5)
+                        {
+                            continue_days = 0;
+                        }
+                    }
+                    
+                    // 严重超标判断
+                    if (last_rate_alert >= refPrewarningIndexAlert)
+                    {
+                        if (acc_total >= 5)
+                        {
+                            continue_days_alert++;
+                        }
+                    }
+                    else
+                    {
+                        if (acc_total >= 5)
+                        {
+                            continue_days_alert = 0;
+                        }
+                    }
+                    
+                    // 已经算入一天,清零累加器
+                    acc_over = 0;
+                    acc_over_alert = 0;
+                    acc_total = 0;
+                    acc_over_2 = 0;
+                }
+                else
+                {
+                    // === 标准模式 ===
+                    // 规则:总笔数>=ref_count(通常 5) 时才检查超标率
+                    
+                    if (acc_total >= refCount)
+                    {
+                        // 普通超标判断
+                        if (last_rate >= refPrewarningIndex)
+                        {
+                            continue_days++;
+                        }
+                        else
+                        {
+                            continue_days = 0;
+                        }
+                        
+                        // 严重超标判断
+                        if (last_rate_alert >= refPrewarningIndexAlert)
+                        {
+                            continue_days_alert++;
+                        }
+                        else
+                        {
+                            continue_days_alert = 0;
+                        }
+                        
+                        // 二级超标判断(广东中石化)
+                        if (last_rate_2 >= refPrewarningIndex) // || day.continueoverproof == 1
+                        {
+                            continue_days_2++;
+                        }
+                        else
+                        {
+                            continue_days_2 = 0;
+                        }
+                        
+                        // 已经算入一天,清零累加器
+                        acc_over = 0;
+                        acc_over_alert = 0;
+                        acc_total = 0;
+                        acc_over_2 = 0;
+                    }
+                    else
+                    {
+                        // 该分支是 ref_count 大于 0(即需要进行累计)的情况下,
+                        // 而 acc_total 小于 ref_count 时进入
+                        
+                        if (isZhejiangSpecial)
+                        {
+                            // === 浙江中石化特殊逻辑 ===
+                            // 不足 5 笔时延续之前的预警状态
+                            if (continue_days > 0)
+                            {
+                                continue_days++;
+                            }
+                            
+                            if (continue_days_alert > 0)
+                            {
+                                continue_days_alert++;
+                            }
+                        }
+                    }
                 }
             }
-
-            // 设置累计统计结果
-            stats.total_count = accumulatedTotal;
-            stats.total_overproof = accumulatedOverproof;
-            stats.total_overproof_alert = accumulatedOverproofAlert;
-            stats.total_overproof_2 = accumulatedOverproof2;
-            stats.accumulated_days = accumulatedDays;
-            stats.is_accumulated = accumulatedTotal >= 5;
-
-            // 计算累计超标率(避免除以 0)
-            if (accumulatedTotal > 0)
-            {
-                stats.total_overproofrate = (100 * accumulatedOverproof) / accumulatedTotal;
-                stats.total_overproofrate_alert = (100 * accumulatedOverproofAlert) / accumulatedTotal;
-                stats.total_overproofrate_2 = (100 * accumulatedOverproof2) / accumulatedTotal;
-            }
-            else
-            {
-                stats.total_overproofrate = 0;
-                stats.total_overproofrate_alert = 0;
-                stats.total_overproofrate_2 = 0;
-            }
+            
+            // 设置最终统计结果
+            stats.continue_days = continue_days;
+            stats.continue_days_2 = continue_days_2;
+            stats.continue_days_alert = continue_days_alert;
+            stats.last_overproofrate = last_rate;
+            stats.last_overproofrate_2 = last_rate_2;
+            stats.last_overproofrate_alert = last_rate_alert;
+            
+            // 同时保留原有的累计字段(用于兼容)
+            stats.total_count = acc_total;
+            stats.total_overproof = acc_over;
+            stats.total_overproof_alert = acc_over_alert;
+            stats.total_overproof_2 = acc_over_2;
+            stats.total_overproofrate = last_rate;
+            stats.total_overproofrate_2 = last_rate_2;
+            stats.total_overproofrate_alert = last_rate_alert;
         }
 
         /// <summary>

+ 30 - 0
EasyTemplate.Tool/Entity/App/WarningStatistics.cs

@@ -100,6 +100,36 @@ namespace EasyTemplate.Tool.Entity.App
         /// 累计天数
         /// </summary>
         public int accumulated_days { get; set; }
+
+        /// <summary>
+        /// 连续超标天数(普通超标)
+        /// </summary>
+        public int continue_days { get; set; }
+
+        /// <summary>
+        /// 连续超标天数(二级超标/广东中石化)
+        /// </summary>
+        public int continue_days_2 { get; set; }
+
+        /// <summary>
+        /// 连续超标天数(严重超标)
+        /// </summary>
+        public int continue_days_alert { get; set; }
+
+        /// <summary>
+        /// 最后累计超标率(用于显示)
+        /// </summary>
+        public int last_overproofrate { get; set; }
+
+        /// <summary>
+        /// 最后二级超标率(用于显示)
+        /// </summary>
+        public int last_overproofrate_2 { get; set; }
+
+        /// <summary>
+        /// 最后严重超标率(用于显示)
+        /// </summary>
+        public int last_overproofrate_alert { get; set; }
     }
 
     /// <summary>

+ 117 - 0
EasyTemplate.Tool/Util/VRRules.cs

@@ -0,0 +1,117 @@
+namespace EasyTemplate.Tool
+{
+    /// <summary>
+    /// 预警告计算规则配置(对应 C++ VR::rules 命名空间)
+    /// </summary>
+    public static class VRRules
+    {
+        private static bool? _refReachCount;
+        private static int? _refCount;
+        private static int? _refPrewarningIndex;
+        private static int? _refPrewarningIndexAlert;
+        private static bool? _bCountAllDay;
+
+        /// <summary>
+        /// 北京模式:是否使用达标计数模式
+        /// 为 true 时:超标率>=阈值 且 总笔数>=5 时计为连续一天
+        /// 为 false 时:使用标准模式(总笔数>=ref_count 时才检查超标率)
+        /// </summary>
+        public static bool RefReachCount
+        {
+            get
+            {
+                var value = Setting.Get<bool?>("VRRules:RefReachCount");
+                return _refReachCount ?? (value ?? false);
+            }
+            set => _refReachCount = value;
+        }
+
+        /// <summary>
+        /// 标准模式下的参考笔数阈值(通常为 5)
+        /// 当累计总笔数达到此值时才进行超标率判断
+        /// </summary>
+        public static int RefCount
+        {
+            get
+            {
+                var value = Setting.Get<int?>("VRRules:RefCount");
+                return _refCount ?? (value ?? 5);
+            }
+            set => _refCount = value;
+        }
+
+        /// <summary>
+        /// 预报警超标率阈值(%)
+        /// 当累计超标率>=此值时判定为超标
+        /// </summary>
+        public static int RefPrewarningIndex
+        {
+            get
+            {
+                var value = Setting.Get<int?>("VRRules:RefPrewarningIndex");
+                return _refPrewarningIndex ?? (value ?? 20);
+            }
+            set => _refPrewarningIndex = value;
+        }
+
+        /// <summary>
+        /// 预报警严重超标率阈值(%)
+        /// 当累计严重超标率>=此值时判定为严重超标
+        /// </summary>
+        public static int RefPrewarningIndexAlert
+        {
+            get
+            {
+                var value = Setting.Get<int?>("VRRules:RefPrewarningIndexAlert");
+                return _refPrewarningIndexAlert ?? (value ?? 50);
+            }
+            set => _refPrewarningIndexAlert = value;
+        }
+
+        /// <summary>
+        /// 浙江中石化特殊规则:是否在不足 5 笔时也延续预警状态
+        /// 为 true 时:即使 acc_total < ref_count,也会延续之前的连续天数
+        /// </summary>
+        public static bool BCountAllDay
+        {
+            get
+            {
+                var value = Setting.Get<bool?>("VRRules:BCountAllDay");
+                return _bCountAllDay ?? (value ?? false);
+            }
+            set => _bCountAllDay = value;
+        }
+
+        /// <summary>
+        /// 从配置文件加载所有规则
+        /// </summary>
+        public static void LoadFromConfig()
+        {
+            _refReachCount = null;
+            _refCount = null;
+            _refPrewarningIndex = null;
+            _refPrewarningIndexAlert = null;
+            _bCountAllDay = null;
+
+            // 触发一次 getter 以重新读取配置
+            _ = RefReachCount;
+            _ = RefCount;
+            _ = RefPrewarningIndex;
+            _ = RefPrewarningIndexAlert;
+            _ = BCountAllDay;
+        }
+
+        /// <summary>
+        /// 手动设置所有规则(用于代码动态配置)
+        /// </summary>
+        public static void SetRules(bool refReachCount, int refCount, int refPrewarningIndex, 
+            int refPrewarningIndexAlert, bool bCountAllDay)
+        {
+            _refReachCount = refReachCount;
+            _refCount = refCount;
+            _refPrewarningIndex = refPrewarningIndex;
+            _refPrewarningIndexAlert = refPrewarningIndexAlert;
+            _bCountAllDay = bCountAllDay;
+        }
+    }
+}