| | |
| | | /** |
| | | * çæä¸æ¡å¼å¸¸åæç»æ |
| | | */ |
| | | abstract fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | ): Y |
| | | // abstract fun newResult( |
| | | // start: BaseRealTimeData, |
| | | // end: BaseRealTimeData?, |
| | | // factor: FactorFilter.SelectedFactor, |
| | | // exceptionData: List<BaseRealTimeData>, |
| | | // ): Y |
| | | } |
| | |
| | | /** |
| | | * ç«å³å¤æï¼å½åºç°å¼å¸¸æ¶ï¼ç¼åå¼å¸¸æ°æ®çåæ¶ï¼ç«å³å¯¹å·²æå¼å¸¸è¿è¡å¤ææ¯å¦æ»¡è¶³å¼å¸¸ç»æè¦æ± |
| | | */ |
| | | open fun immeExcCheck(tag: T): Boolean { |
| | | open fun immeExcCheck(tag: T, factorType: FactorType): Boolean { |
| | | return false |
| | | } |
| | | |
| | |
| | | * 夿å¼å¸¸åºç°çè¿ç»ä¸ªæ°æ¯å¦æ»¡è¶³æ¡ä»¶ |
| | | * @param tag å¼å¸¸æ°æ®å¯¹è±¡ |
| | | */ |
| | | abstract fun judgeExceptionCount(tag: T): Boolean |
| | | abstract fun judgeExceptionCount(tag: T, factorType: FactorType?): Boolean |
| | | |
| | | /** |
| | | * å¼å¸¸æ°æ®çæªå夿 |
| | | * @return é»è®¤ä¸éè¦æªå |
| | | * @return |
| | | */ |
| | | open fun needCut(tag: T, hasException: Boolean?): Boolean { |
| | | // é»è®¤å¤ææ¡ä»¶ä¸º å½å¼å¸¸ä¸åéå¤åºç°æ¶ï¼å½¢æå¼å¸¸ç»æ |
| | |
| | | config.factorFilter.selectedList.forEach { s -> |
| | | val f = s.main |
| | | tagMap[f]?.let { |
| | | it.addHistoryData(data) |
| | | |
| | | it.eIndex++ |
| | | // èµ·å§æ°æ® |
| | | it.endData = data |
| | |
| | | // æå¼å¸¸åºç°æ¶ï¼è®°å½å¼å¸¸æ°æ® |
| | | it.addExceptionData(data) |
| | | // å½ç«å³å¤æéè¿æ¶ï¼å½¢æå¼å¸¸ç»æ |
| | | if (immeExcCheck(it)) { |
| | | if (immeExcCheck(it, f)) { |
| | | recordException(s, it, data) |
| | | } |
| | | } |
| | |
| | | ) { |
| | | val tag = tagMap[factor?.main] |
| | | if (factor != null && tag != null) { |
| | | if (tag.exceptionExisted && judgeExceptionCount(tag)) { |
| | | if (tag.exceptionExisted && judgeExceptionCount(tag, factor.main)) { |
| | | onNewException(tag, factor, exceptionStatus) |
| | | } |
| | | } else { |
| | | config.factorFilter.selectedList.forEach { f -> |
| | | val tag1 = tagMap[f.main] ?: return@forEach |
| | | if (tag1.exceptionExisted && judgeExceptionCount(tag1)) { |
| | | if (tag1.exceptionExisted && judgeExceptionCount(tag1, null)) { |
| | | onNewException(tag1, f, exceptionStatus) |
| | | } |
| | | } |
| | |
| | | */ |
| | | open fun onNewException(tag: T, factor: FactorFilter.SelectedFactor, exceptionStatus: ExceptionStatusType) { |
| | | if (tag.startData == null) return |
| | | val ex = newResult(tag.startData!!, tag.endData, factor, tag.exceptionData) |
| | | // val ex = newResult(tag.startData!!, tag.endData, factor, tag.exceptionData) |
| | | val ex = newResult(tag, factor) |
| | | .apply { status = exceptionStatus.value } |
| | | // å¼å¸¸å·²å建æ¶ï¼æ´æ°å¼å¸¸ä¿¡æ¯ |
| | | if (tag.exceptionCreated) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * çæä¸æ¡å¼å¸¸åæç»æ |
| | | */ |
| | | abstract fun newResult(tag:T, factor: FactorFilter.SelectedFactor): Y |
| | | |
| | | } |
| | |
| | | abstract class ExceptionContinuous(config: DataAnalysisConfig) : |
| | | BaseExceptionContinuous<ExceptionTag, DataAnalysisConfig, ExceptionResult>(config, ExceptionTag::class.java) { |
| | | |
| | | override fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | ): ExceptionResult { |
| | | override fun newResult(tag:ExceptionTag, factor: FactorFilter.SelectedFactor): ExceptionResult { |
| | | val eType = getExceptionType() |
| | | return ExceptionResult(start, end, factor, exceptionData, config.mission.missionCode, eType) |
| | | return ExceptionResult(tag.startData!!, tag.endData, factor, tag.exceptionData, config.mission.missionCode, |
| | | eType) |
| | | } |
| | | } |
| | |
| | | return res |
| | | } |
| | | |
| | | override fun judgeExceptionCount(tag: ExceptionTag): Boolean { |
| | | override fun judgeExceptionCount(tag: ExceptionTag, factorType: FactorType?): Boolean { |
| | | return true |
| | | } |
| | | |
| | | override fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | ): ExceptionResult { |
| | | override fun newResult(tag: ExceptionTag, factor: FactorFilter.SelectedFactor): ExceptionResult { |
| | | val eType = getExceptionType() |
| | | return ExceptionResult(start, end, factor, exceptionData, config.mission.missionCode, eType) |
| | | return ExceptionResult(tag.startData!!, tag.endData, factor, tag.exceptionData, config.mission.missionCode, |
| | | eType) |
| | | } |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | override fun newResult( |
| | | |
| | | |
| | | fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | |
| | | return res |
| | | } |
| | | |
| | | override fun judgeExceptionCount(tag: ExceptionTag): Boolean { |
| | | override fun judgeExceptionCount(tag: ExceptionTag, factorType: FactorType?): Boolean { |
| | | // é¦ä¸ªæ°æ®æ²¡æåä¸ä¸ªæ°æ®åç
§ï¼ä¸ç®å¼å¸¸å¼ï¼æåä¸ä¸ªæ°æ®æ¯å¤æç»æçæ£å¸¸å¼ï¼å æ¤å¼å¸¸æ°æ®ä¸ªæ°ç计ç®ä¸æ 为sIndexåeIndex |
| | | val sIndex = tag.sIndex |
| | | val eIndex = tag.eIndex - 1 |
| | |
| | | // å¼å¸¸æ°æ®æ®µ |
| | | var exceptionData = mutableListOf<BaseRealTimeData>() |
| | | |
| | | // è¿æ®µæ¶é´å
çå岿°æ® |
| | | var historyData = mutableListOf<BaseRealTimeData>() |
| | | |
| | | // æ¯å¦åå¨å¼å¸¸ |
| | | var exceptionExisted = false |
| | | |
| | |
| | | |
| | | var exceptionResult = mutableListOf<BaseExceptionResult>() |
| | | |
| | | fun addHistoryData(data: BaseRealTimeData) { |
| | | historyData.add(data) |
| | | if (historyData.size > 20) { |
| | | historyData.removeAt(0) |
| | | } |
| | | } |
| | | |
| | | fun addExceptionData(data: BaseRealTimeData){ |
| | | exceptionExisted = true |
| | | exceptionData.add(data) |
| | |
| | | TYPE6(6, "忥è¶
æ æ¬¡æ°ä¸´è¿å¤ç½å¼å¸¸"), |
| | | TYPE7(7, "æ»å¨å¹³åå¼çªåå¼å¸¸"), |
| | | TYPE8(8, "ææçå¼å¸¸"), |
| | | TYPE9(9, "ååéçå¼å¸¸"), |
| | | } |
| | |
| | | else |
| | | RTExcWindLevelConfig( |
| | | FactorFilter.builder() |
| | | // .withMain(FactorType.NO2) |
| | | .withMain(FactorType.CO) |
| | | // .withMain(FactorType.H2S) |
| | | // .withMain(FactorType.SO2) |
| | | // .withMain(FactorType.O3) |
| | | // .withMain(FactorType.NO2) |
| | | // .withMain(FactorType.CO) |
| | | // .withMain(FactorType.H2S) |
| | | // .withMain(FactorType.SO2) |
| | | // .withMain(FactorType.O3) |
| | | .withMain(FactorType.PM25) |
| | | .withMain(FactorType.PM10) |
| | | .withMain(FactorType.VOC) |
| | | .create() |
| | | ) |
| | | pollutedSummary = PollutedSummary(config){ summaryCallback(it)} |
| | | pollutedSummary = PollutedSummary(config) { summaryCallback(it) } |
| | | newTask() |
| | | } |
| | | |
| | | constructor(sceneInfoRep: SceneInfoRep) : this(sceneInfoRep, null) |
| | | |
| | | private val pollutedSummary:PollutedSummary |
| | | private val pollutedSummary: PollutedSummary |
| | | |
| | | private val sceneInfoRep: SceneInfoRep |
| | | |
| | |
| | | add(RTExcWindLevel1_1(config) { exceptionCallback(it) }.also { it.init() }) |
| | | add(RTExcWindLevel4(config) { exceptionCallback(it) }.also { it.init() }) |
| | | add(RTExcWindLevel6(config) { exceptionCallback(it) }.also { it.init() }) |
| | | add(RTExcChangeRate(config) { exceptionCallback(it) }.also { it.init() }) |
| | | } |
| | | } |
| | | |
| | |
| | | // æº¯æºæ±¡ææºä¿¡æ¯ |
| | | ex.searchScenes(sceneInfoRep) |
| | | |
| | | // è®°å½æ±¡æçº¿ç´¢ |
| | | pollutedSummary.addClue(ex) |
| | | |
| | | // å¹¿ææ±¡ææº¯æºå¼å¸¸ç»æ |
| | | UnderwayWebSocketSender.broadcast(MsgType.PolClue.value, ex) |
| | | |
| | | // è®°å½æ±¡æçº¿ç´¢ |
| | | pollutedSummary.addClue(ex) |
| | | } |
| | | |
| | | private fun summaryCallback(ex: PollutedSummary.AnalysisResult) { |
| | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.BaseAnalysisConfig |
| | | import com.flightfeather.uav.biz.sourcetrace.model.DistanceType |
| | | import com.flightfeather.uav.socket.eunm.FactorType |
| | | |
| | | /** |
| | | * |
| | |
| | | var distanceLimit = 3000 |
| | | // é宿¶é´å
ï¼åä½ï¼åéï¼ |
| | | var timeLimit = 3 |
| | | // æº¯æºæ©æ£åç§»è§åº¦ï¼åä½ï¼åº¦ï¼ |
| | | var sourceTraceDegOffset = 60.0 |
| | | // 宿¶çº¿ç´¢åææ¶é´é´é(åä½ï¼åé) |
| | | var analysisPeriod = 15 |
| | | // 宿¶åæé´éä¸ï¼ç«å³è¿è¡çº¿ç´¢åæçæå°çº¿ç´¢é(åä½ï¼ä¸ª) |
| | | var analysisCount = 4 |
| | | |
| | | /****æ°æ®çªå*****************************************************************************/ |
| | | // 0 - 1çº§é£ |
| | | var windLevelCondition1 = WindLevelCondition( |
| | | .0 to 1.5, |
| | |
| | | 3 |
| | | ) |
| | | |
| | | // æº¯æºæ©æ£åç§»è§åº¦ï¼åä½ï¼åº¦ï¼ |
| | | var sourceTraceDegOffset = 120.0 |
| | | |
| | | // 宿¶çº¿ç´¢åææ¶é´é´é(åä½ï¼åé) |
| | | var analysisPeriod = 15 |
| | | // 宿¶åæé´éä¸ï¼ç«å³è¿è¡çº¿ç´¢åæçæå°çº¿ç´¢é(åä½ï¼ä¸ª) |
| | | var analysisCount = 2 |
| | | |
| | | |
| | | |
| | | // // 0 - 1çº§é£ |
| | | // var windLevelCondition1 = WindLevelCondition( |
| | | // .0 to 1.5, |
| | | // listOf(0.5 to DistanceType.TYPE1, 0.2 to DistanceType.TYPE2,), |
| | | // listOf(1, 1) |
| | | // ) |
| | | // |
| | | // // 0 - 1çº§é£ |
| | | // var windLevelCondition1_1 = WindLevelCondition( |
| | | // .0 to 1.5, |
| | | // 0.2 to DistanceType.TYPE2, |
| | | // 1 |
| | | // ) |
| | | // |
| | | // // 2 - 4çº§é£ |
| | | // var windLevelCondition2 = WindLevelCondition( |
| | | // 1.6 to 7.9, |
| | | // listOf(0.2 to DistanceType.TYPE3), |
| | | //// listOf(3) |
| | | // listOf(1) |
| | | // ) |
| | | // |
| | | // // 5 - 6çº§é£ |
| | | // var windLevelCondition3 = WindLevelCondition( |
| | | // 8.0 to 13.8, |
| | | // listOf(0.1 to DistanceType.TYPE4), |
| | | // listOf(3) |
| | | // ) |
| | | /****æ°æ®ååéç*****************************************************************************/ |
| | | var changeRateCondition = WindLevelCondition( |
| | | .0 to Double.MAX_VALUE, |
| | | 0.1 to Double.MAX_VALUE, |
| | | DistanceType.TYPE1, |
| | | 3 |
| | | ) |
| | | // çæµå åå¨ä¸ä¸ªçæµå¨æï¼4ç§ï¼å
æ£å¸¸ååçé级èå´ |
| | | var changeRate = mutableMapOf( |
| | | FactorType.PM25 to WindLevelCondition( |
| | | .0 to Double.MAX_VALUE, |
| | | 4.0 to Double.MAX_VALUE, |
| | | DistanceType.TYPE1, |
| | | 3 |
| | | ), |
| | | FactorType.PM10 to WindLevelCondition( |
| | | .0 to Double.MAX_VALUE, |
| | | 4.0 to Double.MAX_VALUE, |
| | | DistanceType.TYPE1, |
| | | 3 |
| | | ), |
| | | FactorType.VOC to WindLevelCondition( |
| | | .0 to Double.MAX_VALUE, |
| | | 6.0 to Double.MAX_VALUE, |
| | | DistanceType.TYPE1, |
| | | 1 |
| | | ), |
| | | ) |
| | | } |
| | |
| | | return res |
| | | } |
| | | |
| | | override fun judgeExceptionCount(tag: ExceptionTag): Boolean { |
| | | override fun judgeExceptionCount(tag: ExceptionTag, factorType: FactorType?): Boolean { |
| | | return tag.exceptionData.size >= windLevelCondition.countLimit |
| | | } |
| | | |
| | |
| | | return b1 || b2 |
| | | } |
| | | |
| | | override fun immeExcCheck(tag: ExceptionTag): Boolean { |
| | | override fun immeExcCheck(tag: ExceptionTag, factorType: FactorType): Boolean { |
| | | // å¼å¸¸åºç°çäºé宿¬¡æ°æ¶ï¼å°±éè¦å½¢ææ±¡æçº¿ç´¢ |
| | | return tag.exceptionData.size == windLevelCondition.countLimit |
| | | } |
| | | |
| | | override fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | ): PollutedClue { |
| | | return PollutedClue(start, end, factor, exceptionData, getExceptionType(), config, windLevelCondition) |
| | | override fun newResult(tag: ExceptionTag, factor: FactorFilter.SelectedFactor): PollutedClue { |
| | | return PollutedClue(tag, factor, getExceptionType(), config, windLevelCondition) |
| | | } |
| | | |
| | | // override fun newResult( |
| | | // start: BaseRealTimeData, |
| | | // end: BaseRealTimeData?, |
| | | // factor: FactorFilter.SelectedFactor, |
| | | // exceptionData: List<BaseRealTimeData>, |
| | | // ): PollutedClue { |
| | | // return PollutedClue(start, end, factor, exceptionData, getExceptionType(), config, windLevelCondition) |
| | | // } |
| | | |
| | | override fun onNewException( |
| | | tag: ExceptionTag, |
| | | factor: FactorFilter.SelectedFactor, |
| | |
| | | // lastData = data |
| | | // } |
| | | |
| | | override fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | ): RealTimeExceptionResult { |
| | | |
| | | override fun newResult(tag:T, factor: FactorFilter.SelectedFactor): RealTimeExceptionResult { |
| | | val eType = getExceptionType() |
| | | return RealTimeExceptionResult(start, end, factor, exceptionData, eType) |
| | | return RealTimeExceptionResult(tag.startData!!, tag.endData, factor, tag.exceptionData, eType) |
| | | } |
| | | |
| | | override fun onNewException(tag: T, factor: FactorFilter.SelectedFactor, exceptionStatus: ExceptionStatusType) { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.exceptiontype |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.BaseExceptionContinuous |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue |
| | | import com.flightfeather.uav.common.utils.MapUtil |
| | | import com.flightfeather.uav.domain.entity.BaseRealTimeData |
| | | import com.flightfeather.uav.lightshare.eunm.ExceptionStatusType |
| | | import com.flightfeather.uav.socket.eunm.FactorType |
| | | import java.time.Duration |
| | | import java.time.LocalDateTime |
| | | import java.time.ZoneId |
| | | |
| | | /** |
| | | * æ°æ®ååéçå¼å¸¸ |
| | | * @date 2025/6/10 |
| | | * @author feiyu02 |
| | | */ |
| | | class RTExcChangeRate(config: RTExcWindLevelConfig) : |
| | | BaseExceptionContinuous<ExceptionTag, RTExcWindLevelConfig, PollutedClue>(config, ExceptionTag::class.java) { |
| | | |
| | | constructor(config: RTExcWindLevelConfig, callback: NewPolluteClueCallback) : this(config){ |
| | | this.callback = callback |
| | | } |
| | | |
| | | private var callback: NewPolluteClueCallback? = null |
| | | |
| | | override fun getExceptionType(): ExceptionType { |
| | | return ExceptionType.TYPE9 |
| | | } |
| | | |
| | | override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> { |
| | | val res = mutableMapOf<FactorType, Boolean>() |
| | | config.factorFilter.mainList().forEach { f -> |
| | | if (p?.getByFactorType(f) == null || n.getByFactorType(f) == null || n.windSpeed == null) { |
| | | res[f] = (false) |
| | | return@forEach |
| | | } |
| | | |
| | | val rate = config.changeRate[f] |
| | | |
| | | val pValue = p.getByFactorType(f)!! |
| | | val nValue = n.getByFactorType(f)!! |
| | | // 计ç®åä¸ä¸ªæ°æ®ç¸æ¯äºåä¸ä¸ªæ°æ®çååéç |
| | | val v = (nValue - pValue) |
| | | |
| | | val b1 = if (rate != null) { |
| | | v >= rate.mutationRate.first |
| | | } else { |
| | | false |
| | | } |
| | | // val r = (nValue - pValue) / pValue |
| | | // val b1 = r >= con.mutationRate.first && r < con.mutationRate.second |
| | | println("å åï¼${f.des}ï¼éçï¼${v}ï¼${b1}") |
| | | res[f] = b1 |
| | | } |
| | | return res |
| | | } |
| | | |
| | | override fun judgeExceptionCount(tag: ExceptionTag, factorType: FactorType?): Boolean { |
| | | return tag.exceptionData.size >= (config.changeRate[factorType]?.countLimit ?: 1) |
| | | } |
| | | |
| | | override fun needCut(tag: ExceptionTag, hasException: Boolean?): Boolean { |
| | | // æç
§æ¶é¿åè·ç¦»éå¶å°å¼å¸¸æªå |
| | | if (tag.exceptionData.isEmpty()) return false |
| | | |
| | | val se = tag.exceptionData.first() |
| | | val ee = tag.exceptionData.last() |
| | | |
| | | val sTime = LocalDateTime.ofInstant(se.dataTime?.toInstant(), ZoneId.systemDefault()) |
| | | val eTime = LocalDateTime.ofInstant(ee.dataTime?.toInstant(), ZoneId.systemDefault()) |
| | | val duration = Duration.between(sTime, eTime).toMinutes() |
| | | // æ°æ®éæ ·çæ¶é¿è¶
è¿éå¶æ¶ï¼éè¦æªå |
| | | val b1 = duration > config.timeLimit |
| | | |
| | | // èµ°èªæ°æ®çè·ç¦»è¶
è¿éå¶æ¶ï¼éè¦æªå |
| | | val b2 = if (se.longitude == null || se.latitude == null || ee.longitude == null || ee.latitude == null) { |
| | | false |
| | | } else { |
| | | val distance = MapUtil.getDistance( |
| | | se.longitude!!.toDouble(), se.latitude!!.toDouble(), ee.longitude!! |
| | | .toDouble(), ee.latitude!!.toDouble() |
| | | ) |
| | | distance > config.distanceLimit |
| | | } |
| | | |
| | | return b1 || b2 |
| | | } |
| | | |
| | | override fun immeExcCheck(tag: ExceptionTag, factorType: FactorType): Boolean { |
| | | // å¼å¸¸åºç°çäºé宿¬¡æ°æ¶ï¼å°±éè¦å½¢ææ±¡æçº¿ç´¢ |
| | | return judgeExceptionCount(tag, factorType) |
| | | } |
| | | |
| | | override fun newResult(tag: ExceptionTag, factor: FactorFilter.SelectedFactor): PollutedClue { |
| | | return PollutedClue(tag, factor, getExceptionType(), config, config.changeRate[factor.main]) |
| | | } |
| | | |
| | | override fun onNewException( |
| | | tag: ExceptionTag, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionStatus: ExceptionStatusType, |
| | | ) { |
| | | super.onNewException(tag, factor, exceptionStatus) |
| | | callback?.let { func -> |
| | | val exc = tag.exceptionResult.last() |
| | | func.invoke(exc as PollutedClue) |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | override fun newResult( |
| | | fun newResult( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | |
| | | return res |
| | | } |
| | | |
| | | override fun judgeExceptionCount(tag: ExceptionTag): Boolean { |
| | | override fun judgeExceptionCount(tag: ExceptionTag, factorType: FactorType?): Boolean { |
| | | val count = tag.exceptionData.size |
| | | |
| | | val b1 = special && count >= (config.mutationNum / 2) |
| | |
| | | */ |
| | | |
| | | constructor( |
| | | historyData: List<BaseRealTimeData>, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | config: RTExcWindLevelConfig, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition?, |
| | | ) : this() { |
| | | distanceType = windLevelCondition.distanceType |
| | | sourceTrace(exceptionData, config, windLevelCondition) |
| | | distanceType = windLevelCondition?.distanceType |
| | | windLevelCondition?.let { sourceTrace(historyData, exceptionData, config, it) } |
| | | } |
| | | |
| | | var address: String? = null |
| | | |
| | | // 污æèå´åºå(ç»çº¬åº¦å¤è¾¹å½¢) |
| | | // 污æèå´æå½¢åºå(ç»çº¬åº¦å¤è¾¹å½¢) |
| | | var polygon: List<Pair<Double, Double>>? = null |
| | | |
| | | // è¿è·ç¦»æ±¡æåå½¢åºå |
| | | var closePolygon: List<Pair<Double, Double>>? = null |
| | | |
| | | // 污æå¯è½çåçè·ç¦» |
| | | var distanceType: DistanceType? = null |
| | |
| | | * ååæº¯æº |
| | | */ |
| | | private fun sourceTrace( |
| | | historyData: List<BaseRealTimeData>, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | config: RTExcWindLevelConfig, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition, |
| | |
| | | val pair = avgData.longitude!!.toDouble() to avgData.latitude!!.toDouble() |
| | | |
| | | polygon = calSector( |
| | | avgData.windSpeed!!.toDouble(), |
| | | avgData.windDirection!!.toDouble(), |
| | | pair, |
| | | windLevelCondition.distanceType.disRange, |
| | | config.sourceTraceDegOffset |
| | |
| | | // å°åæ 转æ¢ä¸ºgcj02ï¼ç«æåæ ç³»ï¼ï¼å ä¸ºæ±¡ææºåºæ¯ä¿¡æ¯é½ä¸ºæ¤åæ ç³» |
| | | MapUtil.wgs84ToGcj02(it) |
| | | } |
| | | |
| | | closePolygon = closeSourceTrace(historyData, pair) |
| | | |
| | | try { |
| | | val address = AMapService.reGeo(pair) |
| | |
| | | val result = mutableListOf<Pair<Double, Double>>() |
| | | |
| | | if (distanceRange.first == .0) { |
| | | result.add(center) |
| | | // result.add(center) |
| | | var startDeg = 0 |
| | | while (startDeg <= 360) { |
| | | val p = MapUtil.getPointByLen(center, 50.0, startDeg * PI / 180) |
| | | result.add(p) |
| | | startDeg++ |
| | | } |
| | | } else { |
| | | // ä»å¼å§è§åº¦å¾ªç¯è®¡ç®åæ ç¹è³ç»æè§åº¦ï¼æ¥é¿1° |
| | | var startDeg = sDeg |
| | |
| | | result.add(p) |
| | | startDeg++ |
| | | } |
| | | if (distanceRange.second > .0) { |
| | | // æ¤å¤éè¦ä»ç»æè§åº¦å¼å§åå循ç¯è®¡ç®è³å¼å§è§åº¦ï¼æ¥é¿1°ï¼ä½¿å¾ä¸¤ç»åæ ç¹æé¡ºåºæåï¼å¯ç»å¶å¯¹åºçå¤è¾¹å½¢ |
| | | startDeg = eDeg |
| | | while (startDeg >= sDeg) { |
| | | val p = MapUtil.getPointByLen(center, distanceRange.second, startDeg * PI / 180) |
| | | result.add(p) |
| | | startDeg-- |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (distanceRange.second > .0) { |
| | | // æ¤å¤éè¦ä»ç»æè§åº¦å¼å§åå循ç¯è®¡ç®è³å¼å§è§åº¦ï¼æ¥é¿1°ï¼ä½¿å¾ä¸¤ç»åæ ç¹æé¡ºåºæåï¼å¯ç»å¶å¯¹åºçå¤è¾¹å½¢ |
| | | var startDeg = eDeg |
| | | while (startDeg >= sDeg) { |
| | | val p = MapUtil.getPointByLen(center, distanceRange.second, startDeg * PI / 180) |
| | | result.add(p) |
| | | startDeg-- |
| | | } |
| | | return result |
| | | } |
| | | |
| | | private fun closeSourceTrace( |
| | | historyData: List<BaseRealTimeData>, |
| | | center: Pair<Double, Double>, |
| | | ): List<Pair<Double, Double>> { |
| | | val result = mutableListOf<Pair<Double, Double>>() |
| | | var startDeg = 0 |
| | | while (startDeg <= 360) { |
| | | val p = MapUtil.getPointByLen(center, 50.0, startDeg * PI / 180) |
| | | result.add(p) |
| | | startDeg++ |
| | | } |
| | | |
| | | return result |
| | |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionTag |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | import com.flightfeather.uav.common.utils.DateUtil |
| | |
| | | */ |
| | | class PollutedClue() : BaseExceptionResult() { |
| | | |
| | | // constructor( |
| | | // start: BaseRealTimeData, |
| | | // end: BaseRealTimeData?, |
| | | // factor: FactorFilter.SelectedFactor, |
| | | // exceptionData: List<BaseRealTimeData>, |
| | | // eType: ExceptionType, |
| | | // config: RTExcWindLevelConfig, |
| | | // windLevelCondition: RTExcWindLevelConfig.WindLevelCondition?, |
| | | // ) : this() { |
| | | // if (exceptionData.isEmpty()) return |
| | | // pollutedData = PollutedData(start, end, factor, exceptionData, eType, windLevelCondition) |
| | | // pollutedArea = PollutedArea(exceptionData, config, windLevelCondition) |
| | | // } |
| | | |
| | | constructor( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | eType: ExceptionType, |
| | | config: RTExcWindLevelConfig, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition |
| | | ) : this() { |
| | | this.factor = factor |
| | | if (exceptionData.isEmpty()) return |
| | | pollutedData = PollutedData(start, end, factor, exceptionData, eType, windLevelCondition) |
| | | pollutedArea = PollutedArea(exceptionData, config, windLevelCondition) |
| | | tag: ExceptionTag, factor: FactorFilter.SelectedFactor, eType: ExceptionType, config: RTExcWindLevelConfig, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition?, |
| | | ) :this() |
| | | // this( |
| | | // tag.startData!!, tag.endData, factor, tag.exceptionData, eType, config, |
| | | // windLevelCondition |
| | | // ) |
| | | { |
| | | if (tag.exceptionData.isEmpty()) return |
| | | pollutedData = PollutedData( |
| | | tag.startData!!, tag.endData, factor, tag.exceptionData, tag.historyData, eType, windLevelCondition |
| | | ) |
| | | pollutedArea = PollutedArea(tag.historyData, tag.exceptionData, config, windLevelCondition) |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | var pollutedSource: PollutedSource? = null |
| | | |
| | | private var factor: FactorFilter.SelectedFactor? = null |
| | | |
| | | /** |
| | | * æ¥æ¾ç³»ç»å
鍿º¯æºèå´å
çæ±¡æä¼ä¸ |
| | | */ |
| | | fun searchScenes(sceneInfoRep: SceneInfoRep) { |
| | | if (pollutedArea == null || factor == null) return |
| | | pollutedSource = PollutedSource().also { it.searchScenes(pollutedArea!!, sceneInfoRep, factor!!) } |
| | | if (pollutedArea == null || pollutedData == null) return |
| | | pollutedSource = PollutedSource().also { |
| | | it.searchScenes(pollutedArea!!, sceneInfoRep, pollutedData!!) |
| | | } |
| | | } |
| | | } |
| | |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | historyData: List<BaseRealTimeData>, |
| | | eType: ExceptionType, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition?, |
| | | ) : this() { |
| | | exception = eType.des |
| | | exceptionType = eType.value |
| | |
| | | endData = end |
| | | |
| | | windSpeed = exceptionData.first().windSpeed?.toDouble() |
| | | percentage = windLevelCondition.mutationRate.first |
| | | times = windLevelCondition.countLimit |
| | | percentage = windLevelCondition?.mutationRate?.first |
| | | times = windLevelCondition?.countLimit |
| | | |
| | | dataList.add(start) |
| | | exceptionData.forEach { |
| | | dataList.add(it) |
| | | } |
| | | dataVoList.addAll(dataList.map { it.toDataVo() }) |
| | | historyDataList.addAll(historyData.map { it.toDataVo() }) |
| | | |
| | | calPer() |
| | | } |
| | |
| | | // åçæ¬¡æ° |
| | | var times: Int? = null |
| | | |
| | | var historyDataList = mutableListOf<DataVo>() |
| | | // å¼å¸¸çæµæ°æ® |
| | | var dataList: MutableList<BaseRealTimeData> = mutableListOf() |
| | | var dataVoList: MutableList<DataVo> = mutableListOf() |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.model |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.common.utils.MapUtil |
| | | import com.flightfeather.uav.domain.entity.SceneInfo |
| | | import com.flightfeather.uav.domain.repository.SceneInfoRep |
| | |
| | | import com.flightfeather.uav.socket.eunm.FactorType |
| | | import org.springframework.beans.BeanUtils |
| | | import org.springframework.web.context.ContextLoader |
| | | import kotlin.math.min |
| | | import kotlin.math.round |
| | | |
| | | /** |
| | | * æ±¡ææ¥æº |
| | |
| | | */ |
| | | |
| | | // 溯æºä¼ä¸ |
| | | var sceneList:List<SceneInfoVo?>? = null |
| | | var sceneList: List<SceneInfoVo?>? = null |
| | | |
| | | init { |
| | | // æº¯æºæ¨çç»è®º |
| | | var conclusion: String? = null |
| | | |
| | | } |
| | | |
| | | fun searchScenes(pollutedArea: PollutedArea, factor: FactorFilter.SelectedFactor) { |
| | | fun searchScenes(pollutedArea: PollutedArea, pollutedData: PollutedData) { |
| | | ContextLoader.getCurrentWebApplicationContext()?.getBean(SceneInfoRep::class.java)?.run { |
| | | searchScenes(pollutedArea, this, factor) |
| | | searchScenes(pollutedArea, this, pollutedData) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¥æ¾ç³»ç»å
鍿º¯æºèå´å
çæ±¡æä¼ä¸ |
| | | */ |
| | | fun searchScenes(pollutedArea: PollutedArea, sceneInfoRep: SceneInfoRep, factor: FactorFilter.SelectedFactor) { |
| | | fun searchScenes(pollutedArea: PollutedArea, sceneInfoRep: SceneInfoRep, pollutedData: PollutedData) { |
| | | // Fixme 2025.5.14: æ±¡ææºçåæ æ¯é«å¾·å°å¾åæ ç³»ï¼ç«æåæ ç³»ï¼ï¼èèµ°èªæ°æ®æ¯WGS84åæ ç³» |
| | | // æç
§åºåæ£ç´¢å
鍿±¡ææºä¿¡æ¯ |
| | | // 1. é¦å
æç
§åè³èå´ä»æ°æ®åºåæ¥çéæ±¡ææº |
| | | // val polygonTmp = pollutedArea.polygon!!.map { |
| | | // MapUtil.gcj02ToWgs84(it) |
| | | // } |
| | | var result = mutableListOf<SceneInfo>() |
| | | // 1. é¦å
æç
§åè³èå´ä»æ°æ®åºåæ¥çéæ±¡ææºï¼æ¤å¤çåºååæ å·²è½¬æ¢ä¸ºç«æåæ ç³» |
| | | val polygonTmp = pollutedArea.polygon!! |
| | | val fb = MapUtil.calFourBoundaries(polygonTmp) |
| | | val sceneList = sceneInfoRep.findByCoordinateRange(fb) |
| | | // 2. åç²¾ç¡®å¤ææ¯å¦å¨ååæº¯æºåºåå¤è¾¹å½¢å
é¨ |
| | | val result = mutableListOf<SceneInfo>() |
| | | sceneList.forEach { |
| | | val point = it!!.longitude.toDouble() to it.latitude.toDouble() |
| | | if (MapUtil.isPointInPolygon(point, polygonTmp)) { |
| | |
| | | } |
| | | } |
| | | |
| | | findClosestStation(sceneInfoRep, result) |
| | | val closePolygonTmp = pollutedArea.closePolygon!! |
| | | val closeFb = MapUtil.calFourBoundaries(closePolygonTmp) |
| | | val closeSceneList = sceneInfoRep.findByCoordinateRange(closeFb) |
| | | // 2. åç²¾ç¡®å¤ææ¯å¦å¨ååæº¯æºåºåå¤è¾¹å½¢å
é¨ |
| | | closeSceneList.forEach { |
| | | val point = it!!.longitude.toDouble() to it.latitude.toDouble() |
| | | if (MapUtil.isPointInPolygon(point, closePolygonTmp)) { |
| | | result.add(it) |
| | | } |
| | | } |
| | | |
| | | // æ ¹æ®æ±¡æå åçé级ï¼è®¡ç®ä¸»è¦ç污æåºæ¯ç±»åï¼çéç»æ |
| | | val mainSceneType = calSceneType(pollutedData) |
| | | if (mainSceneType != null) { |
| | | this.conclusion = mainSceneType.first |
| | | result = result.filter { |
| | | val r = mainSceneType.second.find { s-> |
| | | s.value == it.typeId.toInt() |
| | | } |
| | | r != null |
| | | }.toMutableList() |
| | | } |
| | | |
| | | // TODO("æç
§æéçæµå åç±»åï¼åºåæ±¡ææºç±»å") |
| | | this.sceneList = findClosestStation(sceneInfoRep, result) |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 计ç®å¯è½çç¸å
³æ±¡æåºæ¯ç±»å |
| | | * 计ç®å¯è½çç¸å
³æ±¡æåºæ¯ç±»å以忍çç»è®º |
| | | */ |
| | | private fun calFactorType(factor: FactorFilter.SelectedFactor) { |
| | | // when (factor.main) { |
| | | // FactorType.PM25 -> {} |
| | | // |
| | | // } |
| | | @Throws(Exception::class) |
| | | private fun calSceneType(pollutedData: PollutedData): Pair<String, List<SceneType>>? { |
| | | when (pollutedData.selectedFactor?.main) { |
| | | // 氮氧ååç©ï¼ä¸è¬ç±äºæºå¨è½¦å°¾æ°ï¼åæ¥è®¡ç®CO |
| | | FactorType.NO2 -> { |
| | | val coAvg = round(pollutedData.dataList.map { it.co!! }.average()) / 1000 |
| | | return "氮氧ååç©åé«ï¼COçé级为${coAvg}mg/m³ï¼ä¸è¬ç±äºæºå¨è½¦å°¾æ°é æï¼æ±¡ææºä»¥æ±½ä¿®ãå æ²¹ç«ä¸ºä¸»" to |
| | | listOf(SceneType.TYPE6, SceneType.TYPE10, SceneType.TYPE17) |
| | | } |
| | | |
| | | FactorType.CO -> return null |
| | | |
| | | FactorType.H2S -> return null |
| | | |
| | | FactorType.SO2 -> return null |
| | | |
| | | FactorType.O3 -> return null |
| | | // a) pm2.5ãpm10ç¹å«é«ï¼ä¸¤è
å¨åæ
åµä¸åæ¥å±ç¤ºï¼pm2.5å pm10çæ¯éååï¼æ¯éè¶é«ï¼è¶æå¯è½æ¯é¤é¥® |
| | | // b) pm10ç¹å«é«ãpm2.5è¾é«ï¼å¤§é¢ç²æ¬å°æ±¡æï¼åªå±ç¤ºpm10ï¼pm2.5å pm10çæ¯éååï¼å·¥å°ä¸ºä¸» |
| | | FactorType.PM25, |
| | | FactorType.PM10, |
| | | -> { |
| | | // 计ç®å¼å¸¸æ°æ®çpm2.5å pm10æ¯éçåå¼ |
| | | val percentageAvg = pollutedData.dataList.map { |
| | | it.pm25!! / it.pm10!! |
| | | }.average() |
| | | return if (percentageAvg > 0.666) { |
| | | "PM2.5å PM10çæ¯é为${round(percentageAvg * 100)}%ï¼æ¯éè¾å¤§ï¼æ±¡ææºä»¥é¤é¥®ä¸ºä¸»ï¼å·¥å°æ¬¡ä¹" to |
| | | listOf(SceneType.TYPE1, SceneType.TYPE2, SceneType.TYPE3, SceneType.TYPE14, SceneType.TYPE5) |
| | | } else if (percentageAvg < 0.333) { |
| | | "PM2.5å PM10çæ¯é为${round(percentageAvg * 100)}%ï¼æ¯éè¾å°ï¼å±äºå¤§é¢ç²æ¬å°æ±¡æï¼æ±¡ææºä»¥å·¥å°ä¸ºä¸»" to |
| | | listOf(SceneType.TYPE1, SceneType.TYPE2, SceneType.TYPE3, SceneType.TYPE14, SceneType.TYPE5) |
| | | } else { |
| | | "PM2.5å PM10çæ¯é为${round(percentageAvg * 100)}%ï¼æ±¡ææºä»¥é¤é¥®ãå·¥å°ä¸ºä¸»" to |
| | | listOf(SceneType.TYPE1, SceneType.TYPE2, SceneType.TYPE3, SceneType.TYPE14, SceneType.TYPE5) |
| | | } |
| | | } |
| | | // c) VOCè¾é«ï¼åæ¯è®¡ç®pm2.5çé级ï¼å¯è½åå¨åæ¥åé«ï¼æ±½ä¿®ãå æ²¹ç«ï¼, åæ¥è®¡ç®O3æ¯å¦æé«å¼ |
| | | // d) VOCè¾é«ï¼å¤äºå æ²¹ç«ï¼è½¦è¾æ¥å µæ
åµï¼ï¼COä¸è¬è¾é«, åæ¥è®¡ç®O3æ¯å¦æé«å¼ |
| | | FactorType.VOC -> { |
| | | val pm25Avg = round(pollutedData.dataList.map { it.pm25!! }.average() * 10) / 10 |
| | | val coAvg = round(pollutedData.dataList.map { it.co!! }.average()) / 1000 |
| | | val o3Avg = round(pollutedData.dataList.map { it.o3!! }.average() * 10) / 10 |
| | | return "VOCåé«ï¼åæ¶PM2.5é级为${pm25Avg}μg/m³ï¼COé级为${coAvg}mg/m³ï¼O3é级为${o3Avg}μg/mÂ³ï¼æ±¡ææºä»¥æ±½ä¿®ãå æ²¹ç«ä¸ºä¸»" to |
| | | listOf(SceneType.TYPE6, SceneType.TYPE17, SceneType.TYPE12) |
| | | } |
| | | |
| | | else -> return null |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è®¡ç®æè¿ççæµç«ç¹ |
| | | */ |
| | | private fun findClosestStation(sceneInfoRep: SceneInfoRep, sceneList: List<SceneInfo>) { |
| | | private fun findClosestStation(sceneInfoRep: SceneInfoRep, sceneList: List<SceneInfo>): List<SceneInfoVo> { |
| | | val res1 = sceneInfoRep.findByArea(AreaVo().apply { |
| | | sceneTypeId = SceneType.TYPE19.value.toString() |
| | | }) |
| | |
| | | }) |
| | | val res = res1.toMutableList().apply { addAll(res2) } |
| | | |
| | | this.sceneList = sceneList.map { |
| | | return sceneList.map { |
| | | var minLen = -1.0 |
| | | var selectedRes: SceneInfo? = null |
| | | res.forEach { r-> |
| | | res.forEach { r -> |
| | | val dis = MapUtil.getDistance( |
| | | it.longitude.toDouble(), |
| | | it.latitude.toDouble(), |
| | |
| | | /** |
| | | * åæç»æ |
| | | */ |
| | | inner class AnalysisResult{ |
| | | inner class AnalysisResult { |
| | | // æç
§è¢«æ«ææ¬¡æ°éåºæåçæ±¡ææºå表 |
| | | var sortedSceneList: List<Pair<SceneInfo?, Int>>? = null |
| | | var time: Date? = null |
| | | var advice:String?= null |
| | | var advice: String? = null |
| | | var direction: AMapService.AMapDirection? = null |
| | | } |
| | | |
| | |
| | | private var analysisTimer: Timer? = null |
| | | |
| | | // 宿¶æ±¡æåæä»»å¡ |
| | | private var lastAnalysisOnTimeTask:TimerTask? = null |
| | | private var lastAnalysisOnTimeTask: TimerTask? = null |
| | | |
| | | // 宿¶æ±¡æåæä»»å¡è¿è¡ç¶æ |
| | | private var analysisTaskIsRunning = false |
| | |
| | | val statistic = AnalysisStatistic() |
| | | // å
±æå¤å°ç¸å
³æ±¡ææºï¼åªäºæ±¡ææºè¢«æ«ææ¬¡æ°è¾å¤ |
| | | val sceneMap = mutableMapOf<String?, Pair<SceneInfo?, Int>>() |
| | | clueList.forEach {c-> |
| | | c.pollutedSource?.sceneList?.forEach { s-> |
| | | clueList.forEach { c -> |
| | | c.pollutedSource?.sceneList?.forEach { s -> |
| | | if (!sceneMap.containsKey(s?.guid)) { |
| | | sceneMap[s?.guid] = s to 1 |
| | | } else { |
| | |
| | | * çº¿ç´¢åæ |
| | | */ |
| | | private fun analysis() { |
| | | if (clueList.isEmpty()) return |
| | | val result = AnalysisResult() |
| | | // å
±æå¤å°ç¸å
³æ±¡ææºï¼åªäºæ±¡ææºè¢«æ«ææ¬¡æ°è¾å¤ |
| | | val sceneMap = mutableMapOf<String?, Pair<SceneInfo?, Int>>() |
| | | clueList.forEach {c-> |
| | | c.pollutedSource?.sceneList?.forEach { s-> |
| | | clueList.forEach { c -> |
| | | c.pollutedSource?.sceneList?.forEach { s -> |
| | | if (!sceneMap.containsKey(s?.guid)) { |
| | | sceneMap[s?.guid] = s to 1 |
| | | } else { |
| | |
| | | } |
| | | } |
| | | } |
| | | val res = sceneMap.entries.sortedBy { it.value.second } |
| | | val res = sceneMap.entries.sortedByDescending { it.value.second } |
| | | result.sortedSceneList = res.map { it.value } |
| | | |
| | | // å½åçèµ°èªæ°æ®çå®ä½åæ±¡ææºè·ç¦»æ¯å¦æ¯éæ¸æ¥è¿ï¼è¥èµ°èªè¿ç¦»äºä¸»è¦æ±¡ææºï¼æç¤ºç¨æ·è°æ´èµ°èªè·¯çº¿ |
| | | if (!result.sortedSceneList.isNullOrEmpty()) { |
| | | val sT = clueList.first().pollutedData?.startTime |
| | | val closetScene = result.sortedSceneList?.first() |
| | | result.advice = "æ ¹æ®${sT}èµ·ç${clueList.size}æ¡ææ°æ±¡æçº¿ç´¢ï¼æ±¡ææº[${closetScene?.first?.name}]è¢«å¤æ¬¡æº¯æºï¼å
·æè¾é«æ±¡æé£é©ï¼ç°æä¾æ°çèµ°èªæ¨è路线ï¼å¯ç»è¿è¯¥æ±¡ææºã" |
| | | |
| | | // èµ°èªè·¯çº¿è°æ´å»ºè®® |
| | | result.advice = |
| | | "æ ¹æ®${sT}èµ·ç${clueList.size}æ¡ææ°æ±¡æçº¿ç´¢ï¼æ±¡ææºã${closetScene?.first?.name}ãè¢«å¤æ¬¡æº¯æºï¼å
·æè¾é«æ±¡æé£é©ï¼ç°æä¾æ°çèµ°èªæ¨è路线ï¼å¯ç»è¿è¯¥æ±¡ææºã" |
| | | |
| | | val lastP = realTimeDataList.last() |
| | | // 建议对åºçæ°æ®éæ ·æ¶é´ |
| | | result.time = lastP.dataTime |
| | | if (lastP.longitude != null && lastP.latitude != null && |
| | | lastP.longitude!! > BigDecimal.ZERO && lastP.latitude!! > BigDecimal.ZERO |
| | | && closetScene?.first?.longitude != null && closetScene.first?.latitude != null && |
| | | closetScene.first?.longitude!! > BigDecimal.ZERO && closetScene.first?.latitude!! > BigDecimal.ZERO) { |
| | | closetScene.first?.longitude!! > BigDecimal.ZERO && closetScene.first?.latitude!! > BigDecimal.ZERO |
| | | ) { |
| | | |
| | | val origin = MapUtil.wgs84ToGcj02(lastP.longitude!!.toDouble() to lastP.latitude!!.toDouble()) |
| | | val destination = closetScene.first!!.longitude.toDouble() to closetScene.first!!.latitude.toDouble() |
| | | |
| | | // 建议çèµ°èªè·¯çº¿ |
| | | result.direction = AMapService.directionDriving(origin, destination) |
| | | } |
| | | } |
| | | |
| | | |
| | | result.time = realTimeDataList.last().dataTime |
| | | // 线索åæå®æåï¼ç§»å¨è³åå²çº¿ç´¢å表 |
| | | historyClueList.addAll(clueList) |
| | | clueList.clear() |
| | |
| | | @SpringBootTest |
| | | class PollutedSourceTest { |
| | | |
| | | @Autowired |
| | | lateinit var sceneInfoRep: SceneInfoRep |
| | | @Autowired |
| | | lateinit var sceneInfoRep: SceneInfoRep |
| | | |
| | | @Test |
| | | fun foo1() { |
| | | val source = PollutedSource() |
| | | val pollutedArea = PollutedArea().apply { |
| | | polygon = listOf( |
| | | 121.421521 to 31.195457, |
| | | 121.421721 to 31.195457, |
| | | 121.421521 to 31.195257, |
| | | 121.421721 to 31.195257, |
| | | ) |
| | | } |
| | | source.searchScenes(pollutedArea, sceneInfoRep, FactorFilter.SelectedFactor(FactorType.VOC)) |
| | | @Test |
| | | fun foo1() { |
| | | val source = PollutedSource() |
| | | val pollutedData = PollutedData() |
| | | val pollutedArea = PollutedArea().apply { |
| | | polygon = listOf( |
| | | 121.421521 to 31.195457, |
| | | 121.421721 to 31.195457, |
| | | 121.421521 to 31.195257, |
| | | 121.421721 to 31.195257, |
| | | ) |
| | | } |
| | | source.searchScenes(pollutedArea, sceneInfoRep, pollutedData) |
| | | |
| | | } |
| | | } |
| | | } |