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