From c5f380b69707a9a09fe988a2f4bd98e142bf64ae Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期四, 10 七月 2025 17:29:48 +0800
Subject: [PATCH] 2025.7.10 1. 修改动态溯源异常判断逻辑

---
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt |  277 +++++++++++++++++++++++++++++-------------------------
 1 files changed, 148 insertions(+), 129 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
index 2ea3314..f0acf81 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
@@ -1,194 +1,213 @@
 package com.flightfeather.uav.biz.dataanalysis
 
 import com.flightfeather.uav.biz.FactorFilter
-import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
+import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.lightshare.eunm.ExceptionStatusType
 import com.flightfeather.uav.socket.eunm.FactorType
+import java.time.Duration
 
 /**
  * 杩炵画绫诲瀷鐨勫紓甯稿垎鏋愬熀绫�,閫傜敤浜庡綋鍓嶆暟鎹笌鐩搁偦鏁版嵁涔嬮棿鏈夊叧鑱斿叧绯荤殑鎯呭喌
  */
-abstract class BaseExceptionContinuous(config: DataAnalysisConfig) : BaseExceptionAnalysis(config) {
+abstract class BaseExceptionContinuous<T : ExceptionTag, V : BaseAnalysisConfig, Y : BaseExceptionResult>(
+    config: V, private val tagClz: Class<T>
+) : BaseExceptionAnalysis<V, Y>(config) {
 
     companion object {
         // 璁板綍寮傚父鏁版嵁娈垫椂锛屽垎鍒悜璧峰鍓嶅拰鏈熬鍚庨澶栬褰曠殑鏁版嵁涓暟鍋忕Щ閲�
         private const val OFFSET = 10
     }
 
-    inner class Tag {
-        // 璧峰鏁版嵁涓嬫爣
-        var sIndex = 0
-
-        // 璧峰鏁版嵁瀵硅薄
-        var startData :BaseRealTimeData? = null
-
-        // 鏈熬鏁版嵁涓嬫爣
-        var eIndex = -1
-
-        // 鏈熬鏁版嵁瀵硅薄
-        var endData: BaseRealTimeData? = null
-
-        // 寮傚父鏁版嵁娈�
-        var exceptionData = mutableListOf<BaseRealTimeData>()
-
-        // 鏄惁瀛樺湪寮傚父
-        var existException = false
-
-        fun refreshAfterCheckResult(data: BaseRealTimeData) {
-            sIndex = eIndex
-            startData = data
-            exceptionData.clear()
-            exceptionData.add(data)
-        }
-    }
-
-    protected val tagMap = mutableMapOf<FactorType, Tag>()
-
-//    // 璧峰鏁版嵁涓嬫爣
-//    protected var sIndex = mutableListOf<Int>()
-//
-//    // 璧峰鏁版嵁瀵硅薄
-//    protected var startData = mutableListOf<BaseRealTimeData?>()
-//
-//    // 鏈熬鏁版嵁涓嬫爣
-//    protected var eIndex = mutableListOf<Int>()
-//
-//    // 寮傚父鏁版嵁娈�
-//    protected var exceptionData = mutableListOf<MutableList<BaseRealTimeData>>()
-
-//    protected var existException = mutableListOf<Boolean>()
+    protected val tagMap = mutableMapOf<FactorType, T>()
 
     // 璧峰鏁版嵁涓庢湯灏炬暟鎹棿闅�
     open var durationCount = 1
+
     // 鏈熬鏁版嵁瀵硅薄
     protected var lastData: BaseRealTimeData? = null
 
     /**
-     * 鍒ゆ柇鏄惁婊¤冻寮傚父鏉′欢
+     * 鍚庣疆鍒ゆ柇锛氬綋鐩搁偦鏁版嵁鏃堕棿涓嶈繛缁椂锛屾垨鑰呮弧瓒宠嚜瀹氫箟鏉′欢鏃讹紝瀵逛箣鍓嶅凡鏈夌殑寮傚父杩涜璁板綍
+     */
+    open fun afterExcCheck(isContinue: Boolean, tag: T, hasException: Boolean?): Boolean {
+        return !isContinue || needCut(tag, hasException)
+    }
+
+    /**
+     * 绔嬪嵆鍒ゆ柇锛氬綋鍑虹幇寮傚父鏃讹紝缂撳瓨寮傚父鏁版嵁鐨勫悓鏃讹紝绔嬪嵆瀵瑰凡鏈夊紓甯歌繘琛屽垽鏂槸鍚︽弧瓒冲紓甯哥粨鏋滆姹�
+     */
+    open fun immeExcCheck(tag: T, factorType: FactorType): Boolean {
+        return false
+    }
+
+    /**
+     * 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画
+     */
+    open fun isContinuous(d1: BaseRealTimeData?, d2: BaseRealTimeData?): Boolean {
+        if (d1 == null || d2 == null) return true
+
+        val t1 = d1.dataTime
+        val t2 = d2.dataTime
+        return Duration.between(t1?.toInstant(), t2?.toInstant()).toMillis() <= (20 * 1000)
+    }
+
+    /**
+     * 鍒ゆ柇鏁版嵁閲忕骇鍦ㄥ紓甯稿垽鏂殑鑼冨洿鍐�
+     * 榛樿鎵�鏈夐噺绾ч兘鍦ㄥ紓甯稿垽鏂殑鑼冨洿鍐�
+     */
+    open fun judgeDataScale(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
+        val res = mutableMapOf<FactorType, Boolean>()
+        config.factorFilter.mainList().forEach { f -> res[f] = true }
+        return res
+    }
+
+    /**
+     * 鍒ゆ柇鍓嶅悗鏁版嵁鏄惁婊¤冻寮傚父鏉′欢
      */
     abstract fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean>
 
     /**
-     * 鍒ゆ柇寮傚父鍑虹幇鐨勮繛缁椂闀挎槸鍚︽弧瓒虫潯浠�
+     * 鍒ゆ柇寮傚父鍑虹幇鐨勮繛缁釜鏁版槸鍚︽弧瓒虫潯浠�
+     * @param tag 寮傚父鏁版嵁瀵硅薄
      */
-    abstract fun judgeDuration(sIndex: Int, eIndex: Int): Boolean
+    abstract fun judgeExceptionCount(tag: T, factorType: FactorType?): Boolean
+
+    /**
+     * 鍒ゆ柇鐩戞祴鍥犲瓙鏄惁鍑虹幇寮傚父
+     */
+    open fun judge(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
+        val jds = judgeDataScale(p, n)
+        val jex = judgeException(p, n)
+        val res = mutableMapOf<FactorType, Boolean>()
+        jds.forEach { (t, u) ->
+            res[t] = u && jex[t] ?: false
+        }
+        return res
+    }
+
+    /**
+     * 寮傚父鏁版嵁鐨勬埅鍙栧垽鏂�
+     * @return
+     */
+    open fun needCut(tag: T, hasException: Boolean?): Boolean {
+        // 榛樿鍒ゆ柇鏉′欢涓� 褰撳紓甯镐笉鍐嶉噸澶嶅嚭鐜版椂锛屽舰鎴愬紓甯哥粨鏋�
+        return tag.exceptionExisted && hasException == false
+    }
 
     override fun init() {
         super.init()
         lastData = null
-//        repeat(config.factorCount) {
-//            startData.add(null)
-//            sIndex.add(0)
-//            eIndex.add(-1)
-//            existException.add(false)
-//            exceptionData.add(mutableListOf())
-//        }
-        config.factorFilter.mainList().forEach {f->
-            tagMap[f] = Tag()
+        tagMap.clear()
+        config.factorFilter.mainList().forEach { f ->
+            tagMap[f] = tagClz.newInstance()
         }
     }
 
     override fun onNextData(data: BaseRealTimeData) {
         val isContinue = isContinuous(lastData, data)
-        val hasException = judgeException(lastData, data)
-        config.factorFilter.mainList().forEach {f->
+        val hasException = judge(lastData, data)
+        config.factorFilter.selectedList.forEach { s ->
+            val f = s.main
             tagMap[f]?.let {
+                it.addHistoryData(data)
+
                 it.eIndex++
                 // 璧峰鏁版嵁
-                if (it.endData == null) {
-                    it.refreshAfterCheckResult(data)
+                it.endData = data
+                if (it.startData == null) {
+                    it.refreshWithNextException(data)
                 }
-                // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
-                if (!isContinue) {
-                    checkResult()
-                    // 鏁版嵁涓嶈繛缁椂锛岃褰曞紓甯告儏鍐�
-                    if (it.eIndex - it.sIndex >= durationCount) {
-                        it.refreshAfterCheckResult(data)
-                    }
-                } else {
-                    if (hasException[f] == true) {
-                        it.existException = true
-                        it.exceptionData.add(data)
-                    } else {
-                        // 寮傚父涓嶅啀閲嶅鍑虹幇鏃讹紝璁板綍寮傚父鎯呭喌
-                        checkResult()
-                        if (it.eIndex - it.sIndex >= durationCount) {
-                            it.refreshAfterCheckResult(data)
-                        }
+
+                // 瀵逛簬寮傚父鐨勭敓鎴愬垎鍒墽琛屽悗缃垽鏂�佸拰绔嬪嵆鍒ゆ柇
+                // 1. 鍚庣疆鍒ゆ柇锛氬綋鐩搁偦鏁版嵁鏃堕棿涓嶈繛缁椂锛屾垨鑰呮弧瓒宠嚜瀹氫箟鏉′欢鏃讹紝瀵逛箣鍓嶅凡鏈夌殑寮傚父杩涜璁板綍锛屽舰鎴愬紓甯哥粨鏋�
+//                if (afterExcCheck(isContinue, it, hasException[f])) {
+//                    // 鏁版嵁涓嶈繛缁椂鎴栬�呮弧瓒充富鍔ㄦ埅鏂潯浠舵椂锛岃褰曞紓甯告儏鍐�
+//                    recordException(s, it, data)
+//                }
+                // 2. 绔嬪嵆鍒ゆ柇锛氬綋鍑虹幇寮傚父鏃讹紝缂撳瓨寮傚父鏁版嵁鐨勫悓鏃讹紝绔嬪嵆瀵瑰凡鏈夊紓甯歌繘琛屽垽鏂槸鍚︽弧瓒冲紓甯哥粨鏋滆姹�
+                if (hasException[f] == true) {
+//                    afterExcCheck(isContinue, it, hasException[f])
+                    needCut(it, hasException[f])
+                    // 鏈夊紓甯稿嚭鐜版椂锛岃褰曞紓甯告暟鎹�
+                    it.addExceptionData(data)
+                    // 褰撶珛鍗冲垽鏂�氳繃鏃讹紝褰㈡垚寮傚父缁撴灉
+                    if (immeExcCheck(it, f)) {
+                        recordException(s, it, data)
                     }
                 }
+                // 3. 鏁版嵁姝e父锛屾棤浠讳綍寮傚父鏃禿
+                // TODO("2025.6.3锛氬叾浠栧瓙绫荤殑姝ゅ鍒锋柊閫昏緫寰呭畬鎴愨��)
+//                else {
+//                    it.refreshWithNextException(data)
+//                }
             }
         }
-//        repeat(config.factorCount) { i ->
-//            eIndex[i]++
-//            // 璧峰鏁版嵁
-//            if (lastData == null) {
-//                refreshAfterCheckResult(i, data)
-//            }
-//            // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
-//            if (!isContinue) {
-//                checkResult()
-//                // 鏁版嵁涓嶈繛缁椂锛岃褰曞紓甯告儏鍐�
-//                if (eIndex[i] - sIndex[i] >= durationCount) {
-//                    refreshAfterCheckResult(i, data)
-//                }
-//            } else {
-//                if (hasException[i]) {
-//                    existException[i] = true
-//                    exceptionData[i].add(data)
-//                } else {
-//                    // 寮傚父涓嶅啀閲嶅鍑虹幇鏃讹紝璁板綍寮傚父鎯呭喌
-//                    checkResult()
-//                    if (eIndex[i] - sIndex[i] >= durationCount) {
-//                        refreshAfterCheckResult(i, data)
-//                    }
-//                }
-//            }
-//        }
         lastData = data
     }
 
     override fun onDone() {
-        checkResult()
+        checkResult(exceptionStatus = ExceptionStatusType.Ended)
     }
 
-//    fun refreshAfterCheckResult(i:Int, data: BaseRealTimeData) {
-//        sIndex[i] = eIndex[i]
-//        startData[i] = data
-//        exceptionData[i].clear()
-//        exceptionData[i].add(data)
-//    }
+    /**
+     * 寮傚父缁撴潫锛岃褰曞紓甯�
+     * 鍒ゆ柇宸叉湁鐨勫紓甯告暟鎹槸鍚︽弧瓒冲紓甯告潯浠讹紝婊¤冻鍒欒褰曪紝涓嶆弧瓒冲垯鐣ヨ繃
+     */
+    fun recordException(factor: FactorFilter.SelectedFactor, tag: T, data: BaseRealTimeData) {
+        checkResult(factor, ExceptionStatusType.Ended)
+        tag.refreshWithNextException(data)
+    }
 
     /**
      * 妫�鏌ヨ繛缁紓甯哥粨鏉熸椂锛屾槸鍚︾鍚堝紓甯稿瓨鍌ㄦ潯浠�
      */
-    open fun checkResult(factor: FactorFilter.SelectedFactor? = null) {
+    open fun checkResult(
+        factor: FactorFilter.SelectedFactor? = null,
+        exceptionStatus: ExceptionStatusType = ExceptionStatusType.InProgress
+    ) {
         val tag = tagMap[factor?.main]
         if (factor != null && tag != null) {
-            if (tag.existException && judgeDuration(tag.sIndex, tag.eIndex)) {
-                tag.startData?.let {
-                    resultList.add(newResult(it, lastData, factor, tag.exceptionData))
-                }
-                tag.existException = false
+            if (tag.exceptionExisted && judgeExceptionCount(tag, factor.main)) {
+                onNewException(tag, factor, exceptionStatus)
             }
         } else {
             config.factorFilter.selectedList.forEach { f ->
                 val tag1 = tagMap[f.main] ?: return@forEach
-                if (tag1.existException && judgeDuration(tag1.sIndex, tag1.eIndex)) {
-                    tag1.startData?.let {
-                        resultList.add(newResult(it, lastData, f, tag1.exceptionData))
-                    }
-                    tag1.existException = false
+                if (tag1.exceptionExisted && judgeExceptionCount(tag1, f.main)) {
+                    onNewException(tag1, f, exceptionStatus)
                 }
             }
-//            repeat(config.factorCount) { i ->
-//                if (existException[i] && judgeDuration(sIndex[i], eIndex[i])) {
-//                    startData[i]?.let {
-//                        resultList.add(newResult(it, lastData, i, exceptionData[i]))
-//                    }
-//                    existException[i] = false
-//                }
-//            }
         }
     }
+
+    /**
+     * 鏂板鎴栨洿鏂颁竴鏉″紓甯�
+     */
+    open fun onNewException(tag: T, factor: FactorFilter.SelectedFactor, exceptionStatus: ExceptionStatusType) {
+        if (tag.startData == null) return
+//        val ex = newResult(tag.startData!!, tag.endData, factor, tag.exceptionData)
+        val ex = newResult(tag, factor)
+            .apply { status = exceptionStatus.value }
+        // 寮傚父宸插垱寤烘椂锛屾洿鏂板紓甯镐俊鎭�
+        if (tag.exceptionCreated) {
+            // 灏嗘渶鏂扮殑寮傚父鐨刧uid璧嬪�肩粰ex
+            val lastEx = tag.exceptionResult.last()
+            ex.guid = lastEx.guid
+            tag.exceptionResult.removeLast()
+            tag.exceptionResult.add(ex)
+        }
+        // 寮傚父鏈垱寤烘椂锛屾柊寤哄紓甯镐俊鎭�
+        else {
+            tag.exceptionResult.add(ex)
+//            resultList.add(ex)
+            tag.exceptionCreated = true
+        }
+    }
+
+    /**
+     * 鐢熸垚涓�鏉″紓甯稿垎鏋愮粨鏋�
+     */
+    abstract fun newResult(tag:T, factor: FactorFilter.SelectedFactor): Y
+
 }
\ No newline at end of file

--
Gitblit v1.9.3