feiyu02
2021-12-02 74ffc8ebf3a25d2e3cee758954ce6efc163cb864
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
package com.flightfeather.uav.dataprocess
 
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.socket.eunm.FactorType
import java.math.BigDecimal
import kotlin.math.max
import kotlin.math.min
import kotlin.math.round
import kotlin.math.sqrt
 
/**
 * 预处理数据
 */
class PreData(
    //统计时间
    private val time: String?,
    //是否需要计算分位值
    private val needQuartile: Boolean = true
) {
 
    inner class TempData {
        //数据平方和(用于计算标准差)
        var sumOfSquares: BigDecimal = BigDecimal.ZERO
        //数据和
        var total: BigDecimal = BigDecimal.ZERO
 
        //计数
        var count: Int = 0
        var minV: Double = Double.MAX_VALUE
        var maxV: Double = Double.MIN_VALUE
 
        //数据值记录,按照升序排列,用于获取分位值
        // "10%分位值",
        // "25%分位值",
        // "50%分位值",
        // "75%分位值",
        // "90%分位值"
        val dataList = mutableListOf<Double>()
    }
 
    companion object {
        //需要统计的监测因子
        val needFactor = listOf(
//            FactorType.NO2, FactorType.CO, FactorType.H2S, FactorType.SO2, FactorType.O3, FactorType.PM25, FactorType.PM10,
            FactorType.VOC
        )
        //需要计算的项目
        val items = listOf(
            "记录数", "均值", "标准差", "最小值", "最大值", "10%分位值", "25%分位值", "50%分位值", "75%分位值", "90%分位值"
        )
    }
 
    //按照每种监测因子记录当前时间下的统计中间数据
    private val dataMap = mutableMapOf<String?, TempData>()
 
    fun add(data: DataVo) {
        data.values?.forEach {
            if (!dataMap.containsKey(it.factorName)) {
                dataMap[it.factorName] = TempData()
            }
            dataMap[it.factorName]?.apply {
                sumOfSquares = sumOfSquares.plus(BigDecimal.valueOf(
                    (it.factorData ?: .0) * (it.factorData ?: .0)
                ))
                total = total.plus(BigDecimal.valueOf(it.factorData ?: .0))
                count++
                minV = min(minV, it.factorData?: .0)
                maxV = max(maxV, it.factorData?: .0)
 
                if (needQuartile) {
                    dataList.add(it.factorData ?: .0)
                }
            }
        }
    }
 
    /**
     * 输出当前统计时间下的一行统计数据
     */
    fun getOutPutContent(): Array<Any> {
        //每种监测因子都有对应的一系列统计项
        val content = mutableListOf<Any>()
        //第一列是统计时间
        content.add(time ?: "错误时间")
        needFactor.forEach {
            dataMap[it.name]?.let {t ->
                content.apply {
                    //"记录数",
                    val c = BigDecimal("${t.count}")
                    add(t.count)
                    // "均值",
                    val avg = t.total.div(c)
                    add(avg.toString())
                    // "标准差",
                    add(
                        sqrt(
                            t.sumOfSquares.minus(
                                avg.times(BigDecimal(2)).times(t.total)
                            ).plus(
                                avg.times(avg).times(c)
                            ).div(c).toDouble()
                        ).toString()
                    )
                    // "最小值",
                    add(t.minV)
                    // "最大值",
                    add(t.maxV)
                    //分位值
                    if (needQuartile) {
                        t.dataList.sortBy { d -> d }
                        val size = t.dataList.size
                        // "10%分位值",
                        add(t.dataList[round(size * .1).toInt()])
                        // "25%分位值",
                        add(t.dataList[round(size * .25).toInt()])
                        // "50%分位值",
                        add(t.dataList[round(size * .5).toInt()])
                        // "75%分位值",
                        add(t.dataList[round(size * .75).toInt()])
                        // "90%分位值"
                        add(t.dataList[round(size * .9).toInt()])
                    } else {
                        add("")
                        add("")
                        add("")
                        add("")
                        add("")
                    }
                }
            }
        }
 
        clear()
        return content.toTypedArray()
    }
 
    /**
     * 释放内存
     */
    private fun clear() {
        dataMap.clear()
    }
}