feiyu02
2024-07-02 bf3bf9ff25ac106b556b2427cc382c8fcca63bff
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
package com.flightfeather.uav.biz.dataanalysis
 
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.domain.entity.avg
import com.flightfeather.uav.socket.eunm.FactorType
import java.time.Duration
 
/**
 * 监测数据异常分析基类
 */
abstract class BaseExceptionAnalysis(config: DataAnalysisConfig) :
    BaseDataAnalysis<BaseRealTimeData, DataAnalysisConfig, ExceptionResult>(config) {
 
    /**
     * 确定异常类型
     */
    abstract fun getExceptionType(): ExceptionType
 
    /**
     * 判断相邻数据是否连续
     */
    open fun isContinuous(d1: BaseRealTimeData?, d2: BaseRealTimeData?): Boolean {
        if (d1 == null || d2 == null) return true
 
        val t1 = d1.dataTime
        val t2 = d2.dataTime
        return Duration.between(t1?.toInstant(), t2?.toInstant()).toMillis() <= (20 * 1000)
    }
 
    /**
     * 生成一条异常分析结果
     */
    open fun newResult(
        start: BaseRealTimeData, end: BaseRealTimeData?, factor: FactorFilter.SelectedFactor,
        exceptionData: List<BaseRealTimeData>,
    ): ExceptionResult {
        val eType = getExceptionType()
        return ExceptionResult().apply {
            missionCode = config.mission.missionCode
            deviceCode = start.deviceCode
            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
 
            val avgData = exceptionData.avg()
            // 求取污染数据的中心坐标
            longitude = avgData.longitude
            latitude = avgData.latitude
            // 求取主污染因子的均值和范围
            val s = dataSummary(exceptionData, factor.main)
            avg = s.first
            min = s.second
            max = s.third
 
            exceptionData.forEach { dataList.add(it) }
        }
    }
 
    private fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Float, Float, Float> {
        var min = -1f
        var max = -1f
        var total = 0f
        var count = 0
        exceptionData.forEach {
            val value = it?.getByFactorType(factorType) ?: return@forEach
            if (min == -1f || min > value) {
                min = value
            }
            if (max == -1f || max < value) {
                max = value
            }
            total += value
            count++
        }
        val avg = if (count == 0) 0f else total / count
        return Triple(avg, min, max)
    }
}