| | |
| | | private const val OFFSET = 10 |
| | | } |
| | | |
| | | inner class Tag { |
| | | // èµ·å§æ°æ®ä¸æ |
| | | var sIndex = 0 |
| | | |
| | | // èµ·å§æ°æ®å¯¹è±¡ |
| | | var startData: BaseRealTimeData? = null |
| | | |
| | | // æ«å°¾æ°æ®ä¸æ |
| | | var eIndex = -1 |
| | | |
| | | // æ«å°¾æ°æ®å¯¹è±¡ |
| | | var endData: BaseRealTimeData? = null |
| | | |
| | | // å¼å¸¸æ°æ®æ®µ |
| | | var exceptionData = mutableListOf<BaseRealTimeData>() |
| | | |
| | | // æ¯å¦åå¨å¼å¸¸ |
| | | var exceptionExisted = false |
| | | |
| | | // å¼å¸¸ç»ææ¯å¦å建 |
| | | var exceptionCreated = false |
| | | |
| | | fun addExceptionData(data: BaseRealTimeData) { |
| | | exceptionExisted = true |
| | | exceptionData.add(data) |
| | | } |
| | | |
| | | fun refreshWithNextException(data: BaseRealTimeData) { |
| | | sIndex = eIndex |
| | | startData = data |
| | | exceptionData.clear() |
| | | exceptionExisted = false |
| | | exceptionCreated = false |
| | | } |
| | | } |
| | | |
| | | protected val tagMap = mutableMapOf<FactorType, T>() |
| | | |
| | | // èµ·å§æ°æ®ä¸æ«å°¾æ°æ®é´é |
| | |
| | | |
| | | // æ«å°¾æ°æ®å¯¹è±¡ |
| | | protected var lastData: BaseRealTimeData? = null |
| | | |
| | | /** |
| | | * åç½®å¤æï¼å½ç¸é»æ°æ®æ¶é´ä¸è¿ç»æ¶ï¼æè
满足èªå®ä¹æ¡ä»¶æ¶ï¼å¯¹ä¹åå·²æçå¼å¸¸è¿è¡è®°å½ |
| | | */ |
| | | open fun afterExcCheck(isContinue: Boolean, tag: T, hasException: Boolean?): Boolean { |
| | | return !isContinue || needCut(tag, hasException) |
| | | } |
| | | |
| | | /** |
| | | * ç«å³å¤æï¼å½åºç°å¼å¸¸æ¶ï¼ç¼åå¼å¸¸æ°æ®çåæ¶ï¼ç«å³å¯¹å·²æå¼å¸¸è¿è¡å¤ææ¯å¦æ»¡è¶³å¼å¸¸ç»æè¦æ± |
| | | */ |
| | | open fun immeExcCheck(tag: T): Boolean { |
| | | return false |
| | | } |
| | | |
| | | /** |
| | | * 夿ç¸é»æ°æ®æ¯å¦è¿ç» |
| | |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦æ»¡è¶³å¼å¸¸æ¡ä»¶ |
| | | * 夿ååæ°æ®æ¯å¦æ»¡è¶³å¼å¸¸æ¡ä»¶ |
| | | */ |
| | | abstract fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> |
| | | |
| | |
| | | |
| | | /** |
| | | * å¼å¸¸æ°æ®çæªå夿 |
| | | * æ¯å¦éè¦éå¶ä¸ç»å¼å¸¸æ°æ®çé¿åº¦ |
| | | * @return é»è®¤ä¸éè¦æªå |
| | | */ |
| | | open fun needCut(tag: T): Boolean { |
| | | return false |
| | | open fun needCut(tag: T, hasException: Boolean?): Boolean { |
| | | // é»è®¤å¤ææ¡ä»¶ä¸º å½å¼å¸¸ä¸åéå¤åºç°æ¶ï¼å½¢æå¼å¸¸ç»æ |
| | | return tag.exceptionExisted && hasException == false |
| | | } |
| | | |
| | | override fun init() { |
| | |
| | | if (it.startData == null) { |
| | | it.refreshWithNextException(data) |
| | | } |
| | | // 夿ç¸é»æ°æ®æ¯å¦è¿ç»å¹¶ä¸æ¯å¦æ»¡è¶³å¼å¸¸å¤æ |
| | | if (!isContinue || needCut(it)) { |
| | | // æ°æ®ä¸è¿ç»æ¶ï¼è®°å½å¼å¸¸æ
åµ |
| | | |
| | | // 对äºå¼å¸¸ççæå嫿§è¡åç½®å¤æãåç«å³å¤æ |
| | | // 1. åç½®å¤æï¼å½ç¸é»æ°æ®æ¶é´ä¸è¿ç»æ¶ï¼æè
满足èªå®ä¹æ¡ä»¶æ¶ï¼å¯¹ä¹åå·²æçå¼å¸¸è¿è¡è®°å½ï¼å½¢æå¼å¸¸ç»æ |
| | | if (afterExcCheck(isContinue, it, hasException[f])) { |
| | | // æ°æ®ä¸è¿ç»æ¶æè
æ»¡è¶³ä¸»å¨æªææ¡ä»¶æ¶ï¼è®°å½å¼å¸¸æ
åµ |
| | | recordException(s, it, data) |
| | | } else { |
| | | if (hasException[f] == true) { |
| | | } |
| | | // 2. ç«å³å¤æï¼å½åºç°å¼å¸¸æ¶ï¼ç¼åå¼å¸¸æ°æ®çåæ¶ï¼ç«å³å¯¹å·²æå¼å¸¸è¿è¡å¤ææ¯å¦æ»¡è¶³å¼å¸¸ç»æè¦æ± |
| | | else if (hasException[f] == true) { |
| | | // æå¼å¸¸åºç°æ¶ï¼è®°å½å¼å¸¸æ°æ® |
| | | it.addExceptionData(data) |
| | | } else { |
| | | // å¼å¸¸ä¸åéå¤åºç°æ¶ï¼è®°å½å¼å¸¸æ
åµ |
| | | // å½ç«å³å¤æéè¿æ¶ï¼å½¢æå¼å¸¸ç»æ |
| | | if (immeExcCheck(it)) { |
| | | recordException(s, it, data) |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * å¼å¸¸ç»æï¼è®°å½å¼å¸¸ |
| | | * 夿已æçå¼å¸¸æ°æ®æ¯å¦æ»¡è¶³å¼å¸¸æ¡ä»¶ï¼æ»¡è¶³åè®°å½ï¼ä¸æ»¡è¶³åç¥è¿ |
| | | */ |
| | | fun recordException(factor: FactorFilter.SelectedFactor, tag: T, data: BaseRealTimeData) { |
| | | checkResult(factor, ExceptionStatusType.Ended) |
| | | // if (tag.eIndex - tag.sIndex >= durationCount) { |
| | | tag.refreshWithNextException(data) |
| | | // } |
| | | } |
| | | |
| | | /** |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.config |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.BaseAnalysisConfig |
| | | import com.flightfeather.uav.biz.sourcetrace.model.DistanceType |
| | | |
| | | /** |
| | | * |
| | | * @date 2025/5/29 |
| | | * @author feiyu02 |
| | | */ |
| | | class RTExcWindLevelConfig(factorFilter: FactorFilter): BaseAnalysisConfig(factorFilter) { |
| | | |
| | | inner class WindLevelCondition( |
| | | val windSpeed: Pair<Double, Double>, |
| | | val mutationRate: Pair<Double, DistanceType>, |
| | | val countLimit: Int, |
| | | ) |
| | | |
| | | // éå®è·ç¦»å
ï¼åä½ï¼ç±³ï¼ |
| | | var distanceLimit = 1000 |
| | | // é宿¶é´å
ï¼åä½ï¼åéï¼ |
| | | var timeLimit = 2 |
| | | |
| | | // 0 - 1çº§é£ |
| | | var windLevelCondition1 = WindLevelCondition( |
| | | .0 to 1.5, |
| | | 0.5 to DistanceType.TYPE1, |
| | | 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, |
| | | 0.2 to DistanceType.TYPE3, |
| | | 3 |
| | | ) |
| | | |
| | | // 5 - 6çº§é£ |
| | | var windLevelCondition3 = WindLevelCondition( |
| | | 8.0 to 13.8, |
| | | 0.1 to DistanceType.TYPE4, |
| | | 3 |
| | | ) |
| | | |
| | | // æº¯æºæ©æ£åç§»è§åº¦ï¼åä½ï¼åº¦ï¼ |
| | | var sourceTraceDegOffset = 120.0 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 |
| | | |
| | | |
| | | // å¼å¸¸æ°æ®çæåè°ç±» |
| | | typealias NewPolluteClueCallback = (ex: PollutedClue) -> Unit |
| | | /** |
| | | * ä¸åé£éä¸ï¼æ°æ®çªåå¼å¸¸åºç±» |
| | | * @date 2025/5/29 |
| | | * @author feiyu02 |
| | | */ |
| | | abstract class BaseRTExcWindLevel(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 |
| | | |
| | | abstract var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition |
| | | |
| | | override fun getExceptionType(): ExceptionType { |
| | | return ExceptionType.TYPE4 |
| | | } |
| | | |
| | | 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 con = windLevelCondition |
| | | |
| | | if (n.windSpeed!! in con.windSpeed.first..con.windSpeed.second) { |
| | | val pValue = p.getByFactorType(f)!! |
| | | val nValue = n.getByFactorType(f)!! |
| | | // 计ç®åä¸ä¸ªæ°æ®ç¸æ¯äºåä¸ä¸ªæ°æ®çååç |
| | | val r = (nValue - pValue) / pValue |
| | | val b1 = r >= con.mutationRate.first |
| | | res[f] = b1 |
| | | } else { |
| | | res[f] = false |
| | | } |
| | | } |
| | | |
| | | return res |
| | | } |
| | | |
| | | override fun judgeExceptionCount(tag: ExceptionTag): Boolean { |
| | | return tag.exceptionData.size >= windLevelCondition.countLimit |
| | | } |
| | | |
| | | 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): 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 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) |
| | | } |
| | | } |
| | | } |
| | |
| | | * @date 2025/5/13 |
| | | * @author feiyu02 |
| | | */ |
| | | @Deprecated("2025.5.29, é»è¾ä¸ä¸å¡ä¸å¹é
ï¼åç»å é¤") |
| | | abstract class BaseRealTimeException<T : ExceptionTag>(config: RealTimeAnalysisConfig, tagClz: Class<T>) : |
| | | BaseExceptionContinuous<T, RealTimeAnalysisConfig, RealTimeExceptionResult>(config, tagClz) { |
| | | |
| | |
| | | |
| | | var callback: NewExceptionCallback? = null |
| | | |
| | | override fun onNextData(data: BaseRealTimeData) { |
| | | val isContinue = isContinuous(lastData, data) |
| | | val hasException = judgeException(lastData, data) |
| | | config.factorFilter.selectedList.forEach { s -> |
| | | val f = s.main |
| | | tagMap[f]?.let { |
| | | it.eIndex++ |
| | | // èµ·å§æ°æ® |
| | | it.endData = data |
| | | if (it.startData == null) { |
| | | it.refreshWithNextException(data) |
| | | } |
| | | // 夿ç¸é»æ°æ®æ¯å¦è¿ç»æè
æ¯å¦æ»¡è¶³èªå®ä¹æªåæ¡ä»¶ |
| | | if (!isContinue || needCut(it)) { |
| | | // è®°å½å¼å¸¸ï¼ç»æå¼å¸¸ç宿¶ç¶æææ¥ |
| | | recordException(s, it, data) |
| | | } else { |
| | | // ç§»é¤äºç¶ç±»åæé»è¾ï¼æ¹ä¸ºå½æ»¡è¶³å¼å¸¸æ¡ä»¶æ¶ï¼éè¦å®æ¶æ¨éææ¥å¼å¸¸çç¶æååï¼ä½ä¸æªåå¼å¸¸ |
| | | if (hasException[f] == true) { |
| | | it.addExceptionData(data) |
| | | checkResult(s) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | lastData = data |
| | | } |
| | | // override fun onNextData(data: BaseRealTimeData) { |
| | | // val isContinue = isContinuous(lastData, data) |
| | | // val hasException = judgeException(lastData, data) |
| | | // config.factorFilter.selectedList.forEach { s -> |
| | | // val f = s.main |
| | | // tagMap[f]?.let { |
| | | // it.eIndex++ |
| | | // // èµ·å§æ°æ® |
| | | // it.endData = data |
| | | // if (it.startData == null) { |
| | | // it.refreshWithNextException(data) |
| | | // } |
| | | // // 夿ç¸é»æ°æ®æ¯å¦è¿ç»æè
æ¯å¦æ»¡è¶³èªå®ä¹æªåæ¡ä»¶ |
| | | // if (!isContinue || needCut(it)) { |
| | | // // è®°å½å¼å¸¸ï¼ç»æå¼å¸¸ç宿¶ç¶æææ¥ |
| | | // recordException(s, it, data) |
| | | // } else { |
| | | // // ç§»é¤äºç¶ç±»åæé»è¾ï¼æ¹ä¸ºå½æ»¡è¶³å¼å¸¸æ¡ä»¶æ¶ï¼éè¦å®æ¶æ¨éææ¥å¼å¸¸çç¶æååï¼ä½ä¸æªåå¼å¸¸ |
| | | // if (hasException[f] == true) { |
| | | // it.addExceptionData(data) |
| | | // checkResult(s) |
| | | // } |
| | | // } |
| | | // } |
| | | // } |
| | | // lastData = data |
| | | // } |
| | | |
| | | override fun newResult( |
| | | start: BaseRealTimeData, |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.exceptiontype |
| | | |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | |
| | | /** |
| | | * 0 - 1级é£ï¼è½¯é£ï¼é£é1.5m/så以ä¸ï¼ç¶æä¸ï¼æ°æ®çªåå¼å¸¸ |
| | | * @date 2025/5/29 |
| | | * @author feiyu02 |
| | | */ |
| | | class RTExcWindLevel1 : BaseRTExcWindLevel { |
| | | |
| | | constructor(config: RTExcWindLevelConfig) : super(config) |
| | | |
| | | constructor(config: RTExcWindLevelConfig, callback: NewPolluteClueCallback) : super(config, callback) |
| | | |
| | | override var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition = config.windLevelCondition1 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.exceptiontype |
| | | |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | |
| | | /** |
| | | * 0 - 1级é£ï¼è½¯é£ï¼é£é1.5m/så以ä¸ï¼ç¶æä¸ï¼æ°æ®çªåå¼å¸¸ |
| | | * @date 2025/5/29 |
| | | * @author feiyu02 |
| | | */ |
| | | class RTExcWindLevel1_1 : BaseRTExcWindLevel { |
| | | |
| | | constructor(config: RTExcWindLevelConfig) : super(config) |
| | | |
| | | constructor(config: RTExcWindLevelConfig, callback: NewPolluteClueCallback) : super(config, callback) |
| | | |
| | | override var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition = config.windLevelCondition1_1 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.exceptiontype |
| | | |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | |
| | | /** |
| | | * 2 - 4级é£ï¼åé£ï¼é£é1.6 - 7.9m/så以ä¸ï¼ç¶æä¸ï¼æ°æ®çªåå¼å¸¸ |
| | | * @date 2025/5/29 |
| | | * @author feiyu02 |
| | | */ |
| | | class RTExcWindLevel4:BaseRTExcWindLevel { |
| | | |
| | | constructor(config: RTExcWindLevelConfig) : super(config) |
| | | |
| | | constructor(config: RTExcWindLevelConfig, callback: NewPolluteClueCallback) : super(config, callback) |
| | | |
| | | override var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition = config.windLevelCondition2 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.exceptiontype |
| | | |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | |
| | | /** |
| | | * 4 - 6级é£ï¼å¼ºé£ï¼é£é8 - 13.8m/sï¼ç¶æä¸ï¼æ°æ®çªåå¼å¸¸ |
| | | * @date 2025/5/29 |
| | | * @author feiyu02 |
| | | */ |
| | | class RTExcWindLevel6:BaseRTExcWindLevel { |
| | | |
| | | constructor(config: RTExcWindLevelConfig) : super(config) |
| | | |
| | | constructor(config: RTExcWindLevelConfig, callback: NewPolluteClueCallback) : super(config, callback) |
| | | |
| | | override var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition = config.windLevelCondition3 |
| | | } |
| | |
| | | * @date 2025/5/13 |
| | | * @author feiyu02 |
| | | */ |
| | | @Deprecated("2025.5.29, é»è¾ä¸ä¸å¡ä¸å¹é
ï¼åç»å é¤") |
| | | class RealTimeExceptionSlideAverage : BaseExceptionAnalysis<RealTimeAnalysisConfig, RealTimeExceptionResult> { |
| | | |
| | | constructor(config: RealTimeAnalysisConfig) : super(config) |
| | |
| | | * @date 2025/5/13 |
| | | * @author feiyu02 |
| | | */ |
| | | @Deprecated("2025.5.29, é»è¾ä¸ä¸å¡ä¸å¹é
ï¼åç»å é¤") |
| | | class RealTimeExceptionValueMutation : BaseRealTimeException<ExceptionTag> { |
| | | |
| | | constructor(config: RealTimeAnalysisConfig) : super(config, ExceptionTag::class.java) |
| | |
| | | return b1 || b2 |
| | | } |
| | | |
| | | override fun needCut(tag: ExceptionTag): Boolean { |
| | | override fun needCut(tag: ExceptionTag, hasException: Boolean?): Boolean { |
| | | // æç
§æ¶é¿åè·ç¦»éå¶å°å¼å¸¸æªå |
| | | if (tag.exceptionData.isEmpty()) return false |
| | | |
| | |
| | | * @date 2025/5/28 |
| | | * @author feiyu02 |
| | | */ |
| | | enum class DistanceType(val des: String) { |
| | | TYPE1("50ç±³"), |
| | | TYPE2("50ç±³ - 500ç±³"), |
| | | TYPE3("50ç±³ - 1å
Ž"), |
| | | TYPE4("50ç±³ - 2å
Ž") |
| | | enum class DistanceType(val des: String, val disRange: Pair<Double, Double>) { |
| | | TYPE1("50ç±³", .0 to 50.0), |
| | | TYPE2("50ç±³ - 500ç±³", 50.0 to 500.0), |
| | | TYPE3("50ç±³ - 1å
Ž", 50.0 to 1000.0), |
| | | TYPE4("50ç±³ - 2å
Ž", 50.0 to 2000.0); |
| | | |
| | | override fun toString(): String { |
| | | return this.des |
| | | } |
| | | } |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.model |
| | | |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | import com.flightfeather.uav.common.net.AMapService |
| | | import com.flightfeather.uav.common.utils.MapUtil |
| | | import com.flightfeather.uav.domain.entity.BaseRealTimeData |
| | | import com.flightfeather.uav.domain.entity.avg |
| | | import kotlin.math.PI |
| | | |
| | | /** |
| | | * å¨ææº¯æºæ±¡æåºå |
| | | * éè¿å°å¾åæ ç¹å½¢æå¤è¾¹å½¢æ¥æè¿°ä¸å污æåºå |
| | | * @date 2025/5/27 |
| | | * @author feiyu02 |
| | | */ |
| | | class PollutedArea { |
| | | class PollutedArea() { |
| | | |
| | | var name: String? = null |
| | | /** |
| | | * 溯æºè§åº¦å¯è®¾ç½® |
| | | */ |
| | | |
| | | constructor( |
| | | exceptionData: List<BaseRealTimeData>, |
| | | config: RTExcWindLevelConfig, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition, |
| | | ) : this() { |
| | | distanceType = windLevelCondition.mutationRate.second |
| | | sourceTrace(exceptionData, config, windLevelCondition) |
| | | } |
| | | |
| | | var address: String? = null |
| | | |
| | | // 污æèå´åºå(ç»çº¬åº¦å¤è¾¹å½¢) |
| | | var polygon: List<Pair<Double, Double>>? = null |
| | | |
| | | // 污æå¯è½çåçè·ç¦» |
| | | var distanceType: DistanceType? = null |
| | | |
| | | /** |
| | | * ååæº¯æº |
| | | */ |
| | | private fun sourceTrace( |
| | | exceptionData: List<BaseRealTimeData>, |
| | | config: RTExcWindLevelConfig, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition, |
| | | ) { |
| | | val avgData = if (exceptionData.size == 1) { |
| | | exceptionData.first() |
| | | } else { |
| | | exceptionData.avg() |
| | | } |
| | | |
| | | val pair = avgData.longitude!!.toDouble() to avgData.latitude!!.toDouble() |
| | | |
| | | polygon = calSector( |
| | | avgData.windSpeed!!.toDouble(), |
| | | pair, |
| | | windLevelCondition.mutationRate.second.disRange, |
| | | config.sourceTraceDegOffset |
| | | ) |
| | | |
| | | try { |
| | | val address = AMapService.reGeo(pair) |
| | | this.address = address.township + address.street |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ä¸å¿ç¹åæ ãé£ååæº¯æºè·ç¦»ï¼ä»¥åç»å®ç夹è§ï¼è®¡ç®ä»¥ä¸å¿ç¹æç
§é£åå夿©æ£å½¢æçæå½¢çç¹åæ |
| | | * @param windDir é£åï¼åä½ï¼åº¦ |
| | | * @param center ä¸å¿ç¹åæ ç»çº¬åº¦ |
| | | * @param distanceRange 溯æºè·ç¦»èå´ï¼åä½ï¼ç±³ |
| | | * @param defaultDegOffset æ©æ£åç§»è§åº¦ |
| | | * @return å¤è¾¹å½¢é¡¶ç¹åæ éå |
| | | */ |
| | | private fun calSector( |
| | | windDir: Double, |
| | | center: Pair<Double, Double>, |
| | | distanceRange: Pair<Double, Double>, |
| | | defaultDegOffset: Double = 60.0, |
| | | ): List<Pair<Double, Double>> { |
| | | |
| | | val sDeg = windDir - defaultDegOffset / 2 |
| | | val eDeg = windDir + defaultDegOffset / 2 |
| | | |
| | | val result = mutableListOf<Pair<Double, Double>>() |
| | | |
| | | if (distanceRange.first == .0) { |
| | | result.add(center) |
| | | } else { |
| | | // ä»å¼å§è§åº¦å¾ªç¯è®¡ç®åæ ç¹å¼ç»æè§åº¦ï¼æ¥é¿1° |
| | | var startDeg = sDeg |
| | | while (startDeg <= eDeg) { |
| | | val p = MapUtil.getPointByLen(center, distanceRange.first, 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 |
| | | } |
| | | } |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.model |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | import com.flightfeather.uav.common.utils.DateUtil |
| | | import com.flightfeather.uav.common.utils.MapUtil |
| | | import com.flightfeather.uav.domain.entity.BaseRealTimeData |
| | | import com.flightfeather.uav.domain.entity.SceneInfo |
| | | import com.flightfeather.uav.domain.repository.SceneInfoRep |
| | | |
| | | /** |
| | | * 污æçº¿ç´¢ |
| | | * æ ¹æ® |
| | | * éè¿æ±¡ææ°æ®[PollutedData],污æåºå[PollutedArea],æ±¡ææ¥æº[PollutedSource]ï¼å½¢æä¸æ¡æ±¡ææº¯æºçº¿ç´¢ |
| | | * @date 2025/5/27 |
| | | * @author feiyu02 |
| | | */ |
| | | class PollutedClue { |
| | | class PollutedClue() : BaseExceptionResult() { |
| | | |
| | | 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) |
| | | } |
| | | |
| | | /** |
| | | * 6. å±ç¤ºæ°æ®ååæ
åµï¼ä¸åéççç |
| | | */ |
| | | |
| | | var pollutedData: PollutedData? = null |
| | | |
| | | var pollutedArea: PollutedArea? = null |
| | | |
| | | 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!!) } |
| | | } |
| | | } |
| | |
| | | package com.flightfeather.uav.biz.sourcetrace.model |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType |
| | | import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig |
| | | import com.flightfeather.uav.common.utils.DateUtil |
| | | import com.flightfeather.uav.domain.entity.BaseRealTimeData |
| | | import com.flightfeather.uav.lightshare.bean.DataVo |
| | | |
| | |
| | | * @date 2025/5/27 |
| | | * @author feiyu02 |
| | | */ |
| | | class PollutedData { |
| | | class PollutedData() { |
| | | |
| | | /** |
| | | * |
| | |
| | | * 3. 8 - 13.8 m/s 以ä¸ï¼ååå¼ä¸åå¹
度å¨10%以ä¸3次ï¼è®¤ä¸ºæ¯è¿è·ç¦»åç(50ç±³ - 2å
Ž) |
| | | */ |
| | | |
| | | /** |
| | | * 9. å
³èå å |
| | | * a) pm2.5ãpm10ç¹å«é«ï¼ä¸¤è
å¨åæ
åµä¸åæ¥å±ç¤ºï¼pm2.5å pm10çæ¯éååï¼æ¯éè¶é«ï¼è¶æå¯è½æ¯é¤é¥® |
| | | * b) pm10ç¹å«é«ãpm2.5è¾é«ï¼å¤§é¢ç²æ¬å°æ±¡æï¼åªå±ç¤ºpm10ï¼pm2.5å pm10çæ¯éååï¼å·¥å°ä¸ºä¸» |
| | | * c) VOCè¾é«ï¼åæ¯è®¡ç®pm2.5çé级ï¼å¯è½åå¨åæ¥åé«ï¼æ±½ä¿®ãå æ²¹ç«ï¼, åæ¥è®¡ç®O3æ¯å¦æé«å¼ |
| | | * d) VOCè¾é«ï¼å¤äºå æ²¹ç«ï¼è½¦è¾æ¥å µæ
åµï¼ï¼COä¸è¬è¾é«, åæ¥è®¡ç®O3æ¯å¦æé«å¼ |
| | | * e) 氮氧ååç©ï¼ä¸è¬ç±äºæºå¨è½¦å°¾æ°ï¼åæ¥è®¡ç®CO |
| | | */ |
| | | |
| | | constructor( |
| | | start: BaseRealTimeData, |
| | | end: BaseRealTimeData?, |
| | | factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | eType: ExceptionType, |
| | | windLevelCondition: RTExcWindLevelConfig.WindLevelCondition, |
| | | ) : this() { |
| | | exception = eType.des |
| | | exceptionType = eType.value |
| | | factorId = factor.main.value |
| | | factorName = factor.main.des |
| | | subFactorId = factor.subs.map { it.value } |
| | | subFactorName = factor.subs.map { it.des } |
| | | selectedFactor = factor |
| | | |
| | | startTime = DateUtil.instance.dateToString(start.dataTime, DateUtil.DateStyle.HH_MM_SS) |
| | | endTime = DateUtil.instance.dateToString(end?.dataTime, DateUtil.DateStyle.HH_MM_SS) ?: startTime |
| | | startData = start.getByFactorType(factor.main) |
| | | endData = end?.getByFactorType(factor.main) ?: startData |
| | | |
| | | windSpeed = exceptionData.first().windSpeed?.toDouble() |
| | | percentage = windLevelCondition.mutationRate.first |
| | | times = windLevelCondition.countLimit |
| | | |
| | | exceptionData.forEach { |
| | | dataList.add(it) |
| | | dataVoList.add(it.toDataVo()) |
| | | } |
| | | } |
| | | |
| | | var deviceCode: String? = null |
| | | |
| | | var exception: String? = null |
| | | var exceptionType: Int? = null |
| | | |
| | | var factorId: Int? = null |
| | | var factorName: String? = null |
| | | var subFactorId: List<Int>? = null |
| | | var subFactorName: List<String>? = null |
| | | var selectedFactor: FactorFilter.SelectedFactor? = null |
| | | |
| | | var startTime: String? = null |
| | | var endTime: String? = null |
| | | |
| | | var startData: Float? = null |
| | | var endData: Float? = null |
| | | |
| | | // é£é |
| | | var windSpeed: Float? = null |
| | | var windSpeed: Double? = null |
| | | |
| | | // å åé级ååå¹
度 |
| | | var percentage: Float? = null |
| | | var percentage: Double? = null |
| | | |
| | | // åçæ¬¡æ° |
| | | var times: Int? = null |
| | |
| | | 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 |
| | | |
| | | /** |
| | | * æ±¡ææ¥æº |
| | | * ç³»ç»å
é¨ç污æåºæ¯ãçµåå°å¾æç´¢å¾å°çå®é
路段路å£çæ å¿ä¿¡æ¯ |
| | |
| | | */ |
| | | class PollutedSource { |
| | | |
| | | /** |
| | | * æº¯æºæ¸
åæ¾ç¤ºä¸ä¸´è¿çæµç«ç¹çè·ç¦»ï¼å½æ§ã叿§ãç½æ ¼åçæµç¹ï¼ |
| | | * |
| | | */ |
| | | |
| | | // 溯æºä¼ä¸ |
| | | var sceneList:List<SceneInfo?>? = null |
| | | |
| | | /** |
| | | * æ¥æ¾ç³»ç»å
鍿º¯æºèå´å
çæ±¡æä¼ä¸ |
| | | */ |
| | | fun searchScenes(pollutedArea: PollutedArea, sceneInfoRep: SceneInfoRep, factor: FactorFilter.SelectedFactor) { |
| | | // Fixme 2025.5.14: æ±¡ææºçåæ æ¯é«å¾·å°å¾åæ ç³»ï¼ç«æåæ ç³»ï¼ï¼èèµ°èªæ°æ®æ¯WGS84åæ ç³» |
| | | // æç
§åºåæ£ç´¢å
鍿±¡ææºä¿¡æ¯ |
| | | // 1. é¦å
æç
§åè³èå´ä»æ°æ®åºåæ¥çéæ±¡ææºï¼éè¦å
å°åæ 转æ¢ä¸ºgcj02ï¼ç«æåæ ç³»ï¼ï¼å ä¸ºæ±¡ææºåºæ¯ä¿¡æ¯é½ä¸ºæ¤åæ ç³» |
| | | val polygonTmp = pollutedArea.polygon!!.map { |
| | | MapUtil.gcj02ToWgs84(it) |
| | | } |
| | | 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)) { |
| | | result.add(it) |
| | | } |
| | | } |
| | | |
| | | this.sceneList = result |
| | | |
| | | TODO("æç
§æéçæµå åç±»åï¼åºåæ±¡ææºç±»å") |
| | | |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * 污ææ
嵿±æ» |
| | | * é坹忬¡èµ°èªï¼å®æ¶ç»è®¡å·²ææ±¡æçº¿ç´¢ï¼æç
§çç¥ç»åºèµ°èªå»ºè®® |
| | | * é坹忬¡èµ°èªï¼å®æ¶ç»è®¡å·²ææ±¡æçº¿ç´¢[PollutedClue]ï¼æç
§çç¥ç»åºèµ°èªå»ºè®® |
| | | * @date 2025/5/27 |
| | | * @author feiyu02 |
| | | */ |
| | | class PollutedSummary { |
| | | |
| | | |
| | | /** |
| | | * 5. æ±¡ææºçè¢«æ«ææ¬¡æ° |
| | | * æ¯ä¸å»é对åå²çº¿ç´¢è¿è¡ç»è®¡ï¼æåºä¼å建议ï¼ç¦»æ±¡ææºè¾è¿ãæ±¡ææºæ°éãåºç°æ¬¡æ°ï¼ãèµ°èªè·¯çº¿è°æ´å»ºè®®ï¼ç¦»æ±¡ææºè¾è¿ãèµ°èªè½¨è¿¹æªæ¥è¿æº¯æºåºæ¯ï¼ |
| | | */ |
| | | |
| | | // 污æçº¿ç´¢ |
| | | var clueList = mutableListOf<PollutedClue>() |
| | | } |