package com.flightfeather.uav.model
|
|
import com.flightfeather.uav.common.utils.DateUtil
|
import com.flightfeather.uav.common.utils.ExcelUtil
|
import com.flightfeather.uav.socket.eunm.FactorType
|
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook
|
import java.io.File
|
import java.io.FileOutputStream
|
import java.util.*
|
import kotlin.math.round
|
|
/**
|
* 污染源影响程度权重分析模型
|
* 基类
|
*/
|
abstract class BaseModel<M : BaseMData, S : BaseSOP> {
|
|
abstract var dataPrep: BaseDataPrep<M, S>
|
|
// 权重因子,在进行计算分析时使用的监测因子
|
abstract var factorTypes: List<FactorType>
|
|
// 权重值,多种权重进行乘积计算
|
abstract var weights: List<BaseWeight<M, S>>
|
|
// 计算结果
|
private val result = mutableSetOf<BaseEffect>()
|
|
// 结果筛选方式
|
abstract var sections: List<BaseSection<M, S>>
|
|
/**
|
* 污染源影响程度计算
|
* @param mDataList 监测数据集合
|
* @param sopList 污染源集合
|
*/
|
fun execute(mDataList: List<M>, sopList: List<S>) {
|
result.clear()
|
|
//1. 数据预处理
|
val mList = dataPrep.mDataPrep(mDataList)
|
val sList = dataPrep.sopPrep(sopList)
|
|
mList.forEach m@{ m ->
|
if (!mDataCheck(m)) return@m
|
sList.forEach s@{ s ->
|
if (!sopCheck(s)) return@s
|
weightCompute(m, s)
|
}
|
}
|
}
|
|
/**
|
* 单点权重计算
|
* 计算污染源对单次监测数据产生的影响效果
|
* @param mData 监测数据
|
* @param sop 污染源
|
*/
|
private fun weightCompute(mData: M, sop: S) {
|
val effect = BaseEffect(sop.sourceId, sop.sourceName, sop.index)
|
|
// 将原监测数据按照权重计算出结果值
|
factorTypes.forEach { type ->
|
var result = mData.getFactorData(type) ?: return@forEach
|
weights.forEach {
|
result *= it.getWeight(mData, sop)?: return
|
}
|
effect.value.add(Pair(type, result))
|
}
|
|
// 向结果值添加筛选标签
|
sections.forEach { it.filter(mData, sop, effect) }
|
|
// 保存结果
|
result.add(effect)
|
}
|
|
fun outputToExcel(
|
fName: String? = null,
|
_workbook: HSSFWorkbook? = null,
|
_out: FileOutputStream? = null,
|
sheetName: String = "sheet1",
|
done: Boolean = true
|
): Pair<HSSFWorkbook, FileOutputStream>? {
|
val rMap = formatConversion()
|
|
val workbook = _workbook ?: HSSFWorkbook()
|
val fileName = fName ?: "污染溯源权重模型${DateUtil().DateToString(Date(), "yyyy-MM-ddHHmmss")}.xls"
|
// val filePath = "E:\\work\\export\\$fileName"
|
// val filePath = "E:\\工作\\开发\\走航监测\\算法相关\\自动输出\\$fileName"
|
val filePath = "E:\\工作\\开发\\走航监测\\算法相关\\自动输出\\网格化\\$fileName"
|
val out = _out ?: FileOutputStream(File(filePath))
|
|
// 表头组(多行表头)
|
val heads = mutableListOf<Array<String>>()
|
// 表头行
|
val h1 = mutableListOf<String>()
|
h1.add("编号")
|
h1.add("污染源")
|
// arrayOf("早上", "上午", "中午", "下午", "傍晚", "夜间")
|
|
val contents = mutableListOf<Array<Any>>()
|
var isFirst = true
|
rMap.forEach { (source, tMap) ->
|
// 新建一行
|
val contentList = mutableListOf<Any>()
|
// 添加污染源名称
|
val l = source.split("(")
|
val index = l[1].substring(0, l[1].lastIndex)
|
contentList.add(index.toIntOrNull() ?: 0)
|
contentList.add(l[0])
|
tMap.forEach { (factorType, lMap) ->
|
sections.forEach {
|
val types = mutableListOf<String>().apply {
|
addAll(it.sectionType)
|
addAll(it.constType)
|
}
|
var max = 0.0
|
var maxP = types[0]
|
types.forEach {se ->
|
val lKey = "$se($factorType)"
|
if (lMap.containsKey(lKey)) {
|
val dataList = lMap[lKey]
|
val size = dataList?.size
|
// 添加该分类作为表头
|
val h = lKey
|
// val h = "$lKey($size)"
|
if (!h1.contains(h)) {
|
h1.add(h)
|
}
|
|
// 将原始的数据换算得出结果,可以是求出均值、总和等等,后续修改为可由用户设定
|
// FIXME: 2021/6/23 此处先默认为求均值
|
val average = dataList?.average()
|
|
if (average ?: 0.0 > max) {
|
max = average ?: 0.0
|
maxP = se
|
}
|
|
// 当前行添加该分类下的结果值
|
contentList.add(average ?: 0.0)
|
}
|
}
|
if (isFirst) {
|
h1.add("最高时段")
|
h1.add("最高时段值")
|
}
|
contentList.add(maxP)
|
contentList.add(max)
|
}
|
}
|
isFirst = false
|
contents.add(contentList.toTypedArray())
|
}
|
|
contents.sortByDescending {
|
val i = it[0]
|
if (i is Int) {
|
i
|
} else {
|
0
|
}
|
}
|
|
heads.add(h1.toTypedArray())
|
ExcelUtil.write(heads, contents, workbook, sheetName)
|
return if (!done) {
|
Pair(workbook, out)
|
} else {
|
workbook.write(out)
|
workbook.close()
|
out.flush()
|
out.close()
|
null
|
}
|
}
|
|
private fun formatConversion(): Map<String, Map<String, Map<String?, MutableList<Double>>>> {
|
val rMap = mutableMapOf<String, MutableMap<String, MutableMap<String?, MutableList<Double>>>>()
|
println("结果长度:${result.size}")
|
result.forEach { e ->
|
val rKey = "${e.sourceName}(${e.index})"
|
if (!rMap.containsKey(rKey)) {
|
rMap[rKey] = mutableMapOf()
|
}
|
val lMap = rMap[rKey]!!
|
e.value.forEach { v ->
|
if (!lMap.containsKey(v.first.des)) {
|
lMap[v.first.des] = mutableMapOf()
|
}
|
val tMap = lMap[v.first.des]!!
|
e.tag.forEach { t ->
|
val factorName = v.first.des
|
val lKey = t.levelName + "($factorName)"
|
if (!tMap.containsKey(lKey)) {
|
tMap[lKey] = mutableListOf()
|
}
|
tMap[lKey]?.add(v.second)
|
}
|
}
|
}
|
return rMap
|
}
|
|
/**
|
* 监测数据合法性检查
|
*/
|
abstract fun mDataCheck(m: M): Boolean
|
|
/**
|
* 污染源数据合法性检查
|
*/
|
abstract fun sopCheck(s: S): Boolean
|
}
|