feiyu02
2025-09-01 29383149f7040d89ae00ad48dc48bbcf46587946
src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
@@ -1,9 +1,12 @@
package com.flightfeather.uav.biz.report
import com.flightfeather.uav.domain.entity.Mission
import com.flightfeather.uav.domain.entity.SceneInfo
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
/**
 * 走航溯源清单
@@ -14,7 +17,7 @@
class MissionInventory {
    // 走航清单信息
    inner class MissionInfo : Mission() {
    class MissionInfo : Mission() {
        // 首要污染物
        var mainFactor: String? = null
@@ -26,9 +29,108 @@
    }
    // 走航详情信息
    inner class MissionDetail : Mission() {
    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
    }
    /**
     * 生成走航任务详细信息
     * 整合走航任务基本信息、关键场景、数据统计和异常数量,生成完整的任务详情报告
     * @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
                }
                // 计算距离
                val distance = MapUtil.getDistance(k.longitude!!.toDouble(), k.latitude!!.toDouble(), point.first, point.second)
                // 检查是否距离小于阈值且未添加过
                if (distance < minDis && !relatedScenes.contains(k)) {
                    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
    }
}