package com.flightfeather.uav.model.epw
|
|
import com.flightfeather.uav.common.utils.DateUtil
|
import com.flightfeather.uav.common.utils.GsonUtils
|
import com.flightfeather.uav.lightshare.bean.CompanySOP
|
import com.flightfeather.uav.lightshare.bean.DataVo
|
import com.flightfeather.uav.model.BaseDataPrep
|
import com.flightfeather.uav.model.BaseSOP
|
import com.flightfeather.uav.socket.bean.AirData
|
import com.flightfeather.uav.socket.bean.AirDataPackage
|
import com.flightfeather.uav.socket.eunm.FactorType
|
import kotlin.math.max
|
import kotlin.math.min
|
import kotlin.math.round
|
import kotlin.math.sqrt
|
|
class EPWDataPrep : BaseDataPrep<DataVo, BaseSOP>() {
|
|
// 向前检索的数据记录数
|
private val ncal = 15
|
// 标准差倍数参数
|
private val nstd = 3
|
// 均值倍数参数
|
private val xratio = 3
|
// 需要处理的因子类型
|
private val calTypes =
|
// emptyList<String>()
|
WeightType.prep
|
|
private val lastData = mutableListOf<DataVo>()
|
|
override fun mDataPrep(mDataList: List<DataVo>): List<DataVo> {
|
mDataList.forEach {
|
it.values?.forEach v@{a ->
|
if (!calTypes.contains(a.factorName)) return@v
|
|
val range = FactorType.getRange(a.factorName) ?: return@v
|
// 判断数据是否在合理范围内
|
if (a.factorData != null && (a.factorData!! < range.first || a.factorData!! > range.second)) {
|
a.factorData = null
|
}
|
}
|
}
|
|
// val newDataList = mutableListOf<DataVo>()
|
// mDataList.forEach {
|
// newDataList.add(it.copy())
|
// }
|
|
var i = ncal
|
if (lastData.isNotEmpty()) {
|
i = 0
|
}
|
while (i < mDataList.size) {
|
for (y in mDataList[i].values?.indices ?: 0..0) {
|
val it = mDataList[i].values?.get(y) ?: continue
|
|
if (!calTypes.contains(it.factorName)) continue
|
val vMax = FactorType.getVMax(it.factorName) ?: continue
|
it.factorData ?: continue
|
|
if (it.factorData!! > vMax) {
|
val lastDataIndex = i
|
val thisIndex = if (i-ncal<0) 0 else i - ncal
|
val list = mutableListOf<DataVo>()
|
if (lastDataIndex < lastData.size) {
|
list.addAll(lastData.subList(lastDataIndex, lastData.lastIndex + 1))
|
}
|
list.addAll(mDataList.subList(thisIndex, i))
|
|
// 去除无效值的平均
|
val avg = average(list, it.factorName) ?: continue
|
// 去除无效值的标准差
|
val std = standardDeviation(avg.first, list, it.factorName)
|
// 合理最大值
|
val max = max(avg.first + std * nstd, avg.first + avg.first * xratio)
|
// 合理最小值
|
val min = min(avg.first - std * nstd, avg.first / (1 + xratio))
|
|
// 数据不处于合理范围并且有效个数达标时,采用计算所得均值代替原始值
|
if (avg.second > max(ncal / 5, 2)
|
&& (it.factorData!! < min || it.factorData!! > max)
|
) {
|
// 原始数据
|
it.factorData = null
|
// newDataList[i].values?.get(y)?.factorData = avg.first
|
}
|
}
|
}
|
|
i++
|
}
|
|
lastData.clear()
|
val s = if ((mDataList.lastIndex - ncal + 1) < 0) 0 else mDataList.lastIndex - ncal + 1
|
mDataList.subList(s, mDataList.lastIndex + 1).forEach {
|
lastData.add(it.copy())
|
}
|
|
return mDataList
|
}
|
|
override fun sopPrep(sopList: List<BaseSOP>): List<BaseSOP> {
|
return sopList
|
}
|
|
fun mDataPrep2(dataPackage: AirDataPackage): List<DataVo> {
|
val vo = dataPackage.toDataVo()
|
return mDataPrep2(listOf(vo))
|
}
|
|
fun mDataPrep2(mDataList: List<DataVo>): List<DataVo> {
|
var i = ncal
|
if (lastData.isNotEmpty()) {
|
i = 0
|
}
|
while (i < mDataList.size) {
|
for (y in mDataList[i].values?.indices ?: 0..0) {
|
val it = mDataList[i].values?.get(y) ?: continue
|
|
if (!calTypes.contains(it.factorName)) continue
|
val vMax = FactorType.getVMax(it.factorName) ?: continue
|
// it.factorData ?: continue
|
|
if (it.factorData!! > vMax) {
|
val lastDataIndex = i
|
val thisIndex = if (i-ncal<0) 0 else i - ncal
|
val list = mutableListOf<DataVo>()
|
if (lastDataIndex < lastData.size) {
|
list.addAll(lastData.subList(lastDataIndex, lastData.lastIndex + 1))
|
}
|
list.addAll(mDataList.subList(thisIndex, i))
|
|
// 去除无效值的平均,当所有数据都是无效值时,暂不做处理
|
average(list, it.factorName)?.let { avg ->
|
// 去除无效值的标准差
|
val std = standardDeviation(avg.first, list, it.factorName)
|
// 合理最大值
|
val max = max(avg.first + std * nstd, avg.first + avg.first * xratio)
|
// 合理最小值
|
val min = min(avg.first - std * nstd, avg.first / (1 + xratio))
|
|
// 数据不处于合理范围并且有效个数达标时,采用计算所得均值代替原始值
|
if (avg.second > max(ncal / 5, 2)
|
&& (it.factorData!! < min || it.factorData!! > max)
|
) {
|
// 原始数据
|
// it.factorData = null
|
it.factorData = avg.first
|
}
|
}
|
}
|
}
|
|
i++
|
}
|
|
// 将新数据的至多最后15个保存下来(已经过预处理),用于下一次的判断
|
val newList = mutableListOf<DataVo>()
|
val s = if ((mDataList.lastIndex - ncal + 1) < 0) 0 else mDataList.lastIndex - ncal + 1
|
mDataList.subList(s, mDataList.lastIndex + 1).forEach {
|
newList.add(it.copy())
|
}
|
// 当新数据与旧数据采样时间差超过1分钟时,认为两组数据已无关联性,清空旧数据
|
if (lastData.isNotEmpty() && newList.isNotEmpty()) {
|
val lastTime = DateUtil.instance.StringToDate(lastData.last().time)
|
val thisTime = DateUtil.instance.StringToDate(newList.first().time)
|
if ((thisTime?.time?.minus(lastTime?.time ?: 0) ?: 0) >= (60 * 1000)) {
|
lastData.clear()
|
}
|
}
|
lastData.addAll(newList)
|
// 确保保存的数据最多只有最新的15个
|
while (lastData.size > ncal) {
|
lastData.removeAt(0)
|
}
|
|
return mDataList
|
}
|
|
/**
|
* 去除无效值的平均
|
* @param list 监测数据
|
* @return 均值和有效数据个数
|
*/
|
private fun average(list: List<DataVo>, factorName:String?): Pair<Double, Int>? {
|
var t = 0.0
|
var c = 0
|
list.forEach {
|
for (i in it.values?.indices ?: 0..0) {
|
val f = it.values?.get(i)
|
if (f?.factorName == factorName) {
|
val range = FactorType.getRange(f?.factorName) ?: continue
|
//判断数据是否在合理范围内
|
if (f?.factorData ?: 0.0 in range.first..range.second) {
|
t += f?.factorData!!
|
c++
|
}
|
break
|
}
|
}
|
}
|
|
val avg = if (c == 0) {
|
0.0
|
} else {
|
round(t / c * 1000) / 1000
|
}
|
|
return if (c == 0) {
|
null
|
} else {
|
Pair(avg, c)
|
}
|
}
|
|
/**
|
* 去除无效值的标准差
|
*/
|
private fun standardDeviation(avg: Double, list: List<DataVo>, factorName: String?): Double {
|
var t = 0.0
|
var c = 0
|
list.forEach {
|
for (i in it.values?.indices ?: 0..0) {
|
val f = it.values?.get(i)
|
if (f?.factorName == factorName) {
|
val range = FactorType.getRange(f?.factorName) ?: continue
|
if ((f?.factorData ?: 0.0) in range.first..range.second) {
|
t += (f?.factorData!! - avg) * (f.factorData!! - avg)
|
c++
|
}
|
break
|
}
|
}
|
}
|
|
return if (c <= 1) {
|
0.0
|
} else {
|
sqrt(t / (c - 1))
|
}
|
}
|
}
|