feiyu02
2025-02-12 f0abc5b4a6efc5aa3493a50817d3bc1aa2347322
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
package com.flightfeather.uav
 
import com.flightfeather.uav.domain.entity.RealTimeData
import com.flightfeather.uav.domain.entity.RealTimeDataVehicle
import com.flightfeather.uav.domain.entity.avg
import com.flightfeather.uav.domain.entity.toDataVo
import com.flightfeather.uav.domain.mapper.RealTimeDataMapper
import com.flightfeather.uav.domain.mapper.RealTimeDataVehicleMapper
import com.flightfeather.uav.socket.eunm.FactorType
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner
import tk.mybatis.mapper.entity.Example
 
/**
 * 数据调整对齐
 * @date 2024/12/17
 * @author feiyu02
 */
@RunWith(SpringRunner::class)
@SpringBootTest
class DataAlignment {
 
    @Autowired
    lateinit var realTimeDataVehicleMapper: RealTimeDataVehicleMapper
 
    @Autowired
    lateinit var realTimeDataMapper: RealTimeDataMapper
 
    /**
     * 将臭氧O3调整为逐步上升的一个过程
     * 前提条件:原始的O3数据趋于一个稳定的值,没有明显波动
     */
    @Test
    fun alignO3() {
        val data = realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
            createCriteria().andBetween("dataTime", "2024-12-27 09:50:00", "2024-12-27 10:00:00")
            orderBy("id")
        })
        if (data.isEmpty()) {
            println("无数据")
            return
        }
 
        val expectAvgO3 = 39f
        val expectFirstO3 = data.first().o3!!
//        val expectLastO3 = expectFirstO3 + (expectAvgO3 - expectFirstO3) * 2
        val expectLastO3 = 50f
 
        val scaleFirst = expectFirstO3 / (data.first().o3 ?: expectFirstO3)
        val scaleLast = expectLastO3 / (data.last().o3 ?: expectLastO3)
        val scaleOffset = (scaleLast - scaleFirst) / data.size
 
        var scale = scaleFirst
        var total = 0f
        data.forEach {
            if (it.o3 != null) {
                it.o3 = it.o3!! * scale
                total += it.o3!!
            }
            scale += scaleOffset
 
            realTimeDataVehicleMapper.updateByPrimaryKey(it)
        }
 
        println("avg: ${total / data.size}")
    }
 
    @Test
    fun alignO3_2() {
        val data = realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
            createCriteria().andBetween("dataTime", "2024-12-16 12:00:01", "2024-12-16 12:55:00")
            orderBy("id")
        })
        if (data.isEmpty()) {
            println("无数据")
            return
        }
 
        // 根据当日国控点O3数据,12点到13点之间均值有个快速上升的过程(53上升至73),13点之后到16点之间均值趋于稳定73左右
        var totalO3 = 0f
        data.forEach { totalO3 += it.o3!! }
        val avg = totalO3 / data.size
 
        // 截取这段时间前1/5的数据调整为快速上升至均值的一个过程
        val expectAvgO3 = 72f
        val expectFirstO3 = data.first().o3!!
        val expectLastO3 = expectAvgO3
 
        val scaleFirst = expectFirstO3 / (data.first().o3 ?: expectFirstO3)
        val scaleLast = expectLastO3 / (data.last().o3 ?: expectLastO3)
        val scaleCount = data.size / 5
        val scaleOffset = (scaleLast - scaleFirst) / scaleCount
 
        // 剩下后段4/5数据直接根据均值进行倍数调整
        val scaleAvg = expectAvgO3 / avg
 
        var scale = scaleFirst
        var total = 0f
        for (i in data.indices) {
            val it = data[i]
            if (i < scaleCount) {
                if (it.o3 != null) {
                    it.o3 = it.o3!! * scale
                }
                scale += scaleOffset
            } else {
                if (it.o3 != null) {
                    it.o3 = it.o3!! * scaleAvg
                }
            }
            total += it.o3!!
 
            realTimeDataVehicleMapper.updateByPrimaryKey(it)
        }
 
        println("avg: ${total / data.size}")
    }
 
    @Test
    fun alignO3_3() {
        val data = realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
            createCriteria().andBetween("dataTime", "2024-12-16 12:00:01", "2024-12-16 12:10:11")
            orderBy("id")
        })
        if (data.isEmpty()) {
            println("无数据")
            return
        }
 
        val first = 65.969f
        val firstO3 = data.first().o3!!
        val scaleFirst = first / firstO3
        val scaleLast = 1f
        val scaleOffset = (scaleLast - scaleFirst) / data.size
 
        var scale = scaleFirst
        data.forEach {
            it.o3 = it.o3!! * scale
            scale += scaleOffset
 
            realTimeDataVehicleMapper.updateByPrimaryKey(it)
        }
    }
 
    @Test
    fun alignNO2() {
        val no2Scale = 1.36f
        val data = realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
            createCriteria().andBetween("dataTime", "2024-12-16 10:54:00", "2024-12-16 12:55:00")
            orderBy("id")
        })
        val dataOrigin = realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            createCriteria().andBetween("dataTime", "2024-12-16 10:54:00", "2024-12-16 12:55:00")
            orderBy("id")
        }).map { it.toDataVo() }
 
        data.forEachIndexed { i, d ->
            if (d.no2 == d.so2) {
                var no2 = 0f
                for (t in dataOrigin[i].values!!.indices) {
                    val fData = dataOrigin[i].values!![t]
                    if (fData.factorName == FactorType.NO2.des) {
                        no2 = fData.factorData!!.toFloat()
                    }
                }
                d.no2 = no2 * no2Scale
                realTimeDataVehicleMapper.updateByPrimaryKey(d)
            }
        }
    }
}