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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package cn.flightfeather.supervision.business.autooutput.score
 
import cn.flightfeather.supervision.business.autooutput.AopOutput
import cn.flightfeather.supervision.business.autooutput.datasource.AopDataSource
import cn.flightfeather.supervision.business.autooutput.datasource.AopDbMapper
import cn.flightfeather.supervision.business.autooutput.datasource.AopSceneTypeCheck
import cn.flightfeather.supervision.business.autooutput.score.construction.CsScoreItem1
import cn.flightfeather.supervision.business.autooutput.score.construction.CsScoreItem2
import cn.flightfeather.supervision.business.autooutput.score.mixingplant.MpScoreItem1
import cn.flightfeather.supervision.business.autooutput.score.mixingplant.MpScoreItem2
import cn.flightfeather.supervision.business.autooutput.score.restaurant.*
import cn.flightfeather.supervision.business.autooutput.score.storage.StScoreItem1
import cn.flightfeather.supervision.business.autooutput.score.wharf.WhScoreItem1
import cn.flightfeather.supervision.business.autooutput.score.wharf.WhScoreItem2
import cn.flightfeather.supervision.common.utils.UUIDGenerator
import cn.flightfeather.supervision.domain.ds1.entity.Evaluation
import cn.flightfeather.supervision.domain.ds1.entity.Itemevaluation
import org.springframework.stereotype.Component
import java.util.*
import kotlin.math.abs
 
/**
 * 自动评估流程
 */
@Component
class AopEvaluation(
    private val aopDbMapper: AopDbMapper,
    private val aopSceneTypeCheck: AopSceneTypeCheck,
    private val aopOutput: AopOutput,
    csScoreItem1: CsScoreItem1,
    csScoreItem2: CsScoreItem2,
    mpScoreItem1: MpScoreItem1,
    mpScoreItem2: MpScoreItem2,
    stScoreItem1: StScoreItem1,
    whScoreItem1: WhScoreItem1,
    whScoreItem2: WhScoreItem2,
    reScoreItem5: ReScoreItem5,
    reScoreItem7: ReScoreItem7,
    reScoreItem8: ReScoreItem8,
    reScoreItem9: ReScoreItem9,
    reScoreItem10: ReScoreItem10,
    reScoreItem11: ReScoreItem11,
) {
 
    //数据源
    private var source: AopDataSource? = null
    //特定评分项(除了统一的根据巡查问题直接扣分外,有特定的扣分逻辑的评估项)
    private val itemList = mutableListOf<ScoreItem>()
 
    init {
        itemList.apply {
            add(csScoreItem1)
            add(csScoreItem2)
            add(mpScoreItem1)
            add(mpScoreItem2)
            add(stScoreItem1)
            add(whScoreItem1)
            add(whScoreItem2)
            add(reScoreItem5)
            add(reScoreItem7)
            add(reScoreItem8)
            add(reScoreItem9)
            add(reScoreItem10)
            add(reScoreItem11)
        }
    }
 
    fun setResource(topTaskGuid: String?, sceneType: Int, districtName: String? = null, townCode: String? = null) {
        source = AopDataSource(aopDbMapper, aopSceneTypeCheck)
        source?.setResource(topTaskGuid, sceneType, districtName, townCode)
    }
 
    /**
     * 执行评分逻辑
     */
    fun execute() {
        //获取数据源(待评估的场景)
        //循环处理每个场景
        source?.loop {index, evaluationScene ->
            if (evaluationScene.noRecord()) return@loop
 
            itemGrade(index, evaluationScene)
            totalGrade(index, evaluationScene)?.run {
                aopOutput.toDbEvaluation(evaluationScene, this)
            }
        }
 
    }
 
    /**
     * 条目打分
     */
    private fun itemGrade(index: Int, evaluationScene: AopDataSource.EvaluationScene) {
        // 规则条目得分初始化
        evaluationScene.topItems.value?.forEach { s -> s.extension1 = null }
        evaluationScene.rules.value?.forEach { p ->
            p.first.extension1 = null
            p.second.forEach { e -> e.extension1 = null }
        }
 
        /** 1. 根据评分规则对应的问题自动判断是否扣分***************************************************************/
        // 获取该次巡查任务下的所有问题
        val pList = evaluationScene.problems.value?.map { it.ptguid } ?: emptyList()
        // 计算每条评分规则的得分
        evaluationScene.rules.value?.forEach { r ->
            // 评分条目
            val rule = r.first
            // 具体评分选项
            val subRule = r.second
            subRule.forEach { sr ->
                // 存在多个评分项和同一个问题关联,因此必须全部评分项都判定一遍
                sr.problemlist?.split(",")?.forEach { pId ->
                    if (pList.contains(pId)) {
                        sr.extension1 = (0 - (sr.maxscore ?: 0)).toString()
                    }
                }
            }
 
            ScoreUtil.subRuleCal(r)
        }
        /** 2.部分有特殊评分逻辑的规则进行计算*************************************************************************/
        itemList.forEach { item -> item.execute(evaluationScene) }
 
        /** 3. 补全各上级评分项的计分*************************************************************************/
        evaluationScene.rules.value?.forEach { r ->
            val fatherId = r.first.fatherid
            for (t in (evaluationScene.topItems.value ?: emptyList())) {
                if (t.guid == fatherId) {
                    var s = t.extension1?.toIntOrNull() ?: 0
                    s += r.first.extension1?.toIntOrNull() ?: 0
                    // 限制最高扣分
                    if (abs(s) > (t.maxscore ?: 0)) {
                        s = 0 - (t.maxscore ?: 0)
                    }
                    t.extension1 = s.toString()
                    break
                }
            }
        }
    }
 
    /**
     * 计算总分
     */
    private fun totalGrade(index: Int, evaluationScene: AopDataSource.EvaluationScene): Pair<Evaluation, List<Itemevaluation>>? {
        val scene = evaluationScene.scene.value ?: return null
        val topItems = evaluationScene.topItems.value ?: return null
        val rules = evaluationScene.rules.value ?: return null
        val subTask = evaluationScene.subTask.value
        val inspection = evaluationScene.inspection.value
        val totalScore = evaluationScene.totalScore.value ?: return null
 
        var total = 0//总扣除的分数
        evaluationScene.topItems.value?.forEach top@{ top ->
            total += top.extension1?.toIntOrNull() ?: 0
        }
        val evaluation = Evaluation().apply {
                evaluationScene.baseRule.value?.let {
                guid = UUIDGenerator.generate16ShortUUID()
                iguid = inspection?.guid
                stguid = subTask?.stguid
                sguid = subTask?.scenseid
                scensetypeid = scene.typeid
                scensetype = scene.type
                subscensetypeid = scene.scensesubtypeid
                subscensetype = scene.scensesubtype
                ertype = it.ruletype?.toByte()
                provincecode = scene.provincecode
                provincename = scene.provincename
                citycode = scene.citycode
                cityname = scene.cityname
                districtcode = scene.districtcode
                districtname = scene.districtname
                towncode = scene.towncode
                townname = scene.townname
                scensename = scene.name
                scenseaddress = scene.location
                evaluatetime = subTask?.planstarttime
                evaluatorguid = "admin"
                evaluatorusername = "admin"
                evaluatorrealname = "admin"
                resultscorebef = (totalScore - abs(total)).toString()
                createdate = subTask?.planstarttime
                updatedate = Date()
            }
        }
        //子项具体得分
        val itemevaluationList = mutableListOf<Itemevaluation>()
        topItems.forEach { subRule ->
            val item = ScoreUtil.newItemEvaluation(evaluationScene, subRule)
            itemevaluationList.add(item)
        }
        rules.forEach { p ->
            if (p.first.ertype != 2) {
                val item = ScoreUtil.newItemEvaluation(evaluationScene, p.first)
                itemevaluationList.add(item)
            }
            p.second.forEach { r ->
                val item1 = ScoreUtil.newItemEvaluation(evaluationScene, r)
                itemevaluationList.add(item1)
            }
        }
        return Pair(evaluation, itemevaluationList)
    }
}