feiyu02
2025-09-12 dc4f12f66685260ac357997680e5f3fe723c3c4a
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package cn.flightfeather.supervision.business.autooutput.dataanalysis
 
import cn.flightfeather.supervision.business.autooutput.AopOutput
import cn.flightfeather.supervision.business.autooutput.datasource.AopDataConfig
import cn.flightfeather.supervision.business.autooutput.datasource.AopDataSource
import cn.flightfeather.supervision.business.autooutput.datasource.AopDbMapper
import cn.flightfeather.supervision.business.autooutput.datasource.AopSceneTypeCheck
import cn.flightfeather.supervision.domain.ds1.entity.DustDataResult
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.*
import kotlin.math.round
 
/**
 * 监测数据分析入库
 * 根据每月为一个周期,统计当月的超标次数、均值、最大最小值、超区均值百分比、数据个数、有效率等数据
 */
abstract class AopDataAnalysis<T>(
    private val aopDbMapper: AopDbMapper,
    private val aopSceneTypeCheck: AopSceneTypeCheck,
    private val aopOutput: AopOutput,
) {
 
    /**
     * 统计数据 临时存储结构
     */
    inner class TempResult(
        var total: Double = .0,
        var count: Int = 0,
    ){
        var avg: Double = -1.0
            get() {
                if (field == -1.0) {
                    field = avg()
                }
                return field
            }
 
        private fun avg(): Double {
            return if (count == 0) {
                .0
            } else {
                round((total / count) * 1000) / 1000
            }
        }
    }
 
    //数据源
    private var source: AopDataSource? = null
 
    fun setResource(topTaskGuid: String?, sceneType: Int, year: Int, month: Int) {
        source = AopDataSource(aopDbMapper, aopSceneTypeCheck)
        val st = LocalDateTime.of(year, month, 1, 0, 0, 0)
        val et = st.plusMonths(1).minusSeconds(1)
        val sTime = Date.from(st.atZone(ZoneId.systemDefault()).toInstant())
        val eTime = Date.from(et.atZone(ZoneId.systemDefault()).toInstant())
        val config = AopDataConfig(topTaskGuid = topTaskGuid, sceneType = sceneType, startTime = sTime, endTime = eTime)
        source?.setResource(config)
    }
 
    /**
     * 执行统计逻辑
     */
    fun execute(avg: Double? = null) {
        //计算区均值
        val dAvg = avg ?: districtAvg(source)
        println("均值:${dAvg}")
        //循环处理每个场景
        source?.loop { _, evaluationScene ->
            //获取原始监测数据
            val dataList = fetchDataResources(evaluationScene)
            //计算统计结果
//            var tempExceedTimes = TempResult()
//            var tempAvg = TempResult()
//            var tempMax = TempResult()
//            var tempMin = TempResult()
            dataList.forEach {
                // 监测点有多台设备时,每台设备单独记录
                val deviceCode = if (it.isNotEmpty()) {
                    getDeviceCode(it[0])
                } else {
                    null
                }
                val tempExceedTimes = TempResult()
                val tempAvg = TempResult()
                val tempMax = TempResult()
                val tempMin = TempResult()
//                val _tempExceedTimes = TempResult()
//                val _tempAvg = TempResult()
//                val _tempMax = TempResult()
//                val _tempMin = TempResult()
                it.forEach { t ->
                    t?.let {
                        exceedTimes(t, tempExceedTimes)
                        avg(t, tempAvg)
                        max(t, tempMax)
                        min(t, tempMin)
                    }
                }
                // 保留均值最高的一台设备
//                if (_tempAvg.avg > tempAvg.avg) {
//                    tempExceedTimes = _tempExceedTimes
//                    tempAvg = _tempAvg
//                    tempMax = _tempMax
//                    tempMin = _tempMin
//                }
                val dustDataResult = DustDataResult().apply {
                    drSceneId = evaluationScene.scene.value?.guid
                    drSceneName = evaluationScene.scene.value?.name
                    drDeviceCode = deviceCode
                    drTime = source?.config?.startTime
                    drExceedTimes = tempExceedTimes.count
                    drAvg = tempAvg.avg
                    drMax = tempMax.total
                    drMin = tempMin.total
                    drOverAvgPer = overAvgRate(drAvg, dAvg)
                    drDataNum = count(dataList)
                    // 当数据量为0时,超月度区均值百分比变为0
                    if (drDataNum == 0) drOverAvgPer = .0
                    drEffectiveRate = effectiveRate(dataList, evaluationScene)
                }
                //更新入库
                aopOutput.toDbDataResult(dustDataResult)
            }
        }
    }
 
    /**
     * 计算区均值
     * 当前为范围内全部监测点的均值
     */
    abstract fun districtAvg(source: AopDataSource?): Double?
 
    /**
     * 获取设备编号
     */
    abstract fun getDeviceCode(data: T?): String?
 
    /**
     * 获取原始监测数据
     */
    abstract fun fetchDataResources(evaluationScene: AopDataSource.EvaluationScene): List<List<T?>>
 
    /**
     * 超标次数
     */
    abstract fun exceedTimes(data: T, t: TempResult)
 
    /**
     * 月均值
     */
    abstract fun avg(data: T, t: TempResult)
 
    /**
     * 最大值
     */
    abstract fun max(data: T, t: TempResult)
 
    /**
     * 最小值
     */
    abstract fun min(data: T, t: TempResult)
 
    /**
     * 超月均值百分比
     */
    open fun overAvgRate(avg: Double, dAvg: Double?): Double? {
        return if (dAvg != null && dAvg != .0) {
            round(((avg - dAvg) / dAvg) * 1000) / 1000
        } else {
            .0
        }
    }
 
    /**
     * 数据个数
     */
    open fun count(dataList: List<List<T?>>): Int {
        var count = 0
        dataList.forEach {
            count += it.size
        }
        return count
    }
 
    /**
     * 有效率
     */
    abstract fun effectiveRate(dataList: List<List<T?>>, evaluationScene: AopDataSource.EvaluationScene): Double
}