From 29383149f7040d89ae00ad48dc48bbcf46587946 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期一, 01 九月 2025 17:32:53 +0800 Subject: [PATCH] 2025.9.1 1. 新增走航任务统计功能(待完成) --- src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt | 160 ++++++++++- src/main/resources/mapper/MissionMapper.xml | 3 src/main/kotlin/com/flightfeather/uav/biz/report/MissionRiskArea.kt | 86 ++++++ src/main/kotlin/com/flightfeather/uav/domain/repository/SceneInfoRep.kt | 9 src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt | 1 src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt | 105 ++++++- src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt | 4 src/main/kotlin/com/flightfeather/uav/domain/entity/Mission.java | 16 + /dev/null | 15 - src/main/kotlin/com/flightfeather/uav/domain/repository/MissionRep.kt | 22 + src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt | 15 src/main/resources/generator/generatorConfig.xml | 4 src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImplTest.kt | 30 ++ src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt | 74 +++++ src/main/kotlin/com/flightfeather/uav/lightshare/bean/FactorStatistics.kt | 23 + src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt | 69 +++++ src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt | 7 src/main/kotlin/com/flightfeather/uav/lightshare/web/DataAnalysisController.kt | 58 ++++ src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt | 6 src/main/kotlin/com/flightfeather/uav/socket/eunm/AggregatedFactorType.kt | 24 + src/main/kotlin/com/flightfeather/uav/socket/eunm/FactorType.kt | 2 21 files changed, 649 insertions(+), 84 deletions(-) diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionClue.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionClue.kt deleted file mode 100644 index f61020e..0000000 --- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionClue.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.flightfeather.uav.biz.report - -import com.flightfeather.uav.socket.eunm.FactorType - -/** - * @date 2025/8/25 14:18 - * @author feiyu - */ -class MissionClue { - - class Clue{ - var factor:FactorType?=null - var riskRegion:String?=null - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt index 26a597a..cd8f696 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt @@ -1,11 +1,12 @@ package com.flightfeather.uav.biz.report import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue -import com.flightfeather.uav.domain.entity.Mission -import com.flightfeather.uav.domain.entity.SceneInfo +import com.flightfeather.uav.common.utils.MapUtil +import com.flightfeather.uav.domain.entity.* import com.flightfeather.uav.lightshare.bean.FactorStatistics import com.flightfeather.uav.socket.eunm.FactorType import com.flightfeather.uav.socket.sender.MsgType +import org.springframework.beans.BeanUtils /** * 璧拌埅婧簮娓呭崟 @@ -31,37 +32,105 @@ class MissionDetail : Mission() { var keyScene: List<SceneInfo>? = null var dataStatistics: List<FactorStatistics>? = null + var exceptionCount: Int = 0 } /** - * 杈撳嚭璧拌埅娓呭崟 + * 鐢熸垚璧拌埅浠诲姟娓呭崟 + * 澶勭悊璧拌埅浠诲姟涓庢薄鏌撶嚎绱㈡暟鎹紝缁熻姣忎釜浠诲姟鐨勫紓甯稿洜瀛愩�侀瑕佹薄鏌撶墿鍜屽満鏅暟閲� + * @param missionClues 鍖呭惈璧拌埅浠诲姟鍜屽搴旀薄鏌撶嚎绱㈢殑Pair鍒楄〃 + * @return 鍖呭惈缁熻淇℃伅鐨凪issionInfo鍒楄〃锛屾瘡涓厓绱犲寘鍚换鍔″熀鏈俊鎭強缁熻鏁版嵁 */ - fun missionList(missionClues: List<Pair<Mission?, List<PollutedClue?>>>): List<MissionInfo> { - - val missionMap = mutableMapOf<String, MissionInfo>() - missionClues.forEach { (mission, clue) -> - mission ?: return@forEach - clue ?: return@forEach - val missionInfo = missionMap[mission.missionCode] ?: MissionInfo().apply { - missionMap[mission.missionCode] = this - } + fun generateMissionList(missionClues: List<Pair<Mission, List<PollutedClue?>>>): List<MissionInfo> { + val result = missionClues.map { (mission, clue) -> + val factorMap = mutableMapOf<FactorType, Int>() val abnormalFactors = mutableListOf<FactorType>() var sceneCount = 0 clue.forEach { if (it?.msgType == MsgType.PolClue.value) { it.pollutedData?.statisticMap?.keys?.forEach { k-> + // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬墍鏈夊紓甯稿洜瀛� if (!abnormalFactors.contains(k)) { abnormalFactors.add(k) } + // 璁$畻姣忎釜璧拌埅浠诲姟鐨勯瑕佹薄鏌撶墿 + if (!factorMap.containsKey(k)) { + factorMap[k] = 0 + } + factorMap[k] = factorMap[k]!! + 1 } + // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬函婧愬満鏅暟閲� + sceneCount += it.pollutedSource?.sceneList?.size ?: 0 } } - // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬墍鏈夊紓甯稿洜瀛� - - // 璁$畻姣忎釜璧拌埅浠诲姟鐨勯瑕佹薄鏌撶墿 - - // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬函婧愬満鏅暟閲� + val missionInfo = MissionInfo() + BeanUtils.copyProperties(mission, missionInfo) + missionInfo.apply { + mainFactor = factorMap.maxByOrNull { it.value }?.key?.name + this.abnormalFactors = abnormalFactors + this.sceneCount = sceneCount + } } - return mutableListOf() + return result + } + + /** + * 鐢熸垚璧拌埅浠诲姟璇︾粏淇℃伅 + * 鏁村悎璧拌埅浠诲姟鍩烘湰淇℃伅銆佸叧閿満鏅�佹暟鎹粺璁″拰寮傚父鏁伴噺锛岀敓鎴愬畬鏁寸殑浠诲姟璇︽儏鎶ュ憡 + * @param keyScenes 鍏抽敭鍦烘櫙鍒楄〃锛岀敤浜庡垎鏋愯蛋鑸槸鍚︾粡杩囪鍖哄煙 + * @param mission 璧拌埅浠诲姟鍩烘湰淇℃伅瀵硅薄锛屽寘鍚换鍔D銆佸悕绉般�佹椂闂寸瓑鍏冩暟鎹� + * @param pollutedClues 姹℃煋绾跨储鍒楄〃锛岀敤浜庢彁鍙栧叧閿満鏅俊鎭� + * @param data 瀹炴椂鐩戞祴鏁版嵁鍒楄〃锛岀敤浜庤绠楃幆澧冨洜瀛愮粺璁′俊鎭� + * @param minDis 鏈�灏忚窛绂伙紝鐢ㄤ簬鍒ゆ柇璧拌埅鏄惁缁忚繃鍏抽敭鍦烘櫙 + * @return 鍖呭惈璇︾粏淇℃伅鐨凪issionDetail瀵硅薄锛屽寘鎷細 + * - 浠诲姟鍩烘湰淇℃伅锛堢户鎵胯嚜Mission绫伙級 + * - 鍏抽敭鍦烘櫙鍒楄〃锛圱YPE19鍜孴YPE20绫诲瀷鐨勫満鏅級 + * - 鐜鍥犲瓙缁熻鏁版嵁锛堝钩鍧囧�笺�佹渶灏忓�笺�佹渶澶у�硷級 + * - 寮傚父鏁版嵁鐐规暟閲� + */ + fun generateMissionDetail( + keyScenes: List<SceneInfo?>, + mission: Mission, + pollutedClues: List<PollutedClue?>, + data: List<BaseRealTimeData>, + minDis:Double = 100.0 + ): MissionDetail { + // 鍒涘缓浠诲姟璇︽儏瀵硅薄骞跺鍒跺熀鏈俊鎭� + val missionDetail = MissionDetail() + BeanUtils.copyProperties(mission, missionDetail) + + // 鎻愬彇閫斿緞鍏抽敭鍦烘櫙淇℃伅锛堣绠楄蛋鑸矾绾挎槸鍚︿笌鍏抽敭鍦烘櫙璺濈杈冭繎锛� + val relatedScenes = mutableListOf<SceneInfo>() + data.forEach { d-> + // 璺宠繃缂哄皯缁忕含搴︾殑鏁版嵁鐐� + if (d.longitude == null || d.latitude == null) { + return@forEach + } + // 杞崲涓篏CJ02鍧愭爣绯� + val point = MapUtil.wgs84ToGcj02(d.longitude!!.toDouble() to d.latitude!!.toDouble()) + keyScenes.forEach ks@ { k-> + // 璺宠繃缂哄皯缁忕含搴︾殑鍦烘櫙 + if (k?.longitude == null || k.latitude == null) { + return@ks + } + // 璁$畻璺濈 + val distance = MapUtil.getDistance(k.longitude!!.toDouble(), k.latitude!!.toDouble(), point.first, point.second) + // 妫�鏌ユ槸鍚﹁窛绂诲皬浜庨槇鍊间笖鏈坊鍔犺繃 + if (distance < minDis && !relatedScenes.contains(k)) { + relatedScenes.add(k) + } + } + } + // 瀛樺偍涓庝换鍔$浉鍏宠仈鐨勫叧閿満鏅俊鎭� + missionDetail.keyScene = relatedScenes + + // 璁$畻鐜鍥犲瓙缁熻鏁版嵁锛堝钩鍧囧�笺�佹渶灏忓�笺�佹渶澶у�硷級 + missionDetail.dataStatistics = data.calDataStatistics() + + // 寮傚父鏁版嵁鐐规暟閲忕粺璁� + val clues = pollutedClues.filter { it?.msgType == MsgType.PolClue.value } + missionDetail.exceptionCount = clues.size + + return missionDetail } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionRiskArea.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionRiskArea.kt new file mode 100644 index 0000000..38eef5b --- /dev/null +++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionRiskArea.kt @@ -0,0 +1,86 @@ +package com.flightfeather.uav.biz.report + +import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue +import com.flightfeather.uav.common.utils.MapUtil +import com.flightfeather.uav.domain.entity.SceneInfo +import com.flightfeather.uav.domain.entity.avg +import com.flightfeather.uav.socket.eunm.AggregatedFactorType + +/** + * 璧拌埅鍏稿瀷闅愭偅鍖哄煙 + * @date 2025/8/25 14:18 + * @author feiyu + */ +class MissionRiskArea { + + class ClueByArea { + var sceneInfo: SceneInfo? = null + var clueByFactorList: MutableList<ClueByFactor>? = null + } + + class ClueByFactor { + var factor: String? = null + var clues: MutableList<PollutedClue>? = null + } + + fun generateClueByRiskArea(keyScenes: List<SceneInfo?>, pollutedClues: List<PollutedClue?>): List<ClueByArea> { + val result = mutableListOf<ClueByArea>() + + pollutedClues.forEach { pollutedClue -> + if (pollutedClue == null) return@forEach + val dataList = pollutedClue.pollutedData?.dataList ?: emptyList() + if (dataList.isEmpty()) return@forEach + + // 璁$畻鍗曚釜PollutedClue鐨勫潎鍊肩粡绾害 + val avgData = dataList.avg() + val wgs84Lng = avgData.longitude?.toDouble() ?: return@forEach + val wgs84Lat = avgData.latitude?.toDouble() ?: return@forEach + + // 鍧愭爣杞崲 + val gcj02Point = MapUtil.wgs84ToGcj02(wgs84Lng to wgs84Lat) + + // 鏌ユ壘鏈�杩戝満鏅� + var minDistance = Double.MAX_VALUE + var closestScene: SceneInfo? = null + keyScenes.forEach { scene -> + scene?.let { s -> + val sceneLng = s.longitude?.toDouble() ?: return@let + val sceneLat = s.latitude?.toDouble() ?: return@let + val distance = MapUtil.getDistance(gcj02Point.first, gcj02Point.second, sceneLng, sceneLat) + if (distance < minDistance) { + minDistance = distance + closestScene = s + } + } + } + + // 鎸夊満鏅拰鍥犲瓙鍒嗙粍绾跨储 + closestScene?.let { scene -> + var clueByArea = result.find { it.sceneInfo?.guid == scene.guid } + if (clueByArea == null) { + clueByArea = ClueByArea().apply { + this.sceneInfo = scene + this.clueByFactorList = mutableListOf() + } + result.add(clueByArea) + } + + val firstFactorType = pollutedClue.pollutedData?.statisticMap?.keys?.first() + val afType = AggregatedFactorType.getAFType(firstFactorType) + val factorName = afType?.des ?: firstFactorType?.des + var clueByFactor = clueByArea.clueByFactorList?.find { it.factor == factorName } + if (clueByFactor == null) { + clueByFactor = ClueByFactor().apply { + this.factor = factorName + this.clues = mutableListOf() + } + clueByArea.clueByFactorList?.add(clueByFactor) + } + + clueByFactor.clues?.add(pollutedClue) + } + } + + return result + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt index f33ac6f..53989b5 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt @@ -3,6 +3,7 @@ import com.flightfeather.uav.biz.dataprocess.AvgPair import com.flightfeather.uav.common.utils.DateUtil import com.flightfeather.uav.lightshare.bean.DataVo +import com.flightfeather.uav.lightshare.bean.FactorStatistics import com.flightfeather.uav.socket.bean.AirData import com.flightfeather.uav.socket.eunm.FactorType import java.io.Serializable @@ -146,7 +147,7 @@ } -fun List<BaseRealTimeData>.avg(): BaseRealTimeData { +fun List<BaseRealTimeData>.avg(onEach: (BaseRealTimeData) -> Unit = { }): BaseRealTimeData { if (isEmpty()) { return BaseRealTimeData() } @@ -162,8 +163,9 @@ } forEach { + onEach(it) //椋庡悜 - it.windDirection?.let {w -> + it.windDirection?.let { w -> val r = Math.toRadians(w.toDouble()) u += sin(r) v += cos(r) @@ -325,4 +327,67 @@ windDirection = round(a.toFloat()) } } +} + +/** + * 璁$畻瀹炴椂鐩戞祴鏁版嵁鍒楄〃鐨勭粺璁′俊鎭� + * 涓烘瘡绉嶇幆澧冨洜瀛愯绠楁渶灏忓�笺�佹渶澶у�煎拰骞冲潎鍊� + * + * @return 鍖呭惈鍚勭幆澧冨洜瀛愮粺璁′俊鎭殑FactorStatistics鍒楄〃 + * 姣忎釜FactorStatistics瀵硅薄鍖呭惈鍥犲瓙绫诲瀷銆佹渶灏忓�笺�佹渶澶у�煎拰骞冲潎鍊� + */ +fun List<BaseRealTimeData>.calDataStatistics(): List<FactorStatistics> { + + // 鍒濆鍖栧悇鐜鍥犲瓙鐨勭粺璁″璞″垪琛� + val statistics = mutableListOf<FactorStatistics>() + listOf( + FactorType.NO2, + FactorType.CO, + FactorType.H2S, + FactorType.SO2, + FactorType.O3, + FactorType.PM25, + FactorType.PM10, + FactorType.VOC, + FactorType.NOI, + FactorType.VELOCITY, + FactorType.WIND_SPEED, + FactorType.HEIGHT, + FactorType.NO + ).forEach { statistics.add(FactorStatistics(it)) } + + // 璁$畻骞冲潎鍊煎苟鍚屾椂鏇存柊鍚勫洜瀛愮殑鏈�灏忓�煎拰鏈�澶у�� + val avgData = avg { item -> + // 鏇存柊姣忎釜鍥犲瓙鐨勬渶灏忓拰鏈�澶у�� + statistics[0].updateMinAndMaxValue(item.no2) + statistics[1].updateMinAndMaxValue(item.co) + statistics[2].updateMinAndMaxValue(item.h2s) + statistics[3].updateMinAndMaxValue(item.so2) + statistics[4].updateMinAndMaxValue(item.o3) + statistics[5].updateMinAndMaxValue(item.pm25) + statistics[6].updateMinAndMaxValue(item.pm10) + statistics[7].updateMinAndMaxValue(item.voc) + statistics[8].updateMinAndMaxValue(item.noi) + statistics[9].updateMinAndMaxValue(item.velocity) + statistics[10].updateMinAndMaxValue(item.windSpeed) + statistics[11].updateMinAndMaxValue(item.height) + statistics[12].updateMinAndMaxValue(item.no) + } + + // 灏嗚绠楀緱鍒扮殑骞冲潎鍊艰缃埌瀵瑰簲鐨勭粺璁″璞′腑 + statistics[0].avgValue = avgData.no2 ?: 0f + statistics[1].avgValue = avgData.co ?: 0f + statistics[2].avgValue = avgData.h2s ?: 0f + statistics[3].avgValue = avgData.so2 ?: 0f + statistics[4].avgValue = avgData.o3 ?: 0f + statistics[5].avgValue = avgData.pm25 ?: 0f + statistics[6].avgValue = avgData.pm10 ?: 0f + statistics[7].avgValue = avgData.voc ?: 0f + statistics[8].avgValue = avgData.noi ?: 0f + statistics[9].avgValue = avgData.velocity ?: 0f + statistics[10].avgValue = avgData.windSpeed ?: 0f + statistics[11].avgValue = avgData.height ?: 0f + statistics[12].avgValue = avgData.no ?: 0f + + return statistics } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt index 15b6b78..e0f3799 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt @@ -7,9 +7,6 @@ import com.flightfeather.uav.socket.bean.AirData import com.flightfeather.uav.socket.eunm.FactorType import com.flightfeather.uav.socket.eunm.FactorType.* -import java.time.LocalDateTime -import java.time.ZoneId -import java.util.* import kotlin.math.atan import kotlin.math.cos import kotlin.math.round @@ -26,7 +23,7 @@ list.add("绾害") val values = GsonUtils.parserJsonToArrayBeans(factors, AirData::class.java) values.forEach { - if (FactorType.outputFactor(it.factorName)) { + if (FactorType.isOutputFactor(it.factorName)) { val name = it.factorName ?: "" list.add(name) // list.add("$name(鐗╃悊閲�)") @@ -51,7 +48,7 @@ } val values = GsonUtils.parserJsonToArrayBeans(factors, AirData::class.java) values.forEach { - if (FactorType.outputFactor(it.factorName)) { + if (FactorType.isOutputFactor(it.factorName)) { row.add(it.factorData ?: -1.0) // row.add(it.physicalQuantity ?: -1.0) } diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/Mission.java b/src/main/kotlin/com/flightfeather/uav/domain/entity/Mission.java index 68280ab..e4367b9 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/entity/Mission.java +++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/Mission.java @@ -63,6 +63,8 @@ @Column(name = "pollution_degree") private String pollutionDegree; + private Integer aqi; + /** * @return mission_code */ @@ -312,4 +314,18 @@ public void setPollutionDegree(String pollutionDegree) { this.pollutionDegree = pollutionDegree == null ? null : pollutionDegree.trim(); } + + /** + * @return aqi + */ + public Integer getAqi() { + return aqi; + } + + /** + * @param aqi + */ + public void setAqi(Integer aqi) { + this.aqi = aqi; + } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/MissionRep.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/MissionRep.kt index ce7cdec..164f303 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/repository/MissionRep.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/MissionRep.kt @@ -2,6 +2,7 @@ import com.flightfeather.uav.domain.entity.Mission import com.flightfeather.uav.domain.mapper.MissionMapper +import com.flightfeather.uav.lightshare.bean.AreaVo import org.springframework.stereotype.Repository import tk.mybatis.mapper.entity.Example import java.util.* @@ -44,4 +45,25 @@ .andIsNotNull("endTime") }) } + + /** + * 鏍规嵁鍖哄煙鍜屾椂闂磋寖鍥存煡璇㈡湁鏁堣蛋鑸换鍔″垪琛� + * 绛涢�夋寚瀹氳鏀垮尯鍒掑唴銆佺壒瀹氭椂闂存涓斿凡瀹屾垚鏈夋晥閲岀▼璁板綍鐨勮蛋鑸换鍔� + * @param areaVo 鍖哄煙鍙傛暟瀵硅薄锛屽寘鍚渷銆佸競銆佸尯涓夌骇琛屾斂鍖哄垝缂栫爜 + * @param startTime 鏌ヨ璧峰鏃堕棿锛堝寘鍚級 + * @param endTime 鏌ヨ缁撴潫鏃堕棿锛堝寘鍚級 + * @return 绗﹀悎鏉′欢鐨勮蛋鑸换鍔″垪琛紝鑻ユ棤鍙繑鍥炵┖鍒楄〃 + * @see AreaVo 鍖哄煙鍙傛暟鏁版嵁缁撴瀯 + * @see Mission 璧拌埅浠诲姟瀹炰綋绫� + */ + fun findByAreaAndTime(areaVo: AreaVo, startTime: Date, endTime: Date): List<Mission?> { + return missionMapper.selectByExample(Example(Mission::class.java).apply { + createCriteria().andBetween("startTime", startTime, endTime) + .andEqualTo("provinceCode", areaVo.provinceCode) + .andEqualTo("cityCode", areaVo.cityCode) + .andEqualTo("districtCode", areaVo.districtCode) + .andIsNotNull("kilometres") + .andNotEqualTo("kilometres", 0) + }) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/SceneInfoRep.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/SceneInfoRep.kt index e38cd28..e0e9729 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/repository/SceneInfoRep.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/SceneInfoRep.kt @@ -41,4 +41,13 @@ .andLessThanOrEqualTo("latitude", range[3]) }) } + + fun findBySceneTypes(sceneTypes: List<Int>): List<SceneInfo?> { + if (sceneTypes.isEmpty()){ + return emptyList() + } + return sceneInfoMapper.selectByExample(Example(SceneInfo::class.java).apply { + createCriteria().andIn("typeId", sceneTypes) + }) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt index b8c4c4c..23f46e0 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt @@ -99,9 +99,18 @@ return if (res.isEmpty()) null else res[0] } - fun fetchList(deviceCode: String, startTime: Date, endTime: Date): List<BaseExceptionResult?> { - return sourceTraceMsgBlobMapper.selectWithBlob(deviceCode, startTime, endTime) - .map { stm -> + fun fetchList( + deviceCode: String, + startTime: Date, + endTime: Date, + msgType: MsgType? = null, + ): List<BaseExceptionResult?> { + var res = sourceTraceMsgBlobMapper.selectWithBlob(deviceCode, startTime, endTime) + if (msgType !== null) { + res = res.filter { it?.msgType == msgType.value } + } + + return res.map { stm -> when (stm?.msgType) { MsgType.PolClue.value, MsgType.DataChange.value, diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt index b548bc7..65c0fab 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt @@ -42,7 +42,7 @@ row.add(lng ?: -1.0) row.add(lat ?: -1.0) values?.forEach { - if (FactorType.outputFactor(it.factorName)) { + if (FactorType.isOutputFactor(it.factorName)) { row.add(it.factorData ?: -1.0) // row.add(it.physicalQuantity ?: -1.0) } @@ -57,7 +57,7 @@ list.add("缁忓害") list.add("绾害") values?.forEach { - if (FactorType.outputFactor(it.factorName)) { + if (FactorType.isOutputFactor(it.factorName)) { val name = it.factorName ?: "" list.add(name) // list.add("$name(鐗╃悊閲�)") diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/FactorStatistics.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/FactorStatistics.kt index f81e97f..87f730e 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/FactorStatistics.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/FactorStatistics.kt @@ -9,11 +9,24 @@ */ data class FactorStatistics( // 鐩戞祴鍥犲瓙绫诲瀷 - val factor: FactorType, + var factor: FactorType, // 鏈�灏忓�� - val minValue: Double, + var minValue: Float = Float.NaN, // 鏈�澶у�� - val maxValue: Double, + var maxValue: Float = Float.NaN, // 鍧囧�� - val avgValue: Double -) \ No newline at end of file + var avgValue: Float = Float.NaN, +){ + fun updateMinAndMaxValue(value: Float?){ + minValue = if (minValue.isNaN()) { + value ?: Float.NaN + } else { + minValue.coerceAtMost(value ?: minValue) + } + maxValue = if (maxValue.isNaN()) { + value ?: Float.NaN + } else { + maxValue.coerceAtLeast(value ?: maxValue) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt index 594f4a7..15d6979 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt @@ -26,4 +26,5 @@ TYPE18(18, "鍟嗕笟浣�"), TYPE19(19, "鍥芥帶鐐�"), TYPE20(20, "甯傛帶鐐�"), + TYPE21(21, "灏忓井绔�"), } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt index 61683df..bb440bf 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt @@ -1,14 +1,21 @@ package com.flightfeather.uav.lightshare.service -import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult +import com.flightfeather.uav.biz.report.MissionInventory +import com.flightfeather.uav.biz.report.MissionInventory.MissionDetail +import com.flightfeather.uav.biz.report.MissionRiskArea import com.flightfeather.uav.biz.report.MissionSummary -import com.flightfeather.uav.biz.sourcetrace.model.BasePollutedMsg +import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue +import com.flightfeather.uav.domain.entity.BaseRealTimeData +import com.flightfeather.uav.domain.entity.Mission +import com.flightfeather.uav.domain.entity.SceneInfo import com.flightfeather.uav.lightshare.bean.AreaVo import java.util.* /** - * + * 鏁版嵁鍒嗘瀽鏈嶅姟鎺ュ彛 + * 鎻愪緵璧拌埅浠诲姟鏁版嵁鐨勭粺璁″垎鏋愩�佹薄鏌撴函婧愩�佷换鍔℃竻鍗曠敓鎴愮瓑鏍稿績鍔熻兘 + * 鐢ㄤ簬鏁村悎鍜屽鐞嗘棤浜烘満鐩戞祴鏁版嵁锛岀敓鎴愬悇绫诲垎鏋愭姤鍛婂拰缁熻缁撴灉 * @date 2025/5/8 * @author feiyu02 */ @@ -16,11 +23,68 @@ /** * 姹℃煋婧簮鍒嗘瀽 - * @param missionCode 璧拌埅浠诲姟缂栧彿 + * 鏍规嵁璧拌埅浠诲姟缂栧彿鍒嗘瀽姹℃煋绾跨储锛岃瘑鍒紓甯告暟鎹偣鍜屾綔鍦ㄦ薄鏌撴簮 + * @param missionCode 璧拌埅浠诲姟缂栧彿锛岀敤浜庡敮涓�鏍囪瘑鐗瑰畾鐨勮蛋鑸换鍔� + * @return 寮傚父缁撴灉鍒楄〃锛屾瘡涓厓绱犲寘鍚紓甯哥被鍨嬨�佷綅缃拰璇︾粏淇℃伅 */ fun pollutionTrace(missionCode: String): List<ExceptionResult> + /** + * 鑾峰彇鍘嗗彶姹℃煋婧簮缁撴灉 + * 鏍规嵁浠诲姟缂栧彿鏌ヨ骞惰繑鍥炲巻鍙叉薄鏌撴函婧愮粨鏋� + * @param missionCode 璧拌埅浠诲姟缂栧彿 + * @return 鍘嗗彶姹℃煋婧簮缁撴灉鐨勫瓧绗︿覆琛ㄧず锛堝叿浣撴牸寮忛渶鍙傝�冨疄鐜扮被锛� + */ fun fetchHistory(missionCode: String): String - fun missionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary + /** + * 鐢熸垚璧拌埅浠诲姟姹囨�荤粺璁� + * 鎸夋椂闂磋寖鍥村拰鍖哄煙缁熻璧拌埅浠诲姟鐨勫叧閿寚鏍囧拰鎬讳綋鎯呭喌 + * @param startTime 寮�濮嬫椂闂达紝鐢ㄤ簬绛涢�夋寚瀹氭椂闂存鍐呯殑浠诲姟 + * @param endTime 缁撴潫鏃堕棿锛岀敤浜庣瓫閫夋寚瀹氭椂闂存鍐呯殑浠诲姟 + * @param areaVo 鍖哄煙鍙傛暟锛屽寘鍚粡绾害鑼冨洿绛夊湴鐞嗕俊鎭� + * @return 姹囨�荤粺璁″璞★紝鍖呭惈浠诲姟鎬绘暟銆佸紓甯哥巼銆佸钩鍧囨暟鎹瓑鎸囨爣 + */ + fun generateMissionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary + + /** + * 鐢熸垚璧拌埅浠诲姟娓呭崟锛堟寜鏃堕棿鍜屽尯鍩熺瓫閫夛級 + * 鏍规嵁鏃堕棿鑼冨洿鍜屽湴鐞嗗尯鍩熸煡璇㈣蛋鑸换鍔★紝骞剁敓鎴愬寘鍚粺璁′俊鎭殑浠诲姟鍒楄〃 + * @param startTime 寮�濮嬫椂闂� + * @param endTime 缁撴潫鏃堕棿 + * @param areaVo 鍖哄煙鍙傛暟 + * @return 璧拌埅浠诲姟淇℃伅鍒楄〃锛屾瘡涓厓绱犲寘鍚换鍔″熀鏈俊鎭拰缁熻鏁版嵁 + */ + fun generateMissionList(startTime: Date, endTime: Date, areaVo: AreaVo): List<MissionInventory.MissionInfo> + + /** + * 鐢熸垚璧拌埅浠诲姟娓呭崟锛堢洿鎺ュ鐞嗕换鍔$嚎绱級 + * 澶勭悊宸叉湁鐨勮蛋鑸换鍔″拰姹℃煋绾跨储鏁版嵁锛岀敓鎴愪换鍔℃竻鍗� + * @param missionClues 鍖呭惈璧拌埅浠诲姟鍜屽搴旀薄鏌撶嚎绱㈢殑Pair鍒楄〃 + * @return 璧拌埅浠诲姟淇℃伅鍒楄〃 + */ + fun generateMissionList(missionClues: List<Pair<Mission, List<PollutedClue?>>>): List<MissionInventory.MissionInfo> + + /** + * 鑾峰彇璧拌埅浠诲姟璇︽儏锛堟寜鏃堕棿鍜屽尯鍩熺瓫閫夛級 + * 鏍规嵁鏃堕棿鑼冨洿鍜屽尯鍩熸煡璇㈠苟鐢熸垚璇︾粏鐨勪换鍔℃姤鍛婏紝鍖呭惈鍏抽敭鍦烘櫙鍜屾暟鎹粺璁� + * @param startTime 寮�濮嬫椂闂� + * @param endTime 缁撴潫鏃堕棿 + * @param areaVo 鍖哄煙鍙傛暟 + * @return 浠诲姟璇︽儏鍒楄〃锛屾瘡涓厓绱犲寘鍚换鍔″畬鏁翠俊鎭�佸満鏅暟鎹拰缁熻缁撴灉 + */ + fun generateMissionDetail(startTime: Date, endTime: Date, areaVo: AreaVo): List<MissionDetail> + + /** + * 鑾峰彇璧拌埅浠诲姟璇︽儏锛堢洿鎺ュ鐞嗕换鍔℃暟鎹級 + * 澶勭悊宸叉湁鐨勪换鍔°�佹薄鏌撶嚎绱㈠拰瀹炴椂鏁版嵁锛岀敓鎴愯缁嗕换鍔℃姤鍛� + * @param keyScenes 鍏抽敭鍦烘櫙鍒楄〃锛岀敤浜庡垎鏋愯蛋鑸槸鍚︾粡杩囪鍖哄煙 + * @param missionCluesData 鍖呭惈浠诲姟銆佹薄鏌撶嚎绱㈠拰瀹炴椂鏁版嵁鐨凾riple鍒楄〃 + * @return 浠诲姟璇︽儏鍒楄〃 + */ + fun generateMissionDetail(keyScenes: List<SceneInfo?>, missionCluesData: List<Triple<Mission, List<PollutedClue?>, List<BaseRealTimeData>>>): List<MissionDetail> + + fun generateClueByRiskArea(startTime: Date, endTime: Date, areaVo: AreaVo): List<MissionRiskArea.ClueByArea> + + fun generateClueByRiskArea(keyScenes: List<SceneInfo?>, pollutedClues: List<PollutedClue?>): List<MissionRiskArea.ClueByArea> } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt index 3982b5c..9826661 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt @@ -1,32 +1,33 @@ package com.flightfeather.uav.lightshare.service.impl import com.flightfeather.uav.biz.FactorFilter -import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult import com.flightfeather.uav.biz.dataanalysis.ExceptionAnalysisController import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult +import com.flightfeather.uav.biz.report.MissionInventory +import com.flightfeather.uav.biz.report.MissionRiskArea import com.flightfeather.uav.biz.report.MissionSummary -import com.flightfeather.uav.biz.sourcetrace.model.BasePollutedMsg import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue import com.flightfeather.uav.common.exception.BizException import com.flightfeather.uav.common.location.LocationRoadNearby import com.flightfeather.uav.common.utils.GsonUtils +import com.flightfeather.uav.domain.entity.BaseRealTimeData import com.flightfeather.uav.domain.entity.Mission +import com.flightfeather.uav.domain.entity.SceneInfo import com.flightfeather.uav.domain.mapper.MissionMapper -import com.flightfeather.uav.domain.repository.MissionRep -import com.flightfeather.uav.domain.repository.RealTimeDataRep -import com.flightfeather.uav.domain.repository.SegmentInfoRep -import com.flightfeather.uav.domain.repository.SourceTraceRep +import com.flightfeather.uav.domain.repository.* import com.flightfeather.uav.lightshare.bean.AreaVo +import com.flightfeather.uav.lightshare.eunm.SceneType import com.flightfeather.uav.lightshare.service.DataAnalysisService import com.flightfeather.uav.socket.eunm.FactorType +import com.flightfeather.uav.socket.sender.MsgType import org.springframework.stereotype.Service import tk.mybatis.mapper.entity.Example -import java.time.LocalDateTime -import java.time.ZoneId import java.util.* /** - * + * 鏁版嵁鍒嗘瀽鏈嶅姟鎺ュ彛瀹炵幇绫� + * 鎻愪緵璧拌埅浠诲姟鏁版嵁鐨勭粺璁″垎鏋愩�佹薄鏌撴函婧愩�佷换鍔℃竻鍗曞強璇︽儏鐢熸垚绛夋牳蹇冧笟鍔″姛鑳� + * 鏁村悎澶氭暟鎹簮瀹屾垚鏁版嵁鑱氬悎涓庡垎鏋愶紝涓哄墠绔彁渚涙爣鍑嗗寲鐨勭粺璁$粨鏋� * @date 2025/5/8 * @author feiyu02 */ @@ -37,9 +38,18 @@ private val realTimeDataRep: RealTimeDataRep, private val locationRoadNearby: LocationRoadNearby, private val segmentInfoRep: SegmentInfoRep, - private val sourceTraceRep: SourceTraceRep + private val sourceTraceRep: SourceTraceRep, + private val sceneInfoRep: SceneInfoRep ) : DataAnalysisService { + /** + * 姹℃煋婧簮鍒嗘瀽 + * 瀵规寚瀹氳蛋鑸换鍔¤繘琛屽鍥犲瓙姹℃煋鏁版嵁鍒嗘瀽锛岃瘑鍒紓甯告暟鎹偣鍜屾綔鍦ㄦ薄鏌撴簮 + * @param missionCode 璧拌埅浠诲姟缂栫爜锛堜富閿級 + * @return 寮傚父缁撴灉鍒楄〃锛屽寘鍚紓甯哥被鍨嬨�佷綅缃�佹祿搴﹀�肩瓑璇︾粏淇℃伅 + * @throws BizException 褰撹蛋鑸换鍔′笉瀛樺湪鏃舵姏鍑� + * @see ExceptionAnalysisController 寮傚父鍒嗘瀽鎺у埗鍣紝澶勭悊鍏蜂綋鐨勬暟鎹垎鏋愰�昏緫 + */ override fun pollutionTrace(missionCode: String): List<ExceptionResult> { val mission = missionRep.findOne(missionCode) ?: throw BizException("璧拌埅浠诲姟涓嶅瓨鍦�") @@ -60,6 +70,13 @@ ) } + /** + * 鑾峰彇鍘嗗彶姹℃煋婧簮缁撴灉 + * 鏌ヨ鎸囧畾浠诲姟鐨勫巻鍙叉薄鏌撴函婧愮粨鏋滃苟搴忓垪鍖栦负JSON瀛楃涓� + * @param missionCode 璧拌埅浠诲姟缂栫爜 + * @return 鍘嗗彶姹℃煋婧簮缁撴灉鐨凧SON瀛楃涓诧紝鍏蜂綋鏍煎紡鐢眘ourceTraceRep瀹炵幇鍐冲畾 + * @throws BizException 褰撹蛋鑸换鍔′笉瀛樺湪鏃舵姏鍑� + */ override fun fetchHistory(missionCode: String): String { val mission = missionRep.findOne(missionCode) ?: throw BizException("璧拌埅浠诲姟涓嶅瓨鍦�") @@ -67,21 +84,124 @@ return GsonUtils.gson.toJson(res) } - override fun missionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary { + /** + * 鐢熸垚璧拌埅浠诲姟姹囨�荤粺璁� + * 鎸夋椂闂磋寖鍥村拰琛屾斂鍖哄垝缁熻璧拌埅浠诲姟鐨勫叧閿寚鏍囷紙浠诲姟鏁伴噺銆佸紓甯哥巼銆佸钩鍧囬噷绋嬬瓑锛� + * @param startTime 缁熻璧峰鏃堕棿锛堝寘鍚級 + * @param endTime 缁熻缁撴潫鏃堕棿锛堝寘鍚級 + * @param areaVo 鍖哄煙鍙傛暟锛屽寘鍚渷銆佸競銆佸尯涓夌骇琛屾斂鍖哄垝缂栫爜 + * @return 姹囨�荤粺璁″璞★紝鍖呭惈浠诲姟鎬绘暟銆佸紓甯哥偣鏁伴噺銆佸钩鍧囬噷绋嬬瓑鏍稿績鎸囨爣 + * @see MissionSummary 姹囨�荤粺璁″鐞嗗櫒锛屽皝瑁呭叿浣撶殑缁熻閫昏緫瀹炵幇 + */ + override fun generateMissionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary { val clues = mutableListOf<PollutedClue?>() - val missions = missionMapper.selectByExample(Example(Mission::class.java).apply { - createCriteria().andBetween("startTime", startTime, endTime) - .andEqualTo("provinceCode", areaVo.provinceCode) - .andEqualTo("cityCode", areaVo.cityCode) - .andEqualTo("districtCode", areaVo.districtCode) - .andIsNotNull("kilometres") - .andNotEqualTo("kilometres", 0) - }).onEach { + val missions = missionRep.findByAreaAndTime(areaVo, startTime, endTime).onEach { it ?: return@onEach - val clue = sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime).filterIsInstance<PollutedClue?>() + val clue = sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime, MsgType.PolClue) as List<PollutedClue?> clues.addAll(clue) } val summary = MissionSummary().execute(startTime, endTime, missions, clues) return summary } + + /** + * 鐢熸垚璧拌埅浠诲姟娓呭崟锛堟寜鏃堕棿鍜屽尯鍩熺瓫閫夛級 + * 鏍规嵁鏃堕棿鑼冨洿鍜岃鏀垮尯鍒掓煡璇㈣蛋鑸换鍔★紝骞跺叧鑱旀薄鏌撶嚎绱㈡暟鎹敓鎴愪换鍔″垪琛� + * @param startTime 鏌ヨ璧峰鏃堕棿锛堝寘鍚級 + * @param endTime 鏌ヨ缁撴潫鏃堕棿锛堝寘鍚級 + * @param areaVo 鍖哄煙鍙傛暟锛屽寘鍚渷銆佸競銆佸尯缂栫爜 + * @return 璧拌埅浠诲姟淇℃伅鍒楄〃锛屾瘡涓厓绱犲寘鍚换鍔″熀鏈俊鎭拰鍏宠仈鐨勬薄鏌撶嚎绱� + * @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) + } + + /** + * 鐢熸垚璧拌埅浠诲姟娓呭崟锛堢洿鎺ュ鐞嗕换鍔℃暟鎹級 + * 鎺ユ敹宸插叧鑱旂殑浠诲姟-姹℃煋绾跨储鏁版嵁瀵癸紝鐢熸垚鏍煎紡鍖栫殑浠诲姟鍒楄〃 + * @param missionClues 浠诲姟-姹℃煋绾跨储鏁版嵁瀵瑰垪琛紝Pair.first涓轰换鍔″璞★紝Pair.second涓哄搴旀薄鏌撶嚎绱� + * @return 鏍囧噯鍖栫殑璧拌埅浠诲姟淇℃伅鍒楄〃锛屽寘鍚换鍔″熀鏈睘鎬у拰姹℃煋缁熻淇℃伅 + * @see MissionInventory 浠诲姟娓呭崟鐢熸垚鍣紝灏佽鍏蜂綋鏍煎紡鍖栭�昏緫 + */ + override fun generateMissionList(missionClues: List<Pair<Mission, List<PollutedClue?>>>): List<MissionInventory.MissionInfo> { + return MissionInventory().generateMissionList(missionClues) + } + + /** + * 鐢熸垚璧拌埅浠诲姟璇︽儏锛堟寜鏃堕棿鍜屽尯鍩熺瓫閫夛級 + * 鏍规嵁鏃堕棿鑼冨洿鍜岃鏀垮尯鍒掓煡璇换鍔★紝鏁村悎瀹炴椂鐩戞祴鏁版嵁鐢熸垚璇︾粏浠诲姟鎶ュ憡 + * @param startTime 鏌ヨ璧峰鏃堕棿锛堝寘鍚級 + * @param endTime 鏌ヨ缁撴潫鏃堕棿锛堝寘鍚級 + * @param areaVo 鍖哄煙鍙傛暟锛屽寘鍚渷銆佸競銆佸尯缂栫爜 + * @return 浠诲姟璇︽儏鍒楄〃锛屾瘡涓厓绱犲寘鍚换鍔″畬鏁翠俊鎭�佹薄鏌撶嚎绱㈠強瀹炴椂鐩戞祴鏁版嵁 + * @see MissionRep.findByAreaAndTime 鍖哄煙鏃堕棿绛涢�夋暟鎹簮 + * @see realTimeDataRep.fetchData 瀹炴椂鏁版嵁鑾峰彇鎺ュ彛 + */ + override fun generateMissionDetail(startTime: Date, endTime: Date, areaVo: AreaVo): 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 keyScenes = sceneInfoRep.findBySceneTypes( + listOf( + SceneType.TYPE19.value, + SceneType.TYPE20.value, + SceneType.TYPE21.value + ) + ) + return generateMissionDetail(keyScenes, missionCluesData) + } + + /** + * 鐢熸垚璧拌埅浠诲姟璇︽儏锛堢洿鎺ュ鐞嗕换鍔℃暟鎹級 + * 鎺ユ敹宸插叧鑱旂殑浠诲姟-姹℃煋绾跨储-瀹炴椂鏁版嵁涓夊厓缁勶紝鐢熸垚璇︾粏浠诲姟鎶ュ憡 + * @param keyScenes 鍏抽敭鍦烘櫙鍒楄〃锛岀敤浜庡垎鏋愯蛋鑸槸鍚︾粡杩囪鍖哄煙 + * @param missionCluesData 浠诲姟鏁版嵁涓夊厓缁勫垪琛紝Triple鍒嗗埆涓轰换鍔″璞°�佹薄鏌撶嚎绱㈠垪琛ㄣ�佸疄鏃舵暟鎹垪琛� + * @return 鏍囧噯鍖栫殑浠诲姟璇︽儏鍒楄〃锛屽寘鍚畬鏁寸殑浠诲姟灞炴�с�佹薄鏌撳垎鏋愬拰鐩戞祴鏁版嵁缁熻 + * @see MissionInventory.generateMissionDetail 璇︽儏鐢熸垚鏍稿績閫昏緫 + */ + override fun generateMissionDetail( + keyScenes: List<SceneInfo?>, + missionCluesData: List<Triple<Mission, List<PollutedClue?>, List<BaseRealTimeData>>>, + ): List<MissionInventory.MissionDetail> { + return missionCluesData.map { + MissionInventory().generateMissionDetail(keyScenes, it.first, it.second, it.third) + } + } + + override fun generateClueByRiskArea( + startTime: Date, + endTime: Date, + areaVo: AreaVo, + ): List<MissionRiskArea.ClueByArea> { + 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?> + clues.addAll(clue) + } + val keyScenes = sceneInfoRep.findBySceneTypes( + listOf( + SceneType.TYPE19.value, + SceneType.TYPE20.value, + SceneType.TYPE21.value + ) + ) + return generateClueByRiskArea(keyScenes, clues) + } + + override fun generateClueByRiskArea( + keyScenes: List<SceneInfo?>, + pollutedClues: List<PollutedClue?>, + ): List<MissionRiskArea.ClueByArea> { + return MissionRiskArea().generateClueByRiskArea(keyScenes, pollutedClues) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/web/DataAnalysisController.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/web/DataAnalysisController.kt index 67634b9..f1f7957 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/web/DataAnalysisController.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/web/DataAnalysisController.kt @@ -1,11 +1,14 @@ package com.flightfeather.uav.lightshare.web +import com.fasterxml.jackson.annotation.JsonFormat import com.flightfeather.uav.lightshare.bean.AreaVo import com.flightfeather.uav.lightshare.service.DataAnalysisService import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam +import org.springframework.format.annotation.DateTimeFormat import org.springframework.web.bind.annotation.* +import java.util.* /** * 璧拌埅鏁版嵁鍒嗘瀽 @@ -31,4 +34,59 @@ @ApiParam("璧拌埅浠诲姟缂栧彿") @RequestParam missionCode: String, ) = resPack { dataAnalysisService.fetchHistory(missionCode) } + @ApiOperation(value = "鐢熸垚璧拌埅浠诲姟姹囨�荤粺璁�") + @PostMapping("/report/missionSummary") + fun generateMissionSummary( + @ApiParam("寮�濮嬫椂闂�") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + startTime: Date, + @ApiParam("缁撴潫鏃堕棿") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + endTime: Date, + @ApiParam("鍖哄煙") @RequestBody areaVo: AreaVo, + ) = resPack { dataAnalysisService.generateMissionSummary(startTime, endTime, areaVo) } + + @ApiOperation(value = "鐢熸垚璧拌埅浠诲姟娓呭崟") + @PostMapping("/report/missionList") + fun generateMissionList( + @ApiParam("寮�濮嬫椂闂�") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + startTime: Date, + @ApiParam("缁撴潫鏃堕棿") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + endTime: Date, + @ApiParam("鍖哄煙") @RequestBody areaVo: AreaVo, + ) = resPack { dataAnalysisService.generateMissionList(startTime, endTime, areaVo) } + + @ApiOperation(value = "鐢熸垚璧拌埅浠诲姟璇︽儏") + @PostMapping("/report/missionDetail") + fun generateMissionDetail( + @ApiParam("寮�濮嬫椂闂�") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + startTime: Date, + @ApiParam("缁撴潫鏃堕棿") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + endTime: Date, + @ApiParam("鍖哄煙") @RequestBody areaVo: AreaVo, + ) = resPack { dataAnalysisService.generateMissionDetail(startTime, endTime, areaVo) } + + @ApiOperation(value = "璧拌埅鍏稿瀷闅愭偅鍖哄煙缁熻") + @PostMapping("/report/clueByRiskArea") + fun generateClueByRiskArea( + @ApiParam("寮�濮嬫椂闂�") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + startTime: Date, + @ApiParam("缁撴潫鏃堕棿") @RequestParam + @JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss") + @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") + endTime: Date, + @ApiParam("鍖哄煙") @RequestBody areaVo: AreaVo, + ) = resPack { dataAnalysisService.generateClueByRiskArea(startTime, endTime, areaVo) } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/socket/eunm/AggregatedFactorType.kt b/src/main/kotlin/com/flightfeather/uav/socket/eunm/AggregatedFactorType.kt new file mode 100644 index 0000000..bce6c3e --- /dev/null +++ b/src/main/kotlin/com/flightfeather/uav/socket/eunm/AggregatedFactorType.kt @@ -0,0 +1,24 @@ +package com.flightfeather.uav.socket.eunm + +/** + * 鑱氬悎鐩戞祴鍥犲瓙 + * @date 2025/8/29 + * @author feiyu02 + */ +enum class AggregatedFactorType(val des: String) { + PM_AF("棰楃矑鐗�(PM)"), + NO_AF("姘哀鍖栫墿"); + + companion object { + /** + * 鏍规嵁鍥犲瓙绫诲瀷鑾峰彇鑱氬悎鍥犲瓙绫诲瀷 + */ + fun getAFType(factorType: FactorType?): AggregatedFactorType? { + return when (factorType) { + FactorType.PM25, FactorType.PM10 -> PM_AF + FactorType.NO, FactorType.NO2 -> NO_AF + else -> null + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/socket/eunm/FactorType.kt b/src/main/kotlin/com/flightfeather/uav/socket/eunm/FactorType.kt index bd019b6..cd76007 100644 --- a/src/main/kotlin/com/flightfeather/uav/socket/eunm/FactorType.kt +++ b/src/main/kotlin/com/flightfeather/uav/socket/eunm/FactorType.kt @@ -174,7 +174,7 @@ else -> 10.0 } - fun outputFactor(factorName: String?): Boolean { + fun isOutputFactor(factorName: String?): Boolean { return when (factorName) { NO2.des, CO.des, diff --git a/src/main/resources/generator/generatorConfig.xml b/src/main/resources/generator/generatorConfig.xml index 50c00e3..df72831 100644 --- a/src/main/resources/generator/generatorConfig.xml +++ b/src/main/resources/generator/generatorConfig.xml @@ -4,8 +4,8 @@ "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- 鏁版嵁搴撻┍鍔�:閫夋嫨浣犵殑鏈湴纭洏涓婇潰鐨勬暟鎹簱椹卞姩鍖�--> - <classPathEntry location="C:\Users\feiyu\.m2\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar"/> -<!-- <classPathEntry location="C:\Users\feiyu02\.m2\repository\mysql\mysql-connector-java\8.0.21\mysql-connector-java-8.0.21.jar"/>--> +<!-- <classPathEntry location="C:\Users\feiyu\.m2\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar"/>--> + <classPathEntry location="C:\Users\feiyu02\.m2\repository\mysql\mysql-connector-java\8.0.21\mysql-connector-java-8.0.21.jar"/> <!--defaultModelType{ conditional:杩欎釜妯″瀷涓巋ierarchical妯″瀷鐩镐技,闄や簡濡傛灉涓�涓疄浣撶被鍙寘鍚竴涓瓧娈�,鍒欎笉浼氬崟鐙敓鎴愭瀹炰綋绫汇�傚洜姝�,濡傛灉涓�涓〃鐨勪富閿彧鏈変竴涓瓧娈�,閭d箞涓嶄細涓鸿瀛楁鐢熸垚鍗曠嫭鐨勫疄浣撶被,浼氬皢璇ュ瓧娈靛悎骞跺埌鍩烘湰瀹炰綋绫讳腑銆� flat:璇ユā鍨嬩负姣忎竴寮犺〃鍙敓鎴愪竴涓疄浣撶被銆傝繖涓疄浣撶被鍖呭惈琛ㄤ腑鐨勬墍鏈夊瓧娈点�� diff --git a/src/main/resources/mapper/MissionMapper.xml b/src/main/resources/mapper/MissionMapper.xml index 3a44488..0a10c92 100644 --- a/src/main/resources/mapper/MissionMapper.xml +++ b/src/main/resources/mapper/MissionMapper.xml @@ -22,6 +22,7 @@ <result column="kilometres" jdbcType="REAL" property="kilometres" /> <result column="region" jdbcType="VARCHAR" property="region" /> <result column="pollution_degree" jdbcType="VARCHAR" property="pollutionDegree" /> + <result column="aqi" jdbcType="INTEGER" property="aqi" /> </resultMap> <sql id="Base_Column_List"> <!-- @@ -29,6 +30,6 @@ --> mission_code, device_type, device_code, start_time, end_time, data_pulled, province_code, province_name, city_code, city_name, district_code, district_name, town_code, town_name, - kilometres, region, pollution_degree + kilometres, region, pollution_degree, aqi </sql> </mapper> \ No newline at end of file diff --git a/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt index 398bd1e..3a11591 100644 --- a/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt +++ b/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt @@ -1,7 +1,5 @@ package com.flightfeather.uav.biz.report -import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue -import com.flightfeather.uav.domain.entity.Mission import com.flightfeather.uav.domain.mapper.MissionMapper import com.flightfeather.uav.domain.repository.SourceTraceRep import com.flightfeather.uav.lightshare.bean.AreaVo @@ -11,10 +9,8 @@ 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 import java.time.LocalDateTime import java.time.ZoneId -import java.time.ZoneOffset import java.util.Date @RunWith(SpringRunner::class) @@ -36,7 +32,7 @@ fun testMissionSummary() { val startTime = Date.from(LocalDateTime.of(2025,7,1,0,0,0).atZone(ZoneId.systemDefault()).toInstant()) val endTime = Date.from(LocalDateTime.of(2025, 9, 30, 23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()) - val summary = dataAnalysisService.missionSummary(startTime, endTime, AreaVo().apply { + val summary = dataAnalysisService.generateMissionSummary(startTime, endTime, AreaVo().apply { provinceCode = "31" cityCode = "3100" districtCode = "310106" diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImplTest.kt index c9c3b1a..ddb0aeb 100644 --- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImplTest.kt +++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImplTest.kt @@ -1,5 +1,6 @@ package com.flightfeather.uav.lightshare.service.impl +import com.flightfeather.uav.lightshare.bean.AreaVo import com.flightfeather.uav.lightshare.service.DataAnalysisService import junit.framework.TestCase import org.junit.Test @@ -7,6 +8,9 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.junit4.SpringRunner +import java.time.LocalDateTime +import java.time.ZoneId +import java.util.* @RunWith(SpringRunner::class) @SpringBootTest @@ -14,6 +18,14 @@ @Autowired lateinit var dataAnalysisService: DataAnalysisService + + val startTime = Date.from(LocalDateTime.of(2025,7,1,0,0,0).atZone(ZoneId.systemDefault()).toInstant()) + val endTime = Date.from(LocalDateTime.of(2025, 9, 30, 23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()) + val areaVo = AreaVo().apply { + provinceCode = "31" + cityCode = "3100" + districtCode = "310106" + } @Test fun testPollutionTrace() { @@ -24,4 +36,22 @@ fun fetchHistory() { dataAnalysisService.fetchHistory("SH-CN-20250723(01)") } + + @Test + fun generateMissionList() { + val res = dataAnalysisService.generateMissionList(startTime, endTime, areaVo) + println(res) + } + + @Test + fun generateMissionDetail() { + val res = dataAnalysisService.generateMissionDetail(startTime, endTime, areaVo) + println(res) + } + + @Test + fun generateClueByRiskArea() { + val res = dataAnalysisService.generateClueByRiskArea(startTime, endTime, areaVo) + println(res) + } } \ No newline at end of file -- Gitblit v1.9.3