From 0ddfab15b32dc054464d75c695999fa76c3b9b78 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期五, 03 一月 2025 17:33:50 +0800
Subject: [PATCH] 1. 卫星遥测数据的融合

---
 src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridAnalysisRep.kt                |   17 +++
 src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridRep.kt                        |    4 
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt     |   30 +++++
 src/test/kotlin/com/flightfeather/uav/UAVApplicationTests.kt                                       |   24 ++++
 src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImplTest.kt |   20 ---
 src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteTelemetryService.kt              |    7 +
 src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteDataMix.kt                            |  127 +++++++++++++++++++++++++
 src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt               |    5 +
 src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SatelliteDataType.kt                         |   13 ++
 9 files changed, 228 insertions(+), 19 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteDataMix.kt b/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteDataMix.kt
new file mode 100644
index 0000000..8f4c3c9
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteDataMix.kt
@@ -0,0 +1,127 @@
+package com.flightfeather.uav.biz.satellite
+
+import com.flightfeather.uav.domain.entity.GridData
+import com.flightfeather.uav.domain.entity.GridDataDetail
+import com.flightfeather.uav.domain.mapper.GridDataDetailMapper
+import com.flightfeather.uav.domain.mapper.GridDataMapper
+import com.flightfeather.uav.lightshare.eunm.SatelliteDataType
+import org.springframework.beans.BeanUtils
+import org.springframework.stereotype.Component
+import tk.mybatis.mapper.entity.Example
+import java.util.Date
+
+/**
+ * 鍗槦閬ユ祴鏁版嵁铻嶅悎
+ * @date 2024/12/31
+ * @author feiyu02
+ */
+@Component
+class SatelliteDataMix(
+    private val gridDataMapper: GridDataMapper,
+    private val gridDataDetailMapper: GridDataDetailMapper,
+) {
+
+    /**
+     * 铻嶅悎鍗槦閬ユ祴鏁版嵁
+     * @param dataIdList 姣忔湡鍗槦閬ユ祴鏁版嵁鐨勪富閿甶d鏁扮粍锛岃〃绀洪渶瑕佸皢杩欏嚑缁勬暟鎹繘琛屾暟鎹瀺鍚�
+     */
+    fun mixData(dataIdList: List<Int>): Pair<GridData?, List<GridDataDetail>> {
+        if (dataIdList.isEmpty()) return null to emptyList()
+
+        // 鑾峰彇鍘熷鏁版嵁
+        val originalDataList = gridDataMapper.selectByExample(Example(GridData::class.java).apply {
+            createCriteria().andIn("id", dataIdList).andEqualTo("type", SatelliteDataType.Original.value)
+        })
+        if (originalDataList.isEmpty()) return null to emptyList()
+
+        // 鑾峰彇鍏蜂綋鍘熷缃戞牸鏁版嵁
+        val dataDetailList = mutableListOf<List<GridDataDetail?>>()
+        originalDataList.forEach {
+            val res = gridDataDetailMapper.selectByExample(Example(GridDataDetail::class.java).apply {
+                createCriteria().andEqualTo("dataId", it?.id)
+                orderBy("cellId")
+            })
+            dataDetailList.add(res)
+        }
+
+        // 鍒涘缓铻嶅悎鏁版嵁绱㈠紩淇℃伅
+        val firstGridData = originalDataList.first()
+        val avgGridData = GridData().apply {
+            groupId = firstGridData?.groupId
+            dataTime = Date()
+            type = SatelliteDataType.Mix.value.toByte()
+            mixDataId = dataIdList.joinToString(",")
+        }
+        gridDataMapper.insert(avgGridData)
+
+        // 璁$畻鍧囧��
+        val avgResult = calculateAvg(avgGridData.id, dataDetailList)
+        gridDataDetailMapper.insertList(avgResult)
+
+        return avgGridData to avgResult
+    }
+
+    /**
+     * 灏嗗缁勫師濮嬪崼鏄熼仴娴嬬綉鏍糚M2.5鏁版嵁杩涜铻嶅悎锛岃绠楁瘡涓綉鏍肩殑鍧囧��
+     * @param dataId 铻嶅悎鏁版嵁涓婚敭id
+     * @param dataDetailList 鍘熷鍗槦閬ユ祴鏁版嵁鏁扮粍
+     */
+    fun calculateAvg(dataId: Int, dataDetailList: List<List<GridDataDetail?>>): List<GridDataDetail> {
+        if (dataDetailList.isEmpty()) return emptyList()
+
+        // 鑾峰彇棣栫粍缃戞牸鏁版嵁锛屼綔涓哄悗缁敓鎴愯瀺鍚堟暟鎹殑渚濇嵁
+        val first = dataDetailList.first()
+
+        // 姣忎釜鍗曞厓鏍兼暟鎹洃娴嬪�兼�婚噺
+        val totalList = mutableListOf<Float>()
+        // 姣忎釜鍗曞厓鏍兼暟鎹�绘暟
+        val countList = mutableListOf<Int>()
+
+        // 缁熻鍚勭綉鏍肩殑鏁版嵁鐩戞祴鍊兼�婚噺鍜屾暟鎹�绘暟
+        dataDetailList.forEach {
+            it.forEachIndexed { i, d ->
+                if (i < totalList.size) {
+                    if (d?.pm25 != null) {
+                        totalList[i] += d.pm25
+                        countList[i]++
+                    }
+                } else {
+                    if (d?.pm25 != null) {
+                        totalList.add(d.pm25)
+                        countList.add(1)
+                    } else {
+                        totalList.add(0f)
+                        countList.add(0)
+                    }
+                }
+            }
+        }
+
+        // 璁$畻姣忎釜缃戞牸鐨勫潎鍊�
+        val avgResult = mutableListOf<GridDataDetail>()
+        first.forEachIndexed { i, d ->
+            val total = totalList[i]
+            val count = countList[i]
+            val avg = if (count == 0) {
+                null
+            } else {
+                total / count
+            }
+            val avgData = GridDataDetail().apply {
+                this.dataId = dataId
+                groupId = d?.groupId
+                cellId = d?.cellId
+                pm25 = avg
+            }
+            avgResult.add(avgData)
+        }
+
+        // 鍒锋柊鎺掑悕灞炴��
+        avgResult.sortByDescending { it.pm25 }
+        avgResult.forEachIndexed { i, d ->
+            d.rank = i + 1
+        }
+
+        return avgResult
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridAnalysisRep.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridAnalysisRep.kt
new file mode 100644
index 0000000..f50b590
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridAnalysisRep.kt
@@ -0,0 +1,17 @@
+package com.flightfeather.uav.domain.repository
+
+import com.flightfeather.uav.domain.mapper.GridDataDetailMapper
+import com.flightfeather.uav.domain.mapper.GridDataMapper
+
+/**
+ *
+ * @date 2024/12/31
+ * @author feiyu02
+ */
+class SatelliteGridAnalysisRep(
+    private val gridDataMapper: GridDataMapper,
+    private val gridDataDetailMapper: GridDataDetailMapper,
+) {
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridRep.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridRep.kt
index b88bc35..ce7a41e 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridRep.kt
+++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/SatelliteGridRep.kt
@@ -52,6 +52,10 @@
         })
     }
 
+    fun fetchGridData(gridData: GridData): List<GridData?> {
+        return gridDataMapper.select(gridData)
+    }
+
     fun fetchGridDataDetail(dataId: Int, groupId: Int?, cellId: Int?): List<GridDataDetail?> {
         return gridDataDetailMapper.selectByExample(Example(GridDataDetail::class.java).apply {
             createCriteria().andEqualTo("dataId", dataId)
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SatelliteDataType.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SatelliteDataType.kt
new file mode 100644
index 0000000..c05a840
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SatelliteDataType.kt
@@ -0,0 +1,13 @@
+package com.flightfeather.uav.lightshare.eunm
+
+/**
+ * 鍗槦閬ユ祴鏁版嵁绫诲瀷
+ * @date 2024/12/31
+ * @author feiyu02
+ */
+enum class SatelliteDataType(val value: Int) {
+    // 鍘熷鏁版嵁
+    Original(0),
+    // 铻嶅悎鏁版嵁
+    Mix(1)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteTelemetryService.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteTelemetryService.kt
index 97014cb..ab87849 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteTelemetryService.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteTelemetryService.kt
@@ -14,7 +14,7 @@
 import javax.servlet.http.HttpServletResponse
 
 /**
- *
+ * 鍗槦閬ユ祴鐩稿叧service鏈嶅姟鎺ュ彛
  * @date 2024/12/5
  * @author feiyu02
  */
@@ -28,6 +28,11 @@
 
     fun fetchGridDataDetail(dataId: Int, groupId: Int?, cellId: Int?): List<GridDataDetail?>
 
+    /**
+     * 鏁版嵁铻嶅悎
+     */
+    fun mixGridData(dataIdList: List<Int>): List<GridData?>
+
     @Throws(BizException::class)
     fun importGridData(groupId: Int, dataTime: LocalDateTime?, update: Boolean, file: MultipartFile): GridDataImportResult?
 
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
index db1be82..97e4c67 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.lightshare.service.impl
 
+import com.flightfeather.uav.biz.satellite.SatelliteDataMix
 import com.flightfeather.uav.common.exception.BizException
 import com.flightfeather.uav.common.utils.FileExchange
 import com.flightfeather.uav.domain.entity.GridAod
@@ -14,6 +15,7 @@
 import com.flightfeather.uav.lightshare.service.SatelliteTelemetryService
 import com.github.pagehelper.PageHelper
 import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
 import org.springframework.web.multipart.MultipartFile
 import java.io.ByteArrayInputStream
 import java.io.File
@@ -21,6 +23,7 @@
 import java.time.ZoneId
 import java.util.*
 import javax.servlet.http.HttpServletResponse
+import kotlin.math.round
 
 /**
  *
@@ -28,7 +31,10 @@
  * @author feiyu02
  */
 @Service
-class SatelliteTelemetryServiceImpl(private val satelliteGridRep: SatelliteGridRep) : SatelliteTelemetryService {
+class SatelliteTelemetryServiceImpl(
+    private val satelliteGridRep: SatelliteGridRep,
+    private val satelliteDataMix: SatelliteDataMix,
+) : SatelliteTelemetryService {
 
     private val fileExchange = FileExchange()
     override fun fetchGridGroup(areaVo: AreaVo, page: Int?, perPage: Int?): Pair<DataHead, List<GridGroup?>> {
@@ -50,7 +56,27 @@
     }
 
     override fun fetchGridDataDetail(dataId: Int, groupId: Int?, cellId: Int?): List<GridDataDetail?> {
-        return satelliteGridRep.fetchGridDataDetail(dataId, groupId, cellId)
+        val res =  satelliteGridRep.fetchGridDataDetail(dataId, groupId, cellId)
+        res.forEach {
+            if (it?.pm25 != null) {
+                it.pm25 = round(it.pm25 * 100) / 100
+            }
+        }
+        return res
+    }
+
+    @Transactional
+    override fun mixGridData(dataIdList: List<Int>): List<GridData?> {
+        if (dataIdList.isEmpty()) throw BizException("铻嶅悎鎵�闇�鏁版嵁id涓嶈兘涓虹┖")
+        // 1. 鏍规嵁鏁版嵁涓婚敭id鏁扮粍锛屾煡璇㈣缁勫悎涓嬫槸鍚﹀凡鏈夋暟鎹瀺鍚堣褰�
+        val exist = satelliteGridRep.fetchGridData(GridData().apply {
+            type = 1
+            mixDataId = dataIdList.joinToString(",")
+        })
+        // 2. 鑻ヨ瀺鍚堟暟鎹凡瀛樺湪锛岀洿鎺ヨ繑鍥�
+        return exist.ifEmpty {
+            listOf(satelliteDataMix.mixData(dataIdList).first)
+        }
     }
 
     override fun importGridData(groupId: Int, dataTime: LocalDateTime?, update: Boolean, file: MultipartFile): GridDataImportResult? {
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
index f5b6175..d0c2811 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
@@ -54,6 +54,11 @@
         @ApiParam("缃戞牸鍗曞厓鏍糹d") @RequestParam(required = false) cellId: Int?,
     ) = resPack { satelliteTelemetryService.fetchGridDataDetail(dataId, groupId, cellId) }
 
+    @ApiOperation(value = "澶氭璧拌埅鏁版嵁杩涜铻嶅悎璁$畻")
+    @PostMapping("/grid/data/mix")
+    fun mixGridData(
+        @ApiParam("鍘熷鏁版嵁id鏁扮粍") @RequestBody dataIdList: List<Int>
+    ) = resPack { satelliteTelemetryService.mixGridData(dataIdList) }
 
     @ApiOperation(value = "瀵煎叆鍗槦閬ユ祴PM2.5缁撴灉鏁版嵁")
     @PostMapping("/import/grid/data")
diff --git a/src/test/kotlin/com/flightfeather/uav/UAVApplicationTests.kt b/src/test/kotlin/com/flightfeather/uav/UAVApplicationTests.kt
index 1dd2ccf..6d4fab4 100644
--- a/src/test/kotlin/com/flightfeather/uav/UAVApplicationTests.kt
+++ b/src/test/kotlin/com/flightfeather/uav/UAVApplicationTests.kt
@@ -1,5 +1,7 @@
 package com.flightfeather.uav
 
+import com.flightfeather.uav.domain.entity.GridDataDetail
+import com.flightfeather.uav.domain.mapper.GridDataDetailMapper
 import com.flightfeather.uav.lightshare.service.RealTimeDataService
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -7,6 +9,7 @@
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.test.context.junit4.SpringRunner
+import tk.mybatis.mapper.entity.Example
 
 @RunWith(SpringRunner::class)
 @SpringBootTest
@@ -15,6 +18,27 @@
     @Autowired
     lateinit var realTimeDataService: RealTimeDataService
 
+    @Autowired
+    lateinit var gridDataDetailMapper: GridDataDetailMapper
+
+    /**
+     * 鍒锋柊姣忕粍鏁版嵁鐨勬暟鎹帓鍚�
+     */
+    @Test
+    fun refreshDataRank() {
+        for (i in 29..39) {
+            val dataDetailList = gridDataDetailMapper.selectByExample(Example(GridDataDetail::class.java).apply {
+                createCriteria().andEqualTo("dataId", i)
+                orderBy("pm25").desc()
+            })
+            dataDetailList.forEachIndexed { i, d ->
+                d?.rank = i + 1
+                gridDataDetailMapper.updateByPrimaryKey(d)
+            }
+            println("finish --${i}")
+        }
+    }
+
     @Test
     fun contextLoads() {
     }
diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImplTest.kt
index c272769..7b3269e 100644
--- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImplTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImplTest.kt
@@ -2,6 +2,7 @@
 
 import com.flightfeather.uav.domain.entity.GridDataDetail
 import com.flightfeather.uav.domain.mapper.GridDataDetailMapper
+import com.flightfeather.uav.lightshare.service.SatelliteTelemetryService
 import org.junit.Assert.*
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -15,23 +16,10 @@
 class SatelliteTelemetryServiceImplTest {
 
     @Autowired
-    lateinit var gridDataDetailMapper: GridDataDetailMapper
+    lateinit var satelliteTelemetryService: SatelliteTelemetryService
 
-    /**
-     * 鍒锋柊姣忕粍鏁版嵁鐨勬暟鎹帓鍚�
-     */
     @Test
-    fun refreshDataRank() {
-        for (i in 1..25) {
-            val dataDetailList = gridDataDetailMapper.selectByExample(Example(GridDataDetail::class.java).apply {
-                createCriteria().andEqualTo("dataId", i)
-                orderBy("pm25").desc()
-            })
-            dataDetailList.forEachIndexed { i, d ->
-                d?.rank = i + 1
-                gridDataDetailMapper.updateByPrimaryKey(d)
-            }
-            println("finish --${i}")
-        }
+    fun mixGridData() {
+        satelliteTelemetryService.mixGridData(listOf(24, 25))
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3