feiyu02
2025-07-11 85909f9a78a328de2bc3efc0d1d184320cb8970b
2025.7.11
1. 修改动态溯源异常判断逻辑
已修改7个文件
113 ■■■■ 文件已修改
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionResult.kt 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseAnalysisConfig.kt
@@ -1,14 +1,21 @@
package com.flightfeather.uav.biz.dataanalysis
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.socket.eunm.FactorType
/**
 * 数据分析配置参数基类
 * @date 2025/5/13
 * @author feiyu02
 */
abstract class BaseAnalysisConfig(
abstract class BaseAnalysisConfig{
    constructor(factorFilter: FactorFilter, combination: List<List<FactorType>>?){
        this.factorFilter = factorFilter
        this.combination = combination
    }
    // 因子筛选
    val factorFilter: FactorFilter,
) {
    constructor(factorFilter: FactorFilter):this(factorFilter, null)
    val factorFilter:FactorFilter
    val combination: List<List<FactorType>>?
}
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt
@@ -27,12 +27,11 @@
    // 末尾数据对象
    protected var lastData: BaseRealTimeData? = null
    /**
     * 后置判断:当相邻数据时间不连续时,或者满足自定义条件时,对之前已有的异常进行记录
     */
    open fun afterExcCheck(isContinue: Boolean, tag: T, hasException: Boolean?): Boolean {
        return !isContinue || needCut(tag, hasException)
    }
    // 最新的一组异常,根据设定参数,将相关联的因子产生的异常合并
    protected val latestExceptionResult = mutableListOf<BaseExceptionResult>()
    // 最新的一组合并异常
    protected val latestCombinedResult = mutableListOf<List<BaseExceptionResult>>()
    /**
     * 立即判断:当出现异常时,缓存异常数据的同时,立即对已有异常进行判断是否满足异常结果要求
@@ -90,7 +89,7 @@
     * 异常数据的截取判断
     * @return
     */
    open fun needCut(tag: T, hasException: Boolean?): Boolean {
    open fun needCut(tag: T, hasException: Boolean?, data: BaseRealTimeData): Boolean {
        // 默认判断条件为 当异常不再重复出现时,形成异常结果
        return tag.exceptionExisted && hasException == false
    }
@@ -127,8 +126,11 @@
//                }
                // 2. 立即判断:当出现异常时,缓存异常数据的同时,立即对已有异常进行判断是否满足异常结果要求
                if (hasException[f] == true) {
//                    afterExcCheck(isContinue, it, hasException[f])
                    needCut(it, hasException[f])
                    if (needCut(it, hasException[f], data)) {
                        it.refreshWithNextException(data)
                    }
                    // 有异常出现时,记录异常数据
                    it.addExceptionData(data)
                    // 当立即判断通过时,形成异常结果
@@ -144,6 +146,8 @@
            }
        }
        lastData = data
        mergeExceptionResult()
    }
    override fun onDone() {
@@ -200,9 +204,41 @@
        // 异常未创建时,新建异常信息
        else {
            tag.exceptionResult.add(ex)
//            resultList.add(ex)
            tag.exceptionCreated = true
        }
        latestExceptionResult.add(ex)
    }
    /**
     * 合并异常
     */
    open fun mergeExceptionResult() {
        // 遍历所有的因子组合
        config.combination?.forEach {c ->
            val res = mutableListOf<BaseExceptionResult>()
            var exist = true
            // 查看组合内的所有因子是否都同时出现异常
            c.forEach { f->
                val r = latestExceptionResult.find { e->
                    e.factorId == f.value
                }
                if (r != null) {
                    res.add(r)
                } else {
                    exist = false
                }
            }
            // 如果组合内的所有因子都存在异常,则存储为合并异常
            if (exist) {
                // 将合并异常从单个异常集合中去除
                res.forEach { r->
                    latestExceptionResult.removeIf { e-> e.factorId == r.factorId }
                }
                // 将合并异常存储
                latestCombinedResult.add(res)
            }
        }
    }
    /**
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionResult.kt
@@ -15,6 +15,9 @@
    // 异常的状态
    var status: Int = ExceptionStatusType.InProgress.value
    var factorId: Int? = null
    var factorName: String? = null
    init {
        guid = UUID.randomUUID().toString()
    }
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
@@ -32,19 +32,23 @@
        this.sceneInfoRep = sceneInfoRep
        this.sourceTraceRep = sourceTraceRep
        this.config = if (factorFilter != null) {
            RTExcWindLevelConfig(factorFilter)
            RTExcWindLevelConfig(factorFilter, emptyList())
        } else {
            RTExcWindLevelConfig(
                FactorFilter.builder()
//                    .withMain(FactorType.NO2)
//                    .withMain(FactorType.CO)
                    .withMain(FactorType.NO2)
                    .withMain(FactorType.CO)
//                    .withMain(FactorType.H2S)
//                    .withMain(FactorType.SO2)
//                    .withMain(FactorType.O3)
                    .withMain(FactorType.O3)
                    .withMain(FactorType.PM25)
                    .withMain(FactorType.PM10)
                    .withMain(FactorType.VOC)
                    .create()
                    .create(),
                listOf(
                    listOf(FactorType.PM25, FactorType.PM10),
                    listOf(FactorType.VOC, FactorType.CO),
                )
            )
        }
        pollutedSummary = PollutedSummary(config) { summaryCallback(it) }
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
@@ -10,7 +10,8 @@
 * @date 2025/5/29
 * @author feiyu02
 */
class RTExcWindLevelConfig(factorFilter: FactorFilter): BaseAnalysisConfig(factorFilter) {
class RTExcWindLevelConfig(factorFilter: FactorFilter, combination: List<List<FactorType>>?): BaseAnalysisConfig
    (factorFilter, combination) {
    inner class WindLevelCondition(
        val windSpeed: Pair<Double, Double>,
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcChangeRate.kt
@@ -77,12 +77,12 @@
        return tag.exceptionData.size >= (changeRate[factorType]?.countLimit ?: 1)
    }
    override fun needCut(tag: ExceptionTag, hasException: Boolean?): Boolean {
    override fun needCut(tag: ExceptionTag, hasException: Boolean?, data: BaseRealTimeData): Boolean {
        // 按照时长和距离限制将异常截取
        if (tag.exceptionData.isEmpty()) return false
        val se = tag.exceptionData.first()
        val ee = tag.exceptionData.last()
        val ee = data
        val sTime = LocalDateTime.ofInstant(se.dataTime?.toInstant(), ZoneId.systemDefault())
        val eTime = LocalDateTime.ofInstant(ee.dataTime?.toInstant(), ZoneId.systemDefault())
@@ -119,9 +119,23 @@
        exceptionStatus: ExceptionStatusType,
    ) {
        super.onNewException(tag, factor, exceptionStatus)
//        callback?.let { func ->
//            val exc = tag.exceptionResult.last()
//            func.invoke(exc as PollutedClue)
//        }
    }
    override fun mergeExceptionResult() {
        super.mergeExceptionResult()
        latestExceptionResult
        latestCombinedResult
        callback?.let { func ->
            val exc = tag.exceptionResult.last()
            func.invoke(exc as PollutedClue)
            latestExceptionResult.forEach {
                func.invoke(it as PollutedClue)
            }
            latestCombinedResult.forEach {
                func.invoke(it as PollutedClue)
            }
        }
    }
}
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
@@ -83,12 +83,12 @@
        return tag.exceptionData.size >= windLevelCondition.countLimit
    }
    override fun needCut(tag: ExceptionTag, hasException: Boolean?): Boolean {
    override fun needCut(tag: ExceptionTag, hasException: Boolean?, data: BaseRealTimeData): Boolean {
        // 按照时长和距离限制将异常截取
        if (tag.exceptionData.isEmpty()) return false
        val se = tag.exceptionData.first()
        val ee = tag.exceptionData.last()
        val ee = data
        val sTime = LocalDateTime.ofInstant(se.dataTime?.toInstant(), ZoneId.systemDefault())
        val eTime = LocalDateTime.ofInstant(ee.dataTime?.toInstant(), ZoneId.systemDefault())