feiyu02
2025-09-12 61871594dfa0a5ac2c4d895d9ec4034feba57094
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
package com.flightfeather.uav.biz.report
 
import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
import com.flightfeather.uav.common.utils.MapUtil
import com.flightfeather.uav.domain.entity.*
import com.flightfeather.uav.lightshare.bean.FactorStatistics
import com.flightfeather.uav.socket.eunm.FactorType
import com.flightfeather.uav.socket.sender.MsgType
import org.springframework.beans.BeanUtils
 
/**
 * 走航溯源清单
 * 包含时段内的走航任务汇总清单以及每次走航的数据汇总清单
 * @date 2025/8/25 11:02
 * @author feiyu
 */
class MissionInventory {
 
    // 走航清单信息
    class MissionInfo : Mission() {
        // 首要污染物
        var mainFactor: String? = null
 
        // 监测异常因子
        var abnormalFactors: List<FactorType>? = null
 
        // 溯源问题场景数
        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 dataStatistics: List<FactorStatistics>? = null
//        var exceptionCount: Int = 0
    }
 
    /**
     * 生成走航任务清单
     * 处理走航任务与污染线索数据,统计每个任务的异常因子、首要污染物和场景数量
     * @param missionClues 包含走航任务和对应污染线索的Pair列表
     * @return 包含统计信息的MissionInfo列表,每个元素包含任务基本信息及统计数据
     */
    fun generateMissionList(missionClues: List<Pair<Mission, List<PollutedClue?>>>): List<MissionInfo> {
        val result = missionClues.map { (mission, clue) ->
            val factorMap = mutableMapOf<FactorType, Int>()
            val abnormalFactors = mutableListOf<FactorType>()
            var sceneCount = 0
            clue.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
                }
            }
            val missionInfo = MissionInfo()
            BeanUtils.copyProperties(mission, missionInfo)
            missionInfo.apply {
                mainFactor = factorMap.maxByOrNull { it.value }?.key?.name
                this.abnormalFactors = abnormalFactors
                this.sceneCount = sceneCount
            }
        }
        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
            }
            // 转换为GCJ02坐标系
            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
    }
 
    /**
     * 生成走航任务详细信息
     * 整合走航任务基本信息、关键场景、数据统计和异常数量,生成完整的任务详情报告
     * @param keyScenes 关键场景列表,用于分析走航是否经过该区域
     * @param mission 走航任务基本信息对象,包含任务ID、名称、时间等元数据
     * @param pollutedClues 污染线索列表,用于提取关键场景信息
     * @param data 实时监测数据列表,用于计算环境因子统计信息
     * @param minDis 最小距离,用于判断走航是否经过关键场景
     * @return 包含详细信息的MissionDetail对象,包括:
     *         - 任务基本信息(继承自Mission类)
     *         - 关键场景列表(TYPE19和TYPE20类型的场景)
     *         - 环境因子统计数据(平均值、最小值、最大值)
     *         - 异常数据点数量
     */
    fun generateMissionDetail(
        keyScenes: List<SceneInfo?>,
        mission: Mission,
        pollutedClues: List<PollutedClue?>,
        data: List<BaseRealTimeData>,
        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
//            }
//            // 转换为GCJ02坐标系
//            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.dataStatistics = data.calDataStatistics()
 
        // 异常数据点数量统计
//        val clues = pollutedClues.filter { it?.msgType == MsgType.PolClue.value }
//        missionDetail.exceptionCount = clues.size
 
        return missionDetail
    }
}