feiyu02
2024-06-27 e8f935a01d75c89ac591a80b9318eac2480e2dcd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package com.flightfeather.uav.biz.report
 
import com.flightfeather.uav.biz.FactorFilter
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.common.utils.DateUtil
import com.flightfeather.uav.common.utils.ImageUtil
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
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
 
/**
 * 走航任务报告
 */
@Component
class MissionReport(
    private val exceptionAnalysisController: ExceptionAnalysisController,
    private val missionRep: MissionRep,
    private val realTimeDataRep: RealTimeDataRep,
    @Value("\${filePath}")
    private val filePath: String,
) {
    data class Param(
        val district: String,
        val town: String,
        val year: Int,
        val month: Int,
        val day: Int,
        val first_party: String,
        val start_time: String,
        val end_time: String,
    ) {
        var factor_names: String = ""
        var summary: List<Summary> = emptyList()
            set(value) {
                factor_names = value.map { it.factor }.joinToString("、")
                field = value
            }
        var exceptions: List<ExceptionChart> = emptyList()
 
        /**
         * 传入数据异常集合,自动为每条异常生成折线图
         */
        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
                return@map c
            }
        }
    }
 
    /**
     * 数据统计
     */
    class Summary {
        var id: String? = null
        var factor: String? = null
        var avg: Double? = null
        var min: Double? = null
        var max: Double? = null
 
        // 数据折线图Base64编码
        var pict: String? = null
    }
 
    /**
     * 数据异常所在时段的折线图
     */
    class ExceptionChart : ExceptionResult() {
        // 数据折线图Base64编码
        var pict: String? = null
    }
 
    private val templateName = "report-underway.ftl"
 
    private val dateFormatter = DateTimeFormatter.ofPattern("HH:mm")
 
    // 获取异常分析结果
    fun exceptionAnalysis(mission: Mission, factorFilter: FactorFilter): List<ExceptionResult> {
        return exceptionAnalysisController.run(mission, factorFilter)
    }
 
    // 计算均值和数据范围
    fun dataSummary(mission: Mission, factorFilter: FactorFilter): List<Summary> {
        val preData = PreData(
            DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD),
            factorFilter.mainList()
        )
        val realTimeData = realTimeDataRep.fetchData(mission)
        realTimeData.forEach {
            preData.add(it.toDataVo())
        }
        val resMap = preData.calculate()
 
        val summaries = mutableListOf<Summary>()
        resMap.forEach { (t, u) ->
            summaries.add(Summary().apply {
                id = t.value.toString()
                factor = t.des
                avg = u.avg
                min = u.min
                max = u.max
 
                val byteArray = DataToChartUtil.lineToByteArray(t, realTimeData)
                val base64Str = ImageUtil.compressImage2(byteArray, 400, needPrefix = false)
                pict = base64Str
            })
        }
        return summaries
    }
 
    // 生成参数
    // 根据报告模板生成对应报告
    fun execute(missionCode: String, factorFilter: FactorFilter): String {
        // 1. 任务合法性检查
        val mission = missionRep.findOne(missionCode) ?: throw  BizException("该任务编号不存在")
        // 2. 获取数据异常统计结果,根据
        val exceptions = exceptionAnalysis(mission, factorFilter)
        // 3. 获取均值、范围等统计数据
        val summaries = dataSummary(mission, factorFilter)
        // 4. 生成报告
        val fileName = "report/" + "${mission.districtName}走航监测报告-${
            DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD)
        }.doc"
        val reportTemplate = ReportTemplate(templateName, filePath, fileName)
        val param = getParam(mission, exceptions, summaries)
        val params = reportTemplate.getParam(param)
        GeneratePdfUtil.generateWord(params)
        return fileName
    }
 
    private fun getParam(mission: Mission, exceptions: List<ExceptionResult>, summaries: List<Summary>): Param {
        val startTime = LocalDateTime.ofInstant(mission.startTime.toInstant(), ZoneId.systemDefault())
        val endTime = LocalDateTime.ofInstant(mission.endTime.toInstant(), ZoneId.systemDefault())
        return Param(
            mission.districtName, "", startTime.year, startTime.monthValue, startTime.dayOfMonth, "",
            startTime.format(dateFormatter), endTime.format(dateFormatter)
        ).apply {
            summary = summaries
            addExceptions(exceptions)
        }
    }
}