feiyu02
2024-06-27 e8f935a01d75c89ac591a80b9318eac2480e2dcd
1. 新增走航轨迹融合功能
已修改15个文件
已添加1个文件
487 ■■■■ 文件已修改
src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.flightfeather.uav.biz
import com.flightfeather.uav.socket.eunm.FactorType
/**
 * æ‰€é€‰ä¸»è¦åˆ†æžå› å­ï¼Œä»¥åŠå…³è”因子
 * åœ¨åšæ•°æ®å¼‚常分析以及数据统计时,用于决定是否需要进行处理该因子。
 * @date 2024/6/27
 * @author feiyu02
 */
class FactorFilter private constructor(){
    data class SelectedFactor(
        val main:FactorType,
        var subs:List<FactorType> = emptyList()
    )
    inner class Builder{
        fun withMain(factorType: FactorType): Builder {
            selectedList.add(SelectedFactor(factorType))
            return this
        }
        fun withSubs(subs: List<FactorType>): Builder {
            if (selectedList.isNotEmpty()) {
                selectedList.last().subs = subs
            }
            return this
        }
        fun create(): FactorFilter {
            return this@FactorFilter
        }
    }
    companion object{
        fun builder() = FactorFilter().Builder()
        fun default() = builder().create()
    }
    // æ‰€é€‰å› å­é›†åˆ
    val selectedList = mutableListOf<SelectedFactor>()
    fun mainList(): List<FactorType> {
        return selectedList.map { it.main }
    }
}
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.biz.dataanalysis
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
@@ -34,24 +35,26 @@
     * ç”Ÿæˆä¸€æ¡å¼‚常分析结果
     */
    open fun newResult(
        start: BaseRealTimeData, end: BaseRealTimeData?, factorIndex: Int,
        start: BaseRealTimeData, end: BaseRealTimeData?, factor: FactorFilter.SelectedFactor,
        exceptionData: List<BaseRealTimeData>,
    ): ExceptionResult {
        val eType = getExceptionType()
        val factorType = FactorType.getByIndex(factorIndex)
        return ExceptionResult().apply {
            missionCode = config.mission.missionCode
            deviceCode = start.deviceCode
            exception = eType.des
            exceptionType = eType.value
            factorId = factorType?.value
            factorName = factorType?.des
            factorId = factor.main.value
            factorName = factor.main.des
            subFactorId = factor.subs.map { it.value }
            subFactorName = factor.subs.map { it.des }
            selectedFactor = factor
            startTime = DateUtil.instance.dateToString(start.dataTime, DateUtil.DateStyle.HH_MM_SS)
            endTime = DateUtil.instance.dateToString(end?.dataTime, DateUtil.DateStyle.HH_MM_SS) ?: startTime
            startData = start.getByFactorIndex(factorIndex)
            endData = end?.getByFactorIndex(factorIndex) ?: startData
            startData = start.getByFactorType(factor.main)
            endData = end?.getByFactorType(factor.main) ?: startData
            val s = dataSummary(exceptionData, factorIndex)
            val s = dataSummary(exceptionData, factor.main)
            avg = s.first
            min = s.second
            max = s.third
@@ -60,13 +63,13 @@
        }
    }
    fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorIndex: Int): Triple<Float, Float, Float> {
    fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Float, Float, Float> {
        var min = -1f
        var max = -1f
        var total = 0f
        var count = 0
        exceptionData.forEach {
            val value = it?.getByFactorIndex(factorIndex) ?: return@forEach
            val value = it?.getByFactorType(factorType) ?: return@forEach
            if (min == -1f || min > value) {
                min = value
            }
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
@@ -1,7 +1,9 @@
package com.flightfeather.uav.biz.dataanalysis
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.socket.eunm.FactorType
/**
 * è¿žç»­ç±»åž‹çš„异常分析基类,适用于当前数据与相邻数据之间有关联关系的情况
@@ -13,29 +15,58 @@
        private const val OFFSET = 10
    }
    // èµ·å§‹æ•°æ®ä¸‹æ ‡
    protected var sIndex = mutableListOf<Int>()
    inner class Tag {
        // èµ·å§‹æ•°æ®ä¸‹æ ‡
        var sIndex = 0
    // èµ·å§‹æ•°æ®å¯¹è±¡
    protected var startData = mutableListOf<BaseRealTimeData?>()
        // èµ·å§‹æ•°æ®å¯¹è±¡
        var startData :BaseRealTimeData? = null
    // æœ«å°¾æ•°æ®ä¸‹æ ‡
    protected var eIndex = mutableListOf<Int>()
        // æœ«å°¾æ•°æ®ä¸‹æ ‡
        var eIndex = -1
    // æœ«å°¾æ•°æ®å¯¹è±¡
    protected var lastData: BaseRealTimeData? = null
        // æœ«å°¾æ•°æ®å¯¹è±¡
        var endData: BaseRealTimeData? = null
    // å¼‚常数据段
    protected var exceptionData = mutableListOf<MutableList<BaseRealTimeData>>()
        // å¼‚常数据段
        var exceptionData = mutableListOf<BaseRealTimeData>()
        // æ˜¯å¦å­˜åœ¨å¼‚常
        var existException = false
        fun refreshAfterCheckResult(data: BaseRealTimeData) {
            sIndex = eIndex
            startData = data
            exceptionData.clear()
            exceptionData.add(data)
        }
    }
    protected val tagMap = mutableMapOf<FactorType, Tag>()
//    // èµ·å§‹æ•°æ®ä¸‹æ ‡
//    protected var sIndex = mutableListOf<Int>()
//
//    // èµ·å§‹æ•°æ®å¯¹è±¡
//    protected var startData = mutableListOf<BaseRealTimeData?>()
//
//    // æœ«å°¾æ•°æ®ä¸‹æ ‡
//    protected var eIndex = mutableListOf<Int>()
//
//    // å¼‚常数据段
//    protected var exceptionData = mutableListOf<MutableList<BaseRealTimeData>>()
//    protected var existException = mutableListOf<Boolean>()
    // èµ·å§‹æ•°æ®ä¸Žæœ«å°¾æ•°æ®é—´éš”
    open var durationCount = 1
    protected var existException = mutableListOf<Boolean>()
    // æœ«å°¾æ•°æ®å¯¹è±¡
    protected var lastData: BaseRealTimeData? = null
    /**
     * åˆ¤æ–­æ˜¯å¦æ»¡è¶³å¼‚常条件
     */
    abstract fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): List<Boolean>
    abstract fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean>
    /**
     * åˆ¤æ–­å¼‚常出现的连续时长是否满足条件
@@ -45,44 +76,75 @@
    override fun init() {
        super.init()
        lastData = null
        repeat(config.factorCount) {
            startData.add(null)
            sIndex.add(0)
            eIndex.add(-1)
            existException.add(false)
            exceptionData.add(mutableListOf())
//        repeat(config.factorCount) {
//            startData.add(null)
//            sIndex.add(0)
//            eIndex.add(-1)
//            existException.add(false)
//            exceptionData.add(mutableListOf())
//        }
        config.factorFilter.mainList().forEach {f->
            tagMap[f] = Tag()
        }
    }
    override fun onNextData(data: BaseRealTimeData) {
        val isContinue = isContinuous(lastData, data)
        val hasException = judgeException(lastData, data)
        repeat(config.factorCount) { i ->
            eIndex[i]++
            // èµ·å§‹æ•°æ®
            if (lastData == null) {
                refreshAfterCheckResult(i, data)
            }
            // åˆ¤æ–­ç›¸é‚»æ•°æ®æ˜¯å¦è¿žç»­å¹¶ä¸”是否满足异常判断
            if (!isContinue) {
                checkResult()
                // æ•°æ®ä¸è¿žç»­æ—¶ï¼Œè®°å½•异常情况
                if (eIndex[i] - sIndex[i] >= durationCount) {
                    refreshAfterCheckResult(i, data)
        config.factorFilter.mainList().forEach {f->
            tagMap[f]?.let {
                it.eIndex++
                // èµ·å§‹æ•°æ®
                if (it.endData == null) {
                    it.refreshAfterCheckResult(data)
                }
            } else {
                if (hasException[i]) {
                    existException[i] = true
                    exceptionData[i].add(data)
                } else {
                    // å¼‚常不再重复出现时,记录异常情况
                // åˆ¤æ–­ç›¸é‚»æ•°æ®æ˜¯å¦è¿žç»­å¹¶ä¸”是否满足异常判断
                if (!isContinue) {
                    checkResult()
                    if (eIndex[i] - sIndex[i] >= durationCount) {
                        refreshAfterCheckResult(i, data)
                    // æ•°æ®ä¸è¿žç»­æ—¶ï¼Œè®°å½•异常情况
                    if (it.eIndex - it.sIndex >= durationCount) {
                        it.refreshAfterCheckResult(data)
                    }
                } else {
                    if (hasException[f] == true) {
                        it.existException = true
                        it.exceptionData.add(data)
                    } else {
                        // å¼‚常不再重复出现时,记录异常情况
                        checkResult()
                        if (it.eIndex - it.sIndex >= durationCount) {
                            it.refreshAfterCheckResult(data)
                        }
                    }
                }
            }
        }
//        repeat(config.factorCount) { i ->
//            eIndex[i]++
//            // èµ·å§‹æ•°æ®
//            if (lastData == null) {
//                refreshAfterCheckResult(i, data)
//            }
//            // åˆ¤æ–­ç›¸é‚»æ•°æ®æ˜¯å¦è¿žç»­å¹¶ä¸”是否满足异常判断
//            if (!isContinue) {
//                checkResult()
//                // æ•°æ®ä¸è¿žç»­æ—¶ï¼Œè®°å½•异常情况
//                if (eIndex[i] - sIndex[i] >= durationCount) {
//                    refreshAfterCheckResult(i, data)
//                }
//            } else {
//                if (hasException[i]) {
//                    existException[i] = true
//                    exceptionData[i].add(data)
//                } else {
//                    // å¼‚常不再重复出现时,记录异常情况
//                    checkResult()
//                    if (eIndex[i] - sIndex[i] >= durationCount) {
//                        refreshAfterCheckResult(i, data)
//                    }
//                }
//            }
//        }
        lastData = data
    }
@@ -90,33 +152,43 @@
        checkResult()
    }
    fun refreshAfterCheckResult(i:Int, data: BaseRealTimeData) {
        sIndex[i] = eIndex[i]
        startData[i] = data
        exceptionData[i].clear()
        exceptionData[i].add(data)
    }
//    fun refreshAfterCheckResult(i:Int, data: BaseRealTimeData) {
//        sIndex[i] = eIndex[i]
//        startData[i] = data
//        exceptionData[i].clear()
//        exceptionData[i].add(data)
//    }
    /**
     * æ£€æŸ¥è¿žç»­å¼‚常结束时,是否符合异常存储条件
     */
    open fun checkResult(index: Int? = null) {
        if (index != null) {
            if (existException[index] && judgeDuration(sIndex[index], eIndex[index])) {
                startData[index]?.let {
                    resultList.add(newResult(it, lastData, index, exceptionData[index]))
    open fun checkResult(factor: FactorFilter.SelectedFactor? = null) {
        val tag = tagMap[factor?.main]
        if (factor != null && tag != null) {
            if (tag.existException && judgeDuration(tag.sIndex, tag.eIndex)) {
                tag.startData?.let {
                    resultList.add(newResult(it, lastData, factor, tag.exceptionData))
                }
                existException[index] = false
                tag.existException = false
            }
        } else {
            repeat(config.factorCount) { i ->
                if (existException[i] && judgeDuration(sIndex[i], eIndex[i])) {
                    startData[i]?.let {
                        resultList.add(newResult(it, lastData, i, exceptionData[i]))
            config.factorFilter.selectedList.forEach { f ->
                val tag1 = tagMap[f.main] ?: return@forEach
                if (tag1.existException && judgeDuration(tag1.sIndex, tag1.eIndex)) {
                    tag1.startData?.let {
                        resultList.add(newResult(it, lastData, f, tag1.exceptionData))
                    }
                    existException[i] = false
                    tag1.existException = false
                }
            }
//            repeat(config.factorCount) { i ->
//                if (existException[i] && judgeDuration(sIndex[i], eIndex[i])) {
//                    startData[i]?.let {
//                        resultList.add(newResult(it, lastData, i, exceptionData[i]))
//                    }
//                    existException[i] = false
//                }
//            }
        }
    }
}
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
@@ -11,29 +11,54 @@
    override fun onNextData(data: BaseRealTimeData) {
        val isContinue = isContinuous(lastData, data)
        val hasException = judgeException(lastData, data)
        repeat(config.factorCount) { i ->
            eIndex[i]++
            if (lastData == null) {
                startData[i] = data
            }
            // åˆ¤æ–­ç›¸é‚»æ•°æ®æ˜¯å¦è¿žç»­å¹¶ä¸”是否满足异常判断
            if (!isContinue) {
                checkResult()
                sIndex[i] = eIndex[i]
                startData[i] = data
            } else {
                if (hasException[i]) {
                    // ä¿®æ”¹äº†èµ·å§‹æ•°æ®çš„位置,变更为出现异常的该值,而不是原来的出现异常的数据的前一个值
                    if (!existException[i]) {
                        sIndex[i] = eIndex[i]
                        startData[i] = data
                    }
                    existException[i] = true
                } else {
        config.factorFilter.mainList().forEach {f->
            tagMap[f]?.let {
                it.eIndex++
                if (lastData == null) {
                    it.startData = data
                }
                // åˆ¤æ–­ç›¸é‚»æ•°æ®æ˜¯å¦è¿žç»­å¹¶ä¸”是否满足异常判断
                if (!isContinue) {
                    checkResult()
                    it.sIndex = it.eIndex
                    it.startData = data
                } else {
                    if (hasException[f] == true) {
                        // ä¿®æ”¹äº†èµ·å§‹æ•°æ®çš„位置,变更为出现异常的该值,而不是原来的出现异常的数据的前一个值
                        if (!it.existException) {
                            it.sIndex = it.eIndex
                            it.startData = data
                        }
                        it.existException = true
                    } else {
                        checkResult()
                    }
                }
            }
        }
//        repeat(config.factorCount) { i ->
//            eIndex[i]++
//            if (lastData == null) {
//                startData[i] = data
//            }
//            // åˆ¤æ–­ç›¸é‚»æ•°æ®æ˜¯å¦è¿žç»­å¹¶ä¸”是否满足异常判断
//            if (!isContinue) {
//                checkResult()
//                sIndex[i] = eIndex[i]
//                startData[i] = data
//            } else {
//                if (hasException[i]) {
//                    // ä¿®æ”¹äº†èµ·å§‹æ•°æ®çš„位置,变更为出现异常的该值,而不是原来的出现异常的数据的前一个值
//                    if (!existException[i]) {
//                        sIndex[i] = eIndex[i]
//                        startData[i] = data
//                    }
//                    existException[i] = true
//                } else {
//                    checkResult()
//                }
//            }
//        }
        lastData = data
    }
}
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.biz.dataanalysis
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionDataExceed
import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionValueMutation
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
@@ -29,9 +30,9 @@
        }
    }
    fun run(mission: Mission): List<ExceptionResult> {
    fun run(mission: Mission, factorFilter: FactorFilter): List<ExceptionResult> {
        running = true
        val config = DataAnalysisConfig(mission, ExceptionSetting(), 8)
        val config = DataAnalysisConfig(mission, ExceptionSetting(), 8, factorFilter)
        initTask(config)
        val result = mutableListOf<ExceptionResult>()
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionDataExceed.kt
@@ -4,6 +4,7 @@
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.socket.eunm.FactorType
/**
 * æ•°æ®è¶…标异常分析
@@ -12,18 +13,28 @@
    override fun getExceptionType(): ExceptionType = ExceptionType.TYPE2
    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): List<Boolean> {
        val res = mutableListOf<Boolean>()
        repeat(config.factorCount) { i ->
            val data = n.getByFactorIndex(i)
            val limit = config.exceptionSetting.getByFactorIndex(i)
    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
        val res = mutableMapOf<FactorType, Boolean>()
        config.factorFilter.mainList().forEach { f ->
            val data = n.getByFactorType(f)
            val limit = config.exceptionSetting.getByFactorType(f)
            val bool = if (data != null && limit != null) {
                data >= limit
            } else {
                false
            }
            res.add(bool)
            res[f] = bool
        }
//        repeat(config.factorCount) { i ->
//            val data = n.getByFactorIndex(i)
//            val limit = config.exceptionSetting.getByFactorIndex(i)
//            val bool = if (data != null && limit != null) {
//                data >= limit
//            } else {
//                false
//            }
//            res.add(bool)
//        }
        return res
    }
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/exceptiontype/ExceptionValueMutation.kt
@@ -4,6 +4,7 @@
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.socket.eunm.FactorType
import kotlin.math.abs
/**
@@ -19,21 +20,34 @@
    override fun getExceptionType(): ExceptionType = ExceptionType.TYPE4
    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): List<Boolean> {
        val res = mutableListOf<Boolean>()
        repeat(config.factorCount) { i->
            if (p?.getByFactorIndex(i) == null || n.getByFactorIndex(i) == null) {
                res.add(false)
                return@repeat
    override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
        val res = mutableMapOf<FactorType, Boolean>()
        config.factorFilter.mainList().forEach { f ->
            if (p?.getByFactorType(f) == null || n.getByFactorType(f) == null) {
                res[f] = (false)
                return@forEach
            }
            val pValue = p.getByFactorIndex(i)!!
            val nValue = n.getByFactorIndex(i)!!
            val pValue = p.getByFactorType(f)!!
            val nValue = n.getByFactorType(f)!!
            val r = abs((pValue - nValue) / pValue)
            val b1 = r >= (2 * config.mutationRate)
            val b2 = r >= config.mutationRate
            if (b1) special = true
            res.add(b1 || b2)
            res[f] = (b1 || b2)
        }
//        repeat(config.factorCount) { i->
//            if (p?.getByFactorIndex(i) == null || n.getByFactorIndex(i) == null) {
//                res.add(false)
//                return@repeat
//            }
//            val pValue = p.getByFactorIndex(i)!!
//            val nValue = n.getByFactorIndex(i)!!
//            val r = abs((pValue - nValue) / pValue)
//            val b1 = r >= (2 * config.mutationRate)
//            val b2 = r >= config.mutationRate
//            if (b1) special = true
//            res.add(b1 || b2)
//        }
        return res
    }
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.biz.dataanalysis.model
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.domain.entity.Mission
/**
@@ -12,6 +13,8 @@
    val exceptionSetting: ExceptionSetting,
    // æ¶‰åŠç›‘测因子数量
    val factorCount: Int,
    // å› å­ç­›é€‰
    val factorFilter: FactorFilter,
){
    // è¿žç»­çªå˜æ•°æ®ä¸ªæ•°
    var mutationNum = 6
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionResult.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.biz.dataanalysis.model
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import java.math.BigDecimal
@@ -14,6 +15,9 @@
    var exceptionValue: Float? = null
    var factorId: Int? = null
    var factorName: String? = null
    var subFactorId: List<Int>? = null
    var subFactorName: List<String>? = null
    var selectedFactor: FactorFilter.SelectedFactor? = null
    var startTime: String? = null
    var endTime: String? = null
    var startData: Float? = null
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/ExceptionSetting.kt
@@ -1,5 +1,7 @@
package com.flightfeather.uav.biz.dataanalysis.model
import com.flightfeather.uav.socket.eunm.FactorType
/**
 * èµ°èˆªæ•°æ®å¼‚常标准
 */
@@ -28,4 +30,28 @@
            else -> null
        }
    }
    fun getByFactorType(factorType: FactorType): Float? {
        return when (factorType) {
            FactorType.NO2 -> no2
            FactorType.CO -> co
            FactorType.H2S -> h2s
            FactorType.SO2 -> so2
            FactorType.O3 -> o3
            FactorType.PM25 -> pm25
            FactorType.PM10 -> pm10
//            FactorType.TEMPERATURE -> temperature
//            FactorType.HUMIDITY -> humidity
            FactorType.VOC -> voc
//            FactorType.NOI -> noi
//            FactorType.LNG -> longitude?.toFloat()
//            FactorType.LAT -> latitude?.toFloat()
//            FactorType.VELOCITY -> velocity
//            FactorType.TIME -> noi
//            FactorType.WIND_SPEED -> windSpeed
//            FactorType.WIND_DIRECTION -> windDirection
//            FactorType.HEIGHT -> height
            else -> null
        }
    }
}
src/main/kotlin/com/flightfeather/uav/biz/datamerge/GridMerge.kt
@@ -3,7 +3,7 @@
import com.flightfeather.uav.lightshare.bean.DataVo
/**
 *
 * ç½‘格融合模式:根据走航范围,划分矩形网格,将所有监测数据根据经纬度划分至对应网格,计算获取网格监测数据均值;
 * @date 2024/6/26
 * @author feiyu02
 */
@@ -11,8 +11,9 @@
    fun merge(data:List<DataVo>) {
        //1. ç¡®å®šæ•°æ®èŒƒå›´ï¼Œç”¨çŸ©å½¢æ¡†å‡ºæ‰€æœ‰ç›‘测数据
        val lt = foo1(data)
        //2. æ ¹æ®æ­£æ–¹å½¢ç½‘格的边长,计算得出所有正方形网格
        //3. åŒ¹é…ç›‘测数据和对应网格,计算网格均值
    }
src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.biz.report
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.dataanalysis.ExceptionAnalysisController
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
import com.flightfeather.uav.biz.dataprocess.PreData
@@ -54,7 +55,7 @@
         */
        fun addExceptions(exceptions: List<ExceptionResult>) {
            this.exceptions = exceptions.map {
                val byteArray = DataToChartUtil.lineToByteArray(FactorType.getByValue(it.factorId!!), it.dataList)
                val byteArray = DataToChartUtil.lineToByteArray(it.selectedFactor, it.dataList)
                val base64Str = ImageUtil.compressImage2(byteArray, 400, needPrefix = false)
                val c = ExceptionChart()
                BeanUtils.copyProperties(it, c)
@@ -91,13 +92,16 @@
    private val dateFormatter = DateTimeFormatter.ofPattern("HH:mm")
    // èŽ·å–å¼‚å¸¸åˆ†æžç»“æžœ
    fun exceptionAnalysis(mission: Mission): List<ExceptionResult> {
        return exceptionAnalysisController.run(mission)
    fun exceptionAnalysis(mission: Mission, factorFilter: FactorFilter): List<ExceptionResult> {
        return exceptionAnalysisController.run(mission, factorFilter)
    }
    // è®¡ç®—均值和数据范围
    fun dataSummary(mission: Mission): List<Summary> {
        val preData = PreData(DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD))
    fun dataSummary(mission: Mission, factorFilter: FactorFilter): List<Summary> {
        val preData = PreData(
            DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD),
            factorFilter.mainList()
        )
        val realTimeData = realTimeDataRep.fetchData(mission)
        realTimeData.forEach {
            preData.add(it.toDataVo())
@@ -123,13 +127,13 @@
    // ç”Ÿæˆå‚æ•°
    // æ ¹æ®æŠ¥å‘Šæ¨¡æ¿ç”Ÿæˆå¯¹åº”报告
    fun execute(missionCode: String): String {
    fun execute(missionCode: String, factorFilter: FactorFilter): String {
        // 1. ä»»åŠ¡åˆæ³•æ€§æ£€æŸ¥
        val mission = missionRep.findOne(missionCode) ?: throw  BizException("该任务编号不存在")
        // 2. èŽ·å–æ•°æ®å¼‚å¸¸ç»Ÿè®¡ç»“æžœ
        val exceptions = exceptionAnalysis(mission)
        // 2. èŽ·å–æ•°æ®å¼‚å¸¸ç»Ÿè®¡ç»“æžœï¼Œæ ¹æ®
        val exceptions = exceptionAnalysis(mission, factorFilter)
        // 3. èŽ·å–å‡å€¼ã€èŒƒå›´ç­‰ç»Ÿè®¡æ•°æ®
        val summaries = dataSummary(mission)
        val summaries = dataSummary(mission, factorFilter)
        // 4. ç”ŸæˆæŠ¥å‘Š
        val fileName = "report/" + "${mission.districtName}走航监测报告-${
            DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD)
src/main/kotlin/com/flightfeather/uav/common/chart/ChartUtil.kt
@@ -3,9 +3,16 @@
import org.jfree.chart.ChartFactory
import org.jfree.chart.ChartUtils
import org.jfree.chart.JFreeChart
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator
import org.jfree.chart.labels.StandardCategorySeriesLabelGenerator
import org.jfree.chart.plot.CategoryPlot
import org.jfree.chart.renderer.category.LineAndShapeRenderer
import org.jfree.chart.title.TextTitle
import org.jfree.data.category.DefaultCategoryDataset
import java.awt.BasicStroke
import java.awt.Color
import java.awt.Font
import java.awt.Paint
import java.io.ByteArrayOutputStream
/**
@@ -19,8 +26,9 @@
    fun line(title: String, dataset: DefaultCategoryDataset): JFreeChart {
        val line = ChartFactory.createLineChart(title, "时间", "浓度", dataset)
        line.categoryPlot.domainAxis.labelFont = Font("宋体", Font.PLAIN, 12)
        line.categoryPlot.rangeAxis.labelFont = Font("宋体", Font.PLAIN, 12)
//        line.categoryPlot.domainAxis.labelFont = Font("宋体", Font.PLAIN, 12)
//        line.categoryPlot.rangeAxis.labelFont = Font("宋体", Font.PLAIN, 12)
        setLine(line)
        return line
    }
@@ -41,4 +49,31 @@
        }
        return dataset
    }
    /**
     * è®¾ç½®æŠ˜çº¿å›¾æ ·å¼
     */
    private fun setLine(chart: JFreeChart) {
        chart.legend.itemFont = Font("SimHei", Font.PLAIN, 16)
        chart.title.font = Font("SimHei", Font.BOLD, 20)
        chart.categoryPlot.apply {
            backgroundPaint = Color(255, 255, 255)
            rangeGridlinePaint = Color(200, 200, 200)
            rangeGridlineStroke = BasicStroke(1f)
            isRangeGridlinesVisible = true
        }
    }
    private fun setRenderer(plot:CategoryPlot, datasetList:List<DefaultCategoryDataset>) {
        val renderer = newBasicRenderer(paint = Color(191, 0, 0))
    }
    private fun newBasicRenderer(series:Int = 0, paint:Paint): LineAndShapeRenderer {
        return LineAndShapeRenderer().apply {
            legendItemLabelGenerator = StandardCategorySeriesLabelGenerator()
            setSeriesStroke(series, BasicStroke(3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 2000f))
            setSeriesShapesVisible(series, false)
            setSeriesPaint(series, paint)
        }
    }
}
src/main/kotlin/com/flightfeather/uav/common/chart/DataToChartUtil.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.common.chart
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.socket.eunm.FactorType
@@ -11,13 +12,13 @@
 */
object DataToChartUtil {
    fun lineToByteArray(type: FactorType?, data: List<BaseRealTimeData>): ByteArray {
        val title = type?.des ?: "未知监测因子"
        val seriesName = type?.des ?: "未知系列"
    fun lineToByteArray(type: FactorFilter.SelectedFactor?, data: List<BaseRealTimeData>): ByteArray {
        val title = type?.main?.des ?: "未知监测因子"
        val seriesName = type?.main?.des ?: "未知系列"
        val dataList = data.map { d ->
            ChartUtil.ChartValue(
                DateUtil.instance.dateToString(d.dataTime, DateUtil.DateStyle.HH_MM_SS),
                d.getByFactorType(type) ?: 0f
                d.getByFactorType(type?.main) ?: 0f
            )
        }
        val dataset = ChartUtil.newDataset(dataList, seriesName)
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.lightshare.service.impl
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.report.MissionReport
import com.flightfeather.uav.common.exception.BizException
import com.flightfeather.uav.domain.entity.Mission
@@ -60,6 +61,6 @@
    }
    override fun getReport(missionCode: String, response: HttpServletResponse) {
        missionReport.execute(missionCode)
        missionReport.execute(missionCode, FactorFilter.default())
    }
}
src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
@@ -1,5 +1,6 @@
package com.flightfeather.uav.lightshare.service.impl
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.report.MissionReport
import com.flightfeather.uav.lightshare.service.MissionService
import org.junit.Test
@@ -23,6 +24,6 @@
    @Test
    fun getReport() {
        missionReport.execute("SH-CN-20240514")
        missionReport.execute("SH-CN-20240514", FactorFilter.default())
    }
}