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)
|
}
|
}
|
}
|