From 38d72198bfcced01ed9513b978163e5cd1d84625 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期一, 21 七月 2025 15:31:41 +0800
Subject: [PATCH] 2025.7.21 1. 修改动态溯源异常判断逻辑

---
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt        |    2 
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt                        |   18 ++-
 src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt                    |   76 +++++++++++++++
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt                     |  110 ++++++++++++++++-----
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt            |    2 
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionTag.kt                          |   15 ++
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt                  |    2 
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt           |    2 
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt |    4 
 src/test/kotlin/com/flightfeather/uav/Test.kt                                                         |   33 ++++++
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt             |    4 
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt                           |    5 +
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt                        |    8 +
 13 files changed, 241 insertions(+), 40 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 733641e..36fdfa1 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
@@ -15,6 +15,11 @@
     config: V, private val tagClz: Class<T>,
 ) : BaseExceptionAnalysis<V, Y>(config) {
 
+    enum class JudgeMethod(val des: String) {
+        M1("鍦ㄤ竴瀹氱殑绌洪棿鍜屾椂闂磋寖鍥村唴锛屾暟鎹疮璁″嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛"),
+        M2("瑕佹眰鏁版嵁涓嶉棿鏂繛缁嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛"),
+    }
+
     companion object {
         // 璁板綍寮傚父鏁版嵁娈垫椂锛屽垎鍒悜璧峰鍓嶅拰鏈熬鍚庨澶栬褰曠殑鏁版嵁涓暟鍋忕Щ閲�
         private const val OFFSET = 10
@@ -40,6 +45,13 @@
      * 寮傚父缁撴灉
      */
     protected val result = mutableListOf<Y>()
+
+    /**
+     * 涓嶉�傜敤浜庢寮傚父绫诲瀷鐨勭洃娴嬪洜瀛�
+     */
+    open var excludedFactor: List<FactorType> = emptyList()
+
+    abstract var judgeMethod: JudgeMethod
 
     /**
      * 绔嬪嵆鍒ゆ柇锛氬綋鍑虹幇寮傚父鏃讹紝缂撳瓨寮傚父鏁版嵁鐨勫悓鏃讹紝绔嬪嵆瀵瑰凡鏈夊紓甯歌繘琛屽垽鏂槸鍚︽弧瓒冲紓甯哥粨鏋滆姹�
@@ -98,7 +110,7 @@
      * @return
      */
     open fun needCut(tag: T, hasException: Boolean?, data: BaseRealTimeData): Boolean {
-        // 榛樿鍒ゆ柇鏉′欢涓� 褰撳紓甯镐笉鍐嶉噸澶嶅嚭鐜版椂锛屽舰鎴愬紓甯哥粨鏋�
+        // 榛樿鍒ゆ柇鏉′欢涓� 褰撳紓甯镐笉鍐嶉噸澶嶅嚭鐜版椂
         return tag.exceptionExisted && hasException == false
     }
 
@@ -116,9 +128,10 @@
         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
@@ -126,31 +139,13 @@
                     it.refreshWithNextException(data)
                 }
 
-                // 瀵逛簬寮傚父鐨勭敓鎴愬垎鍒墽琛屽悗缃垽鏂�佸拰绔嬪嵆鍒ゆ柇
-                // 1. 鍚庣疆鍒ゆ柇锛氬綋鐩搁偦鏁版嵁鏃堕棿涓嶈繛缁椂锛屾垨鑰呮弧瓒宠嚜瀹氫箟鏉′欢鏃讹紝瀵逛箣鍓嶅凡鏈夌殑寮傚父杩涜璁板綍锛屽舰鎴愬紓甯哥粨鏋�
-//                if (afterExcCheck(isContinue, it, hasException[f])) {
-//                    // 鏁版嵁涓嶈繛缁椂鎴栬�呮弧瓒充富鍔ㄦ埅鏂潯浠舵椂锛岃褰曞紓甯告儏鍐�
-//                    recordException(s, it, data)
-//                }
-                // 2. 绔嬪嵆鍒ゆ柇锛氬綋鍑虹幇寮傚父鏃讹紝缂撳瓨寮傚父鏁版嵁鐨勫悓鏃讹紝绔嬪嵆瀵瑰凡鏈夊紓甯歌繘琛屽垽鏂槸鍚︽弧瓒冲紓甯哥粨鏋滆姹�
-                if (hasException[f] == true) {
-
-//                    afterExcCheck(isContinue, it, hasException[f])
-                    if (needCut(it, hasException[f], data)) {
-                        it.refreshWithNextException(data)
-                    }
-                    // 鏈夊紓甯稿嚭鐜版椂锛岃褰曞紓甯告暟鎹�
-                    it.addExceptionData(data)
-                    // 褰撶珛鍗冲垽鏂�氳繃鏃讹紝褰㈡垚寮傚父缁撴灉
-                    if (immeExcCheck(it, f)) {
-                        recordException(s, it, data)
-                    }
+                // 鎸夌収涓嶅悓鐨勬柟寮忚繘琛屽紓甯稿垽鏂�
+                when (judgeMethod) {
+                    JudgeMethod.M1 -> judgeMethod1(hasException, f, it, data, s)
+                    JudgeMethod.M2 -> judgeMethod2(isContinue, hasException, f, it, data, s)
                 }
-                // 3. 鏁版嵁姝e父锛屾棤浠讳綍寮傚父鏃禿
-                // TODO("2025.6.3锛氬叾浠栧瓙绫荤殑姝ゅ鍒锋柊閫昏緫寰呭畬鎴愨��)
-//                else {
-//                    it.refreshWithNextException(data)
-//                }
+
+                it.addHistoryData(data)
             }
         }
         lastData = data
@@ -164,6 +159,67 @@
     }
 
     /**
+     * 鏁版嵁寮傚父鍒ゆ柇鏂瑰紡涓�
+     * 鍦ㄤ竴瀹氱殑绌洪棿鍜屾椂闂磋寖鍥村唴锛屾暟鎹疮璁″嚭鐜癗娆″紓甯稿悗锛岃涓鸿寮傚父鎴愮珛
+     */
+    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)
+        }
+    }
+
+    /**
      * 寮傚父缁撴潫锛岃褰曞紓甯�
      * 鍒ゆ柇宸叉湁鐨勫紓甯告暟鎹槸鍚︽弧瓒冲紓甯告潯浠讹紝婊¤冻鍒欒褰曪紝涓嶆弧瓒冲垯鐣ヨ繃
      */
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt
index f2db635..2e382b4 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt
@@ -16,6 +16,8 @@
 class ExceptionDataExceed(config: DataAnalysisConfig) :
     BaseExceptionContinuousSingle<ExceptionTag, DataAnalysisConfig, ExceptionResult>(config, ExceptionTag::class.java) {
 
+    override var judgeMethod: JudgeMethod = JudgeMethod.M2
+
     override fun getExceptionType(): ExceptionType = ExceptionType.TYPE2
 
     override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt
index bb399d7..5633645 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt
@@ -20,6 +20,8 @@
 
     override fun getExceptionType(): ExceptionType = ExceptionType.TYPE4
 
+    override var judgeMethod: JudgeMethod = JudgeMethod.M2
+
     override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
         val res = mutableMapOf<FactorType, Boolean>()
         config.factorFilter.mainList().forEach { f ->
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionTag.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionTag.kt
index 15368b2..4d7cb93 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionTag.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionTag.kt
@@ -9,6 +9,9 @@
  * @author feiyu02
  */
 open class ExceptionTag {
+    companion object {
+        const val MAX_HISTORY = 10
+    }
     // 璧峰鏁版嵁涓嬫爣
     var sIndex = 0
 
@@ -37,8 +40,16 @@
 
     fun addHistoryData(data: BaseRealTimeData) {
         historyData.add(data)
-        if (historyData.size > 15) {
-            historyData.removeAt(0)
+        if (exceptionData.isNotEmpty()) {
+            // 淇濊瘉鍘嗗彶鏁版嵁鍖呭惈鎵�鏈夊紓甯告暟鎹紙寮傚父鏁版嵁鍙兘涓嶈繛缁級锛屽苟涓斿湪棣栦釜寮傚父鏁版嵁涔嬪墠鏈�澶氬啀淇濆瓨10涓暟鎹�
+            val i = historyData.indexOf(exceptionData.first())
+            if (i > MAX_HISTORY) {
+                historyData = historyData.subList(i - MAX_HISTORY, historyData.size)
+            }
+        } else {
+            if (historyData.size > MAX_HISTORY) {
+                historyData = historyData.subList(historyData.size - MAX_HISTORY, historyData.size)
+            }
         }
     }
 
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
index 0e4c5ef..83bb5c7 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
@@ -43,7 +43,7 @@
                     .withMain(FactorType.O3)
                     .withMain(FactorType.PM25)
                     .withMain(FactorType.PM10)
-                    .withMain(FactorType.VOC)
+//                    .withMain(FactorType.VOC)
                     .withCombination(
                         listOf(
                             listOf(FactorType.PM25, FactorType.PM10),
@@ -63,6 +63,8 @@
     private val sceneInfoRep: SceneInfoRep
     private val sourceTraceRep: SourceTraceRep
     private val config: RTExcWindLevelConfig
+    private val timer = Timer()
+    private var timerTask: TimerTask? = null
 
     private val taskList = mutableListOf<BaseExceptionAnalysis<RTExcWindLevelConfig, PollutedClue>>()
 
@@ -92,23 +94,27 @@
      * 璁$畻鏂扮殑涓�鏉″疄鏃惰蛋鑸暟鎹�
      */
     fun addOneData(data: BaseRealTimeData) {
+//        println("====================>")
         // 璁$畻寮傚父
         taskList.forEach { it.onNextData(data) }
         pollutedSummary.refreshLatestMonitorData(data)
         // 闄愬畾鏃堕棿鍐呮病鏈夋柊鏁版嵁浼犲叆锛屽垯缁撴潫褰撳墠鐨勮绠�
+        dealOnTimeout()
     }
 
     /**
      * 瓒呮椂澶勭悊锛岃緝闀挎椂闂存病鏈夋柊鏁版嵁杩涘叆锛岃繘琛屽垵濮嬪寲鎿嶄綔
      */
     private fun dealOnTimeout() {
-        val timer = Timer(true)
-        timer.schedule(object : TimerTask() {
+//        val timer = Timer()
+        timerTask?.cancel()
+        timer.purge()
+        timerTask = object : TimerTask() {
             override fun run() {
-                TODO("Not yet implemented")
+                initTask()
             }
-        }, 60 * 1000)
-        timer.cancel()
+        }
+        timer.schedule(timerTask, 2 * 60 * 60 * 1000)
     }
 
     // 鏁版嵁绐佸彉寮傚父鍥炶皟
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
index e855a98..81d3ef6 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
@@ -27,7 +27,7 @@
     // 婧簮鎵╂暎鍋忕Щ瑙掑害锛堝崟浣嶏細搴︼級
     var sourceTraceDegOffset = 120.0
     // 瀹氭椂绾跨储鍒嗘瀽鏃堕棿闂撮殧(鍗曚綅锛氬垎閽�)
-    var analysisPeriod = 15
+    var analysisPeriod = 5
     // 瀹氭椂鍒嗘瀽闂撮殧涓紝绔嬪嵆杩涜绾跨储鍒嗘瀽鐨勬渶灏忕嚎绱㈤噺(鍗曚綅锛氫釜)
     var analysisCount = 4
 
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt
index c0c0cd3..28d1591 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt
@@ -30,6 +30,8 @@
 
     abstract var changeRate: MutableMap<FactorType, RTExcWindLevelConfig.WindLevelCondition>
 
+    override var judgeMethod: JudgeMethod = JudgeMethod.M2
+
     override fun getExceptionType(): ExceptionType {
         return ExceptionType.TYPE9
     }
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
index 5fc728c..24fa6d7 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
@@ -29,10 +29,14 @@
         this.callback = callback
     }
 
+    override var excludedFactor: List<FactorType> = listOf(FactorType.NO2)
+
     private var callback: NewPolluteClueCallback? = null
 
     abstract var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition
 
+    override var judgeMethod: JudgeMethod = JudgeMethod.M1
+
     override fun getExceptionType(): ExceptionType {
         return ExceptionType.TYPE4
     }
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt
index a7dece6..3bccabf 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt
@@ -32,6 +32,8 @@
         return ExceptionType.TYPE4
     }
 
+    override var judgeMethod: JudgeMethod = JudgeMethod.M2
+
     override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
         val res = mutableMapOf<FactorType, Boolean>()
         config.factorFilter.mainList().forEach { f ->
@@ -67,7 +69,7 @@
         if (tag.exceptionData.isEmpty()) return false
 
         val se = tag.exceptionData.first()
-        val ee = tag.exceptionData.last()
+        val ee = data
 
         val sTime = LocalDateTime.ofInstant(se.dataTime?.toInstant(), ZoneId.systemDefault())
         val eTime = LocalDateTime.ofInstant(ee.dataTime?.toInstant(), ZoneId.systemDefault())
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
index cd82f6c..9375913 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
@@ -26,6 +26,8 @@
         windLevelCondition: RTExcWindLevelConfig.WindLevelCondition?,
     ) : this() {
         distanceType = windLevelCondition?.distanceType
+        distanceRange = distanceType?.disRange
+        distanceDes = distanceType?.des
         windLevelCondition?.let { sourceTrace(historyData, exceptionData, config, it) }
     }
 
@@ -40,6 +42,9 @@
     // 姹℃煋鍙兘鐨勫彂鐢熻窛绂�
     var distanceType: DistanceType? = null
 
+    var distanceRange: Pair<Double, Double>? = null
+    var distanceDes: String? = null
+
     /**
      * 鍙嶅悜婧簮
      */
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
index 6741ee7..188bb7f 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
@@ -64,15 +64,16 @@
 
     // 鏂板涓�鏉℃薄鏌撶嚎绱�
     fun addClue(pollutedClue: PollutedClue) {
-        clueList.add(pollutedClue)
+        // 褰撴函婧愭湭鎵惧埌椋庨櫓婧愭椂锛屾娆℃函婧愪俊鎭笉浣滀负绾跨储缁熻椤�
+        if (pollutedClue.pollutedSource?.sceneList?.isNotEmpty() == true)
+            clueList.add(pollutedClue)
 //        realTimeSummary()
         analysisOnClueCount()
     }
 
     // 鏂板涓�鏉℃薄鏌撶嚎绱�
     fun addClueList(pollutedClues: List<PollutedClue>) {
-        clueList.addAll(pollutedClues)
-        analysisOnClueCount()
+        pollutedClues.forEach { addClue(it) }
     }
 
     // 鍒锋柊褰撳墠鏈�鏂扮殑璧拌埅鐩戞祴鏁版嵁
@@ -181,6 +182,7 @@
 
                 // 寤鸿鐨勮蛋鑸矾绾�
                 result.direction = AMapService.directionDriving(origin, destination)
+                Thread.sleep(200)
             }
             // 绾跨储鍒嗘瀽瀹屾垚鍚庯紝绉诲姩鑷冲巻鍙茬嚎绱㈠垪琛�
             historyClueList.addAll(clueList)
diff --git a/src/test/kotlin/com/flightfeather/uav/Test.kt b/src/test/kotlin/com/flightfeather/uav/Test.kt
index 4941af9..11a50e1 100644
--- a/src/test/kotlin/com/flightfeather/uav/Test.kt
+++ b/src/test/kotlin/com/flightfeather/uav/Test.kt
@@ -168,4 +168,37 @@
     fun foo18() {
         println(-4.382398 in 4.0..Double.MAX_VALUE)
     }
+
+    @Test
+    fun foo19() {
+        val timer = Timer(true)
+//        var running = true
+        val task = object : TimerTask() {
+            override fun run() {
+                println("task run")
+                println(Date())
+//                running = false
+            }
+        }
+        println(Date())
+        timer.schedule(task, 5000)
+        task.cancel()
+        timer.purge()
+
+        val task2 = object : TimerTask() {
+            override fun run() {
+                println("task2 run")
+                println(Date())
+//                running = false
+            }
+        }
+        timer.schedule(task2, 4000)
+//        while (running) {
+//
+//        }
+        val sc = Scanner(System.`in`)
+        while (sc.hasNext()) {
+            println(sc.nextLine())
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt
new file mode 100644
index 0000000..3ae933c
--- /dev/null
+++ b/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt
@@ -0,0 +1,76 @@
+package com.flightfeather.uav.biz.sourcetrace
+
+import com.flightfeather.uav.common.utils.DateUtil
+import com.flightfeather.uav.domain.entity.Mission
+import com.flightfeather.uav.domain.entity.RealTimeDataVehicle
+import com.flightfeather.uav.domain.mapper.MissionMapper
+import com.flightfeather.uav.domain.repository.MissionRep
+import com.flightfeather.uav.domain.repository.SceneInfoRep
+import com.flightfeather.uav.domain.repository.SourceTraceRep
+import com.flightfeather.uav.lightshare.service.RealTimeDataService
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit4.SpringRunner
+import tk.mybatis.mapper.entity.Example
+
+@RunWith(SpringRunner::class)
+@SpringBootTest
+class SourceTraceControllerTest {
+
+    @Autowired
+    lateinit var sceneInfoRep: SceneInfoRep
+
+    @Autowired
+    lateinit var sourceTraceRep: SourceTraceRep
+
+    @Autowired
+    lateinit var missionMapper: MissionMapper
+
+    @Autowired
+    lateinit var realTimeDataService: RealTimeDataService
+
+    @Test
+    fun autoSourceTrace() {
+        val sourceTraceController = SourceTraceController(sceneInfoRep, sourceTraceRep)
+        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
+            createCriteria().andEqualTo("deviceType", "0a")
+                .andLessThanOrEqualTo("startTime", "2024-11-07 15:00:00")
+            orderBy("startTime").desc()
+        })
+        missions.forEach { m ->
+            val rtData = realTimeDataService.getSecondData(
+                m?.deviceType,
+                m?.deviceCode,
+                DateUtil.instance.dateToString(m?.startTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
+                DateUtil.instance.dateToString(m?.endTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
+                null,
+                1,
+                10000
+            )
+            rtData.data?.forEach { d ->
+                val rtdVehicle = d.toBaseRealTimeData(RealTimeDataVehicle::class.java)
+//            Thread.sleep(500)
+                sourceTraceController.addOneData(rtdVehicle)
+            }
+            sourceTraceController.initTask()
+        }
+//        val rtData = realTimeDataService.getSecondData(
+//            "0a",
+//            "0a0000000001",
+//            "2025-01-06 13:32:00",
+//            "2025-01-06 15:52:36",
+//            null,
+//            1,
+//            10000
+//        )
+//        rtData.data?.forEach { d ->
+//            val rtdVehicle = d.toBaseRealTimeData(RealTimeDataVehicle::class.java)
+////            Thread.sleep(500)
+//            sourceTraceController.addOneData(rtdVehicle)
+//        }
+
+    }
+
+}
\ No newline at end of file

--
Gitblit v1.9.3