feiyu02
2025-07-03 c56e1e74426238939f229f0005828d05089715ff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
 */
open 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
 
    open var changeRate = this.config.changeRateUp
 
    override fun getExceptionType(): ExceptionType {
        return ExceptionType.TYPE9
    }
 
    override fun judgeDataScale(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 nValue = n.getByFactorType(f)!!
            val minValue = FactorType.getVMin(f)
            res[f] = nValue >= minValue
        }
        return res
    }
 
    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 = changeRate[f]
 
            val pValue = p.getByFactorType(f)!!
            val nValue = n.getByFactorType(f)!!
            // 计算后一个数据相比于前一个数据的变化速率
            val v = (nValue - pValue)
 
            val b1 = if (rate != null) {
                v in rate.mutationRate.first..rate.mutationRate.second
            } 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 >= (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, 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)
        }
    }
}