package com.flightfeather.uav.biz.sourcetrace.model
|
|
import com.flightfeather.uav.biz.FactorFilter
|
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
|
import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig
|
import com.flightfeather.uav.common.utils.DateUtil
|
import com.flightfeather.uav.domain.entity.BaseRealTimeData
|
import com.flightfeather.uav.lightshare.bean.DataVo
|
import com.flightfeather.uav.socket.eunm.FactorType
|
import java.util.Date
|
import kotlin.math.round
|
|
/**
|
* 污染数据
|
* @date 2025/5/27
|
* @author feiyu02
|
*/
|
class PollutedData() {
|
|
inner class Statistic(){
|
var factorId: Int? = null
|
var factorName: String? = null
|
var subFactorId: List<Int>? = null
|
var subFactorName: List<String>? = null
|
var selectedFactor: FactorFilter.SelectedFactor? = null
|
|
// 因子量级平均变化幅度
|
var avgPer: Double? = null
|
// 因子量级平均变化速率
|
var avgRate: Double? = null
|
|
var avg: Double? = null
|
var min: Double? = null
|
var max: Double? = null
|
}
|
|
/**
|
* 9. 关联因子
|
* a) pm2.5、pm10特别高,两者在各情况下同步展示,pm2.5占pm10的比重变化,比重越高,越有可能是餐饮
|
* b) pm10特别高、pm2.5较高,大颗粒扬尘污染,只展示pm10,pm2.5占pm10的比重变化,工地为主
|
* c) VOC较高,同比计算pm2.5的量级,可能存在同步偏高(汽修、加油站), 同步计算O3是否有高值
|
* d) VOC较高,处于加油站(车辆拥堵情况),CO一般较高, 同步计算O3是否有高值
|
* e) 氮氧化合物,一般由于机动车尾气,同步计算CO
|
*/
|
|
constructor(
|
start: BaseRealTimeData,
|
end: BaseRealTimeData?,
|
factorList: List<FactorFilter.SelectedFactor>,
|
exceptionData: List<BaseRealTimeData>,
|
historyData: List<BaseRealTimeData>,
|
eType: ExceptionType,
|
windLevelCondition: RTExcWindLevelConfig.WindLevelCondition?,
|
) : this() {
|
exception = eType.des
|
exceptionType = eType.value
|
|
startTime = start.dataTime
|
endTime = end?.dataTime
|
// startData = start.getByFactorType(factor.main)
|
// endData = end?.getByFactorType(factor.main) ?: startData
|
startData = start
|
endData = end
|
|
windSpeed = exceptionData.first().windSpeed?.toDouble()
|
times = windLevelCondition?.countLimit
|
|
dataList.add(start)
|
exceptionData.forEach {
|
dataList.add(it)
|
}
|
dataVoList.addAll(dataList.map { it.toDataVo() })
|
historyDataList.addAll(historyData.map { it.toDataVo() })
|
|
|
factorList.forEach { f->
|
statisticMap[f.main] = Statistic().apply {
|
factorId = f.main.value
|
factorName = f.main.des
|
subFactorId = f.subs.map { it.value }
|
subFactorName = f.subs.map { it.des }
|
selectedFactor = f
|
|
avgPer = calPer(f.main)
|
avgRate = calRate(f.main)
|
|
val s = dataSummary(exceptionData, f.main)
|
avg = s.first
|
min = s.second
|
max = s.third
|
}
|
}
|
}
|
|
var deviceCode: String? = null
|
|
var exception: String? = null
|
var exceptionType: Int? = null
|
|
var startTime: Date? = null
|
var endTime: Date? = null
|
|
var startData: BaseRealTimeData? = null
|
var endData: BaseRealTimeData? = null
|
|
// 风速
|
var windSpeed: Double? = null
|
|
// 发生次数
|
var times: Int? = null
|
|
var historyDataList = mutableListOf<DataVo>()
|
// 异常监测数据
|
var dataList: MutableList<BaseRealTimeData> = mutableListOf()
|
var dataVoList: MutableList<DataVo> = mutableListOf()
|
|
var statisticMap = mutableMapOf<FactorType, Statistic>()
|
|
fun toFactorNames(): String {
|
val factors = statisticMap.entries.map { it.key }.sortedBy { it.value }.joinToString(";") { it.des }
|
return factors
|
}
|
|
private fun calPer(factorType: FactorType): Double? {
|
val list = dataList
|
if (list.size < 2) return null
|
|
var total = .0
|
for (i in 0 until list.size - 1) {
|
val p = list[i].getByFactorType(factorType)!!
|
val n = list[i + 1].getByFactorType(factorType)!!
|
total += (n - p) / p
|
}
|
return total / (list.size - 1)
|
}
|
|
private fun calRate(factorType: FactorType): Double? {
|
val list = dataList
|
if (list.size < 2) return null
|
|
var total = .0
|
for (i in 0 until list.size - 1) {
|
val p = list[i].getByFactorType(factorType)!!
|
val n = list[i + 1].getByFactorType(factorType)!!
|
total += (n - p) / 4
|
}
|
return total / (list.size - 1)
|
}
|
|
private fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Double, Double,
|
Double> {
|
var min = -1.0
|
var max = -1.0
|
var total = .0
|
var count = 0
|
exceptionData.forEach {
|
val value = it?.getByFactorType(factorType)?.toDouble() ?: return@forEach
|
if (min == -1.0 || min > value) {
|
min = round(value * 1000) / 1000
|
}
|
if (max == -1.0 || max < value) {
|
max = round(value * 1000) / 1000
|
}
|
total += value
|
count++
|
}
|
val avg = if (count == 0) .0 else round(total / count * 1000) / 1000
|
return Triple(avg, min, max)
|
}
|
}
|