feiyu02
2024-05-31 da431c25dfe5122e4ed70372da36ede3e4eaec4a
src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt
@@ -1,51 +1,61 @@
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 com.flightfeather.uav.socket.eunm.UWDeviceType
import kotlin.math.max
import kotlin.math.min
import kotlin.math.round
import kotlin.math.sqrt
class EPWDataPrep : BaseDataPrep<DataVo, BaseSOP>() {
/**
 * 数据平滑预处理
 * 对于最新的一组数据,根据其之前连续的若干数据,进行数据平滑处理
 * @Date 2024.5.16
 */
class EPWDataPrep(val deviceType: UWDeviceType? = UWDeviceType.GRID) : BaseDataPrep<DataVo, BaseSOP>() {
    // 向前检索的数据记录数
    private val ncal = 15
    // 标准差倍数参数
    private val nstd = 3
    // 均值倍数参数
    private val xratio = 3
    // 连续数据的合理最大增长倍率
    private val multiplier = 20
    // 需要处理的因子类型
    private val calTypes =
//        emptyList<String>()
        WeightType.prep
    private var calTypes = when (deviceType) {
        UWDeviceType.VEHICLE,
        UWDeviceType.UAV,
        UWDeviceType.BOAT,
        -> WeightType.prepUnderWay
        UWDeviceType.GRID -> WeightType.prepFixed
        else -> WeightType.prepFixed
    }
    private val lastData = mutableListOf<DataVo>()
    override fun mDataPrep(mDataList: List<DataVo>): List<DataVo> {
        mDataList.forEach {
            it.values?.forEach v@{a ->
            it.values?.forEach v@{ a ->
                if (!calTypes.contains(a.factorName)) return@v
                val range = FactorType.getRange(a.factorName) ?: return@v
                // 判断数据是否在合理范围内
                if (a.factorData ?: 0.0 < range.first || a.factorData ?: 0.0 > range.second) {
                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()) {
@@ -61,7 +71,7 @@
                if (it.factorData!! > vMax) {
                    val lastDataIndex = i
                    val thisIndex = if (i-ncal<0) 0 else i - ncal
                    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))
@@ -104,11 +114,18 @@
        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()) {
@@ -117,14 +134,12 @@
        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
                it.factorData ?: continue
                if (it.factorData!! > vMax) {
                    val lastDataIndex = i
                    val thisIndex = if (i-ncal<0) 0 else i - ncal
                    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))
@@ -140,14 +155,22 @@
                        // 合理最小值
                        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
                        // 判断监测因子是否需要进行平滑处理,
                        // 若不需要,则判断量级是否在合理范围内以及变化倍率是否在合理范围内
                        if (!calTypes.contains(it.factorName)) {
                            if (isInRange(it) != true || excessiveChange(it) == true) {
                                // 采用计算所得均值代替原始值
                                it.factorData = avg.first
                            }
                        } else {
                            // 数据不处于合理范围并且有效个数达标时,采用计算所得均值代替原始值
                            if (avg.second > max(ncal / 5, 2)
                                && (it.factorData!! < min || it.factorData!! > max)
                            ) {
                                it.factorData = avg.first
                            }
                        }
                    }
                }
            }
@@ -165,7 +188,7 @@
        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)) {
            if ((thisTime?.time?.minus(lastTime?.time ?: 0) ?: 0) >= (60 * 1000)) {
                lastData.clear()
            }
        }
@@ -183,7 +206,7 @@
     * @param list 监测数据
     * @return 均值和有效数据个数
     */
    private fun average(list: List<DataVo>, factorName:String?): Pair<Double, Int>? {
    private fun average(list: List<DataVo>, factorName: String?): Pair<Double, Int>? {
        var t = 0.0
        var c = 0
        list.forEach {
@@ -192,7 +215,7 @@
                if (f?.factorName == factorName) {
                    val range = FactorType.getRange(f?.factorName) ?: continue
                    //判断数据是否在合理范围内
                    if (f?.factorData ?: 0.0 in range.first..range.second) {
                    if ((f?.factorData ?: 0.0) in range.first..range.second) {
                        t += f?.factorData!!
                        c++
                    }
@@ -225,7 +248,7 @@
                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) {
                    if ((f?.factorData ?: 0.0) in range.first..range.second) {
                        t += (f?.factorData!! - avg) * (f.factorData!! - avg)
                        c++
                    }
@@ -240,4 +263,32 @@
            sqrt(t / (c - 1))
        }
    }
    /**
     * 判断数据是否在正常量程内
     */
    private fun isInRange(airData: AirData): Boolean? {
        val range = FactorType.getRange(airData.factorName) ?: return null
        //判断数据是否在合理范围内
        return (airData.factorData ?: 0.0) in range.first..range.second
    }
    /**
     * 判断连续的数据量级上升幅度是否过大
     */
    private fun excessiveChange(airData: AirData): Boolean? {
        airData.factorData ?: return null
        if (lastData.isEmpty()) return false
        val latestData = lastData.last()
        // 结果倍率
        var m = 1.0
        for (i in latestData.values?.indices ?: 0..0) {
            val f = latestData.values?.get(i)
            if (f?.factorName == airData.factorName) {
                m = airData.factorData!!.div(f?.factorData ?: airData.factorData!!)
                break
            }
        }
        return m > multiplier
    }
}