From 61871594dfa0a5ac2c4d895d9ec4034feba57094 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期五, 12 九月 2025 17:20:53 +0800
Subject: [PATCH] 2025.9.5 1. 新增走航任务统计功能
---
src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt | 7 +
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt | 36 ++++++-
src/main/kotlin/com/flightfeather/uav/biz/report/MissionGridFusion.kt | 6
src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt | 161 +++++++++++++++++++++++++------
src/main/kotlin/com/flightfeather/uav/biz/report/MissionSummary.kt | 53 +++++++++-
5 files changed, 213 insertions(+), 50 deletions(-)
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionGridFusion.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionGridFusion.kt
index 4bebc3f..a274fae 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionGridFusion.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionGridFusion.kt
@@ -23,7 +23,7 @@
class GridFusionByAQI {
var pollutionDegree: String? = null
var gridLen:Int? = null
- var missionList: MutableList<MissionInventory.MissionDetail> = mutableListOf()
+ var missionList: MutableList<MissionInventory.MissionInfo> = mutableListOf()
var gridFusionList: MutableList<FusionGrid> = mutableListOf()
var highRiskGridList: MutableList<HighRiskGridByFactor> = mutableListOf()
}
@@ -70,7 +70,7 @@
factorTypes: List<FactorType>,
gridLen: Int,
gridCells: List<GridCell>,
- dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionDetail>, List<GridDataDetailMixVo>>>,
+ dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionInfo>, List<GridDataDetailMixVo>>>,
): List<GridFusionByAQI> {
return dataList.map {
GridFusionByAQI().apply {
@@ -85,7 +85,7 @@
highRiskGridList.addAll(factorTypes.map { f->
HighRiskGridByFactor().apply {
factorType = f
- highRiskGrid = gridFusionList.sortedBy { gf->gf.data.rank }.firstOrNull()
+ highRiskGrid = gridFusionList.maxByOrNull { gf->gf.data.getByFactorType(f) ?: 0f }
if (highRiskGrid != null) {
factorValue = highRiskGrid!!.data.getByFactorType(f)
if (highRiskGrid!!.cell.longitude != null && highRiskGrid!!.cell.latitude != null) {
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
index cd8f696..f6700d7 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
@@ -26,13 +26,21 @@
// 婧簮闂鍦烘櫙鏁�
var sceneCount: Int = 0
+
+ // 婧簮闂鍦烘櫙
+ var scenes: List<SceneInfo>? = null
+
+ // 璧拌埅娑夊強鍖哄煙
+ var keyScene: List<SceneInfo>? = null
+
+ var exceptionCount: Int = 0
}
// 璧拌埅璇︽儏淇℃伅
class MissionDetail : Mission() {
- var keyScene: List<SceneInfo>? = null
+// var keyScene: List<SceneInfo>? = null
var dataStatistics: List<FactorStatistics>? = null
- var exceptionCount: Int = 0
+// var exceptionCount: Int = 0
}
/**
@@ -48,7 +56,7 @@
var sceneCount = 0
clue.forEach {
if (it?.msgType == MsgType.PolClue.value) {
- it.pollutedData?.statisticMap?.keys?.forEach { k->
+ it.pollutedData?.statisticMap?.keys?.forEach { k ->
// 璁$畻姣忎釜璧拌埅浠诲姟鐨勬墍鏈夊紓甯稿洜瀛�
if (!abnormalFactors.contains(k)) {
abnormalFactors.add(k)
@@ -74,6 +82,87 @@
return result
}
+ fun generateMissionInfo(
+ keyScenes: List<SceneInfo?>,
+ mission: Mission,
+ pollutedClues: List<PollutedClue?>,
+ data: List<BaseRealTimeData>,
+ minDis: Double = 100.0,
+ ): MissionInfo {
+ val factorMap = mutableMapOf<FactorType, Int>()
+ val abnormalFactors = mutableListOf<FactorType>()
+ var sceneCount = 0
+ val scenes = mutableListOf<SceneInfo>()
+ // 鎻愬彇閫斿緞鍏抽敭鍦烘櫙淇℃伅锛堣绠楄蛋鑸矾绾挎槸鍚︿笌鍏抽敭鍦烘櫙璺濈杈冭繎锛�
+ val relatedScenes = mutableListOf<SceneInfo>()
+ data.forEach { d ->
+ // 璺宠繃缂哄皯缁忕含搴︾殑鏁版嵁鐐�
+ if (d.longitude == null || d.latitude == null) {
+ return@forEach
+ }
+ // 杞崲涓篏CJ02鍧愭爣绯�
+ val point = MapUtil.wgs84ToGcj02(d.longitude!!.toDouble() to d.latitude!!.toDouble())
+ keyScenes.forEach ks@{ k ->
+ // 璺宠繃缂哄皯缁忕含搴︾殑鍦烘櫙
+ if (k?.longitude == null || k.latitude == null) {
+ return@ks
+ }
+ // 妫�鏌ユ槸鍚︽湭娣诲姞杩�
+ if (!relatedScenes.contains(k)) {
+ // 璁$畻璺濈
+ val distance = MapUtil.getDistance(
+ k.longitude!!.toDouble(),
+ k.latitude!!.toDouble(),
+ point.first,
+ point.second
+ )
+ // 妫�鏌ユ槸鍚﹁窛绂诲皬浜庨槇鍊�
+ if (distance < minDis) {
+ relatedScenes.add(k)
+ }
+ }
+ }
+ }
+ pollutedClues.forEach {
+ if (it?.msgType == MsgType.PolClue.value) {
+ it.pollutedData?.statisticMap?.keys?.forEach { k ->
+ // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬墍鏈夊紓甯稿洜瀛�
+ if (!abnormalFactors.contains(k)) {
+ abnormalFactors.add(k)
+ }
+ // 璁$畻姣忎釜璧拌埅浠诲姟鐨勯瑕佹薄鏌撶墿
+ if (!factorMap.containsKey(k)) {
+ factorMap[k] = 0
+ }
+ factorMap[k] = factorMap[k]!! + 1
+ }
+ // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬函婧愬満鏅暟閲�
+ sceneCount += it.pollutedSource?.sceneList?.size ?: 0
+ it.pollutedSource?.sceneList?.forEach { s->
+ if (scenes.find { s1 -> s1.guid == s.guid } == null) {
+ scenes.add(s)
+ }
+ }
+ }
+ }
+
+ // 寮傚父鏁版嵁鐐规暟閲忕粺璁�
+ val clues = pollutedClues.filter { it?.msgType == MsgType.PolClue.value }
+
+ val missionInfo = MissionInfo()
+ BeanUtils.copyProperties(mission, missionInfo)
+ missionInfo.apply {
+ mainFactor = factorMap.maxByOrNull { it.value }?.key?.name
+ this.abnormalFactors = abnormalFactors
+ this.sceneCount = sceneCount
+ this.scenes = scenes
+ keyScene = relatedScenes
+ exceptionCount = clues.size
+ }
+
+ return missionInfo
+ }
+
/**
* 鐢熸垚璧拌埅浠诲姟璇︾粏淇℃伅
* 鏁村悎璧拌埅浠诲姟鍩烘湰淇℃伅銆佸叧閿満鏅�佹暟鎹粺璁″拰寮傚父鏁伴噺锛岀敓鎴愬畬鏁寸殑浠诲姟璇︽儏鎶ュ憡
@@ -93,44 +182,52 @@
mission: Mission,
pollutedClues: List<PollutedClue?>,
data: List<BaseRealTimeData>,
- minDis:Double = 100.0
+ minDis: Double = 100.0,
): MissionDetail {
// 鍒涘缓浠诲姟璇︽儏瀵硅薄骞跺鍒跺熀鏈俊鎭�
val missionDetail = MissionDetail()
BeanUtils.copyProperties(mission, missionDetail)
-
+
// 鎻愬彇閫斿緞鍏抽敭鍦烘櫙淇℃伅锛堣绠楄蛋鑸矾绾挎槸鍚︿笌鍏抽敭鍦烘櫙璺濈杈冭繎锛�
- val relatedScenes = mutableListOf<SceneInfo>()
- data.forEach { d->
- // 璺宠繃缂哄皯缁忕含搴︾殑鏁版嵁鐐�
- if (d.longitude == null || d.latitude == null) {
- return@forEach
- }
- // 杞崲涓篏CJ02鍧愭爣绯�
- val point = MapUtil.wgs84ToGcj02(d.longitude!!.toDouble() to d.latitude!!.toDouble())
- keyScenes.forEach ks@ { k->
- // 璺宠繃缂哄皯缁忕含搴︾殑鍦烘櫙
- if (k?.longitude == null || k.latitude == null) {
- return@ks
- }
- // 璁$畻璺濈
- val distance = MapUtil.getDistance(k.longitude!!.toDouble(), k.latitude!!.toDouble(), point.first, point.second)
- // 妫�鏌ユ槸鍚﹁窛绂诲皬浜庨槇鍊间笖鏈坊鍔犺繃
- if (distance < minDis && !relatedScenes.contains(k)) {
- relatedScenes.add(k)
- }
- }
- }
+// val relatedScenes = mutableListOf<SceneInfo>()
+// data.forEach { d ->
+// // 璺宠繃缂哄皯缁忕含搴︾殑鏁版嵁鐐�
+// if (d.longitude == null || d.latitude == null) {
+// return@forEach
+// }
+// // 杞崲涓篏CJ02鍧愭爣绯�
+// val point = MapUtil.wgs84ToGcj02(d.longitude!!.toDouble() to d.latitude!!.toDouble())
+// keyScenes.forEach ks@{ k ->
+// // 璺宠繃缂哄皯缁忕含搴︾殑鍦烘櫙
+// if (k?.longitude == null || k.latitude == null) {
+// return@ks
+// }
+// // 妫�鏌ユ槸鍚︽湭娣诲姞杩�
+// if (!relatedScenes.contains(k)) {
+// // 璁$畻璺濈
+// val distance = MapUtil.getDistance(
+// k.longitude!!.toDouble(),
+// k.latitude!!.toDouble(),
+// point.first,
+// point.second
+// )
+// // 妫�鏌ユ槸鍚﹁窛绂诲皬浜庨槇鍊�
+// if (distance < minDis) {
+// relatedScenes.add(k)
+// }
+// }
+// }
+// }
// 瀛樺偍涓庝换鍔$浉鍏宠仈鐨勫叧閿満鏅俊鎭�
- missionDetail.keyScene = relatedScenes
-
+// missionDetail.keyScene = relatedScenes
+
// 璁$畻鐜鍥犲瓙缁熻鏁版嵁锛堝钩鍧囧�笺�佹渶灏忓�笺�佹渶澶у�硷級
missionDetail.dataStatistics = data.calDataStatistics()
-
+
// 寮傚父鏁版嵁鐐规暟閲忕粺璁�
- val clues = pollutedClues.filter { it?.msgType == MsgType.PolClue.value }
- missionDetail.exceptionCount = clues.size
-
+// val clues = pollutedClues.filter { it?.msgType == MsgType.PolClue.value }
+// missionDetail.exceptionCount = clues.size
+
return missionDetail
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionSummary.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionSummary.kt
index f82bf96..ff1ab18 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionSummary.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionSummary.kt
@@ -2,11 +2,9 @@
import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
import com.flightfeather.uav.domain.entity.Mission
-import com.flightfeather.uav.domain.repository.MissionRep
import com.flightfeather.uav.lightshare.bean.AreaVo
import com.flightfeather.uav.socket.eunm.FactorType
import com.flightfeather.uav.socket.sender.MsgType
-import org.springframework.stereotype.Component
import java.util.*
import kotlin.math.round
@@ -16,6 +14,10 @@
* @author feiyu02
*/
class MissionSummary() {
+
+ companion object {
+ private const val FOCUS_AREA_COUNT = 2
+ }
data class Summary(
// 姹囨�诲懆鏈熷紑濮嬫椂闂�
@@ -33,11 +35,13 @@
// 鍚勭瓑绾х┖姘旇川閲忚儗鏅蛋鑸鏁�,<绌烘皵璐ㄩ噺绛夌骇锛屾鏁帮紝鍗犳瘮>
val countByDegree: List<Triple<String, Int, Double>>,
// 闂鎬绘暟
- val probCount:Int,
+ val probCount: Int,
// 楂橀闄╁満鏅�绘暟
- val highRiskSceneCount:Int,
+ val highRiskSceneCount: Int,
// 闂鎸夌洃娴嬪洜瀛愮被鍨嬪垎甯冩儏鍐�, <鍥犲瓙绫诲瀷锛屾鏁帮紝鍗犳瘮>
- val probByFactor:List<Triple<String, Int, Double>>
+ val probByFactor: List<Triple<String, Int, Double>>,
+ // 鑱氱劍鍖哄煙鎴栧満鏅�
+ val focusRegion: List<String>,
)
/**
@@ -61,7 +65,8 @@
countByDegree = emptyList(),
probCount = 0,
highRiskSceneCount = 0,
- probByFactor = emptyList()
+ probByFactor = emptyList(),
+ focusRegion = emptyList()
)
}
@@ -100,7 +105,10 @@
val highRiskSceneCount = clueRes.second // 闇�鍏宠仈鍦烘櫙琛ㄧ粺璁�
val probByFactor = clueRes.third
- // 7. 鏋勫缓骞惰繑鍥炵粺璁$粨鏋�
+ // 7. 浠庡紓甯告墍鍦ㄥ湴鍖哄拰婧簮鐨勫満鏅腑缁熻鑱氱劍鍖哄煙
+ val focusRegion = calFocusRegion(clues)
+
+ // 8. 鏋勫缓骞惰繑鍥炵粺璁$粨鏋�
return Summary(
startTime = startTime,
endTime = endTime,
@@ -111,7 +119,8 @@
countByDegree = countByDegree,
probCount = probCount,
highRiskSceneCount = highRiskSceneCount,
- probByFactor = probByFactor
+ probByFactor = probByFactor,
+ focusRegion = focusRegion
)
}
@@ -137,4 +146,32 @@
}
return Triple(probCount, highRiskSceneCount, probByFactor)
}
+
+ private fun calFocusRegion(clues: List<PollutedClue?>): List<String> {
+ // 缁熻姣忎釜鍖哄煙鎴栧満鏅嚭鐜扮殑娆℃暟
+ val focusArea = mutableMapOf<String, Int>()
+ val focusScene = mutableMapOf<String, Int>()
+ clues.forEach { c->
+ if (c?.msgType == MsgType.PolClue.value) {
+ if (!c.pollutedArea?.address.isNullOrBlank()) {
+ if (focusArea.containsKey(c.pollutedArea?.address)) {
+ focusArea[c.pollutedArea?.address!!] = focusArea[c.pollutedArea?.address]!! + 1
+ } else {
+ focusArea[c.pollutedArea?.address!!] = 1
+ }
+ }
+ c.pollutedSource?.sceneList?.forEach { s->
+ if (s.name != null) {
+ if (focusScene.containsKey(s.name!!)) {
+ focusScene[s.name!!] = focusScene[s.name!!]!! + 1
+ } else {
+ focusScene[s.name!!] = 1
+ }
+ }
+ }
+ }
+ }
+ return focusArea.entries.sortedByDescending { it.value }.map { it.key }.take(FOCUS_AREA_COUNT) +
+ focusScene.entries.sortedByDescending { it.value }.map { it.key }.take(FOCUS_AREA_COUNT)
+ }
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt
index 5bd59a6..2fa37ca 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt
@@ -70,6 +70,11 @@
*/
fun generateMissionList(missionClues: List<Pair<Mission, List<PollutedClue?>>>): List<MissionInventory.MissionInfo>
+ fun generateMissionInfo(
+ keyScenes: List<SceneInfo?>,
+ missionCluesData: List<Triple<Mission, List<PollutedClue?>, List<BaseRealTimeData>>>,
+ ): List<MissionInventory.MissionInfo>
+
/**
* 鑾峰彇璧拌埅浠诲姟璇︽儏锛堟寜鏃堕棿鍜屽尯鍩熺瓫閫夛級
* 鏍规嵁鏃堕棿鑼冨洿鍜屽尯鍩熸煡璇㈠苟鐢熸垚璇︾粏鐨勪换鍔℃姤鍛婏紝鍖呭惈鍏抽敭鍦烘櫙鍜屾暟鎹粺璁�
@@ -100,6 +105,6 @@
factorTypes: List<FactorType>,
gridLen: Int,
gridCells: List<GridCell>,
- dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionDetail>, List<GridDataDetailMixVo>>>,
+ dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionInfo>, List<GridDataDetailMixVo>>>,
): List<MissionGridFusion.GridFusionByAQI>
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
index 0dcbb4a..3e20de7 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
@@ -119,10 +119,25 @@
* @see generateMissionList 閲嶈浇鏂规硶锛屽鐞嗗凡鍏宠仈鐨勬暟鎹
*/
override fun generateMissionList(startTime: Date, endTime: Date, areaVo: AreaVo): List<MissionInventory.MissionInfo> {
- val missionClues = missionRep.findByAreaAndTime(areaVo, startTime, endTime).filterNotNull().map {
- it to sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?>
+// val missionClues = missionRep.findByAreaAndTime(areaVo, startTime, endTime).filterNotNull().map {
+// it to sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?>
+// }
+// return generateMissionList(missionClues)
+ val missionCluesData = missionRep.findByAreaAndTime(areaVo, startTime, endTime).filterNotNull().map {
+ Triple(
+ it,
+ sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?>,
+ realTimeDataRep.fetchData(it)
+ )
}
- return generateMissionList(missionClues)
+ val keyScenes = sceneInfoRep.findBySceneTypes(
+ listOf(
+ SceneType.TYPE19.value,
+ SceneType.TYPE20.value,
+ SceneType.TYPE21.value
+ )
+ )
+ return generateMissionInfo(keyScenes, missionCluesData)
}
/**
@@ -134,6 +149,15 @@
*/
override fun generateMissionList(missionClues: List<Pair<Mission, List<PollutedClue?>>>): List<MissionInventory.MissionInfo> {
return MissionInventory().generateMissionList(missionClues)
+ }
+
+ override fun generateMissionInfo(
+ keyScenes: List<SceneInfo?>,
+ missionCluesData: List<Triple<Mission, List<PollutedClue?>, List<BaseRealTimeData>>>,
+ ): List<MissionInventory.MissionInfo> {
+ return missionCluesData.map {
+ MissionInventory().generateMissionInfo(keyScenes, it.first, it.second, it.third)
+ }
}
/**
@@ -256,9 +280,9 @@
SceneType.TYPE21.value
)
)
- val missionDetails = generateMissionDetail(keyScenes, missionCluesData)
+ val missionInfos = generateMissionInfo(keyScenes, missionCluesData)
- return@mapNotNull Triple(degree, missionDetails, gridDataDetailMixVos)
+ return@mapNotNull Triple(degree, missionInfos, gridDataDetailMixVos)
}.filter { it.second.isNotEmpty() }
return generateGridFusion(factorTypes, gridLen, gridCells, gridDataDetailList)
@@ -268,7 +292,7 @@
factorTypes: List<FactorType>,
gridLen: Int,
gridCells: List<GridCell>,
- dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionDetail>, List<GridDataDetailMixVo>>>,
+ dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionInfo>, List<GridDataDetailMixVo>>>,
): List<MissionGridFusion.GridFusionByAQI> {
return MissionGridFusion(sceneInfoRep).generateGridFusion(factorTypes, gridLen, gridCells, dataList)
}
--
Gitblit v1.9.3