| | |
| | | |
| | | companion object{ |
| | | fun builder() = FactorFilter().Builder() |
| | | fun default() = builder().create() |
| | | fun default() = builder() |
| | | .withMain(FactorType.VOC) |
| | | .withSubs(listOf( |
| | | FactorType.H2S, |
| | | FactorType.O3, |
| | | FactorType.PM25, |
| | | )) |
| | | .withMain(FactorType.H2S) |
| | | .withSubs(listOf( |
| | | FactorType.VOC, |
| | | FactorType.O3, |
| | | FactorType.PM25, |
| | | )) |
| | | .withMain(FactorType.O3) |
| | | .withSubs(listOf( |
| | | FactorType.VOC, |
| | | FactorType.H2S, |
| | | FactorType.PM25, |
| | | )) |
| | | .withMain(FactorType.PM25) |
| | | .withSubs(listOf( |
| | | FactorType.VOC, |
| | | FactorType.H2S, |
| | | FactorType.O3, |
| | | )) |
| | | // .withSubs(listOf( |
| | | // FactorType.NO2, |
| | | // FactorType.CO, |
| | | // FactorType.SO2, |
| | | // FactorType.O3, |
| | | // FactorType.PM25, |
| | | // FactorType.PM10, |
| | | // FactorType.VOC |
| | | // )) |
| | | .create() |
| | | } |
| | | |
| | | // æéå åéå |
| | |
| | | |
| | | /** |
| | | * 夿å¼å¸¸åºç°çè¿ç»æ¶é¿æ¯å¦æ»¡è¶³æ¡ä»¶ |
| | | * @param sIndex |
| | | * @param eIndex |
| | | */ |
| | | abstract fun judgeDuration(sIndex: Int, eIndex: Int): Boolean |
| | | |
| | |
| | | // existException.add(false) |
| | | // exceptionData.add(mutableListOf()) |
| | | // } |
| | | tagMap.clear() |
| | | config.factorFilter.mainList().forEach {f-> |
| | | tagMap[f] = Tag() |
| | | } |
| | |
| | | override fun onNextData(data: BaseRealTimeData) { |
| | | val isContinue = isContinuous(lastData, data) |
| | | val hasException = judgeException(lastData, data) |
| | | config.factorFilter.mainList().forEach {f-> |
| | | config.factorFilter.selectedList.forEach {s-> |
| | | val f = s.main |
| | | tagMap[f]?.let { |
| | | it.eIndex++ |
| | | // èµ·å§æ°æ® |
| | | it.endData = lastData |
| | | if (it.endData == null) { |
| | | it.refreshAfterCheckResult(data) |
| | | } |
| | | // 夿ç¸é»æ°æ®æ¯å¦è¿ç»å¹¶ä¸æ¯å¦æ»¡è¶³å¼å¸¸å¤æ |
| | | if (!isContinue) { |
| | | checkResult() |
| | | checkResult(s) |
| | | // æ°æ®ä¸è¿ç»æ¶ï¼è®°å½å¼å¸¸æ
åµ |
| | | if (it.eIndex - it.sIndex >= durationCount) { |
| | | it.refreshAfterCheckResult(data) |
| | |
| | | it.exceptionData.add(data) |
| | | } else { |
| | | // å¼å¸¸ä¸åéå¤åºç°æ¶ï¼è®°å½å¼å¸¸æ
åµ |
| | | checkResult() |
| | | checkResult(s) |
| | | if (it.eIndex - it.sIndex >= durationCount) { |
| | | it.refreshAfterCheckResult(data) |
| | | } |
| | |
| | | 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)) { |
| | | if (tag.existException && judgeDuration(tag.sIndex, tag.eIndex - 1)) { |
| | | tag.startData?.let { |
| | | resultList.add(newResult(it, lastData, factor, tag.exceptionData)) |
| | | } |
| | |
| | | } else { |
| | | config.factorFilter.selectedList.forEach { f -> |
| | | val tag1 = tagMap[f.main] ?: return@forEach |
| | | if (tag1.existException && judgeDuration(tag1.sIndex, tag1.eIndex)) { |
| | | if (tag1.existException && judgeDuration(tag1.sIndex, tag1.eIndex - 1)) { |
| | | tag1.startData?.let { |
| | | resultList.add(newResult(it, lastData, f, tag1.exceptionData)) |
| | | } |
| | |
| | | override fun onNextData(data: BaseRealTimeData) { |
| | | val isContinue = isContinuous(lastData, data) |
| | | val hasException = judgeException(lastData, data) |
| | | config.factorFilter.mainList().forEach {f-> |
| | | config.factorFilter.selectedList.forEach {s-> |
| | | val f = s.main |
| | | tagMap[f]?.let { |
| | | it.eIndex++ |
| | | if (lastData == null) { |
| | |
| | | } |
| | | // 夿ç¸é»æ°æ®æ¯å¦è¿ç»å¹¶ä¸æ¯å¦æ»¡è¶³å¼å¸¸å¤æ |
| | | if (!isContinue) { |
| | | checkResult() |
| | | checkResult(s) |
| | | it.sIndex = it.eIndex |
| | | it.startData = data |
| | | } else { |
| | |
| | | } |
| | | it.existException = true |
| | | } else { |
| | | checkResult() |
| | | checkResult(s) |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionDataExceed |
| | | import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionSlideAverage |
| | | import com.flightfeather.uav.biz.dataanalysis.exceptiontype.ExceptionValueMutation |
| | | import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult |
| | |
| | | private fun initTask(config: DataAnalysisConfig) { |
| | | taskList.clear() |
| | | taskList.apply { |
| | | add(ExceptionDataExceed(config)) |
| | | add(ExceptionValueMutation(config)) |
| | | // add(ExceptionDataExceed(config)) |
| | | // add(ExceptionValueMutation(config)) |
| | | add(ExceptionSlideAverage(config)) |
| | | } |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.uav.biz.dataanalysis.exceptiontype |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.biz.dataanalysis.BaseExceptionAnalysis |
| | | 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 |
| | | |
| | | /** |
| | | * æ»å¨å¹³åå¼çªåå¼å¸¸ |
| | | */ |
| | | class ExceptionSlideAverage(config: DataAnalysisConfig) : BaseExceptionAnalysis(config) { |
| | | |
| | | private val historyDataList = mutableListOf<BaseRealTimeData>() |
| | | private val tempDataList = mutableListOf<BaseRealTimeData>() |
| | | private var lastData: BaseRealTimeData? = null |
| | | // private val avgListReverse = mutableListOf<Pair<Double, Boolean>>() |
| | | // private var startData: BaseRealTimeData? = null |
| | | // private var sIndex = 0 |
| | | // private var eIndex = -1 |
| | | // private var existException = false |
| | | |
| | | inner class Tag { |
| | | // èµ·å§æ°æ®ä¸æ |
| | | var sIndex = 0 |
| | | |
| | | // èµ·å§æ°æ®å¯¹è±¡ |
| | | var startData :BaseRealTimeData? = null |
| | | |
| | | // æ«å°¾æ°æ®ä¸æ |
| | | var eIndex = -1 |
| | | |
| | | // æ«å°¾æ°æ®å¯¹è±¡ |
| | | var endData: BaseRealTimeData? = null |
| | | |
| | | // æ°æ®ç»åå¼çéå |
| | | val avgListReverse = mutableListOf<Pair<Double, Boolean>>() |
| | | |
| | | // å¼å¸¸æ°æ®æ®µ |
| | | var exceptionData = mutableListOf<BaseRealTimeData>() |
| | | |
| | | // æ¯å¦åå¨å¼å¸¸ |
| | | var existException = false |
| | | |
| | | fun refreshAfterCheckResult(data: BaseRealTimeData) { |
| | | // å¤æå¹¶æ´æ°èµ·å§ç¹ä½ç½® |
| | | // val len = config.changeTrendGroup - 1 + config.changeTrendTimes + config.changeTrendInterval |
| | | val len = config.changeTrendGroup |
| | | if ((eIndex - sIndex + 1) > len) { |
| | | sIndex = eIndex + 1 - len |
| | | startData = historyDataList[sIndex] |
| | | exceptionData.clear() |
| | | exceptionData.addAll(historyDataList.subList(sIndex, eIndex + 1)) |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected val tagMap = mutableMapOf<FactorType, Tag>() |
| | | |
| | | override fun init() { |
| | | super.init() |
| | | historyDataList.clear() |
| | | tempDataList.clear() |
| | | lastData = null |
| | | |
| | | tagMap.clear() |
| | | config.factorFilter.mainList().forEach {f-> |
| | | tagMap[f] = Tag() |
| | | } |
| | | // avgListReverse.clear() |
| | | // startData = null |
| | | // sIndex = 0 |
| | | // eIndex = -1 |
| | | // existException = false |
| | | } |
| | | |
| | | override fun getExceptionType(): ExceptionType = ExceptionType.TYPE7 |
| | | |
| | | override fun onNextData(data: BaseRealTimeData) { |
| | | historyDataList.add(data) |
| | | // æ°æ®å å
¥ä¸´æ¶æ°ç» |
| | | tempDataList.add(data) |
| | | // æ°æ®éè¶
åºè®¾ç½®æ°éæ¶ï¼å»é¤å½åæ°æ®ç»é¦ä¸ªæ°æ® |
| | | if (tempDataList.size > config.changeTrendGroup) { |
| | | tempDataList.removeAt(0) |
| | | } |
| | | config.factorFilter.selectedList.forEach {s-> |
| | | val f = s.main |
| | | tagMap[f]?.let { |
| | | it.eIndex++ |
| | | it.endData = lastData |
| | | if (it.startData == null) { |
| | | it.startData = data |
| | | } |
| | | // æ°æ®éçäºè®¾ç½®æ°éæ¶ï¼è®¡ç®å½åæ°æ®ç»åå¼ |
| | | if (tempDataList.size == config.changeTrendGroup) { |
| | | calAvg(f, tempDataList) |
| | | if (checkSlideAvg(f)) { |
| | | it.existException = true |
| | | it.exceptionData.add(data) |
| | | } else { |
| | | checkResult(s) |
| | | it.refreshAfterCheckResult(data) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | lastData = data |
| | | } |
| | | |
| | | override fun onDone() { |
| | | checkResult() |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸ç»æ°æ®çåå¼ |
| | | */ |
| | | private fun calAvg(type: FactorType, list: List<BaseRealTimeData>) { |
| | | var total = .0 |
| | | var valid = true |
| | | val count = list.size |
| | | if (count == 0) return |
| | | list.forEach { |
| | | val v = it.getByFactorType(type) |
| | | if (v == null) { |
| | | valid = false |
| | | } else { |
| | | total += v |
| | | } |
| | | } |
| | | val avg = total / count |
| | | tagMap[type]?.avgListReverse?.add(0, Pair(avg, valid)) |
| | | } |
| | | |
| | | /** |
| | | * è®¡ç®æ°æ®ç»ä¹é´çåå¼å·®å¼æ¯å¦è¿ç»è¶
è¿é宿¯ç |
| | | */ |
| | | private fun checkSlideAvg(type: FactorType): Boolean { |
| | | val tag = tagMap[type] ?: return false |
| | | // è®¡ç®æ»å¨å弿ä½è¦æ±ä¸ªæ° |
| | | val minSize = config.changeTrendTimes + config.changeTrendInterval |
| | | if (tag.avgListReverse.size < minSize) { |
| | | return false |
| | | } else { |
| | | // æ»å¨å弿»¡è¶³æ°éæ¶ï¼è®¡ç®åå¼ä¹é´æ¯å¦è¿ç»è¶
è¿é宿¯ç |
| | | val rateList = mutableListOf<Pair<Double, Boolean>>() |
| | | for (i in tag.avgListReverse.indices) { |
| | | if (i >= config.changeTrendTimes) break |
| | | val r = calAvgChangeRate(tag.avgListReverse[i], tag.avgListReverse[i + config.changeTrendInterval]) |
| | | rateList.add(r) |
| | | } |
| | | for (y in rateList) { |
| | | if (!y.second || y.first < config.changeTrendRate) { |
| | | return false |
| | | } |
| | | } |
| | | return true |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è®¡ç®æ»å¨åå¼ååç |
| | | * æ±a1ç¸å¯¹äºa2çååç |
| | | */ |
| | | private fun calAvgChangeRate(a1: Pair<Double, Boolean>, a2: Pair<Double, Boolean>): Pair<Double, Boolean> { |
| | | val valid = a1.second && a2.second |
| | | return if (a2.first == .0) { |
| | | Pair(1.0, valid) |
| | | } else { |
| | | Pair(abs(a1.first - a2.first) / a2.first, valid) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å½åæ°æ®æªåºç°å¼å¸¸æ¶ï¼ææ°æ®å¾ªç¯ç»ææ¶ï¼å¤æåç»æ¥éª¤ |
| | | */ |
| | | private fun checkResult(factor: FactorFilter.SelectedFactor? = null) { |
| | | val tag = tagMap[factor?.main] |
| | | if (factor != null && tag != null) { |
| | | if (tag.existException) { |
| | | tag.startData?.let { |
| | | resultList.add(newResult(it, lastData, factor, tag.exceptionData)) |
| | | } |
| | | tag.existException = false |
| | | } |
| | | } else { |
| | | config.factorFilter.selectedList.forEach { f -> |
| | | val tag1 = tagMap[f.main] ?: return@forEach |
| | | if (tag1.existException) { |
| | | tag1.startData?.let { |
| | | resultList.add(newResult(it, lastData, f, tag1.exceptionData)) |
| | | } |
| | | tag1.existException = false |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | val b2 = r >= config.mutationRate |
| | | if (b1) special = true |
| | | res[f] = (b1 || b2) |
| | | if (res[f] == true) println("p: $pValue --- n: $nValue --- r: $r") |
| | | } |
| | | // repeat(config.factorCount) { i-> |
| | | // if (p?.getByFactorIndex(i) == null || n.getByFactorIndex(i) == null) { |
| | |
| | | val b1 = special && (eIndex - sIndex) >= (config.mutationNum / 2) |
| | | val b2 = (eIndex - sIndex) >= config.mutationNum |
| | | special = false |
| | | println("sIndex: $sIndex --- eIndex: $eIndex --- special: $special") |
| | | return b1 || b2 |
| | | } |
| | | } |
| | |
| | | var mutationNum = 6 |
| | | // çªåç |
| | | var mutationRate = .5 |
| | | |
| | | // æ±æ»å¨å¹³åå¼çæ°æ®ç»ä¸ªæ° |
| | | var changeTrendGroup = 12 |
| | | // æ»å¨å¹³åå¼è¿ç» |
| | | var changeTrendInterval = 12 |
| | | var changeTrendRate = 1 |
| | | // æ»å¨å¹³åå¼ååçå¼å¸¸è¿ç»æ¬¡æ° |
| | | var changeTrendTimes = 3 |
| | | } |
| | |
| | | import com.flightfeather.uav.biz.dataanalysis.ExceptionAnalysisController |
| | | import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult |
| | | import com.flightfeather.uav.biz.dataprocess.PreData |
| | | import com.flightfeather.uav.common.chart.ChartUtil |
| | | import com.flightfeather.uav.common.chart.DataToChartUtil |
| | | import com.flightfeather.uav.common.exception.BizException |
| | | import com.flightfeather.uav.common.pdf.GeneratePdfUtil |
| | |
| | | import com.flightfeather.uav.domain.entity.Mission |
| | | import com.flightfeather.uav.domain.repository.MissionRep |
| | | import com.flightfeather.uav.domain.repository.RealTimeDataRep |
| | | import com.flightfeather.uav.socket.eunm.FactorType |
| | | import org.springframework.beans.BeanUtils |
| | | import org.springframework.beans.factory.annotation.Value |
| | | import org.springframework.stereotype.Component |
| | |
| | | */ |
| | | fun addExceptions(exceptions: List<ExceptionResult>) { |
| | | this.exceptions = exceptions.map { |
| | | val byteArray = DataToChartUtil.lineToByteArray(it.selectedFactor, it.dataList) |
| | | val base64Str = ImageUtil.compressImage2(byteArray, 400, needPrefix = false) |
| | | val c = ExceptionChart() |
| | | BeanUtils.copyProperties(it, c) |
| | | c.pict = base64Str |
| | | // å建主污æå åçæ°æ®æçº¿å¾ |
| | | val byteArray = DataToChartUtil.lineToByteArray(it.selectedFactor?.main, it.dataList) |
| | | val base64Str = ImageUtil.compressImage2(byteArray, 800, needPrefix = false) |
| | | c.mainPict = base64Str |
| | | // å建å
³èå åçæ°æ®æçº¿å¾ |
| | | if (it.selectedFactor?.subs?.isNotEmpty() == true) { |
| | | val subList = mutableListOf<String>() |
| | | it.selectedFactor!!.subs.forEach { type -> |
| | | val byteArray1 = DataToChartUtil.lineToByteArray(type, it.dataList) |
| | | val base64Str1 = ImageUtil.compressImage2(byteArray1, 800, needPrefix = false) |
| | | subList.add(base64Str1) |
| | | } |
| | | c.subPictList = subList |
| | | } |
| | | return@map c |
| | | } |
| | | } |
| | |
| | | * æ°æ®å¼å¸¸æå¨æ¶æ®µçæçº¿å¾ |
| | | */ |
| | | class ExceptionChart : ExceptionResult() { |
| | | // æ°æ®æçº¿å¾Base64ç¼ç |
| | | var pict: String? = null |
| | | // 污æå åçå¼å¸¸æ°æ®æçº¿å¾Base64ç¼ç |
| | | var mainPict: String? = null |
| | | |
| | | // å
³èå åçå¼å¸¸æ°æ®æçº¿å¾Base64ç¼ç |
| | | var subPictList: List<String>? = null |
| | | } |
| | | |
| | | private val templateName = "report-underway.ftl" |
| | |
| | | max = u.max |
| | | |
| | | val byteArray = DataToChartUtil.lineToByteArray(t, realTimeData) |
| | | val base64Str = ImageUtil.compressImage2(byteArray, 400, needPrefix = false) |
| | | val base64Str = ImageUtil.compressImage2(byteArray, 800, needPrefix = false) |
| | | pict = base64Str |
| | | }) |
| | | } |
| | |
| | | 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.axis.NumberAxis |
| | | import org.jfree.chart.axis.NumberTickUnit |
| | | import org.jfree.chart.labels.StandardCategorySeriesLabelGenerator |
| | | import org.jfree.chart.plot.CategoryPlot |
| | | import org.jfree.chart.plot.PlotOrientation |
| | | 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 |
| | | import java.text.DecimalFormat |
| | | import kotlin.math.max |
| | | import kotlin.math.min |
| | | |
| | | /** |
| | | * å¾è¡¨çæ |
| | |
| | | */ |
| | | object ChartUtil { |
| | | |
| | | data class ChartValue(val x: String?, val y: Number) |
| | | private const val FONT_NAME = "SimHei" |
| | | private val defaultColors = listOf( |
| | | Color(191, 0, 0), |
| | | Color(181, 125, 69), |
| | | Color(236, 204, 6), |
| | | Color(84, 151, 57), |
| | | Color(13, 221, 151), |
| | | Color(57, 75, 151), |
| | | Color(115, 51, 206), |
| | | ) |
| | | |
| | | 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) |
| | | // å¾è¡¨æ°æ®å¼åæ |
| | | data class ChartValue(val x: String?, val y: Double) |
| | | // å¾è¡¨æ°æ®é |
| | | data class ChartDataset(val dataset: DefaultCategoryDataset, val minValue: Double, val maxValue: Double) |
| | | |
| | | /** |
| | | * å建æçº¿å¾ |
| | | */ |
| | | fun line(title: String, chartDatasetList: List<ChartDataset>): JFreeChart? { |
| | | if (chartDatasetList.isEmpty()) return null |
| | | |
| | | val line = ChartFactory.createLineChart( |
| | | title, "æ¶é´", "æµåº¦(μg/m3)", |
| | | null, PlotOrientation.VERTICAL, true, false, false |
| | | ) |
| | | // val line = ChartFactory.createLineChart( |
| | | // title, "", "æµåº¦(μg/m³)", |
| | | // null, PlotOrientation.VERTICAL, true, false, false |
| | | // ) |
| | | var minValue = chartDatasetList[0].minValue |
| | | var maxValue = chartDatasetList[0].maxValue |
| | | val datasetList = mutableListOf<DefaultCategoryDataset>() |
| | | chartDatasetList.forEach { |
| | | minValue = min(minValue, it.minValue) |
| | | maxValue = max(maxValue, it.maxValue) |
| | | datasetList.add(it.dataset) |
| | | } |
| | | val plot = line.categoryPlot |
| | | setLine(line) |
| | | setRenderer(plot, datasetList) |
| | | setX(plot) |
| | | setY(plot, "æµåº¦(μg/m3)", minValue, maxValue) |
| | | return line |
| | | } |
| | | |
| | | fun lineToByteArray(title: String, dataset: DefaultCategoryDataset):ByteArray { |
| | | /** |
| | | * æ°å»ºæçº¿å¾å¹¶è½¬æ¢ä¸ºbyteæ°ç» |
| | | */ |
| | | fun lineToByteArray(title: String, dataset: List<ChartDataset>): ByteArray { |
| | | val chart = line(title, dataset) |
| | | val output = ByteArrayOutputStream() |
| | | ChartUtils.writeChartAsPNG(output, chart, 600, 400) |
| | | ChartUtils.writeChartAsJPEG(output, chart, 1080, 607) |
| | | val byteArray = output.toByteArray() |
| | | output.flush() |
| | | output.close() |
| | | return byteArray |
| | | } |
| | | |
| | | fun newDataset(dataList:List<ChartValue>, seriesName:String): DefaultCategoryDataset { |
| | | /** |
| | | * æ°å»ºå¾è¡¨æ°æ®é |
| | | */ |
| | | fun newDataset(dataList: List<ChartValue>, seriesName: String): ChartDataset? { |
| | | if (dataList.isEmpty()) return null |
| | | val dataset = DefaultCategoryDataset() |
| | | var minValue = dataList[0].y |
| | | var maxValue = minValue |
| | | dataList.forEach { |
| | | dataset.setValue(it.y, seriesName, it.x) |
| | | minValue = min(minValue, it.y) |
| | | maxValue = max(maxValue, it.y) |
| | | } |
| | | return dataset |
| | | return ChartDataset(dataset, minValue, maxValue) |
| | | } |
| | | |
| | | /** |
| | | * 设置æçº¿å¾æ ·å¼ |
| | | */ |
| | | private fun setLine(chart: JFreeChart) { |
| | | chart.legend.itemFont = Font("SimHei", Font.PLAIN, 16) |
| | | chart.title.font = Font("SimHei", Font.BOLD, 20) |
| | | chart.legend.itemFont = Font(FONT_NAME, Font.PLAIN, 16) |
| | | chart.title.font = Font(FONT_NAME, Font.BOLD, 20) |
| | | chart.categoryPlot.apply { |
| | | backgroundPaint = Color(255, 255, 255) |
| | | rangeGridlinePaint = Color(200, 200, 200) |
| | |
| | | } |
| | | |
| | | private fun setRenderer(plot:CategoryPlot, datasetList:List<DefaultCategoryDataset>) { |
| | | val renderer = newBasicRenderer(paint = Color(191, 0, 0)) |
| | | datasetList.forEachIndexed { index, v -> |
| | | val renderer = newBasicRenderer(paint = defaultColors[index % defaultColors.size]) |
| | | plot.setDataset(index, v) |
| | | plot.setRenderer(index, renderer) |
| | | } |
| | | |
| | | } |
| | | |
| | | private fun setX(plot: CategoryPlot) { |
| | | plot.domainAxis.apply { |
| | | // 设置xè½´æ¯ä¸ªå»åº¦çåä½ |
| | | tickLabelFont = Font(FONT_NAME, Font.BOLD, 16) |
| | | // 设置xè½´æ ç¾çåä½ |
| | | labelFont = Font(FONT_NAME, Font.BOLD, 20) |
| | | // 设置x轴轴线æ¯å¦æ¾ç¤º |
| | | isAxisLineVisible = false |
| | | // 设置xè½´å»åº¦æ¯å¦æ¾ç¤º |
| | | isTickMarksVisible = false |
| | | |
| | | upperMargin = .0 |
| | | lowerMargin = .0 |
| | | } |
| | | } |
| | | |
| | | private fun setY(plot: CategoryPlot, label:String, minValue: Double, maxValue: Double) { |
| | | val tickUnit = (maxValue - minValue) / 10 |
| | | val axis1 = NumberAxis().apply { |
| | | this.label = label |
| | | // å»åº¦å±ç¤ºæ ¼å¼å |
| | | numberFormatOverride = DecimalFormat("0.0") |
| | | if (tickUnit != .0) { |
| | | // åæ¶èªå¨åé
é´è· |
| | | isAutoTickUnitSelection = false |
| | | // 设置é´éè·ç¦» |
| | | setTickUnit(NumberTickUnit(tickUnit)) |
| | | // 设置æ¾ç¤ºèå´ |
| | | setRange(minValue, maxValue) |
| | | } |
| | | // 设置yè½´æ¯ä¸ªå»åº¦çåä½ |
| | | tickLabelFont = Font(FONT_NAME, Font.BOLD, 16) |
| | | // 设置yè½´æ ç¾çåä½ |
| | | labelFont = Font(FONT_NAME, Font.BOLD, 20) |
| | | // 设置yè½´è½´çº¿ä¸æ¾ç¤º |
| | | isAxisLineVisible = false |
| | | // 设置yè½´å»åº¦ä¸æ¾ç¤º |
| | | isTickMarksVisible = false |
| | | } |
| | | plot.rangeAxis = axis1 |
| | | } |
| | | |
| | | private fun newBasicRenderer(series:Int = 0, paint:Paint): LineAndShapeRenderer { |
| | |
| | | package com.flightfeather.uav.common.chart |
| | | |
| | | import com.flightfeather.uav.biz.FactorFilter |
| | | import com.flightfeather.uav.common.exception.BizException |
| | | import com.flightfeather.uav.common.utils.DateUtil |
| | | import com.flightfeather.uav.domain.entity.BaseRealTimeData |
| | | import com.flightfeather.uav.socket.eunm.FactorType |
| | |
| | | */ |
| | | object DataToChartUtil { |
| | | |
| | | fun lineToByteArray(type: FactorFilter.SelectedFactor?, data: List<BaseRealTimeData>): ByteArray { |
| | | val title = type?.main?.des ?: "æªç¥çæµå å" |
| | | val seriesName = type?.main?.des ?: "æªç¥ç³»å" |
| | | fun lineToByteArray(type: FactorType?, data: List<BaseRealTimeData>): ByteArray { |
| | | val title = type?.des ?: "æªç¥çæµå å" |
| | | val seriesName = type?.des ?: "æªç¥ç³»å" |
| | | val dataList = data.map { d -> |
| | | ChartUtil.ChartValue( |
| | | DateUtil.instance.dateToString(d.dataTime, DateUtil.DateStyle.HH_MM_SS), |
| | | d.getByFactorType(type?.main) ?: 0f |
| | | d.getByFactorType(type)?.toDouble() ?: .0 |
| | | ) |
| | | } |
| | | val dataset = ChartUtil.newDataset(dataList, seriesName) |
| | | return ChartUtil.lineToByteArray(title, dataset) |
| | | val dataset = ChartUtil.newDataset(dataList, seriesName) ?: throw BizException("æçº¿å¾æ°æ®é为空") |
| | | return ChartUtil.lineToByteArray(title, listOf(dataset)) |
| | | } |
| | | } |
| | |
| | | <Relationship Id="imageId_${item_index}" |
| | | Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" |
| | | Target="media/image_${item_index}.png" /> |
| | | <#list item.subPictList as subItem> |
| | | <Relationship Id="imageId_sub_${item_index}-${subItem_index}" |
| | | Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" |
| | | Target="media/image_sub_${item_index}-${subItem_index}.png" /> |
| | | </#list> |
| | | </#list> |
| | | <#list summary as item> |
| | | <Relationship Id="imageId2_${item_index}" |
| | |
| | | <w:szCs w:val="28" /> |
| | | <w:lang w:val="en-US" w:eastAsia="zh-CN" /> |
| | | </w:rPr> |
| | | <w:t>ä»${item.startTime}è³${item.endTime}ï¼${item.factorName}åºç°${item.exception}<#if item.relatedSceneName??>ï¼ç»åçæµæ°æ®ååååç¹ååæº¯æºï¼<#list item.relatedSceneName as scene>${scene}ã</#list>çå¯è½å卿±¡æé£é©ã<#else>ã</#if></w:t> |
| | | <w:t>${item_index + 1}. ä»${item.startTime}è³${item.endTime}ï¼${item.factorName}åºç°${item.exception}<#if item.relatedSceneName??>ï¼ç»åçæµæ°æ®ååååç¹ååæº¯æºï¼<#list item.relatedSceneName as scene>${scene}ã</#list>çå¯è½å卿±¡æé£é©ã<#else>ã</#if></w:t> |
| | | </w:r> |
| | | </w:p> |
| | | <w:p> |
| | |
| | | <w:pict> |
| | | <v:shape id="_x0000_i1025_${item_index}" o:spt="75" |
| | | alt="f1725d6e3fb17a0e748045906f55ced" type="#_x0000_t75" |
| | | style="height:222.8pt;width:414.65pt;" filled="f" |
| | | style="height:225pt;width:400pt;" filled="f" |
| | | o:preferrelative="t" stroked="f" coordsize="21600,21600"> |
| | | <v:path /> |
| | | <v:fill on="f" focussize="0,0" /> |
| | |
| | | </w:pict> |
| | | </w:r> |
| | | </w:p> |
| | | <#if item.subPictList??> |
| | | <w:p> |
| | | <w:pPr> |
| | | <w:keepNext w:val="0" /> |
| | | <w:keepLines w:val="0" /> |
| | | <w:pageBreakBefore w:val="0" /> |
| | | <w:widowControl w:val="0" /> |
| | | <w:kinsoku /> |
| | | <w:wordWrap /> |
| | | <w:overflowPunct /> |
| | | <w:topLinePunct w:val="0" /> |
| | | <w:autoSpaceDE /> |
| | | <w:autoSpaceDN /> |
| | | <w:bidi w:val="0" /> |
| | | <w:adjustRightInd /> |
| | | <w:snapToGrid /> |
| | | <w:ind w:firstLine="560" w:firstLineChars="200" /> |
| | | <w:textAlignment w:val="auto" /> |
| | | <w:rPr> |
| | | <w:rFonts w:hint="default" w:ascii="仿å®_GB2312" w:hAnsi="仿å®" |
| | | w:eastAsia="仿å®_GB2312" |
| | | w:cs="Times New Roman" /> |
| | | <w:sz w:val="28" /> |
| | | <w:szCs w:val="28" /> |
| | | <w:lang w:val="en-US" w:eastAsia="zh-CN" /> |
| | | </w:rPr> |
| | | </w:pPr> |
| | | <w:r> |
| | | <w:rPr> |
| | | <w:rFonts w:hint="eastAsia" w:ascii="仿å®_GB2312" w:hAnsi="仿å®" |
| | | w:eastAsia="仿å®_GB2312" |
| | | w:cs="Times New Roman" /> |
| | | <w:color w:val="000000" /> |
| | | <w:sz w:val="28" /> |
| | | <w:szCs w:val="28" /> |
| | | <w:lang w:val="en-US" w:eastAsia="zh-CN" /> |
| | | </w:rPr> |
| | | <w:t>å
³èå å<#list item.subFactorName as subItem><#if (subItem_index > 0)>ã</#if>${subItem}</#list>æ°æ®é级å¦ä¸ï¼</w:t> |
| | | </w:r> |
| | | </w:p> |
| | | <#list item.subPictList as subItem> |
| | | <w:p> |
| | | <w:pPr> |
| | | <w:jc w:val="center" /> |
| | | <w:rPr> |
| | | <w:rFonts w:hint="default" w:ascii="仿å®_GB2312" w:hAnsi="仿å®" |
| | | w:eastAsia="仿å®_GB2312" /> |
| | | <w:sz w:val="28" /> |
| | | <w:szCs w:val="28" /> |
| | | <w:highlight w:val="none" /> |
| | | <w:lang w:val="en-US" w:eastAsia="zh-CN" /> |
| | | </w:rPr> |
| | | </w:pPr> |
| | | <w:r> |
| | | <w:rPr> |
| | | <w:rFonts w:hint="default" w:ascii="仿å®_GB2312" w:hAnsi="仿å®" |
| | | w:eastAsia="仿å®_GB2312" /> |
| | | <w:sz w:val="28" /> |
| | | <w:szCs w:val="28" /> |
| | | <w:highlight w:val="none" /> |
| | | <w:lang w:val="en-US" w:eastAsia="zh-CN" /> |
| | | </w:rPr> |
| | | <w:pict> |
| | | <v:shape id="_x0000_i1025_sub_${item_index}-${subItem_index}" o:spt="75" |
| | | alt="f1725d6e3fb17a0e748045906f55ced" type="#_x0000_t75" |
| | | style="height:225pt;width:400pt;" filled="f" |
| | | o:preferrelative="t" stroked="f" coordsize="21600,21600"> |
| | | <v:path /> |
| | | <v:fill on="f" focussize="0,0" /> |
| | | <v:stroke on="f" /> |
| | | <v:imagedata r:id="imageId_sub_${item_index}-${subItem_index}" |
| | | o:title="f1725d6e3fb17a0e748045906f55ced" /> |
| | | <o:lock v:ext="edit" aspectratio="t" /> |
| | | <w10:wrap type="none" /> |
| | | <w10:anchorlock /> |
| | | </v:shape> |
| | | </w:pict> |
| | | </w:r> |
| | | </w:p> |
| | | </#list> |
| | | </#if> |
| | | </#list> |
| | | <w:p> |
| | | <w:pPr> |
| | |
| | | <w:pict> |
| | | <v:shape id="_x0000_i1026_${item_index}" o:spt="75" |
| | | alt="f1725d6e3fb17a0e748045906f55ced" type="#_x0000_t75" |
| | | style="height:222.8pt;width:414.65pt;" filled="f" |
| | | style="height:225pt;width:400pt;" filled="f" |
| | | o:preferrelative="t" stroked="f" coordsize="21600,21600"> |
| | | <v:path /> |
| | | <v:fill on="f" focussize="0,0" /> |
| | |
| | | </pkg:part> |
| | | <#list exceptions as item> |
| | | <pkg:part pkg:name="/word/media/image_${item_index}.png" pkg:contentType="image/png"> |
| | | <pkg:binaryData>${item.pict}</pkg:binaryData> |
| | | <pkg:binaryData>${item.mainPict}</pkg:binaryData> |
| | | </pkg:part> |
| | | <#list item.subPictList as subItem> |
| | | <pkg:part pkg:name="/word/media/image_sub_${item_index}-${subItem_index}.png" pkg:contentType="image/png"> |
| | | <pkg:binaryData>${subItem}</pkg:binaryData> |
| | | </pkg:part> |
| | | </#list> |
| | | </#list> |
| | | <#list summary as item> |
| | | <pkg:part pkg:name="/word/media/image2_${item_index}.png" pkg:contentType="image/png"> |