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/exceptiontype/ExceptionValueMutation.kt | 5 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RemainException.kt | 62 ++++++ src/main/kotlin/com/flightfeather/uav/common/exception/BizException.kt | 6 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt | 8 src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt | 2 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt | 183 ++++++++++++++++--- src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt | 24 - src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionTag.kt | 26 ++ src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt | 3 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt | 4 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt | 5 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt | 6 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedClue.kt | 8 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt | 29 +-- src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt | 7 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt | 2 src/test/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousTest.kt | 156 +++++++++++++++++ 17 files changed, 450 insertions(+), 86 deletions(-) diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt index f1ee8b6..8c2d780 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt @@ -1,7 +1,6 @@ package com.flightfeather.uav.biz.dataanalysis import com.flightfeather.uav.biz.FactorFilter -import com.flightfeather.uav.socket.eunm.FactorType /** * 鏁版嵁鍒嗘瀽閰嶇疆鍙傛暟鍩虹被 @@ -11,4 +10,7 @@ abstract class BaseAnalysisConfig( // 鍥犲瓙绛涢�� val factorFilter: FactorFilter, -) \ No newline at end of file +){ + // 鏁版嵁寮傚父鍚堝苟鏃讹紝鍏佽寤惰繜鏈�澶ф暟鎹懆鏈� + var maxDelayPeriod: Int = 1 +} \ No newline at end of file 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 36fdfa1..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,10 +2,10 @@ 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 -import org.springframework.beans.BeanUtils import java.time.Duration /** @@ -34,17 +34,20 @@ protected var lastData: BaseRealTimeData? = null // 鏈�鏂扮殑涓�缁勫紓甯革紝璁板綍鍗曞洜瀛愬紓甯� - protected val latestExceptions = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>() + val latestExceptions = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>() /** * 鏈�鏂扮殑涓�缁勫悎骞跺紓甯革紝鏍规嵁閰嶇疆鍙傛暟浠嶽latestExceptions]鍗曞洜瀛愬紓甯镐腑锛屽悎骞跺紓甯� */ protected val latestCombinedExc = mutableListOf<List<Pair<FactorFilter.SelectedFactor, T>>>() + // 璁板綍闇�瑕佸欢杩熸暟鎹懆鏈熻繘琛屽悎骞剁殑寮傚父 + val remainingExceptions = mutableListOf<RemainException<T>>() + /** * 寮傚父缁撴灉 */ - protected val result = mutableListOf<Y>() + val result = mutableListOf<Y>() /** * 涓嶉�傜敤浜庢寮傚父绫诲瀷鐨勭洃娴嬪洜瀛� @@ -150,7 +153,10 @@ } lastData = data - mergeExceptionResult() + removeSingleFactor(data) + checkDelayedExceptions(data) + mergeExceptionResult(data) + onNewResult(result) clearExceptions(data) } @@ -277,54 +283,163 @@ } /** + * 灏嗕笉鍦ㄥ叧鑱斿叧绯讳腑鐨勭洃娴嬪洜瀛愬紓甯稿瓨鍌紝骞跺墧闄� + */ + fun removeSingleFactor(data: BaseRealTimeData) { + // 鏌ユ壘涓嶅湪鍥犲瓙鍏宠仈缁勫悎涓殑寮傚父鍥犲瓙 + val sfList = latestExceptions.filter { + config.factorFilter.combination.find { c -> c.find { f -> f == it.first.main } != null } == null + } + // 鐢熸垚瀵瑰簲鐨勫紓甯哥粨鏋滐紝骞跺垵濮嬪寲璇ュ紓甯� + 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() { + open fun mergeExceptionResult(data: BaseRealTimeData) { + val combinedExc = mutableListOf<List<Pair<FactorFilter.SelectedFactor, T>>>() // 閬嶅巻鎵�鏈夌殑鍥犲瓙缁勫悎 config.factorFilter.combination.forEach { c -> - val res = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>() - var exist = true - // 鏌ョ湅缁勫悎鍐呯殑鎵�鏈夊洜瀛愭槸鍚﹂兘鍚屾椂鍑虹幇寮傚父 - c.forEach { f -> - val r = latestExceptions.find { e -> - e.first.main == f - } - if (r != null) { - res.add(r) - } else { - exist = false - } - } + val combRes = matchCombFactor(c, latestExceptions) + val res = combRes.second + val exist = combRes.first // 濡傛灉缁勫悎鍐呯殑鎵�鏈夊洜瀛愰兘瀛樺湪寮傚父锛屽垯瀛樺偍涓哄悎骞跺紓甯� if (exist) { - // 灏嗗悎骞跺紓甯镐粠鍗曚釜寮傚父闆嗗悎涓幓闄� - res.forEach { r -> - latestExceptions.removeIf { e -> e.first.main == r.first.main } - } // 灏嗗悎骞跺紓甯稿瓨鍌� - latestCombinedExc.add(res) + combinedExc.add(res) + } + // 鍚﹀垯灏嗗紓甯哥殑娣辨嫹璐濈増鏈瓨鍏ュ緟鍚堝苟寮傚父闆嗗悎 + // TODO 2025.8.4: 鍚庣画娣诲姞褰撳叧鑱旂殑鐩戞祴鍥犲瓙绱寮傚父璁℃暟鎺ヨ繎闃堝�兼椂锛屾墠瀛樺叆闆嗗悎鐨勯�昏緫 + else { + remainingExceptions.add(RemainException(res, c)) } } - // 瀛樺偍寮傚父缁撴灉 - latestExceptions.forEach { - result.add(newResult(listOf(it))) - } - latestCombinedExc.forEach { + + // 瀛樺偍鍚堝苟寮傚父 + 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() - latestCombinedExc.forEach { - it.forEach { e -> - e.second.refreshWithNextException(data) - } - } - latestCombinedExc.clear() result.clear() } 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 2e382b4..babc0c4 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 @@ -48,4 +48,8 @@ override fun newResult(exceptions: List<Pair<FactorFilter.SelectedFactor, ExceptionTag>>): ExceptionResult { return ExceptionResult() } + + override fun onNewResult(result: List<ExceptionResult>) { + TODO("Not yet implemented") + } } \ No newline at end of file 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 5633645..7b09f49 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 @@ -1,6 +1,7 @@ package com.flightfeather.uav.biz.dataanalysis.exceptiontype import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig +import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType import com.flightfeather.uav.domain.entity.BaseRealTimeData @@ -53,4 +54,8 @@ // println("sIndex: $sIndex --- eIndex: $eIndex --- special: $special") return b1 || b2 } + + override fun onNewResult(result: List<ExceptionResult>) { + TODO("Not yet implemented") + } } \ No newline at end of file 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 4d7cb93..65507b3 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 @@ -2,16 +2,20 @@ import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult import com.flightfeather.uav.domain.entity.BaseRealTimeData +import org.apache.commons.lang3.SerializationUtils +import org.springframework.beans.BeanUtils +import java.io.Serializable /** * 寮傚父鏁版嵁鏍囩 * @date 2025/5/13 * @author feiyu02 */ -open class ExceptionTag { +open class ExceptionTag : Serializable { companion object { const val MAX_HISTORY = 10 } + // 璧峰鏁版嵁涓嬫爣 var sIndex = 0 @@ -53,7 +57,7 @@ } } - fun addExceptionData(data: BaseRealTimeData){ + fun addExceptionData(data: BaseRealTimeData) { exceptionExisted = true exceptionData.add(data) } @@ -69,4 +73,22 @@ exceptionExisted = false exceptionCreated = false } + + fun clone(): ExceptionTag { + val exceptionTag = SerializationUtils.clone(this) +// val exceptionTag = ExceptionTag() +// BeanUtils.copyProperties(this, exceptionTag) +// exceptionTag.apply { +// this.sIndex = this@ExceptionTag.sIndex +// this.startData = this@ExceptionTag.startData +// this.eIndex = this@ExceptionTag.eIndex +// this.endData = this@ExceptionTag.endData +// this.exceptionData = this@ExceptionTag.exceptionData +// this.historyData = this@ExceptionTag.historyData +// this.exceptionExisted = this@ExceptionTag.exceptionExisted +// this.exceptionCreated = this@ExceptionTag.exceptionCreated +// this.exceptionResult = this@ExceptionTag.exceptionResult +// } + return exceptionTag + } } \ No newline at end of file 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 042bcf2..b56fb48 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 @@ -21,12 +21,15 @@ } // 鏄惁鑱旂綉鏌ユ壘瀵瑰簲璺鍦板潃淇℃伅 var isSearchAddress = true + // 闄愬畾璺濈鍐咃紙鍗曚綅锛氱背锛� var distanceLimit = 3000 // 闄愬畾鏃堕棿鍐咃紙鍗曚綅锛氬垎閽燂級 var timeLimit = 3 + // 婧簮鎵╂暎鍋忕Щ瑙掑害锛堝崟浣嶏細搴︼級 var sourceTraceDegOffset = 120.0 + // 瀹氭椂绾跨储鍒嗘瀽鏃堕棿闂撮殧(鍗曚綅锛氬垎閽�) var analysisPeriod = 5 // 瀹氭椂鍒嗘瀽闂撮殧涓紝绔嬪嵆杩涜绾跨储鍒嗘瀽鐨勬渶灏忕嚎绱㈤噺(鍗曚綅锛氫釜) 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 28d1591..81cb8a6 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 @@ -122,30 +122,20 @@ PollutedClue(exceptions, getExceptionType(), config, changeRate[exceptions[0].first.main]) } - override fun onNewException( - tag: ExceptionTag, - factor: FactorFilter.SelectedFactor, - exceptionStatus: ExceptionStatusType, - ) { - super.onNewException(tag, factor, exceptionStatus) +// override fun mergeExceptionResult() { +// super.mergeExceptionResult() // callback?.let { func -> -// val exc = tag.exceptionResult.last() -// func.invoke(exc as PollutedClue) +// result.forEach { +// func.invoke(it) +// } // } - } +// } - override fun mergeExceptionResult() { - super.mergeExceptionResult() + override fun onNewResult(result: List<PollutedClue>) { callback?.let { func -> result.forEach { func.invoke(it) } -// latestExceptions.forEach { -// func.invoke(listOf(it as PollutedClue)) -// } -// latestCombinedExc.forEach { -// func.invoke(it as List<PollutedClue>) -// } } } } \ No newline at end of file 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 24fa6d7..13b0f3d 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 @@ -139,30 +139,21 @@ // return PollutedClue(start, end, factor, exceptionData, getExceptionType(), config, windLevelCondition) // } - override fun onNewException( - tag: ExceptionTag, - factor: FactorFilter.SelectedFactor, - exceptionStatus: ExceptionStatusType, - ) { - super.onNewException(tag, factor, exceptionStatus) -// callback?.let { func -> -// val exc = tag.exceptionResult.last() -// func.invoke(exc as PollutedClue) -// } - } - override fun mergeExceptionResult() { - super.mergeExceptionResult() +// override fun mergeExceptionResult() { +// super.mergeExceptionResult() +// callback?.let { func -> +// result.forEach { +// func.invoke(it) +// } +// } +// } + + override fun onNewResult(result: List<PollutedClue>) { callback?.let { func -> result.forEach { func.invoke(it) } -// latestExceptions.forEach { -// func.invoke(listOf(it as PollutedClue)) -// } -// latestCombinedExc.forEach { -// func.invoke(it as List<PollutedClue>) -// } } } } \ No newline at end of file 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 3bccabf..2a3d11c 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 @@ -3,6 +3,7 @@ import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType import com.flightfeather.uav.biz.sourcetrace.RealTimeAnalysisConfig +import com.flightfeather.uav.biz.sourcetrace.model.RealTimeExceptionResult import com.flightfeather.uav.common.utils.MapUtil import com.flightfeather.uav.domain.entity.BaseRealTimeData import com.flightfeather.uav.socket.eunm.FactorType @@ -90,4 +91,8 @@ return b1 || b2 } + + override fun onNewResult(result: List<RealTimeExceptionResult>) { + TODO("Not yet implemented") + } } \ No newline at end of file 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 e9092d6..9993a86 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 @@ -63,7 +63,7 @@ val pair = avgData.longitude!!.toDouble() to avgData.latitude!!.toDouble() polygon = calSector( - avgData.windDirection!!.toDouble(), + avgData.windDirection?.toDouble() ?: .0, pair, windLevelCondition.distanceType.disRange, config.sourceTraceDegOffset diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedClue.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedClue.kt index 19eedc2..6035ec5 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedClue.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedClue.kt @@ -45,6 +45,7 @@ var exceptionData = mutableListOf<BaseRealTimeData>() var historyData = mutableListOf<BaseRealTimeData>() exceptions.forEach { e -> + // 灏嗛噰鏍锋椂闂存渶鏃╃殑浣滀负寮�濮嬫暟鎹� if (startData == null) { startData = e.second.startData } else { @@ -53,6 +54,7 @@ } } + // 灏嗛噰鏍锋椂闂存渶鏅氱殑浣滀负缁撴潫鏁版嵁 if (endData == null) { endData = e.second.endData } else { @@ -61,6 +63,7 @@ } } + // 灏嗘墍鏈夊紓甯告暟鎹幓閲嶅悎骞� if (exceptionData.isEmpty()) { exceptionData = e.second.exceptionData } else { @@ -71,6 +74,7 @@ } } + // 灏嗘墍鏈夊巻鍙叉暟鎹幓閲嶅悎骞� if (historyData.isEmpty()) { historyData = e.second.historyData } else { @@ -81,10 +85,12 @@ } } } + // 鎸夌収閲囨牱鏃堕棿鍗囧簭鎺掑垪 exceptionData.sortBy { it.dataTime } historyData.sortBy { it.dataTime } - val factorList = exceptions.map { it.first } + // 鑾峰彇鍘婚噸鍚庣殑鐩戞祴鍥犲瓙绫诲瀷 + val factorList = exceptions.map { it.first }.distinct() pollutedData = PollutedData( startData!!, endData, factorList, exceptionData, historyData, eType, windLevelCondition ) diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt index 3dc2e05..266ed2a 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt @@ -127,8 +127,8 @@ var total = .0 for (i in 0 until list.size - 1) { - val p = list[i].getByFactorType(factorType)!! - val n = list[i + 1].getByFactorType(factorType)!! + val p = list[i].getByFactorType(factorType) ?: .0f + val n = list[i + 1].getByFactorType(factorType) ?: .0f total += (n - p) / p } return total / (list.size - 1) @@ -140,8 +140,8 @@ var total = .0 for (i in 0 until list.size - 1) { - val p = list[i].getByFactorType(factorType)!! - val n = list[i + 1].getByFactorType(factorType)!! + val p = list[i].getByFactorType(factorType) ?: .0f + val n = list[i + 1].getByFactorType(factorType) ?: .0f total += (n - p) / 4 } return total / (list.size - 1) diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RemainException.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RemainException.kt new file mode 100644 index 0000000..cff1723 --- /dev/null +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RemainException.kt @@ -0,0 +1,62 @@ +package com.flightfeather.uav.biz.sourcetrace.model + +import com.flightfeather.uav.biz.FactorFilter +import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag +import com.flightfeather.uav.socket.eunm.FactorType + +/** + * 寰呭悎骞跺紓甯� + * 寮傚父鍑虹幇鍚庯紝鑻ョ浉鍏崇殑鍏朵粬鍥犲瓙绱寮傚父娆℃暟鎺ヨ繎闃堝�硷紝鍒欒寮傚父鍙互绛夊緟鑻ュ共涓暟鎹懆鏈熷悗鍐嶅悎骞躲�� + * @date 2025/8/1 + * @author feiyu02 + */ +class RemainException<T : ExceptionTag>( + exceptions: List<Pair<FactorFilter.SelectedFactor, T>>, + combination: List<FactorType>, +) { + + // 宸叉湁鐨勫紓甯� + var exceptions = mutableListOf<Pair<FactorFilter.SelectedFactor, T>>() + + // 闇�瑕佸欢杩熸娴嬬殑鍥犲瓙鍏宠仈鍏崇郴 + val combination = mutableListOf<FactorType>() + + // 缂哄け鐨勭洃娴嬪洜瀛� + val lackFactors = mutableListOf<FactorType>() + + // 宸茬粡杩囩殑鏁版嵁鍛ㄦ湡 + var period: Int = 1 + + init { + // 瀛樺偍鐩戞祴鍥犲瓙寮傚父瀵硅薄鐨勫厠闅嗙増鏈紝 + this.exceptions.addAll(exceptions.map { + it.first to (it.second.clone() as T) + }) + this.combination.addAll(combination) + calLackFactors() + } + + /** + * 娣诲姞鏂扮殑寮傚父闆嗗悎 + */ + fun addExceptions(exceptions: List<Pair<FactorFilter.SelectedFactor, T>>) { + // 瀛樺偍鐩戞祴鍥犲瓙寮傚父瀵硅薄鐨勫厠闅嗙増鏈紝 + this.exceptions.addAll(exceptions.map { + it.first to (it.second.clone() as T) + }) + calLackFactors() + } + + /** + * 璁$畻缂哄け鐨勭洃娴嬪洜瀛� + */ + private fun calLackFactors() { + lackFactors.clear() + combination.forEach { c -> + val e = exceptions.find { it.first.main == c } + if (e == null) { + lackFactors.add(c) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/common/exception/BizException.kt b/src/main/kotlin/com/flightfeather/uav/common/exception/BizException.kt index a0198cd..7a7746b 100644 --- a/src/main/kotlin/com/flightfeather/uav/common/exception/BizException.kt +++ b/src/main/kotlin/com/flightfeather/uav/common/exception/BizException.kt @@ -6,8 +6,8 @@ class BizException : Exception { constructor():super() constructor(message: String) : super(message) - constructor(message: String, cause: Throwable) : super(message, cause) - constructor(cause: Throwable) : super(cause) - constructor(message: String, cause: Throwable, enableSuppression: Boolean, writableStackTrace: Boolean) + constructor(message: String, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) + constructor(message: String, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(message, cause, enableSuppression, writableStackTrace) } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt b/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt index 52e1940..9b25bff 100644 --- a/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt +++ b/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt @@ -105,7 +105,7 @@ a["streetNumber"].asJsonObject["street"].asString, ) } catch (e: Exception) { - throw BizException("楂樺痉API鍧愭爣杞崲閿欒锛�${e.message}") + throw BizException("楂樺痉API鍧愭爣杞崲閿欒锛�${e.message}", e.cause) } } diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt index 741a06a..dccef45 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt @@ -5,6 +5,7 @@ import com.flightfeather.uav.lightshare.bean.DataVo import com.flightfeather.uav.socket.bean.AirData import com.flightfeather.uav.socket.eunm.FactorType +import java.io.Serializable import java.math.BigDecimal import java.time.LocalDateTime import java.time.ZoneId @@ -21,7 +22,7 @@ /** * 瀹炴椂鐩戞祴鏁版嵁鍩虹被 */ -open class BaseRealTimeData { +open class BaseRealTimeData : Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Int? = null @@ -277,7 +278,9 @@ } return RealTimeDataGridMin().apply { - val time = LocalDateTime.ofInstant(get(0).dataTime?.toInstant(), ZoneId.systemDefault()).withSecond(0) + val time = LocalDateTime + .ofInstant(get(0).dataTime?.toInstant() ?: Date().toInstant(), ZoneId.systemDefault()) + .withSecond(0) deviceCode = get(0).deviceCode dataTime = Date.from(time.atZone(ZoneId.systemDefault()).toInstant()) createTime = dataTime diff --git a/src/test/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousTest.kt new file mode 100644 index 0000000..450871f --- /dev/null +++ b/src/test/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousTest.kt @@ -0,0 +1,156 @@ +package com.flightfeather.uav.biz.dataanalysis + +import com.flightfeather.uav.biz.FactorFilter +import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag +import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType +import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig +import com.flightfeather.uav.biz.sourcetrace.exceptiontype.* +import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue +import com.flightfeather.uav.biz.sourcetrace.model.RemainException +import com.flightfeather.uav.domain.entity.BaseRealTimeData +import com.flightfeather.uav.socket.eunm.FactorType +import org.junit.Test +import kotlin.test.assertContentEquals + + +class BaseExceptionContinuousTest { + + private val exceptionTag = ExceptionTag().apply { + sIndex = 1 + startData = BaseRealTimeData().apply { id = 1 } + eIndex = 5 + endData = BaseRealTimeData().apply { id = 4 } + exceptionData = mutableListOf( + startData!!, + BaseRealTimeData().apply { id = 2 }, + BaseRealTimeData().apply { id = 3 }, + endData!! + ) + historyData = mutableListOf() + exceptionExisted = true + exceptionCreated = false +// exceptionResult = + } + + private val combination = listOf( + listOf(FactorType.PM25, FactorType.PM10), + listOf(FactorType.VOC, FactorType.CO), + listOf(FactorType.VOC, FactorType.PM25), + listOf(FactorType.VOC, FactorType.PM25, FactorType.CO), + ) + + private val config = RTExcWindLevelConfig( + FactorFilter.builder() + .withMain(FactorType.NO2) + .withMain(FactorType.CO) +// .withMain(FactorType.H2S) +// .withMain(FactorType.SO2) + .withMain(FactorType.O3) + .withMain(FactorType.PM25) + .withMain(FactorType.PM10) + .withMain(FactorType.VOC) + .withCombination(combination) + .create() + ).apply { isSearchAddress = false } + + private fun taskList() = mutableListOf( + RTExcWindLevel1(config).also { it.init() }, +// RTExcWindLevel1_1(config).also { it.init() }, +// RTExcWindLevel4(config).also { it.init() }, +// RTExcWindLevel6(config).also { it.init() }, + RTExcChangeRate1(config).also { it.init() }, +// RTExcChangeRate4(config).also { it.init() }, +// RTExcChangeRate6(config).also { it.init() }, +// RTWarnChangeRate(config).also { it.init() }, +// RTWarnChangeRate2(config).also { it.init() } + ) + + // 鏈�鏂扮殑涓�缁勫紓甯革紝璁板綍鍗曞洜瀛愬紓甯� + private fun exceptions() = mutableListOf( + FactorFilter.SelectedFactor(FactorType.NO2) to exceptionTag.clone(), + FactorFilter.SelectedFactor(FactorType.CO) to exceptionTag.clone(), + FactorFilter.SelectedFactor(FactorType.O3) to exceptionTag.clone(), + FactorFilter.SelectedFactor(FactorType.PM25) to exceptionTag.clone(), + FactorFilter.SelectedFactor(FactorType.PM10) to exceptionTag.clone(), + FactorFilter.SelectedFactor(FactorType.VOC) to exceptionTag.clone(), + ) + + @Test + fun removeSingleFactor() { + taskList().forEach { exc -> + exc.latestExceptions.clear() + exc.latestExceptions.addAll(exceptions()) + + exc.removeSingleFactor(BaseRealTimeData()) + + val resList = exc.result.map { + it.pollutedData?.statisticMap?.entries?.map { e -> e.key } + } + assertContentEquals( + listOf(listOf(FactorType.NO2), listOf(FactorType.O3)), + resList, + "寮傚父缁撴灉搴旇閮芥槸涓嶅湪缁勫悎涓殑寮傚父" + ) + + val resList2 = exc.latestExceptions.map { it.first.main } + assertContentEquals( + listOf(FactorType.CO, FactorType.PM25, FactorType.PM10, FactorType.VOC), + resList2, + "鍓╀綑鐨勫簲璇ユ槸涓嶅湪缁勫悎涓殑寮傚父" + ) + } + } + + @Test + fun checkDelayedExceptions() { + taskList().forEach { exc -> + val e = exceptions() + exc.remainingExceptions.add(RemainException(listOf(e[3], e[5]), listOf(FactorType.VOC, FactorType.PM25, FactorType.CO))) + exc.remainingExceptions.add(RemainException(listOf(e[1]), listOf(FactorType.VOC, FactorType.CO))) + exc.remainingExceptions.add(RemainException(listOf(e[3]), listOf(FactorType.PM10, FactorType.PM25))) + + exc.latestExceptions.clear() + exc.latestExceptions.addAll(exceptions()) + + exc.removeSingleFactor(BaseRealTimeData()) + + val resList = exc.result.map { + it.pollutedData?.statisticMap?.entries?.map { e -> e.key } + } + assertContentEquals( + listOf(listOf(FactorType.NO2), listOf(FactorType.O3)), + resList, + "寮傚父缁撴灉搴旇閮芥槸涓嶅湪缁勫悎涓殑寮傚父" + ) + + val resList2 = exc.latestExceptions.map { it.first.main } + assertContentEquals( + listOf(FactorType.CO, FactorType.PM25, FactorType.PM10, FactorType.VOC), + resList2, + "鍓╀綑鐨勫簲璇ユ槸涓嶅湪缁勫悎涓殑寮傚父" + ) + } + } + + @Test + fun mergeExceptionResult() { + val factorList = listOf( + FactorFilter.SelectedFactor(FactorType.PM10), + FactorFilter.SelectedFactor(FactorType.PM25), + FactorFilter.SelectedFactor(FactorType.CO), + ) + val factorList2 = listOf( + FactorFilter.SelectedFactor(FactorType.CO), + FactorFilter.SelectedFactor(FactorType.PM25), + FactorFilter.SelectedFactor(FactorType.PM10), + ) + println(factorList == factorList2) + } + + @Test + fun clearExceptions() { + + } + + +} \ No newline at end of file -- Gitblit v1.9.3