From e8f935a01d75c89ac591a80b9318eac2480e2dcd Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期四, 27 六月 2024 17:40:01 +0800
Subject: [PATCH] 1. 新增走航轨迹融合功能

---
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt             |    3 
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt |   32 ++-
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt              |  182 ++++++++++++++------
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt          |    5 
 src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt        |    3 
 src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt                                      |   47 +++++
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt    |   23 +
 src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt                                |   39 ++++
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt                |    4 
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt               |   26 ++
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt        |   63 ++++--
 src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt                               |    5 
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt                |   21 +-
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt            |    3 
 src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt                          |    9 
 src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt                              |   22 +-
 16 files changed, 368 insertions(+), 119 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt b/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt
new file mode 100644
index 0000000..3589b05
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt
@@ -0,0 +1,47 @@
+package com.flightfeather.uav.biz
+
+import com.flightfeather.uav.socket.eunm.FactorType
+
+/**
+ * 鎵�閫変富瑕佸垎鏋愬洜瀛愶紝浠ュ強鍏宠仈鍥犲瓙
+ * 鍦ㄥ仛鏁版嵁寮傚父鍒嗘瀽浠ュ強鏁版嵁缁熻鏃讹紝鐢ㄤ簬鍐冲畾鏄惁闇�瑕佽繘琛屽鐞嗚鍥犲瓙銆�
+ * @date 2024/6/27
+ * @author feiyu02
+ */
+class FactorFilter private constructor(){
+
+    data class SelectedFactor(
+        val main:FactorType,
+        var subs:List<FactorType> = emptyList()
+    )
+
+    inner class Builder{
+        fun withMain(factorType: FactorType): Builder {
+            selectedList.add(SelectedFactor(factorType))
+            return this
+        }
+
+        fun withSubs(subs: List<FactorType>): Builder {
+            if (selectedList.isNotEmpty()) {
+                selectedList.last().subs = subs
+            }
+            return this
+        }
+
+        fun create(): FactorFilter {
+            return this@FactorFilter
+        }
+    }
+
+    companion object{
+        fun builder() = FactorFilter().Builder()
+        fun default() = builder().create()
+    }
+
+    // 鎵�閫夊洜瀛愰泦鍚�
+    val selectedList = mutableListOf<SelectedFactor>()
+
+    fun mainList(): List<FactorType> {
+        return selectedList.map { it.main }
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt
index 94d782f..139166f 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt
@@ -1,5 +1,6 @@
 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.ExceptionResult
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
@@ -34,24 +35,26 @@
      * 鐢熸垚涓�鏉″紓甯稿垎鏋愮粨鏋�
      */
     open fun newResult(
-        start: BaseRealTimeData, end: BaseRealTimeData?, factorIndex: Int,
+        start: BaseRealTimeData, end: BaseRealTimeData?, factor: FactorFilter.SelectedFactor,
         exceptionData: List<BaseRealTimeData>,
     ): ExceptionResult {
         val eType = getExceptionType()
-        val factorType = FactorType.getByIndex(factorIndex)
         return ExceptionResult().apply {
             missionCode = config.mission.missionCode
             deviceCode = start.deviceCode
             exception = eType.des
             exceptionType = eType.value
-            factorId = factorType?.value
-            factorName = factorType?.des
+            factorId = factor.main.value
+            factorName = factor.main.des
+            subFactorId = factor.subs.map { it.value }
+            subFactorName = factor.subs.map { it.des }
+            selectedFactor = factor
             startTime = DateUtil.instance.dateToString(start.dataTime, DateUtil.DateStyle.HH_MM_SS)
             endTime = DateUtil.instance.dateToString(end?.dataTime, DateUtil.DateStyle.HH_MM_SS) ?: startTime
-            startData = start.getByFactorIndex(factorIndex)
-            endData = end?.getByFactorIndex(factorIndex) ?: startData
+            startData = start.getByFactorType(factor.main)
+            endData = end?.getByFactorType(factor.main) ?: startData
 
-            val s = dataSummary(exceptionData, factorIndex)
+            val s = dataSummary(exceptionData, factor.main)
             avg = s.first
             min = s.second
             max = s.third
@@ -60,13 +63,13 @@
         }
     }
 
-    fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorIndex: Int): Triple<Float, Float, Float> {
+    fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Float, Float, Float> {
         var min = -1f
         var max = -1f
         var total = 0f
         var count = 0
         exceptionData.forEach {
-            val value = it?.getByFactorIndex(factorIndex) ?: return@forEach
+            val value = it?.getByFactorType(factorType) ?: return@forEach
             if (min == -1f || min > value) {
                 min = value
             }
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 9177f77..2ea3314 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
@@ -1,7 +1,9 @@
 package com.flightfeather.uav.biz.dataanalysis
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.socket.eunm.FactorType
 
 /**
  * 杩炵画绫诲瀷鐨勫紓甯稿垎鏋愬熀绫�,閫傜敤浜庡綋鍓嶆暟鎹笌鐩搁偦鏁版嵁涔嬮棿鏈夊叧鑱斿叧绯荤殑鎯呭喌
@@ -13,29 +15,58 @@
         private const val OFFSET = 10
     }
 
-    // 璧峰鏁版嵁涓嬫爣
-    protected var sIndex = mutableListOf<Int>()
+    inner class Tag {
+        // 璧峰鏁版嵁涓嬫爣
+        var sIndex = 0
 
-    // 璧峰鏁版嵁瀵硅薄
-    protected var startData = mutableListOf<BaseRealTimeData?>()
+        // 璧峰鏁版嵁瀵硅薄
+        var startData :BaseRealTimeData? = null
 
-    // 鏈熬鏁版嵁涓嬫爣
-    protected var eIndex = mutableListOf<Int>()
+        // 鏈熬鏁版嵁涓嬫爣
+        var eIndex = -1
 
-    // 鏈熬鏁版嵁瀵硅薄
-    protected var lastData: BaseRealTimeData? = null
+        // 鏈熬鏁版嵁瀵硅薄
+        var endData: BaseRealTimeData? = null
 
-    // 寮傚父鏁版嵁娈�
-    protected var exceptionData = mutableListOf<MutableList<BaseRealTimeData>>()
+        // 寮傚父鏁版嵁娈�
+        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>()
 
     // 璧峰鏁版嵁涓庢湯灏炬暟鎹棿闅�
     open var durationCount = 1
-    protected var existException = mutableListOf<Boolean>()
+    // 鏈熬鏁版嵁瀵硅薄
+    protected var lastData: BaseRealTimeData? = null
 
     /**
      * 鍒ゆ柇鏄惁婊¤冻寮傚父鏉′欢
      */
-    abstract fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): List<Boolean>
+    abstract fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean>
 
     /**
      * 鍒ゆ柇寮傚父鍑虹幇鐨勮繛缁椂闀挎槸鍚︽弧瓒虫潯浠�
@@ -45,44 +76,75 @@
     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())
+//        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()
         }
     }
 
     override fun onNextData(data: BaseRealTimeData) {
         val isContinue = isContinuous(lastData, data)
         val hasException = judgeException(lastData, 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)
+        config.factorFilter.mainList().forEach {f->
+            tagMap[f]?.let {
+                it.eIndex++
+                // 璧峰鏁版嵁
+                if (it.endData == null) {
+                    it.refreshAfterCheckResult(data)
                 }
-            } else {
-                if (hasException[i]) {
-                    existException[i] = true
-                    exceptionData[i].add(data)
-                } else {
-                    // 寮傚父涓嶅啀閲嶅鍑虹幇鏃讹紝璁板綍寮傚父鎯呭喌
+                // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
+                if (!isContinue) {
                     checkResult()
-                    if (eIndex[i] - sIndex[i] >= durationCount) {
-                        refreshAfterCheckResult(i, data)
+                    // 鏁版嵁涓嶈繛缁椂锛岃褰曞紓甯告儏鍐�
+                    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)
+                        }
                     }
                 }
             }
         }
+//        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
     }
 
@@ -90,33 +152,43 @@
         checkResult()
     }
 
-    fun refreshAfterCheckResult(i:Int, data: BaseRealTimeData) {
-        sIndex[i] = eIndex[i]
-        startData[i] = data
-        exceptionData[i].clear()
-        exceptionData[i].add(data)
-    }
+//    fun refreshAfterCheckResult(i:Int, data: BaseRealTimeData) {
+//        sIndex[i] = eIndex[i]
+//        startData[i] = data
+//        exceptionData[i].clear()
+//        exceptionData[i].add(data)
+//    }
 
     /**
      * 妫�鏌ヨ繛缁紓甯哥粨鏉熸椂锛屾槸鍚︾鍚堝紓甯稿瓨鍌ㄦ潯浠�
      */
-    open fun checkResult(index: Int? = null) {
-        if (index != null) {
-            if (existException[index] && judgeDuration(sIndex[index], eIndex[index])) {
-                startData[index]?.let {
-                    resultList.add(newResult(it, lastData, index, exceptionData[index]))
+    open fun checkResult(factor: FactorFilter.SelectedFactor? = null) {
+        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))
                 }
-                existException[index] = false
+                tag.existException = false
             }
         } else {
-            repeat(config.factorCount) { i ->
-                if (existException[i] && judgeDuration(sIndex[i], eIndex[i])) {
-                    startData[i]?.let {
-                        resultList.add(newResult(it, lastData, i, exceptionData[i]))
+            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))
                     }
-                    existException[i] = false
+                    tag1.existException = false
                 }
             }
+//            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
+//                }
+//            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
index 027f57d..e65d775 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
@@ -11,29 +11,54 @@
     override fun onNextData(data: BaseRealTimeData) {
         val isContinue = isContinuous(lastData, data)
         val hasException = judgeException(lastData, data)
-        repeat(config.factorCount) { i ->
-            eIndex[i]++
-            if (lastData == null) {
-                startData[i] = data
-            }
-            // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
-            if (!isContinue) {
-                checkResult()
-                sIndex[i] = eIndex[i]
-                startData[i] = data
-            } else {
-                if (hasException[i]) {
-                    // 淇敼浜嗚捣濮嬫暟鎹殑浣嶇疆,鍙樻洿涓哄嚭鐜板紓甯哥殑璇ュ��,鑰屼笉鏄師鏉ョ殑鍑虹幇寮傚父鐨勬暟鎹殑鍓嶄竴涓��
-                    if (!existException[i]) {
-                        sIndex[i] = eIndex[i]
-                        startData[i] = data
-                    }
-                    existException[i] = true
-                } else {
+        config.factorFilter.mainList().forEach {f->
+            tagMap[f]?.let {
+                it.eIndex++
+                if (lastData == null) {
+                    it.startData = data
+                }
+                // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
+                if (!isContinue) {
                     checkResult()
+                    it.sIndex = it.eIndex
+                    it.startData = data
+                } else {
+                    if (hasException[f] == true) {
+                        // 淇敼浜嗚捣濮嬫暟鎹殑浣嶇疆,鍙樻洿涓哄嚭鐜板紓甯哥殑璇ュ��,鑰屼笉鏄師鏉ョ殑鍑虹幇寮傚父鐨勬暟鎹殑鍓嶄竴涓��
+                        if (!it.existException) {
+                            it.sIndex = it.eIndex
+                            it.startData = data
+                        }
+                        it.existException = true
+                    } else {
+                        checkResult()
+                    }
                 }
             }
         }
+//        repeat(config.factorCount) { i ->
+//            eIndex[i]++
+//            if (lastData == null) {
+//                startData[i] = data
+//            }
+//            // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
+//            if (!isContinue) {
+//                checkResult()
+//                sIndex[i] = eIndex[i]
+//                startData[i] = data
+//            } else {
+//                if (hasException[i]) {
+//                    // 淇敼浜嗚捣濮嬫暟鎹殑浣嶇疆,鍙樻洿涓哄嚭鐜板紓甯哥殑璇ュ��,鑰屼笉鏄師鏉ョ殑鍑虹幇寮傚父鐨勬暟鎹殑鍓嶄竴涓��
+//                    if (!existException[i]) {
+//                        sIndex[i] = eIndex[i]
+//                        startData[i] = data
+//                    }
+//                    existException[i] = true
+//                } else {
+//                    checkResult()
+//                }
+//            }
+//        }
         lastData = data
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
index 1a5c06f..45008af 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.biz.dataanalysis
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionDataExceed
 import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionValueMutation
 import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
@@ -29,9 +30,9 @@
         }
     }
 
-    fun run(mission: Mission): List<ExceptionResult> {
+    fun run(mission: Mission, factorFilter: FactorFilter): List<ExceptionResult> {
         running = true
-        val config = DataAnalysisConfig(mission, ExceptionSetting(), 8)
+        val config = DataAnalysisConfig(mission, ExceptionSetting(), 8, factorFilter)
         initTask(config)
 
         val result = mutableListOf<ExceptionResult>()
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 24decf6..0d140d9 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
@@ -4,6 +4,7 @@
 import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.socket.eunm.FactorType
 
 /**
  * 鏁版嵁瓒呮爣寮傚父鍒嗘瀽
@@ -12,18 +13,28 @@
 
     override fun getExceptionType(): ExceptionType = ExceptionType.TYPE2
 
-    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): List<Boolean> {
-        val res = mutableListOf<Boolean>()
-        repeat(config.factorCount) { i ->
-            val data = n.getByFactorIndex(i)
-            val limit = config.exceptionSetting.getByFactorIndex(i)
+    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
+        val res = mutableMapOf<FactorType, Boolean>()
+        config.factorFilter.mainList().forEach { f ->
+            val data = n.getByFactorType(f)
+            val limit = config.exceptionSetting.getByFactorType(f)
             val bool = if (data != null && limit != null) {
                 data >= limit
             } else {
                 false
             }
-            res.add(bool)
+            res[f] = bool
         }
+//        repeat(config.factorCount) { i ->
+//            val data = n.getByFactorIndex(i)
+//            val limit = config.exceptionSetting.getByFactorIndex(i)
+//            val bool = if (data != null && limit != null) {
+//                data >= limit
+//            } else {
+//                false
+//            }
+//            res.add(bool)
+//        }
         return res
     }
 
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 f9da13a..0a9e73c 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
@@ -4,6 +4,7 @@
 import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.socket.eunm.FactorType
 import kotlin.math.abs
 
 /**
@@ -19,21 +20,34 @@
 
     override fun getExceptionType(): ExceptionType = ExceptionType.TYPE4
 
-    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): List<Boolean> {
-        val res = mutableListOf<Boolean>()
-        repeat(config.factorCount) { i->
-            if (p?.getByFactorIndex(i) == null || n.getByFactorIndex(i) == null) {
-                res.add(false)
-                return@repeat
+    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
+        val res = mutableMapOf<FactorType, Boolean>()
+        config.factorFilter.mainList().forEach { f ->
+            if (p?.getByFactorType(f) == null || n.getByFactorType(f) == null) {
+                res[f] = (false)
+                return@forEach
             }
-            val pValue = p.getByFactorIndex(i)!!
-            val nValue = n.getByFactorIndex(i)!!
+            val pValue = p.getByFactorType(f)!!
+            val nValue = n.getByFactorType(f)!!
             val r = abs((pValue - nValue) / pValue)
             val b1 = r >= (2 * config.mutationRate)
             val b2 = r >= config.mutationRate
             if (b1) special = true
-            res.add(b1 || b2)
+            res[f] = (b1 || b2)
         }
+//        repeat(config.factorCount) { i->
+//            if (p?.getByFactorIndex(i) == null || n.getByFactorIndex(i) == null) {
+//                res.add(false)
+//                return@repeat
+//            }
+//            val pValue = p.getByFactorIndex(i)!!
+//            val nValue = n.getByFactorIndex(i)!!
+//            val r = abs((pValue - nValue) / pValue)
+//            val b1 = r >= (2 * config.mutationRate)
+//            val b2 = r >= config.mutationRate
+//            if (b1) special = true
+//            res.add(b1 || b2)
+//        }
 
         return res
     }
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt
index ff7522d..06ffce6 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.biz.dataanalysis.model
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.domain.entity.Mission
 
 /**
@@ -12,6 +13,8 @@
     val exceptionSetting: ExceptionSetting,
     // 娑夊強鐩戞祴鍥犲瓙鏁伴噺
     val factorCount: Int,
+    // 鍥犲瓙绛涢��
+    val factorFilter: FactorFilter,
 ){
     // 杩炵画绐佸彉鏁版嵁涓暟
     var mutationNum = 6
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt
index 8ae9ffa..92a406a 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.biz.dataanalysis.model
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
 import java.math.BigDecimal
 
@@ -14,6 +15,9 @@
     var exceptionValue: Float? = null
     var factorId: Int? = null
     var factorName: String? = null
+    var subFactorId: List<Int>? = null
+    var subFactorName: List<String>? = null
+    var selectedFactor: FactorFilter.SelectedFactor? = null
     var startTime: String? = null
     var endTime: String? = null
     var startData: Float? = null
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt
index ab7193e..021ed20 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt
@@ -1,5 +1,7 @@
 package com.flightfeather.uav.biz.dataanalysis.model
 
+import com.flightfeather.uav.socket.eunm.FactorType
+
 /**
  * 璧拌埅鏁版嵁寮傚父鏍囧噯
  */
@@ -28,4 +30,28 @@
             else -> null
         }
     }
+
+    fun getByFactorType(factorType: FactorType): Float? {
+        return when (factorType) {
+            FactorType.NO2 -> no2
+            FactorType.CO -> co
+            FactorType.H2S -> h2s
+            FactorType.SO2 -> so2
+            FactorType.O3 -> o3
+            FactorType.PM25 -> pm25
+            FactorType.PM10 -> pm10
+//            FactorType.TEMPERATURE -> temperature
+//            FactorType.HUMIDITY -> humidity
+            FactorType.VOC -> voc
+//            FactorType.NOI -> noi
+//            FactorType.LNG -> longitude?.toFloat()
+//            FactorType.LAT -> latitude?.toFloat()
+//            FactorType.VELOCITY -> velocity
+//            FactorType.TIME -> noi
+//            FactorType.WIND_SPEED -> windSpeed
+//            FactorType.WIND_DIRECTION -> windDirection
+//            FactorType.HEIGHT -> height
+            else -> null
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt b/src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt
index 35420e1..4c3ea43 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt
@@ -3,7 +3,7 @@
 import com.flightfeather.uav.lightshare.bean.DataVo
 
 /**
- *
+ * 缃戞牸铻嶅悎妯″紡锛氭牴鎹蛋鑸寖鍥达紝鍒掑垎鐭╁舰缃戞牸锛屽皢鎵�鏈夌洃娴嬫暟鎹牴鎹粡绾害鍒掑垎鑷冲搴旂綉鏍硷紝璁$畻鑾峰彇缃戞牸鐩戞祴鏁版嵁鍧囧�硷紱
  * @date 2024/6/26
  * @author feiyu02
  */
@@ -11,8 +11,9 @@
 
     fun merge(data:List<DataVo>) {
         //1. 纭畾鏁版嵁鑼冨洿锛岀敤鐭╁舰妗嗗嚭鎵�鏈夌洃娴嬫暟鎹�
-
+        val lt = foo1(data)
         //2. 鏍规嵁姝f柟褰㈢綉鏍肩殑杈归暱锛岃绠楀緱鍑烘墍鏈夋鏂瑰舰缃戞牸
+
         //3. 鍖归厤鐩戞祴鏁版嵁鍜屽搴旂綉鏍硷紝璁$畻缃戞牸鍧囧��
     }
 
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
index 0a497c4..ccc8b72 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.biz.report
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.dataanalysis.ExceptionAnalysisController
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
 import com.flightfeather.uav.biz.dataprocess.PreData
@@ -54,7 +55,7 @@
          */
         fun addExceptions(exceptions: List<ExceptionResult>) {
             this.exceptions = exceptions.map {
-                val byteArray = DataToChartUtil.lineToByteArray(FactorType.getByValue(it.factorId!!), it.dataList)
+                val byteArray = DataToChartUtil.lineToByteArray(it.selectedFactor, it.dataList)
                 val base64Str = ImageUtil.compressImage2(byteArray, 400, needPrefix = false)
                 val c = ExceptionChart()
                 BeanUtils.copyProperties(it, c)
@@ -91,13 +92,16 @@
     private val dateFormatter = DateTimeFormatter.ofPattern("HH:mm")
 
     // 鑾峰彇寮傚父鍒嗘瀽缁撴灉
-    fun exceptionAnalysis(mission: Mission): List<ExceptionResult> {
-        return exceptionAnalysisController.run(mission)
+    fun exceptionAnalysis(mission: Mission, factorFilter: FactorFilter): List<ExceptionResult> {
+        return exceptionAnalysisController.run(mission, factorFilter)
     }
 
     // 璁$畻鍧囧�煎拰鏁版嵁鑼冨洿
-    fun dataSummary(mission: Mission): List<Summary> {
-        val preData = PreData(DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD))
+    fun dataSummary(mission: Mission, factorFilter: FactorFilter): List<Summary> {
+        val preData = PreData(
+            DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD),
+            factorFilter.mainList()
+        )
         val realTimeData = realTimeDataRep.fetchData(mission)
         realTimeData.forEach {
             preData.add(it.toDataVo())
@@ -123,13 +127,13 @@
 
     // 鐢熸垚鍙傛暟
     // 鏍规嵁鎶ュ憡妯℃澘鐢熸垚瀵瑰簲鎶ュ憡
-    fun execute(missionCode: String): String {
+    fun execute(missionCode: String, factorFilter: FactorFilter): String {
         // 1. 浠诲姟鍚堟硶鎬ф鏌�
         val mission = missionRep.findOne(missionCode) ?: throw  BizException("璇ヤ换鍔$紪鍙蜂笉瀛樺湪")
-        // 2. 鑾峰彇鏁版嵁寮傚父缁熻缁撴灉
-        val exceptions = exceptionAnalysis(mission)
+        // 2. 鑾峰彇鏁版嵁寮傚父缁熻缁撴灉锛屾牴鎹�
+        val exceptions = exceptionAnalysis(mission, factorFilter)
         // 3. 鑾峰彇鍧囧�笺�佽寖鍥寸瓑缁熻鏁版嵁
-        val summaries = dataSummary(mission)
+        val summaries = dataSummary(mission, factorFilter)
         // 4. 鐢熸垚鎶ュ憡
         val fileName = "report/" + "${mission.districtName}璧拌埅鐩戞祴鎶ュ憡-${
             DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD)
diff --git a/src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt b/src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt
index 4c30e1d..4ce6f08 100644
--- a/src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt
+++ b/src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt
@@ -3,9 +3,16 @@
 import org.jfree.chart.ChartFactory
 import org.jfree.chart.ChartUtils
 import org.jfree.chart.JFreeChart
+import org.jfree.chart.labels.StandardCategoryItemLabelGenerator
+import org.jfree.chart.labels.StandardCategorySeriesLabelGenerator
+import org.jfree.chart.plot.CategoryPlot
+import org.jfree.chart.renderer.category.LineAndShapeRenderer
 import org.jfree.chart.title.TextTitle
 import org.jfree.data.category.DefaultCategoryDataset
+import java.awt.BasicStroke
+import java.awt.Color
 import java.awt.Font
+import java.awt.Paint
 import java.io.ByteArrayOutputStream
 
 /**
@@ -19,8 +26,9 @@
 
     fun line(title: String, dataset: DefaultCategoryDataset): JFreeChart {
         val line = ChartFactory.createLineChart(title, "鏃堕棿", "娴撳害", dataset)
-        line.categoryPlot.domainAxis.labelFont = Font("瀹嬩綋", Font.PLAIN, 12)
-        line.categoryPlot.rangeAxis.labelFont = Font("瀹嬩綋", Font.PLAIN, 12)
+//        line.categoryPlot.domainAxis.labelFont = Font("瀹嬩綋", Font.PLAIN, 12)
+//        line.categoryPlot.rangeAxis.labelFont = Font("瀹嬩綋", Font.PLAIN, 12)
+        setLine(line)
         return line
     }
 
@@ -41,4 +49,31 @@
         }
         return dataset
     }
+
+    /**
+     * 璁剧疆鎶樼嚎鍥炬牱寮�
+     */
+    private fun setLine(chart: JFreeChart) {
+        chart.legend.itemFont = Font("SimHei", Font.PLAIN, 16)
+        chart.title.font = Font("SimHei", Font.BOLD, 20)
+        chart.categoryPlot.apply {
+            backgroundPaint = Color(255, 255, 255)
+            rangeGridlinePaint = Color(200, 200, 200)
+            rangeGridlineStroke = BasicStroke(1f)
+            isRangeGridlinesVisible = true
+        }
+    }
+
+    private fun setRenderer(plot:CategoryPlot, datasetList:List<DefaultCategoryDataset>) {
+        val renderer = newBasicRenderer(paint = Color(191, 0, 0))
+    }
+
+    private fun newBasicRenderer(series:Int = 0, paint:Paint): LineAndShapeRenderer {
+        return LineAndShapeRenderer().apply {
+            legendItemLabelGenerator = StandardCategorySeriesLabelGenerator()
+            setSeriesStroke(series, BasicStroke(3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 2000f))
+            setSeriesShapesVisible(series, false)
+            setSeriesPaint(series, paint)
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt b/src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt
index 2170aa9..1530fc2 100644
--- a/src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt
+++ b/src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.common.chart
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.common.utils.DateUtil
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
 import com.flightfeather.uav.socket.eunm.FactorType
@@ -11,13 +12,13 @@
  */
 object DataToChartUtil {
 
-    fun lineToByteArray(type: FactorType?, data: List<BaseRealTimeData>): ByteArray {
-        val title = type?.des ?: "鏈煡鐩戞祴鍥犲瓙"
-        val seriesName = type?.des ?: "鏈煡绯诲垪"
+    fun lineToByteArray(type: FactorFilter.SelectedFactor?, data: List<BaseRealTimeData>): ByteArray {
+        val title = type?.main?.des ?: "鏈煡鐩戞祴鍥犲瓙"
+        val seriesName = type?.main?.des ?: "鏈煡绯诲垪"
         val dataList = data.map { d ->
             ChartUtil.ChartValue(
                 DateUtil.instance.dateToString(d.dataTime, DateUtil.DateStyle.HH_MM_SS),
-                d.getByFactorType(type) ?: 0f
+                d.getByFactorType(type?.main) ?: 0f
             )
         }
         val dataset = ChartUtil.newDataset(dataList, seriesName)
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
index 340cdc2..a7a0458 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.lightshare.service.impl
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.report.MissionReport
 import com.flightfeather.uav.common.exception.BizException
 import com.flightfeather.uav.domain.entity.Mission
@@ -60,6 +61,6 @@
     }
 
     override fun getReport(missionCode: String, response: HttpServletResponse) {
-        missionReport.execute(missionCode)
+        missionReport.execute(missionCode, FactorFilter.default())
     }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
index a5b4ef3..bf2247e 100644
--- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.lightshare.service.impl
 
+import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.report.MissionReport
 import com.flightfeather.uav.lightshare.service.MissionService
 import org.junit.Test
@@ -23,6 +24,6 @@
 
     @Test
     fun getReport() {
-        missionReport.execute("SH-CN-20240514")
+        missionReport.execute("SH-CN-20240514", FactorFilter.default())
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3