feiyu02
2025-12-25 d649f734c44541641158aec2d6b10d630f5a0827
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
@@ -77,13 +77,14 @@
     * 获取历史污染溯源结果
     * 查询指定任务的历史污染溯源结果并序列化为JSON字符串
     * @param missionCode 走航任务编码
     * @param minPer 最小污染百分比,用于筛选异常数据点(可选)
     * @return 历史污染溯源结果的JSON字符串,具体格式由sourceTraceRep实现决定
     * @throws BizException 当走航任务不存在时抛出
     */
    override fun fetchHistory(missionCode: String): String {
    override fun fetchHistory(missionCode: String, minPer: Double?): String {
        val mission = missionRep.findOne(missionCode) ?: throw BizException("走航任务不存在")
        val res = sourceTraceRep.fetchList(mission.deviceCode, mission.startTime, mission.endTime)
        val res = sourceTraceRep.fetchList(mission.deviceCode, mission.startTime, mission.endTime, minPer = minPer ?: 0.5)
        return GsonUtils.gson.toJson(res)
    }
@@ -94,26 +95,33 @@
     * @param endTime 统计结束时间(包含)
     * @param areaVo 区域参数,包含省、市、区三级行政区划编码
     * @return 汇总统计对象,包含任务总数、异常点数量、平均里程等核心指标
     * @see MissionSummary 汇总统计处理器,封装具体的统计逻辑实现
     * @see MissionSummary 汇总统计处理器,封装具体统计逻辑的实现
     */
    override fun generateMissionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary {
    override fun generateMissionSummary(
        startTime: Date, endTime: Date, areaVo: AreaVo, removeOtherDistrict: Boolean,
        removeNoPollutedSource: Boolean, minPer: Double?,
    ): MissionSummary.Summary {
        val clues = mutableListOf<PollutedClue?>()
        val missions = missionRep.findByAreaAndTime(areaVo, startTime, endTime).onEach {
            it ?: return@onEach
            val clue = sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?>
            val clue = sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue, minPer ?: 0.5) as List<PollutedClue?>
            clues.addAll(clue)
        }
        filterClue(areaVo, clues, removeOtherDistrict, removeNoPollutedSource)
        val summary = MissionSummary().execute(startTime, endTime, missions, clues)
        return summary
    }
    override fun generateMissionSummary(missionCode: String): MissionSummary.Summary {
    override fun generateMissionSummary(
        missionCode: String, minPer: Double?,
    ): MissionSummary.Summary {
        val mission = missionRep.findOne(missionCode) ?: throw BizException("走航任务不存在")
        val clues = sourceTraceRep.fetchList(
            mission.deviceCode,
            mission.startTime,
            mission.endTime,
            MsgType.PolClue
            MsgType.PolClue,
            minPer ?: 0.5,
        ) as List<PollutedClue?>
        val summary = MissionSummary().execute(mission.startTime, mission.endTime, listOf(mission), clues)
        return summary
@@ -129,17 +137,20 @@
     * @see MissionRep.findByAreaAndTime 区域时间筛选数据源
     * @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?>
//        }
//        return generateMissionList(missionClues)
    override fun generateMissionList(
        startTime: Date, endTime: Date, areaVo: AreaVo, removeOtherDistrict: Boolean,
        removeNoPollutedSource: Boolean, minPer: Double?,
    ): List<MissionInventory.MissionInfo> {
        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)
            )
            val clues = sourceTraceRep.fetchList(
                it.deviceCode,
                it.startTime,
                it.endTime,
                MsgType.PolClue,
                minPer ?: 0.5
            ) as List<PollutedClue?>
            filterClue(areaVo, clues.toMutableList(), removeOtherDistrict, removeNoPollutedSource)
            Triple(it, clues, realTimeDataRep.fetchData(it))
        }
        val keyScenes = sceneInfoRep.findBySceneTypes(
            listOf(
@@ -187,13 +198,20 @@
        endTime: Date,
        areaVo: AreaVo,
        granularity: String?,
        removeOtherDistrict: Boolean,
        removeNoPollutedSource: Boolean,
        minPer: Double?,
    ): List<MissionInventory.MissionDetail> {
        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)
            )
            val clues = sourceTraceRep.fetchList(
                it.deviceCode,
                it.startTime,
                it.endTime,
                MsgType.PolClue,
                minPer ?: 0.5
            ) as List<PollutedClue?>
            filterClue(areaVo, clues.toMutableList(), removeOtherDistrict, removeNoPollutedSource)
            Triple(it, clues, realTimeDataRep.fetchData(it))
        }
        val keyScenes = sceneInfoRep.findBySceneTypes(
            listOf(
@@ -205,13 +223,18 @@
        return generateMissionDetail(keyScenes, missionCluesData, granularity ?: "MINUTE")
    }
    override fun generateMissionDetail(missionCode: String, granularity: String?): MissionInventory.MissionDetail {
    override fun generateMissionDetail(
        missionCode: String,
        granularity: String?,
        minPer: Double?,
    ): MissionInventory.MissionDetail {
        val mission = missionRep.findOne(missionCode) ?: throw BizException("任务不存在")
        val missionClues = sourceTraceRep.fetchList(
            mission.deviceCode,
            mission.startTime,
            mission.endTime,
            MsgType.PolClue
            MsgType.PolClue,
            minPer ?: 0.5
        ) as List<PollutedClue?>
        val realTimeData = realTimeDataRep.fetchData(mission)
        val keyScenes = sceneInfoRep.findBySceneTypes(
@@ -248,33 +271,42 @@
        areaVo: AreaVo,
        removeOtherDistrict: Boolean,
        removeNoPollutedSource: Boolean,
        minPer: Double?,
    ): List<MissionRiskArea.ClassifyClue> {
        val clues = mutableListOf<PollutedClue?>()
        missionRep.findByAreaAndTime(areaVo, startTime, endTime).onEach {
            it ?: return@onEach
            val clue = sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?>
            val clue = sourceTraceRep.fetchList(
                it.deviceCode,
                it.startTime,
                it.endTime,
                MsgType.PolClue,
                minPer ?: 0.5
            ) as List<PollutedClue?>
            clues.addAll(clue)
        }
        if (removeOtherDistrict) {
            clues.removeIf {
                !areaVo.districtName.isNullOrBlank() &&
                        (it?.pollutedArea?.address.isNullOrBlank()
                                || !it!!.pollutedArea!!.address!!.contains(areaVo.districtName!!))
            }
        }
        if (removeNoPollutedSource) {
            clues.removeIf { it?.pollutedSource?.sceneList.isNullOrEmpty() }
        }
//        if (removeOtherDistrict) {
//            clues.removeIf {
//                !areaVo.districtName.isNullOrBlank() &&
//                        (it?.pollutedArea?.address.isNullOrBlank()
//                                || !it!!.pollutedArea!!.address!!.contains(areaVo.districtName!!))
//            }
//        }
//        if (removeNoPollutedSource) {
//            clues.removeIf { it?.pollutedSource?.sceneList.isNullOrEmpty() }
//        }
        filterClue(areaVo, clues, removeOtherDistrict, removeNoPollutedSource)
        return MissionRiskArea().generateClueByRiskArea(clues)
    }
    override fun generateClueByRiskArea(missionCode: String): List<MissionRiskArea.ClueByArea> {
    override fun generateClueByRiskArea(missionCode: String, minPer: Double?): List<MissionRiskArea.ClueByArea> {
        val mission = missionRep.findOne(missionCode) ?: throw BizException("任务不存在")
        val pollutedClues = sourceTraceRep.fetchList(
            mission.deviceCode,
            mission.startTime,
            mission.endTime,
            MsgType.PolClue
            MsgType.PolClue,
            minPer ?: 0.5
        ) as List<PollutedClue?>
        val keyScenes = sceneInfoRep.findBySceneTypes(
            listOf(
@@ -298,6 +330,9 @@
        startTime: Date,
        endTime: Date,
        areaVo: AreaVo,
        removeOtherDistrict: Boolean,
        removeNoPollutedSource: Boolean,
        minPer: Double?,
    ): List<MissionGridFusion.GridFusionByAQI> {
        val gridLen = 100
        // 查询100米网格的具体网格数据
@@ -328,11 +363,15 @@
            val gridDataDetailMixVos = satelliteDataCalculateService.mixUnderwayGridData(gridGroup.id, gridDataIds)
            // 统计每个走航任务的走航详情信息
            val missionCluesData = validMissions.filterNotNull().map {
                Triple(
                    it,
                    sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?>,
                    realTimeDataRep.fetchData(it)
                )
                val clues = sourceTraceRep.fetchList(
                    it.deviceCode,
                    it.startTime,
                    it.endTime,
                    MsgType.PolClue,
                    minPer ?: 0.5
                ) as List<PollutedClue?>
                filterClue(areaVo, clues.toMutableList(), removeOtherDistrict, removeNoPollutedSource)
                Triple(it, clues, realTimeDataRep.fetchData(it))
            }
            val keyScenes = sceneInfoRep.findBySceneTypes(
                listOf(
@@ -357,4 +396,26 @@
    ): List<MissionGridFusion.GridFusionByAQI> {
        return MissionGridFusion(sceneInfoRep).generateGridFusion(factorTypes, gridLen, gridCells, dataList)
    }
    private fun filterClue(
        areaVo: AreaVo, clues: MutableList<PollutedClue?>, removeOtherDistrict: Boolean,
        removeNoPollutedSource: Boolean,
    ) {
        if (removeOtherDistrict) {
            clues.removeIf {
                !areaVo.districtName.isNullOrBlank() &&
                        (it?.pollutedArea?.address.isNullOrBlank()
                                || !it!!.pollutedArea!!.address!!.contains(areaVo.districtName!!))
            }
            clues.forEach {
                it?.pollutedSource?.sceneList = it?.pollutedSource?.sceneList?.filter { s->
                    s.districtCode == areaVo.districtCode
                }
            }
        }
        if (removeNoPollutedSource) {
            clues.removeIf { it?.pollutedSource?.sceneList.isNullOrEmpty() }
        }
    }
}