From 176d7d8283e66ccf63878c9ab823e900df94b748 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期二, 05 八月 2025 17:20:58 +0800
Subject: [PATCH] 2025.8.5 1. 动态溯源模块添加延迟数据周期异常合并功能

---
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt |  359 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 312 insertions(+), 47 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 2bfe2be..3866509 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
@@ -2,6 +2,7 @@
 
 import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag
+import com.flightfeather.uav.biz.sourcetrace.model.RemainException
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
 import com.flightfeather.uav.lightshare.eunm.ExceptionStatusType
 import com.flightfeather.uav.socket.eunm.FactorType
@@ -11,8 +12,13 @@
  * 杩炵画绫诲瀷鐨勫紓甯稿垎鏋愬熀绫�,閫傜敤浜庡綋鍓嶆暟鎹笌鐩搁偦鏁版嵁涔嬮棿鏈夊叧鑱斿叧绯荤殑鎯呭喌
  */
 abstract class BaseExceptionContinuous<T : ExceptionTag, V : BaseAnalysisConfig, Y : BaseExceptionResult>(
-    config: V, private val tagClz: Class<T>
+    config: V, private val tagClz: Class<T>,
 ) : BaseExceptionAnalysis<V, Y>(config) {
+
+    enum class JudgeMethod(val des: String) {
+        M1("鍦ㄤ竴瀹氱殑绌洪棿鍜屾椂闂磋寖鍥村唴锛屾暟鎹疮璁″嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛"),
+        M2("瑕佹眰鏁版嵁涓嶉棿鏂繛缁嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛"),
+    }
 
     companion object {
         // 璁板綍寮傚父鏁版嵁娈垫椂锛屽垎鍒悜璧峰鍓嶅拰鏈熬鍚庨澶栬褰曠殑鏁版嵁涓暟鍋忕Щ閲�
@@ -27,12 +33,28 @@
     // 鏈熬鏁版嵁瀵硅薄
     protected var lastData: BaseRealTimeData? = null
 
+    // 鏈�鏂扮殑涓�缁勫紓甯革紝璁板綍鍗曞洜瀛愬紓甯�
+    val latestExceptions = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>()
+
     /**
-     * 鍚庣疆鍒ゆ柇锛氬綋鐩搁偦鏁版嵁鏃堕棿涓嶈繛缁椂锛屾垨鑰呮弧瓒宠嚜瀹氫箟鏉′欢鏃讹紝瀵逛箣鍓嶅凡鏈夌殑寮傚父杩涜璁板綍
+     * 鏈�鏂扮殑涓�缁勫悎骞跺紓甯革紝鏍规嵁閰嶇疆鍙傛暟浠嶽latestExceptions]鍗曞洜瀛愬紓甯镐腑锛屽悎骞跺紓甯�
      */
-    open fun afterExcCheck(isContinue: Boolean, tag: T, hasException: Boolean?): Boolean {
-        return !isContinue || needCut(tag, hasException)
-    }
+    protected val latestCombinedExc = mutableListOf<List<Pair<FactorFilter.SelectedFactor, T>>>()
+
+    // 璁板綍闇�瑕佸欢杩熸暟鎹懆鏈熻繘琛屽悎骞剁殑寮傚父
+    val remainingExceptions = mutableListOf<RemainException<T>>()
+
+    /**
+     * 寮傚父缁撴灉
+     */
+    val result = mutableListOf<Y>()
+
+    /**
+     * 涓嶉�傜敤浜庢寮傚父绫诲瀷鐨勭洃娴嬪洜瀛�
+     */
+    open var excludedFactor: List<FactorType> = emptyList()
+
+    abstract var judgeMethod: JudgeMethod
 
     /**
      * 绔嬪嵆鍒ゆ柇锛氬綋鍑虹幇寮傚父鏃讹紝缂撳瓨寮傚父鏁版嵁鐨勫悓鏃讹紝绔嬪嵆瀵瑰凡鏈夊紓甯歌繘琛屽垽鏂槸鍚︽弧瓒冲紓甯哥粨鏋滆姹�
@@ -53,6 +75,16 @@
     }
 
     /**
+     * 鍒ゆ柇鏁版嵁閲忕骇鍦ㄥ紓甯稿垽鏂殑鑼冨洿鍐�
+     * 榛樿鎵�鏈夐噺绾ч兘鍦ㄥ紓甯稿垽鏂殑鑼冨洿鍐�
+     */
+    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>
@@ -64,11 +96,24 @@
     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 {
-        // 榛樿鍒ゆ柇鏉′欢涓� 褰撳紓甯镐笉鍐嶉噸澶嶅嚭鐜版椂锛屽舰鎴愬紓甯哥粨鏋�
+    open fun needCut(tag: T, hasException: Boolean?, data: BaseRealTimeData): Boolean {
+        // 榛樿鍒ゆ柇鏉′欢涓� 褰撳紓甯镐笉鍐嶉噸澶嶅嚭鐜版椂
         return tag.exceptionExisted && hasException == false
     }
 
@@ -83,12 +128,13 @@
 
     override fun onNextData(data: BaseRealTimeData) {
         val isContinue = isContinuous(lastData, data)
-        val hasException = judgeException(lastData, data)
+        val hasException = judge(lastData, data)
         config.factorFilter.selectedList.forEach { s ->
             val f = s.main
-            tagMap[f]?.let {
-                it.addHistoryData(data)
+            // 鎺掗櫎姝ゅ紓甯哥被鍨嬩笉閫傜敤鐨勭洃娴嬪洜瀛�
+            if (excludedFactor.contains(f)) return@forEach
 
+            tagMap[f]?.let {
                 it.eIndex++
                 // 璧峰鏁版嵁
                 it.endData = data
@@ -96,33 +142,87 @@
                     it.refreshWithNextException(data)
                 }
 
-                // 瀵逛簬寮傚父鐨勭敓鎴愬垎鍒墽琛屽悗缃垽鏂�佸拰绔嬪嵆鍒ゆ柇
-                // 1. 鍚庣疆鍒ゆ柇锛氬綋鐩搁偦鏁版嵁鏃堕棿涓嶈繛缁椂锛屾垨鑰呮弧瓒宠嚜瀹氫箟鏉′欢鏃讹紝瀵逛箣鍓嶅凡鏈夌殑寮傚父杩涜璁板綍锛屽舰鎴愬紓甯哥粨鏋�
-                if (afterExcCheck(isContinue, it, hasException[f])) {
-                    // 鏁版嵁涓嶈繛缁椂鎴栬�呮弧瓒充富鍔ㄦ埅鏂潯浠舵椂锛岃褰曞紓甯告儏鍐�
-                    recordException(s, it, data)
+                // 鎸夌収涓嶅悓鐨勬柟寮忚繘琛屽紓甯稿垽鏂�
+                when (judgeMethod) {
+                    JudgeMethod.M1 -> judgeMethod1(hasException, f, it, data, s)
+                    JudgeMethod.M2 -> judgeMethod2(isContinue, hasException, f, it, data, s)
                 }
-                // 2. 绔嬪嵆鍒ゆ柇锛氬綋鍑虹幇寮傚父鏃讹紝缂撳瓨寮傚父鏁版嵁鐨勫悓鏃讹紝绔嬪嵆瀵瑰凡鏈夊紓甯歌繘琛屽垽鏂槸鍚︽弧瓒冲紓甯哥粨鏋滆姹�
-                else if (hasException[f] == true) {
-                    // 鏈夊紓甯稿嚭鐜版椂锛岃褰曞紓甯告暟鎹�
-                    it.addExceptionData(data)
-                    // 褰撶珛鍗冲垽鏂�氳繃鏃讹紝褰㈡垚寮傚父缁撴灉
-                    if (immeExcCheck(it, f)) {
-                        recordException(s, it, data)
-                    }
-                }
-                // 3. 鏁版嵁姝e父锛屾棤浠讳綍寮傚父鏃禿
-                // TODO("2025.6.3锛氬叾浠栧瓙绫荤殑姝ゅ鍒锋柊閫昏緫寰呭畬鎴愨��)
-                else {
-                    it.refreshWithNoException(data)
-                }
+
+                it.addHistoryData(data)
             }
         }
         lastData = data
+
+        removeSingleFactor(data)
+        checkDelayedExceptions(data)
+        mergeExceptionResult(data)
+        onNewResult(result)
+        clearExceptions(data)
     }
 
     override fun onDone() {
         checkResult(exceptionStatus = ExceptionStatusType.Ended)
+    }
+
+    /**
+     * 鏁版嵁寮傚父鍒ゆ柇鏂瑰紡涓�
+     * 鍦ㄤ竴瀹氱殑绌洪棿鍜屾椂闂磋寖鍥村唴锛屾暟鎹疮璁″嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛
+     */
+    private fun judgeMethod1(
+        hasException: MutableMap<FactorType, Boolean>,
+        f: FactorType,
+        tag: T,
+        data: BaseRealTimeData,
+        s: FactorFilter.SelectedFactor,
+    ) {
+        // 鍑虹幇寮傚父
+        if (hasException[f] == true) {
+            // 鍒ゆ柇鏁版嵁鍦ㄧ┖闂村拰鏃堕棿鍙樺寲涓婃槸鍚﹁秴鍑洪檺瀹氳寖鍥达紝鑻ヨ秴鍑哄垯鍒犻櫎閬楃暀鐨勫紓甯歌褰曪紝鍒锋柊璧峰鐐规暟鎹�
+            if (needCut(tag, hasException[f], data)) {
+                tag.refreshWithNextException(data)
+            }
+            // 璁板綍寮傚父鏁版嵁
+            tag.addExceptionData(data)
+            // 褰撶珛鍗冲垽鏂�氳繃鏃讹紝褰㈡垚寮傚父缁撴灉
+            if (immeExcCheck(tag, f)) {
+                recordException(s, tag, data)
+            }
+        }
+        // 鏁版嵁姝e父锛屽苟涓旀病鏈夊巻鍙插紓甯告暟鎹椂锛屽埛鏂拌捣濮嬬偣鏁版嵁
+        else if (!tag.exceptionExisted) {
+            tag.refreshWithNextException(data)
+        }
+    }
+
+    /**
+     * 鏁版嵁寮傚父鍒ゆ柇鏂瑰紡浜�
+     * 瑕佹眰鏁版嵁涓嶉棿鏂繛缁嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛
+     */
+    private fun judgeMethod2(
+        isContinue: Boolean,
+        hasException: MutableMap<FactorType, Boolean>,
+        f: FactorType,
+        tag: T,
+        data: BaseRealTimeData,
+        s: FactorFilter.SelectedFactor,
+    ) {
+        // 褰撶浉閭绘暟鎹椂闂翠笉杩炵画鏃讹紝鍒锋柊璧峰鐐规暟鎹紝绉婚櫎鍘嗗彶寮傚父璁板綍
+        if (!isContinue) {
+            tag.refreshWithNextException(data)
+        }
+        // 鍑虹幇寮傚父
+        else if (hasException[f] == true) {
+            // 鏈夊紓甯稿嚭鐜版椂锛岃褰曞紓甯告暟鎹�
+            tag.addExceptionData(data)
+            // 褰撶珛鍗冲垽鏂�氳繃鏃讹紝褰㈡垚寮傚父缁撴灉
+            if (immeExcCheck(tag, f)) {
+                recordException(s, tag, data)
+            }
+        }
+        // 鏁版嵁姝e父锛屽埛鏂拌捣濮嬬偣鏁版嵁锛岀Щ闄ゅ巻鍙插紓甯歌褰�
+        else {
+            tag.refreshWithNextException(data)
+        }
     }
 
     /**
@@ -131,7 +231,7 @@
      */
     fun recordException(factor: FactorFilter.SelectedFactor, tag: T, data: BaseRealTimeData) {
         checkResult(factor, ExceptionStatusType.Ended)
-        tag.refreshWithNextException(data)
+//        tag.refreshWithNextException(data)
     }
 
     /**
@@ -139,7 +239,7 @@
      */
     open fun checkResult(
         factor: FactorFilter.SelectedFactor? = null,
-        exceptionStatus: ExceptionStatusType = ExceptionStatusType.InProgress
+        exceptionStatus: ExceptionStatusType = ExceptionStatusType.InProgress,
     ) {
         val tag = tagMap[factor?.main]
         if (factor != null && tag != null) {
@@ -149,7 +249,7 @@
         } else {
             config.factorFilter.selectedList.forEach { f ->
                 val tag1 = tagMap[f.main] ?: return@forEach
-                if (tag1.exceptionExisted && judgeExceptionCount(tag1, null)) {
+                if (tag1.exceptionExisted && judgeExceptionCount(tag1, f.main)) {
                     onNewException(tag1, f, exceptionStatus)
                 }
             }
@@ -162,27 +262,192 @@
     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)
+//        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)
+//            tag.exceptionCreated = true
+//        }
+//        val tagClone = tagClz.newInstance()
+//        BeanUtils.copyProperties(tag, tagClone)
+        latestExceptions.add(factor to tag)
+    }
+
+    /**
+     * 灏嗕笉鍦ㄥ叧鑱斿叧绯讳腑鐨勭洃娴嬪洜瀛愬紓甯稿瓨鍌紝骞跺墧闄�
+     */
+    fun removeSingleFactor(data: BaseRealTimeData) {
+        // 鏌ユ壘涓嶅湪鍥犲瓙鍏宠仈缁勫悎涓殑寮傚父鍥犲瓙
+        val sfList = latestExceptions.filter {
+            config.factorFilter.combination.find { c -> c.find { f -> f == it.first.main } != null } == null
         }
-        // 寮傚父鏈垱寤烘椂锛屾柊寤哄紓甯镐俊鎭�
-        else {
-            tag.exceptionResult.add(ex)
-//            resultList.add(ex)
-            tag.exceptionCreated = true
+        // 鐢熸垚瀵瑰簲鐨勫紓甯哥粨鏋滐紝骞跺垵濮嬪寲璇ュ紓甯�
+        sfList.forEach {
+            result.add(newResult(listOf(it)))
+            it.second.refreshWithNextException(data)
         }
+        // 鍓旈櫎
+        latestExceptions.removeAll(sfList)
+    }
+
+    /**
+     * 妫�鏌ュ欢杩熺殑寰呭悎骞跺紓甯镐笌褰撳墠寮傚父鏄惁鑳藉尮閰�
+     * 1. 灏嗛仐鐣欑殑瓒呰繃绛夊緟鏁版嵁鍛ㄦ湡鐨勫紓甯稿瓨鍌�
+     * 2. 灏嗗尮閰嶆垚鍔熺殑鍚堝苟寮傚父瀛樺偍
+     * 3. 淇濈暀渚濇棫鏈悎骞舵垚鍔熷苟涓斿彲缁х画绛夊緟鐨勫紓甯�
+     * @return 琚尮閰嶆垚鍔熺殑鍏宠仈鍏崇郴
+     */
+    fun checkDelayedExceptions(data: BaseRealTimeData): List<List<FactorType>> {
+        // 琚尮閰嶆垚鍔熺殑鐩戞祴鍥犲瓙鍏宠仈鍏崇郴
+        val fittedComb = mutableListOf<List<FactorType>>()
+        // 閬楃暀鐨勮繘鍏ヤ笅涓�涓暟鎹懆鏈熷仛鍒ゆ柇鐨勫緟鍚堝苟寮傚父闆嗗悎
+        val leftExc = mutableListOf<RemainException<T>>()
+        // 鎴愬姛鍖归厤鐨勫悎骞跺紓甯搁泦鍚�
+        val combinedExc = mutableListOf<List<Pair<FactorFilter.SelectedFactor, T>>>()
+        // 鏈鏁版嵁鍛ㄦ湡涓紝琚尮閰嶆垚鍔熺殑寮傚父闆嗗悎
+        val exceps = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>()
+        remainingExceptions.forEach {
+            // 妫�鏌ュ綋鍓嶆柊寮傚父涓紝鏄惁鍖呭惈鍥犲瓙鍏宠仈鍏崇郴涓殑寮傚父
+            val combRes = matchCombFactor(it.combination, latestExceptions)
+            val res = combRes.second
+            // 鍒ゆ柇鏈鏁版嵁鍛ㄦ湡涓壘鍒扮殑鍥犲瓙鍜屽凡鏈夌殑鍥犲瓙鏄惁婊¤冻鍏宠仈鍏崇郴
+            val findFactors = mutableListOf<FactorType>()
+            res.forEach {r -> findFactors.add(r.first.main) }
+            it.exceptions.forEach {r -> findFactors.add(r.first.main) }
+            // 鍒ゆ柇鏄惁杩樻湁缂哄け寮傚父
+            val isFitAll = findFactors.distinct() == it.combination
+            // 濡傛灉宸茬粡娌℃湁缂哄け鐨勫紓甯稿洜瀛愶紝鍒欏彲鍚堝苟涓虹粍鍚堝紓甯�
+            if (isFitAll) {
+                fittedComb.add(it.combination)
+                // 灏嗘煡鎵剧粨鏋滄坊鍔犺嚦宸叉湁寮傚父闆嗗悎涓�
+                it.addExceptions(res)
+//                // 璁板綍琚尮閰嶆垚鍔熺殑寮傚父
+//                res.forEach { r->
+//                    if (exceps.find { e -> e.second == r.second } == null) {
+//                        exceps.add(r)
+//                    }
+//                }
+                // 灏嗗悎骞跺紓甯稿瓨鍌�
+                combinedExc.add(it.exceptions)
+
+            }
+            // 鍚﹀垯鐣欎綔涓嬫鏁版嵁鍛ㄦ湡鍐嶅垽瀹氬瓨鍏ュ緟鍚堝苟寮傚父闆嗗悎
+            else {
+                it.period++
+                // 褰撳緟鍚堝苟鐨勫紓甯哥瓑寰呮暟鎹懆鏈熷ぇ浜庤瀹氬�兼椂锛屼笉鍐嶇瓑寰咃紝鐩存帴杈撳嚭寮傚父
+                if (it.period > config.maxDelayPeriod) {
+                    result.add(newResult(it.exceptions))
+                    return@forEach
+                } else {
+                    fittedComb.add(it.combination)
+                    // 灏嗘煡鎵剧粨鏋滄坊鍔犺嚦宸叉湁寮傚父闆嗗悎涓�
+                    it.addExceptions(res)
+//                    // 璁板綍琚尮閰嶆垚鍔熺殑寮傚父
+//                    res.forEach { r->
+//                        if (exceps.find { e -> e.second == r.second } == null) {
+//                            exceps.add(r)
+//                        }
+//                    }
+                    leftExc.add(it)
+                }
+            }
+        }
+        // 瀛樺偍鍚堝苟寮傚父
+        combinedExc.forEach {
+            result.add(newResult(it))
+        }
+//        // 灏嗚鍖归厤鎴愬姛鐨勫紓甯稿埛鏂帮紝骞朵粠鏈鏁版嵁鍛ㄦ湡鐨勫紓甯搁泦鍚堜腑绉婚櫎
+//        exceps.forEach { r-> r.second.refreshWithNextException(data) }
+//        latestExceptions.removeAll(exceps)
+        // 淇濈暀鏈尮閰嶇殑缁勫悎
+        remainingExceptions.clear()
+        remainingExceptions.addAll(leftExc)
+
+        return fittedComb
+    }
+
+    /**
+     * 鍚堝苟寮傚父
+     */
+    open fun mergeExceptionResult(data: BaseRealTimeData) {
+        val combinedExc = mutableListOf<List<Pair<FactorFilter.SelectedFactor, T>>>()
+        // 閬嶅巻鎵�鏈夌殑鍥犲瓙缁勫悎
+        config.factorFilter.combination.forEach { c ->
+            val combRes = matchCombFactor(c, latestExceptions)
+            val res = combRes.second
+            val exist = combRes.first
+            // 濡傛灉缁勫悎鍐呯殑鎵�鏈夊洜瀛愰兘瀛樺湪寮傚父锛屽垯瀛樺偍涓哄悎骞跺紓甯�
+            if (exist) {
+                // 灏嗗悎骞跺紓甯稿瓨鍌�
+                combinedExc.add(res)
+            }
+            // 鍚﹀垯灏嗗紓甯哥殑娣辨嫹璐濈増鏈瓨鍏ュ緟鍚堝苟寮傚父闆嗗悎
+            // TODO 2025.8.4: 鍚庣画娣诲姞褰撳叧鑱旂殑鐩戞祴鍥犲瓙绱寮傚父璁℃暟鎺ヨ繎闃堝�兼椂锛屾墠瀛樺叆闆嗗悎鐨勯�昏緫
+            else {
+                remainingExceptions.add(RemainException(res, c))
+            }
+        }
+
+        // 瀛樺偍鍚堝苟寮傚父
+        combinedExc.forEach {
+            result.add(newResult(it))
+        }
+    }
+
+    /**
+     * 鍖归厤鍏宠仈寮傚父鍥犲瓙
+     * @param comb 鍏宠仈鍥犲瓙鍏崇郴
+     * @param exceptions 鍚勭洃娴嬪洜瀛愬紓甯搁泦鍚�
+     * @return exist琛ㄧず鏄惁鎵惧埌鍏宠仈鍏崇郴[comb]涓墍鏈夌殑鍥犲瓙锛宺es琛ㄧず鎵惧埌鐨勭粨鏋�
+     */
+    private fun matchCombFactor(
+        comb: List<FactorType>,
+        exceptions: List<Pair<FactorFilter.SelectedFactor, T>>,
+    ): Pair<Boolean, MutableList<Pair<FactorFilter.SelectedFactor, T>>> {
+        val res = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>()
+        var exist = true
+        // 鏌ョ湅缁勫悎鍐呯殑鎵�鏈夊洜瀛愭槸鍚﹂兘鍚屾椂鍑虹幇寮傚父
+        comb.forEach { f ->
+            val r = exceptions.find { e ->
+                e.first.main == f
+            }
+            if (r != null) {
+                res.add(r)
+            } else {
+                exist = false
+            }
+        }
+        return exist to res
+    }
+
+    abstract fun onNewResult(result: List<Y>)
+
+    /**
+     * 鍦ㄥ紓甯哥敓鎴愮粨鏋滃悗锛岃繘琛屽垵濮嬪寲
+     */
+    private fun clearExceptions(data: BaseRealTimeData) {
+        // 姝ゆ椂latestExceptions涓簲璇ュ寘鍚殑渚濇棫鏄湰娆℃暟鎹懆鏈熷唴鐨勬墍鏈夊紓甯�
+        latestExceptions.forEach {
+            it.second.refreshWithNextException(data)
+        }
+        latestExceptions.clear()
+        result.clear()
     }
 
     /**
      * 鐢熸垚涓�鏉″紓甯稿垎鏋愮粨鏋�
      */
-    abstract fun newResult(tag:T, factor: FactorFilter.SelectedFactor): Y
+    abstract fun newResult(tag: T, factor: FactorFilter.SelectedFactor): Y
+
+    abstract fun newResult(exceptions: List<Pair<FactorFilter.SelectedFactor, ExceptionTag>>): Y
 
 }
\ No newline at end of file

--
Gitblit v1.9.3