From da431c25dfe5122e4ed70372da36ede3e4eaec4a Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期五, 31 五月 2024 17:43:41 +0800
Subject: [PATCH] 1. 新增自动报告生成功能

---
 src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt |  185 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 162 insertions(+), 23 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt b/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt
index 3f23d11..c17296d 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt
@@ -1,45 +1,61 @@
 package com.flightfeather.uav.model.epw
 
-import com.flightfeather.uav.lightshare.bean.CompanySOP
+import com.flightfeather.uav.common.utils.DateUtil
 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, CompanySOP>() {
+/**
+ * 鏁版嵁骞虫粦棰勫鐞�
+ * 瀵逛簬鏈�鏂扮殑涓�缁勬暟鎹紝鏍规嵁鍏朵箣鍓嶈繛缁殑鑻ュ共鏁版嵁锛岃繘琛屾暟鎹钩婊戝鐞�
+ * @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()) {
@@ -55,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))
@@ -63,7 +79,7 @@
                     list.addAll(mDataList.subList(thisIndex, i))
 
                     // 鍘婚櫎鏃犳晥鍊肩殑骞冲潎
-                    val avg = average(list, it.factorName)
+                    val avg = average(list, it.factorName) ?: continue
                     // 鍘婚櫎鏃犳晥鍊肩殑鏍囧噯宸�
                     val std = standardDeviation(avg.first, list, it.factorName)
                     // 鍚堢悊鏈�澶у��
@@ -86,15 +102,103 @@
         }
 
         lastData.clear()
-        mDataList.subList(mDataList.lastIndex - ncal + 1, mDataList.lastIndex + 1).forEach {
+        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<CompanySOP>): List<CompanySOP> {
+    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
+                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 (!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
+                            }
+                        }
+
+                    }
+                }
+            }
+
+            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
     }
 
     /**
@@ -102,15 +206,17 @@
      * @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 {
             for (i in it.values?.indices ?: 0..0) {
                 val f = it.values?.get(i)
                 if (f?.factorName == factorName) {
-                    if (f?.factorData != null) {
-                        t += f.factorData!!
+                    val range = FactorType.getRange(f?.factorName) ?: continue
+                    //鍒ゆ柇鏁版嵁鏄惁鍦ㄥ悎鐞嗚寖鍥村唴
+                    if ((f?.factorData ?: 0.0) in range.first..range.second) {
+                        t += f?.factorData!!
                         c++
                     }
                     break
@@ -121,10 +227,14 @@
         val avg = if (c == 0) {
             0.0
         } else {
-            t / c
+            round(t / c * 1000) / 1000
         }
 
-        return Pair(avg, c)
+        return if (c == 0) {
+            null
+        } else {
+            Pair(avg, c)
+        }
     }
 
     /**
@@ -137,8 +247,9 @@
             for (i in it.values?.indices ?: 0..0) {
                 val f = it.values?.get(i)
                 if (f?.factorName == factorName) {
-                    if (f?.factorData != null) {
-                        t += (f.factorData!! - avg) * (f.factorData!! - avg)
+                    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
@@ -152,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
+    }
 }
\ No newline at end of file

--
Gitblit v1.9.3