feiyu02
2025-11-14 c03e1d823eb86c856ecbe40d8d2180ffce7c7b0f
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
package cn.flightfeather.supervision.lightshare.service.impl
 
import cn.flightfeather.supervision.business.autooutput.datasource.AopDbMapper
import cn.flightfeather.supervision.common.utils.QueryByCache
import cn.flightfeather.supervision.domain.ds1.entity.Problemlist
import cn.flightfeather.supervision.domain.ds1.entity.Problemtype
import cn.flightfeather.supervision.domain.ds1.entity.Subtask
import cn.flightfeather.supervision.lightshare.service.DataProdSingleSceneService
import cn.flightfeather.supervision.lightshare.vo.ProblemListVo
import cn.flightfeather.supervision.lightshare.vo.dataprod.DPChangeInfo
import cn.flightfeather.supervision.lightshare.vo.dataprod.DPProblemRecurrence
import cn.flightfeather.supervision.lightshare.vo.dataprod.QueryOptSingle
import org.springframework.beans.BeanUtils
import org.springframework.stereotype.Service
import tk.mybatis.mapper.entity.Example
 
/**
 * 单场景纵向数据统计产品服务实现类
 * @date 2025/10/30
 * @author feiyu02
 */
@Service
class DataProdSingleSceneServiceImpl(private val aopDbMapper: AopDbMapper) : DataProdSingleSceneService {
 
    // 整改要求最大耗时(天)
    private val MAX_CHANGE_TIME = 3
 
    override fun getChangeInfo(option: QueryOptSingle): DPChangeInfo {
        return QueryByCache.queryCache(
            cache = { return@queryCache null },
            calculate = {
                val subtaskList = aopDbMapper.subtaskMapper.selectByExample(Example(Subtask::class.java).apply {
                    createCriteria().andEqualTo("scenseid", option.sceneId)
                        .andBetween("planstarttime", option.startTime, option.endTime)
                    orderBy("planstarttime").desc()
                })
                if (subtaskList.isEmpty()) return@queryCache DPChangeInfo()
                val problemList = aopDbMapper.problemlistMapper.selectByExample(Example(Problemlist::class.java).apply {
                    createCriteria().andIn("stguid", subtaskList.map { it.stguid })
                })
                return@queryCache DPChangeInfo().apply {
                    subTasks = subtaskList
                    problems = problemList.map { problem ->
                        val problemListVo = ProblemListVo()
                        BeanUtils.copyProperties(problem, problemListVo)
                        problemListVo
                    }
                    proCount = problemList.size
 
                    val changeTimeList = mutableListOf<Long>()
                    problemList.forEach { p ->
                        if (p.ischanged != true) return@forEach
                        // 整改耗时(天)
                        val day = ((p.changedtime?.time ?: 0L) - (p?.time?.time ?: 0L)).div(1000 * 60 * 60 * 24)
                        changeTimeList.add(day)
 
                        // 及时现场整改
                        if (day <= 1) {
                            immeChangeCount++
                        }
                        // 常态/规范整改(48小时内整改)
                        else if (day < MAX_CHANGE_TIME) {
                            normalChangeCount++
                        }
                        // 最终整改
                        changeCount++
                    }
                    immeChangePer = if (proCount == 0) 0.0 else immeChangeCount.toDouble() / proCount
                    normalChangePer = if (proCount == 0) 0.0 else normalChangeCount.toDouble() / proCount
                    changePer = if (proCount == 0) 0.0 else changeCount.toDouble() / proCount
 
                    if (changeTimeList.isNotEmpty()) {
                        changeTime = changeTimeList.maxOrNull()?.toInt() ?: 0
                        val eff = if (changeTime == 0) 1.0 else MAX_CHANGE_TIME.toDouble() / changeTime
                        changeEfficiency = if (eff > 1.0) 1.0 else eff
 
                        avgChangeTime = changeTimeList.average().toInt()
                        val effAvg = if (avgChangeTime == 0) 1.0 else MAX_CHANGE_TIME.toDouble() / avgChangeTime
                        avgChangeEfficiency = if (effAvg > 1.0) 1.0 else effAvg
                    }
                }
            }
        )
    }
 
    override fun getChangeInfoList(options: List<QueryOptSingle>): List<DPChangeInfo> {
        return options.map { getChangeInfo(it) }
    }
 
    override fun getProblemRecurrence(option: QueryOptSingle): List<DPProblemRecurrence> {
        return QueryByCache.queryCache(
            cache = { return@queryCache null },
            calculate = {
                val problemList = aopDbMapper.problemlistMapper.selectByExample(Example(Problemlist::class.java).apply {
                    createCriteria().andEqualTo("sguid", option.sceneId)
                        .andBetween("time", option.startTime, option.endTime)
                    orderBy("time").desc()
                })
                if (problemList.isEmpty()) return@queryCache emptyList()
                val problemTypeList = aopDbMapper.problemtypeMapper.selectByExample(
                    Example(Problemtype::class.java)
                        .apply { createCriteria().andIn("guid", problemList.map { it.ptguid }) })
 
                val problemMap = problemList
                    .filter {
                        val type = problemTypeList.find { type -> type.guid == it.ptguid }
                        type?.typename != "道路扬尘" || type.description == "工地内多条道路明显泥痕/泥泞/积尘/遗撒"
                    }.groupBy { problem ->
                        val type = problemTypeList.find { type -> type.guid == problem.ptguid } ?: return@groupBy null
//                    /**
//                     * 2025.10.30 目前根据业务要求,在工地类型中,“道路扬尘”问题出现概率非常高,
//                     * 因此该问题在做重复性统计时, 只统计用其子类型"工地内多条道路明显泥痕/泥泞/积尘/遗撒"为分类类型
//                     */
//                    if (type.typename == "道路扬尘") {
//                        type.description
//                    } else {
//                        type.typename
//                    }
                        type.description
                    }
                return@queryCache problemMap.map { (key, value) ->
                    val type = problemTypeList.find { type -> type.guid == value.first().ptguid }
                    DPProblemRecurrence().apply {
                        problemTag = key
                        problemType = type
                        this.problemList = value
                        count = value.size
                        changeCount = value.count { it.ischanged == true }
                        changePer = if (count == 0) 0.0 else changeCount.toDouble() / count
                    }
                }
            }
        )
    }
}