feiyu02
2025-08-14 f373bbf83d9d2a7e5f96118d7dcd658c9fea8bc8
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
package cn.flightfeather.supervision.business.autooutput.dataanalysis
 
import cn.flightfeather.supervision.business.autooutput.AopOutput
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.ds3.entity.FumeDailyAnalysis
import cn.flightfeather.supervision.domain.ds3.entity.FumeExceptionData
import cn.flightfeather.supervision.domain.ds3.entity.FumeSiteMap
import cn.flightfeather.supervision.domain.ds3.mapper.FumeDailyAnalysisMapper
import cn.flightfeather.supervision.domain.ds3.mapper.FumeExceptionDataMapper
import cn.flightfeather.supervision.domain.ds3.mapper.FumeSiteMapMapper
import org.springframework.stereotype.Component
import tk.mybatis.mapper.entity.Example
import kotlin.math.round
 
/**
 * 徐汇油烟监测数据统计
 */
@Component
class XHFuDataAnalysis(
    aopDbMapper: AopDbMapper,
    aopSceneTypeCheck: AopSceneTypeCheck,
    aopOutput: AopOutput,
    private val fumeSiteMapMapper: FumeSiteMapMapper,
    private val fumeDailyAnalysisMapper: FumeDailyAnalysisMapper,
    private val fumeExceptionDataMapper: FumeExceptionDataMapper,
) : AopDataAnalysis<FumeDailyAnalysis>(aopDbMapper, aopSceneTypeCheck, aopOutput) {
 
    // 油烟数据暂无区均值的计算
    override fun districtAvg(source: AopDataSource?): Double? {
        return null
    }
 
    private fun getDeviceCodes(evaluationScene: AopDataSource.EvaluationScene): List<String?> {
        val fumeSiteMaps = fumeSiteMapMapper.selectByExample(Example(FumeSiteMap::class.java).apply {
            createCriteria().andEqualTo("svUserId", evaluationScene.userInfo.value?.guid)
                .andIsNotNull("xhDeviceCode")
        })
        return fumeSiteMaps.map { it?.xhDeviceCode }
    }
 
    override fun getDeviceCode(data: FumeDailyAnalysis?): String? {
        return data?.fumeDevId
    }
 
    override fun fetchDataResources(evaluationScene: AopDataSource.EvaluationScene): List<List<FumeDailyAnalysis?>> {
        val deviceCodeList = getDeviceCodes(evaluationScene)
        val map = mutableMapOf<String?, MutableList<FumeDailyAnalysis?>>()
        fumeDailyAnalysisMapper.selectByExample(Example(FumeDailyAnalysis::class.java).apply {
            createCriteria().andBetween("fumeDate", evaluationScene.config?.startTime, evaluationScene.config?.endTime)
                .apply {
                    if (deviceCodeList.isNotEmpty()) {
                        andIn("fumeDevId", deviceCodeList)
                    }
                }
        }).forEach {
            if (!map.containsKey(it?.fumeDevId)) {
                map[it?.fumeDevId] = mutableListOf()
            }
            map[it?.fumeDevId]?.add(it)
        }
        val res = mutableListOf<List<FumeDailyAnalysis?>>()
        map.forEach { (_, u) ->
            res.add(u)
        }
        return res
    }
 
    fun fetchExceptionData(evaluationScene: AopDataSource.EvaluationScene): List<FumeExceptionData?> {
        val deviceCodeList = getDeviceCodes(evaluationScene)
        return if (deviceCodeList.isEmpty()) {
            emptyList()
        } else {
            val code = deviceCodeList[0]
            fumeExceptionDataMapper.selectByExample(Example(FumeExceptionData::class.java).apply {
                createCriteria().andBetween("beginTime",
                    evaluationScene.config?.startTime,
                    evaluationScene.config?.endTime)
                    .andEqualTo("devId", code)
                    .andEqualTo("exception", "数据异常")
                    .andEqualTo("exceptionType", "0")
            })
        }
    }
 
    /**
     * 油烟超标数
     * 只统计重点时段内(中午、晚上)的超标情况
     */
    override fun exceedTimes(data: FumeDailyAnalysis, t: TempResult) {
        data.noonExceedingNum?.toInt()?.let {
            t.count += it
        }
        data.nightExceedingNum?.toInt()?.let {
            t.count += it
        }
    }
 
    override fun avg(data: FumeDailyAnalysis, t: TempResult) {
        data.fumeDayAverage?.let {
            t.total += it
            t.count++
        }
    }
 
    override fun max(data: FumeDailyAnalysis, t: TempResult) {
        data.fumeDayMax?.let {
            if (it > t.total) {
                t.total = it
            }
        }
    }
 
    override fun min(data: FumeDailyAnalysis, t: TempResult) {
        data.fumeDayMin?.let {
            if (t.count == 0 || it < t.total) {
                t.total = it
            }
            // 通过t.count 来判定是否是初始化状态
            if (t.count == 0) t.count = 1
        }
    }
 
    override fun overAvgRate(avg: Double, dAvg: Double?): Double? {
        return null
    }
 
    override fun effectiveRate(
        dataList: List<List<FumeDailyAnalysis?>>,
        evaluationScene: AopDataSource.EvaluationScene,
    ): Double {
        var total = .0
        var count = 0
        dataList.forEach { list ->
            list.forEach {
                val noon = it?.noonOnlineRate?.removeSuffix("%")?.toDouble()?.div(100)
                val night = it?.nightOnlineRate?.removeSuffix("%")?.toDouble()?.div(100)
                noon?.let {
                    total += noon
                    count++
                }
                night?.let {
                    total += night
                    count++
                }
            }
        }
        return if (count == 0) {
            .0
        } else {
            round((total / count) * 1000) / 1000
        }
    }
}