feiyu02
2025-08-14 b10c22af595bd995e56946bff63b8f2f984b13e8
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
    }
 
    override var excludedFactor: List<FactorType> = listOf(FactorType.NO2)
 
    private var callback: NewPolluteClueCallback? = null
 
    abstract var windLevelCondition: RTExcWindLevelConfig.WindLevelCondition
 
    override var judgeMethod: JudgeMethod = JudgeMethod.M1
 
    override fun getExceptionType(): ExceptionType {
        return ExceptionType.TYPE4
    }
 
    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 con = windLevelCondition
 
            if (n.windSpeed!! in con.windSpeed.first..con.windSpeed.second) {
                println("风速:${n.windSpeed},[${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 && r < con.mutationRate.second
                println("因子:${f.des},幅度:${r},限定:${con.mutationRate.first},${b1}")
                res[f] = b1
            } else {
                res[f] = false
            }
        }
 
 
        return res
    }
 
    override fun judgeExceptionCount(tag: ExceptionTag, factorType: FactorType?): Boolean {
        return tag.exceptionData.size >= windLevelCondition.countLimit
    }
 
    override fun needCut(tag: ExceptionTag, hasException: Boolean?, data: BaseRealTimeData): Boolean {
        // 按照时长和距离限制将异常截取
        if (tag.exceptionData.isEmpty()) return false
 
        val se = tag.exceptionData.first()
        val ee = data
 
        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 tag.exceptionData.size == windLevelCondition.countLimit
    }
 
    override fun newResult(tag: ExceptionTag, factor: FactorFilter.SelectedFactor): PollutedClue {
        return PollutedClue()
    }
 
    override fun newResult(exceptions: List<Pair<FactorFilter.SelectedFactor, ExceptionTag>>): PollutedClue {
        return if (exceptions.isEmpty())
            PollutedClue()
        else
            PollutedClue(exceptions, 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 mergeExceptionResult() {
//        super.mergeExceptionResult()
//        callback?.let { func ->
//            result.forEach {
//                func.invoke(it)
//            }
//        }
//    }
 
    override fun onNewResult(result: List<PollutedClue>) {
        callback?.let { func ->
            result.forEach {
                func.invoke(it)
            }
        }
    }
}