From 8eb584869b4fd4de0f51c93f2616f12e51df9193 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期四, 18 十二月 2025 17:48:29 +0800
Subject: [PATCH] 2025.12.18 1. 动态溯源相关分析逻辑调整; 2. 走航报告接口参数调整;
---
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 275 insertions(+), 16 deletions(-)
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 8ae7734..0483664 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
@@ -1,35 +1,294 @@
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.biz.dataanalysis.model.ExceptionType
+import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig
+import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.domain.entity.avg
import com.flightfeather.uav.lightshare.bean.DataVo
+import com.flightfeather.uav.socket.eunm.FactorType
+import java.util.Date
+import kotlin.math.round
/**
* 姹℃煋鏁版嵁
* @date 2025/5/27
* @author feiyu02
*/
-class PollutedData {
+class PollutedData() {
+
+ companion object {
+ // 榛樿鏁版嵁閲囨牱鏃堕棿闂撮殧锛屽崟浣嶏細绉�
+ const val DEFAULT_PERIOD = 4
+ }
/**
- *
- * 1. 杞1.5m/s鍙婁互涓嬶紝
- * 鍓嶅悗鍊间笂鍗囧箙搴﹀湪50%浠ヤ笂1娆★紝璁や负鏄复杩戝彂鐢�(50绫�)
- * 鍓嶅悗鍊间笂鍗囧箙搴﹀湪20%浠ヤ笂1娆★紝璁や负鏄繙璺濈鍙戠敓锛�50绫� - 500绫筹級
- * 1.5 m/s鍙婁互涓嬶紝闈欑ǔ澶╂皵锛屼复杩戝彂鐢�(50绫�)
- * 2. 1.6 - 7.9 m/s锛屽墠鍚庡�间笂鍗囧箙搴﹀湪20%浠ヤ笂3娆★紝璁や负鏄繙璺濈鍙戠敓锛�50绫� - 1鍏噷锛�
- * 3. 8 - 13.8 m/s 浠ヤ笂锛屽墠鍚庡�间笂鍗囧箙搴﹀湪10%浠ヤ笂3娆★紝璁や负鏄繙璺濈鍙戠敓(50绫� - 2鍏噷)
+ * 寮傚父鏁版嵁鍒嗙粍鎯呭喌缁熻
*/
+ inner class ExcGroup{
+ constructor(dataIndexList: List<Int>, factorType: FactorType){
+ this.dataIndexList = dataIndexList
+ this.factorType = factorType
+ val first = getFirstDataValue()?.toDouble()
+ val last = getLastDataValue()?.toDouble()
+ if (first != null && last != null) {
+ per = round((last - first) / first * 100) / 100
+ rate = round((last - first) / DEFAULT_PERIOD * 100) / 100
+ }
+ }
+ var factorType: FactorType? = null
+ /**
+ * 寮傚父鏁版嵁瀵瑰簲鍘嗗彶鏁版嵁[historyDataList]涓殑绱㈠紩鍊�
+ */
+ var dataIndexList: List<Int>? = null
+ // 鍙樺寲骞呭害
+ var per: Double? = null
+ // 鍙樺寲閫熺巼
+ var rate: Double? = null
+ /**
+ * 鑾峰彇寮傚父鏁版嵁鐨勭涓�涓暟鎹�
+ * !!!!绗竴涓暟鎹叾瀹炴槸棣栦釜寮傚父鏁版嵁鐨勫墠涓�涓暟鎹��!!!!
+ */
+ fun getFirstData(): BaseRealTimeData? {
+ return dataIndexList?.firstOrNull()?.let {
+ val i = if (it > 0) it - 1 else it
+ historyDataList[i].toBaseRealTimeData(BaseRealTimeData::class.java)
+ }
+ }
+ fun getFirstDataValue(): Float? {
+ return getFirstData()?.getByFactorType(factorType)
+ }
+
+ /**
+ * 鑾峰彇寮傚父鏁版嵁鐨勬渶鍚庝竴涓暟鎹�
+ */
+ fun getLastData(): BaseRealTimeData? {
+ return dataIndexList?.lastOrNull()?.let {
+ historyDataList[it].toBaseRealTimeData(BaseRealTimeData::class.java)
+ }
+ }
+ fun getLastDataValue(): Float? {
+ return getLastData()?.getByFactorType(factorType)
+ }
+ }
+
+
+ /**
+ * 鍚勭洃娴嬪洜瀛愬紓甯哥粺璁′俊鎭�
+ */
+ inner class Statistic(){
+ var factorId: Int? = null
+ var factorName: String? = null
+ var subFactorId: List<Int>? = null
+ var subFactorName: List<String>? = null
+ var selectedFactor: FactorFilter.SelectedFactor? = null
+
+ /**
+ * 寮傚父鏁版嵁瀵瑰簲鍘嗗彶鏁版嵁[historyDataList]涓殑绱㈠紩鍊�
+ */
+ var dataIndexList: List<Int>? = null
+
+ // 鍥犲瓙閲忕骇骞冲潎鍙樺寲骞呭害
+ var avgPer: Double? = null
+ // 鍥犲瓙閲忕骇骞冲潎鍙樺寲閫熺巼
+ var avgRate: Double? = null
+
+ var avg: Double? = null
+ var min: Double? = null
+ var max: Double? = null
+
+ var excGroup: List<ExcGroup>? = null
+
+ /**
+ * 鑾峰彇寮傚父鏁版嵁
+ */
+ fun getExceptionData(): List<BaseRealTimeData>? {
+ return dataIndexList?.map { historyDataList[it].toBaseRealTimeData(BaseRealTimeData::class.java) }
+ }
+
+ /**
+ * 鑾峰彇寮傚父鏁版嵁鍒嗘鎯呭喌
+ * 灏嗚繛缁殑寮傚父鏁版嵁鍒嗕负涓�缁�
+ */
+ fun getExceptionDataGroup(): List<List<Int>> {
+ val res = mutableListOf<MutableList<Int>>()
+ var curGroup = mutableListOf<Int>()
+ var lastIndex = -2
+ dataIndexList?.forEach {
+ if (curGroup.isEmpty()) {
+ curGroup.add(it)
+ } else if (it - lastIndex == 1) {
+ curGroup.add(it)
+ } else {
+ res.add(curGroup)
+ curGroup = mutableListOf(it)
+ }
+ lastIndex = it
+ }
+ if (curGroup.isNotEmpty()) {
+ res.add(curGroup)
+ }
+ return res
+ }
+ }
+
+ constructor(exceptions: List<Pair<FactorFilter.SelectedFactor, ExceptionTag>>, eType: ExceptionType,) : this() {
+ // 閬嶅巻鎵�鏈夌殑鍥犲瓙鐨勫紓甯革紝鏁村悎缁熶竴鐨勫紓甯哥粨鏋滐紝鍏蜂綋濡備笅
+ var startData: BaseRealTimeData? = null
+ var endData: BaseRealTimeData? = null
+ var historyData = mutableListOf<BaseRealTimeData>()
+ var _times = 0
+ exceptions.forEach { e ->
+ // 灏嗛噰鏍锋椂闂存渶鏃╃殑鏁版嵁浣滀负寮�濮嬫暟鎹�
+ if (startData == null) {
+ startData = e.second.startData
+ } else {
+ if (e.second.startData?.dataTime!! < startData!!.dataTime) {
+ startData = e.second.startData
+ }
+ }
+
+ // 灏嗛噰鏍锋椂闂存渶鏅氱殑浣滀负缁撴潫鏁版嵁
+ if (endData == null) {
+ endData = e.second.endData
+ } else {
+ if (e.second.endData?.dataTime!! > endData!!.dataTime) {
+ endData = e.second.endData
+ }
+ }
+ // 灏嗘墍鏈夊巻鍙叉暟鎹幓閲嶅悎骞�
+ if (historyData.isEmpty()) {
+ historyData = e.second.historyData
+ } else {
+ e.second.historyData.forEach {
+ if (historyData.find { d -> d.dataTime == it.dataTime } == null) {
+ historyData.add(it)
+ }
+ }
+ }
+
+ _times += e.second.exceptionData.size
+ }
+ // 鎸夌収閲囨牱鏃堕棿鍗囧簭鎺掑垪
+ historyData.sortBy { it.dataTime }
+
+ exception = eType.des
+ exceptionType = eType.value
+ startTime = startData?.dataTime
+ endTime = endData?.dataTime
+ windSpeed = historyData.avg().windSpeed?.toDouble()
+ times = _times
+ historyDataList.addAll(historyData.map { it.toDataVo() })
+
+ // 鍐嶆鏁村悎寮傚父鏁版嵁锛屽垎鍒绠楀悇鍥犲瓙鐨勫紓甯哥粨鏋滅粺璁�
+ exceptions.forEach {e ->
+ statisticMap[e.first.main] = Statistic().apply {
+ factorId = e.first.main.value
+ factorName = e.first.main.des
+ subFactorId = e.first.subs.map { it.value }
+ subFactorName = e.first.subs.map { it.des }
+ selectedFactor = e.first
+ dataIndexList = e.second.exceptionData.map {
+ historyDataList.indexOfFirst { d ->
+ d.time == DateUtil.instance.dateToString(it.dataTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)
+ }
+ }
+
+ val s = dataSummary(e.second.exceptionData, e.first.main)
+ avg = s.first
+ min = s.second
+ max = s.third
+
+ excGroup = getExceptionDataGroup().map { ExcGroup(it, e.first.main) }
+ avgPer = excGroup?.mapNotNull { it.per }?.average()
+ avgRate = excGroup?.mapNotNull { it.rate }?.average()
+ }
+ }
+ }
+
+ var deviceCode: String? = null
+ var exception: String? = null
+ var exceptionType: Int? = null
+ var startTime: Date? = null
+ var endTime: Date? = null
// 椋庨��
- var windSpeed: Float? = null
-
- // 鍥犲瓙閲忕骇鍙樺寲骞呭害
- var percentage: Float? = null
-
+ var windSpeed: Double? = null
// 鍙戠敓娆℃暟
var times: Int? = null
+ var historyDataList = mutableListOf<DataVo>()
+ // 寮傚父鐩戞祴鏁版嵁锛屽寘鍚崟娆″紓甯镐腑鎵�鏈夊彂鐢熶簡寮傚父鐨勬暟鎹�硷紙鍙兘涓嶆槸鏃堕棿杩炵画鐨勬暟鎹級
+// var dataList: MutableList<BaseRealTimeData> = mutableListOf()
+// var dataVoList: MutableList<DataVo> = mutableListOf()
+ var statisticMap = mutableMapOf<FactorType, Statistic>()
- // 寮傚父鐩戞祴鏁版嵁
- var dataList: MutableList<BaseRealTimeData> = mutableListOf()
- var dataVoList: MutableList<DataVo> = mutableListOf()
+ /**
+ * 鑾峰彇鎵�鏈夊紓甯稿洜瀛愬悕绉�
+ */
+ fun toFactorNames(): String {
+ val factors = statisticMap.entries.map { it.key }.sortedBy { it.value }.joinToString(";") { it.des }
+ return factors
+ }
+
+ fun getExceptionAvgData(): BaseRealTimeData {
+ val exceptionDataList = statisticMap.flatMap { it.value.getExceptionData() ?: emptyList() }
+ val avgData = exceptionDataList.avg()
+ return avgData
+ }
+ /**
+ * 鑾峰彇寮傚父鏁版嵁涓績鍧愭爣锛堝紓甯告暟鎹腑缁忓害绾害鐨勫钩鍧囧�硷級
+ */
+ fun getExceptionCenter(): Pair<Double, Double>? {
+ val avgData = getExceptionAvgData()
+ val wgs84Lng = avgData.longitude?.toDouble()
+ val wgs84Lat = avgData.latitude?.toDouble()
+ return if (wgs84Lng == null || wgs84Lat == null) null else Pair(wgs84Lng, wgs84Lat)
+ }
+
+ private fun calPer(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Double? {
+ if (exceptionData.size < 2) return null
+
+ var total = .0
+ for (i in 0 until exceptionData.size - 1) {
+ val p = exceptionData[i]?.getByFactorType(factorType) ?: .0f
+ val n = exceptionData[i + 1]?.getByFactorType(factorType) ?: .0f
+ total += (n - p) / p
+ }
+ return total / (exceptionData.size - 1)
+ }
+
+ private fun calRate(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Double? {
+ if (exceptionData.size < 2) return null
+
+ var total = .0
+ for (i in 0 until exceptionData.size - 1) {
+ val p = exceptionData[i]?.getByFactorType(factorType) ?: .0f
+ val n = exceptionData[i + 1]?.getByFactorType(factorType) ?: .0f
+ total += (n - p) / 4
+ }
+ return total / (exceptionData.size - 1)
+ }
+
+ private fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Double, Double,
+ Double> {
+ var min = -1.0
+ var max = -1.0
+ var total = .0
+ var count = 0
+ exceptionData.forEach {
+ val value = it?.getByFactorType(factorType)?.toDouble() ?: return@forEach
+ if (min == -1.0 || min > value) {
+ min = round(value * 1000) / 1000
+ }
+ if (max == -1.0 || max < value) {
+ max = round(value * 1000) / 1000
+ }
+ total += value
+ count++
+ }
+ val avg = if (count == 0) .0 else round(total / count * 1000) / 1000
+ return Triple(avg, min, max)
+ }
}
\ No newline at end of file
--
Gitblit v1.9.3