| | |
| | | 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 |
| | | import com.flightfeather.uav.common.utils.DateUtil |
| | | import com.flightfeather.uav.domain.entity.BaseRealTimeData |
| | | import com.flightfeather.uav.domain.entity.avg |
| | | import com.flightfeather.uav.socket.eunm.FactorType |
| | | import java.time.Duration |
| | | |
| | | /** |
| | | * 监测数据异常分析基类 |
| | | */ |
| | | abstract class BaseExceptionAnalysis(config: DataAnalysisConfig) : |
| | | BaseDataAnalysis<BaseRealTimeData, DataAnalysisConfig, ExceptionResult>(config) { |
| | | abstract class BaseExceptionAnalysis<V : BaseAnalysisConfig, Y : BaseExceptionResult>(config: V) : |
| | | BaseDataAnalysis<BaseRealTimeData, V, Y>(config) { |
| | | |
| | | /** |
| | | * 确定异常类型 |
| | | */ |
| | | abstract fun getExceptionType(): ExceptionType |
| | | |
| | | /** |
| | | * 判断相邻数据是否连续 |
| | | */ |
| | | open fun isContinuous(d1: BaseRealTimeData?, d2: BaseRealTimeData?): Boolean { |
| | | if (d1 == null || d2 == null) return true |
| | | |
| | | val t1 = d1.dataTime |
| | | val t2 = d2.dataTime |
| | | return Duration.between(t1?.toInstant(), t2?.toInstant()).toMillis() <= (20 * 1000) |
| | | } |
| | | |
| | | /** |
| | | * 生成一条异常分析结果 |
| | | */ |
| | | open fun newResult( |
| | | start: BaseRealTimeData, end: BaseRealTimeData?, factor: FactorFilter.SelectedFactor, |
| | | exceptionData: List<BaseRealTimeData>, |
| | | ): ExceptionResult { |
| | | val eType = getExceptionType() |
| | | return ExceptionResult().apply { |
| | | missionCode = config.mission.missionCode |
| | | deviceCode = start.deviceCode |
| | | exception = eType.des |
| | | exceptionType = eType.value |
| | | factorId = factor.main.value |
| | | factorName = factor.main.des |
| | | subFactorId = factor.subs.map { it.value } |
| | | subFactorName = factor.subs.map { it.des } |
| | | selectedFactor = factor |
| | | startDate = start.dataTime |
| | | endDate = end?.dataTime |
| | | 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.getByFactorType(factor.main) |
| | | endData = end?.getByFactorType(factor.main) ?: startData |
| | | |
| | | val avgData = exceptionData.avg() |
| | | // 求取污染数据的中心坐标 |
| | | longitude = avgData.longitude |
| | | latitude = avgData.latitude |
| | | // 求取主污染因子的均值和范围 |
| | | val s = dataSummary(exceptionData, factor.main) |
| | | avg = s.first |
| | | min = s.second |
| | | max = s.third |
| | | |
| | | exceptionData.forEach { dataList.add(it) } |
| | | } |
| | | } |
| | | |
| | | private 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?.getByFactorType(factorType) ?: return@forEach |
| | | if (min == -1f || min > value) { |
| | | min = value |
| | | } |
| | | if (max == -1f || max < value) { |
| | | max = value |
| | | } |
| | | total += value |
| | | count++ |
| | | } |
| | | val avg = if (count == 0) 0f else total / count |
| | | return Triple(avg, min, max) |
| | | } |
| | | } |