From 2de612e9b260df2e76d4dd620ca739aa3b6e8c57 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期一, 25 八月 2025 16:07:16 +0800 Subject: [PATCH] 2025.8.25 1. 添加走航季度报告相关统计功能(待完成) --- src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt | 246 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 241 insertions(+), 5 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 9fcf324..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,19 +1,34 @@ 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.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 +import org.springframework.beans.BeanUtils import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.util.Date +import kotlin.math.round /** - * + * 鍗槦缃戞牸鍧愭爣鍙婄洃娴嬫暟鎹簩娆¤绠� * @date 2025/1/15 * @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?> { @@ -45,7 +60,228 @@ return cellList } - override fun splitGrid(groupId: Int): List<GridCell?> { - TODO("Not yet implemented") + @Transactional + override fun splitGrid(groupId: Int, scale: Int): List<GridCell?> { + // 妫�鏌ヨ缃戞牸灞炴�ф槸鍚﹀悎瑙� + val gridGroup = + satelliteGridRep.fetchGridGroup(groupId) ?: throw BizException("璇ョ綉鏍肩粍涓嶅瓨鍦紝鏃犳硶杩涜缃戞牸缁嗗垎") + if (gridGroup.length == null) throw BizException("璇ョ綉鏍肩粍娌℃湁璁惧畾缃戞牸杈归暱锛屾棤娉曡繘琛岀綉鏍肩粏鍒�") + + // 妫�鏌ヨ缃戞牸涓嬭绉嶇被鐨勭粏鍒嗙綉鏍兼槸鍚﹀瓨鍦紝鑻ヤ笉瀛樺湪锛屽垯鏂板缓 + val searchGridGroup = GridGroup().apply { + type = GridType.Sub.name.lowercase() + fatherGroupId = gridGroup.id + length = round(gridGroup.length / scale) + } + val subGridGroupList = satelliteGridRep.fetchGridGroup(searchGridGroup) + // 鑻ョ粏鍒嗙綉鏍艰褰曡秴杩�1涓紝璇存槑涓氬姟閫昏緫瀛樺湪闂锛岀浉鍚岃竟闀跨殑缁嗗垎缃戞牸搴旇鍙湁1涓� + if (subGridGroupList.size > 1) { + throw BizException("璇ョ綉鏍肩粍涓�${searchGridGroup.length}绫宠竟闀跨殑缃戞牸璁板綍瓒呰繃1涓紝鏃犳硶鍐嶈繘琛岀綉鏍肩粏鍒嗭紝骞朵笖璇锋鏌ョ敓鎴愰�昏緫鏄惁闂") + } + // 鑻ョ粏鍒嗙綉鏍艰褰曟湁涓斿彧鏈�1涓紝鍒欐棤闇�鍐嶆缁嗗垎锛岀洿鎺ヨ繑鍥炲凡鏈夌粨鏋� + else if (subGridGroupList.size == 1) { + val g = subGridGroupList.first() + ?: throw BizException("璇ョ綉鏍肩粍涓嬬殑缁嗗垎缃戞牸璁板綍宸叉崯鍧忥紝鏃犳硶浣跨敤锛岃妫�鏌ユ暟鎹簱璁板綍") + return satelliteGridRep.fetchGridCell(g.id) + } + // 褰撴病鏈夎褰曟椂锛屾墽琛岀敓鎴愰�昏緫 + + // 鐢熸垚鏂扮殑缁嗗垎缃戞牸缁勮褰� + val newGridGroup = GridGroup() + BeanUtils.copyProperties(gridGroup, newGridGroup) + newGridGroup.apply { + id = null + name += "${searchGridGroup.length.toInt()}绫崇粏鍒�" + createTime = Date() + length = searchGridGroup.length + type = GridType.Sub.name.lowercase() + fatherGroupId = groupId + } + satelliteGridRep.insertGridGroup(newGridGroup) + + // 鑾峰彇鍏蜂綋缃戞牸淇℃伅 + val cellList = satelliteGridRep.fetchGridCell(groupId) + // 鎸夌収缁欏畾鐨勬媶鍒嗙郴鏁拌繘琛屾媶鍒� + val subCellList = SatelliteGridManage.splitGrid(cellList, scale, newGridGroup.id) + satelliteGridRep.insertGridCell(subCellList) + + return subCellList + } + + @Transactional + override fun splitData(groupId: Int, dataId: Int): List<GridDataDetail?> { + // 妫�鏌ユ槸鍚︽槸缁嗗垎缃戞牸绫诲瀷 + 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) + + val subGridData = GridData().apply { + this.groupId = groupId + dataTime = originGridData?.dataTime + type = SatelliteDataType.Sub.value.toByte() + } + satelliteGridRep.insertGridData(subGridData) + + val subGridDataDetailList = + SatelliteGridManage.splitData(subGridCellList, subGridData, originGridDataDetailList) + + satelliteGridRep.insertGridDataDetail(subGridDataDetailList) + + 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