From 9c797fa0d704ef8ffb65cd1716b8eb694b4c46c3 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期五, 04 七月 2025 17:28:00 +0800
Subject: [PATCH] 2025.7.4 1. 新增动态污染溯源新的判定逻辑

---
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt |  175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 167 insertions(+), 8 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
index d69174c..93866e6 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
@@ -1,12 +1,14 @@
 package com.flightfeather.uav.lightshare.service.impl
 
+import com.flightfeather.uav.biz.satellite.GridGroupOption
 import com.flightfeather.uav.biz.satellite.SatelliteGridManage
 import com.flightfeather.uav.common.exception.BizException
-import com.flightfeather.uav.domain.entity.GridCell
-import com.flightfeather.uav.domain.entity.GridData
-import com.flightfeather.uav.domain.entity.GridDataDetail
-import com.flightfeather.uav.domain.entity.GridGroup
+import com.flightfeather.uav.common.utils.TimeUtil
+import com.flightfeather.uav.domain.entity.*
+import com.flightfeather.uav.domain.repository.MissionRep
+import com.flightfeather.uav.domain.repository.RealTimeDataRep
 import com.flightfeather.uav.domain.repository.SatelliteGridRep
+import com.flightfeather.uav.lightshare.bean.GridDataDetailMixVo
 import com.flightfeather.uav.lightshare.eunm.GridType
 import com.flightfeather.uav.lightshare.eunm.SatelliteDataType
 import com.flightfeather.uav.lightshare.service.SatelliteDataCalculateService
@@ -22,7 +24,11 @@
  * @author feiyu02
  */
 @Service
-class SatelliteDataCalculateServiceImpl(private val satelliteGridRep: SatelliteGridRep) : SatelliteDataCalculateService {
+class SatelliteDataCalculateServiceImpl(
+    private val satelliteGridRep: SatelliteGridRep,
+    private val realTimeDataRep: RealTimeDataRep,
+    private val missionRep: MissionRep,
+) : SatelliteDataCalculateService {
 
 
     override fun calGridVertex(groupId: Int): List<GridCell?> {
@@ -54,6 +60,7 @@
         return cellList
     }
 
+    @Transactional
     override fun splitGrid(groupId: Int, scale: Int): List<GridCell?> {
         // 妫�鏌ヨ缃戞牸灞炴�ф槸鍚﹀悎瑙�
         val gridGroup =
@@ -102,14 +109,15 @@
     }
 
     @Transactional
-    override fun splitData(groupId: Int, dataId:Int): List<GridDataDetail?> {
+    override fun splitData(groupId: Int, dataId: Int): List<GridDataDetail?> {
         // 妫�鏌ユ槸鍚︽槸缁嗗垎缃戞牸绫诲瀷
-        val gridGroup = satelliteGridRep.fetchGridGroup(groupId) ?: throw BizException("璇ョ綉鏍肩粍涓嶅瓨鍦紝鏃犳硶杩涜缁嗗垎缃戞牸鏁版嵁鏄犲皠")
+        val gridGroup =
+            satelliteGridRep.fetchGridGroup(groupId) ?: throw BizException("璇ョ綉鏍肩粍涓嶅瓨鍦紝鏃犳硶杩涜缁嗗垎缃戞牸鏁版嵁鏄犲皠")
         if (gridGroup.type != GridType.Sub.name.lowercase()) throw BizException("璇ョ綉鏍肩粍涓嶆槸缁嗗垎缃戞牸绫诲瀷瀛樺湪锛屾棤娉曡繘琛岀粏鍒嗙綉鏍兼暟鎹槧灏�")
 
         val subGridCellList = satelliteGridRep.fetchGridCell(groupId)
         val originGridData = satelliteGridRep.fetchGridData(dataId)
-        val originGridDataDetailList = satelliteGridRep.fetchGridDataDetail(dataId, null, null)
+        val originGridDataDetailList = satelliteGridRep.fetchGridDataDetail(dataId)
 
         val subGridData = GridData().apply {
             this.groupId = groupId
@@ -125,4 +133,155 @@
 
         return subGridDataDetailList
     }
+
+    @Transactional
+    override fun dataFusion(gridData: GridData): List<GridDataDetail?> {
+        val missionCode = gridData.missionCode ?: throw BizException("缂哄皯浠诲姟缂栧彿")
+        val groupId = gridData.groupId ?: throw BizException("缂哄皯缃戞牸缁刬d")
+
+        // 鏌ヨ璧拌埅浠诲姟鍙婂搴旇蛋鑸洃娴嬫暟鎹�
+        val mission = missionRep.findOne(missionCode) ?: throw BizException("浠诲姟涓嶅瓨鍦�")
+        val data = realTimeDataRep.fetchData(mission)
+
+        // 鏌ユ壘鏄惁宸叉湁璧拌埅铻嶅悎璁板綍
+        val oldGridDataList = satelliteGridRep.fetchGridData(GridData().apply {
+            this.groupId = groupId
+            this.missionCode = missionCode
+            this.type = SatelliteDataType.Monitor.value.toByte()
+        })
+
+        if (oldGridDataList.isEmpty()) {
+            // 鍒涘缓铻嶅悎鏁版嵁绱㈠紩瀵硅薄
+            val newGridData = gridData.apply {
+                this.groupId = groupId
+                dataTime = mission.startTime
+                type = SatelliteDataType.Monitor.value.toByte()
+                this.missionCode = mission.missionCode
+                provinceCode = mission.provinceCode
+                provinceName = mission.provinceName
+                cityCode = mission.cityCode
+                cityName = mission.cityName
+                districtCode = mission.districtCode
+                districtName = mission.districtName
+                // 2025.3.27: 鎵�灞炵洃娴嬬偣鍖哄煙闇�瑕侀�氳繃鐢ㄦ埛閫夋嫨纭畾
+                zone
+                pollutionDegreeIndex
+                pollutionDegree
+
+                val period = TimeUtil.getDayTimeTag(mission.startTime, mission.endTime)
+                dayTimePeriod = period?.first
+                dayTimePeriodStart = period?.second
+                dayTimePeriodEnd = period?.third
+            }
+            satelliteGridRep.insertGridData(newGridData)
+
+            // 鏌ヨ缃戞牸鍗曞厓鏍间俊鎭�
+            val gridCellList = satelliteGridRep.fetchGridCell(groupId)
+
+            // 灏嗚蛋鑸暟鎹拰鍗槦缃戞牸杩涜铻嶅悎璁$畻
+            val gridDataDetailList = SatelliteGridManage.dataFusion(data, newGridData, gridCellList)
+            satelliteGridRep.insertGridDataDetail(gridDataDetailList)
+
+            return gridDataDetailList
+        } else {
+            val oldGridData = oldGridDataList.first()
+            val oldGridDataDetailList = satelliteGridRep.fetchGridDataDetail(oldGridData?.id, oldGridData?.groupId)
+            // 鏌ヨ缃戞牸鍗曞厓鏍间俊鎭�
+            val gridCellList = satelliteGridRep.fetchGridCell(groupId)
+            // 灏嗚蛋鑸暟鎹拰鍗槦缃戞牸杩涜铻嶅悎璁$畻
+            val gridDataDetailList = SatelliteGridManage.dataFusion(data, oldGridData, gridCellList)
+
+            // 灏嗗凡鏈夌殑鏁版嵁id璧嬪�肩粰鏂扮殑铻嶅悎缁撴灉锛屼袱缁勭粨鏋滃潎浠ユ牴鎹甤ellId椤哄簭鎺掑垪锛屾墍浠ョ洿鎺ュ惊鐜祴鍊�
+            gridDataDetailList.forEachIndexed { index, gridDataDetail ->
+                gridDataDetail.id = oldGridDataDetailList[index]?.id
+            }
+
+            satelliteGridRep.updateGridDataDetail(gridDataDetailList)
+
+            return gridDataDetailList
+        }
+    }
+
+    override fun mixUnderwayGridData(groupId: Int, dataIdList: List<Int>): List<GridDataDetailMixVo> {
+        // 鑾峰彇鎵�浣跨敤鐨勭綉鏍肩粍缃戞牸淇℃伅
+        val gridCellList = satelliteGridRep.fetchGridCell(groupId)
+
+        val gridDataDetailMap = mutableMapOf<Int?, MutableList<GridDataDetail>>()
+
+        // 褰掗泦鎵�鏈夌浉鍚屽崟鍏冪綉鏍肩殑鏁版嵁
+        dataIdList.forEach { id ->
+            satelliteGridRep.fetchGridDataDetail(id, groupId).forEach gdd@{ gdd ->
+                if (gdd == null) return@gdd
+                if (!gridDataDetailMap.containsKey(gdd.cellId)) {
+                    gridDataDetailMap[gdd.cellId] = mutableListOf()
+                }
+                gridDataDetailMap[gdd.cellId]?.add(gdd)
+            }
+        }
+
+        // 灏嗘墍鏈夌粨鏋滄牸寮忓寲锛屽悓鏃堕噸鍙犵綉鏍艰繘琛岀洃娴嬫暟鎹潎鍊艰绠�
+        val result = mutableListOf<GridDataDetailMixVo>()
+        gridDataDetailMap.forEach { (_, v) ->
+            val target = GridDataDetailMixVo()
+            if (v.size == 1) {
+                BeanUtils.copyProperties(v[0], target)
+            } else {
+                BeanUtils.copyProperties(v.avg(), target)
+                target.mixData = true
+                target.originDataList = v
+            }
+            target.apply {
+                this.dataId = v.first().dataId
+                this.groupId = v.first().groupId
+                this.cellId = v.first().cellId
+            }
+            result.add(target)
+        }
+        result.sortBy { it.pm25 }
+        result.forEachIndexed { index, d ->
+            d.rank = index + 1
+        }
+        result.sortBy { it.cellId }
+
+        return result
+    }
+
+    override fun buildHeatmap(
+        groupId: Int,
+        gridDataDetailList: List<GridDataDetail>,
+        searchLength: Int,
+    ): List<GridDataDetail> {
+        val gridGroup =satelliteGridRep.fetchGridGroup(groupId)
+        val gridCellList = satelliteGridRep.fetchGridCell(groupId)
+        val originCellIdList = gridDataDetailList.map { it.cellId }
+        // Fixme 2025.3.24: 姝ゅ鏍规嵁鐜版湁鐨勭綉鏍间俊鎭璁℃柟寮忥紝浣跨敤涓存椂鐨勫弬鏁帮紝鍚庣画灏嗙綉鏍奸�氳繃浜岀淮鍧愭爣褰㈠紡琛ㄧず锛屾澶勫弬鏁板幓闄�
+        val option = GridGroupOption(gridGroup?.maxXaxis ?: 120, gridGroup?.maxYaxis ?: 90, 10, 10)
+
+        val resMap = mutableMapOf<Int, MutableList<GridDataDetail>>()
+
+        // 寰幆璁$畻姣忎釜缃戞牸鐨勫懆杈规墿鏁g綉鏍肩粨鏋�
+        gridDataDetailList.forEach { gdd ->
+            SatelliteGridManage.heatMap(gdd, gridCellList, option, searchLength).forEach { r ->
+                if (!originCellIdList.contains(r.cellId)) {
+                    if (!resMap.containsKey(r.cellId)) {
+                        resMap[r.cellId] = mutableListOf()
+                    }
+                    resMap[r.cellId]?.add(r)
+                }
+            }
+        }
+
+        // 灏嗘墍鏈夌粨鏋滄牸寮忓寲锛屽悓鏃堕噸鍙犵綉鏍艰繘琛岀洃娴嬫暟鎹潎鍊艰绠�
+        val result = mutableListOf<GridDataDetail>()
+        resMap.forEach { (_, v) ->
+            result.add(v.avg().apply {
+                this.dataId = v.first().dataId
+                this.groupId = v.first().groupId
+                this.cellId = v.first().cellId
+            })
+        }
+        result.addAll(gridDataDetailList)
+
+        return result
+    }
 }
\ No newline at end of file

--
Gitblit v1.9.3