fuliqi
2024-10-15 c4d949d801ef6261741567ddbd7594631503ef82
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
package com.ycl.calculate;
 
import com.ycl.platform.domain.entity.CheckIndexCar;
import com.ycl.platform.domain.result.HK.SnapshotDataMonitorResult;
import com.ycl.platform.mapper.CheckIndexCarMapper;
import com.ycl.platform.service.ICheckIndexCarService;
import com.ycl.system.entity.SysDictData;
import com.ycl.system.mapper.SysDictDataMapper;
import com.ycl.utils.DateUtils;
import constant.ApiConstants;
import constant.CheckConstants;
import constant.CheckThreadConstants;
import constant.RedisConstant;
import enumeration.general.AreaDeptEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
 
/**
 * 计算车辆视图库对接稳定性
 * 抓拍数据量监测结果接口数据
 * 获取分省厅、区域的map<k,v> k为deptId或者Province_deptId
 * 循环map计算点位在线率
 * 更新或新增
 */
@Component
@Slf4j
public class CarSnapshopDataCalculation extends IndexCalculationServe<SnapshotDataMonitorResult, CarSnapshopDataCalculation.AreaStats> implements CalculationStrategy<SnapshotDataMonitorResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
    private ICheckIndexCarService checkIndexCarService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysDictDataMapper dictDataMapper;
 
    //区域车辆视图库对接稳定性的内部类
    protected static class AreaStats {
        int totalSites = 0;
        int totalDataSum = 0;
        //加权后的同期抓拍量
        int lastSnapCount = 0;
    }
 
    @Override
    public void calculate(List<SnapshotDataMonitorResult> list) {
        //获取分区域的指标数量
        Map<String, CarSnapshopDataCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list, Boolean.FALSE);
        if (areaStatsMap == null) return;
 
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取本月的第一天
        LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
        // 判断今天是否是本月的第一天
        if (today.equals(firstDayOfMonth)) {
            // 如果是,则清除Redis中记录中断次数的数据
            redisTemplate.delete(RedisConstant.Check_Car_ViewConnect);
        }
        //从字典获取同期抓拍量
        List<SysDictData> lastSnap = dictDataMapper.selectDictDataByType(CheckConstants.DICT_LAST_SNAP);
        //根据各个区县点位数据对同期抓拍量做加权处理
        fillLastSnap(areaStatsMap, lastSnap);
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
        List<CheckIndexCar> checkIndexCars = new ArrayList<>();
        areaStatsMap.forEach((key, stats) -> {
            if (stats.totalSites > 0) {
                CheckIndexCar checkIndexCar = createOrUpdateCheckIndexCar(key, stats, checkIndexCarList);
                if (checkIndexCar != null) {
                    checkIndexCars.add(checkIndexCar);
                }
            }
        });
 
        checkIndexCarService.saveOrUpdateBatch(checkIndexCars);
    }
 
    //根据点位数量对同期抓拍量作加权处理
    private void fillLastSnap(Map<String, AreaStats> areaStatsMap, List<SysDictData> lastSnap) {
        //省厅总点位数
        int provinceTotalSites = 0;
        //区县总点位数
        int countyTotalSites = 0;
        //从字典里筛选省厅值
        int lastProvinceSnap = Integer.parseInt(lastSnap.stream().filter(sysDictData -> CheckConstants.SNAP_PROVINCE_CAR.equals(sysDictData.getDictLabel())).findFirst().get().getDictValue());
        //从字典里筛选区县值
        int lastCountySnap = Integer.parseInt(lastSnap.stream().filter(sysDictData -> CheckConstants.SNAP_COUNTY_CAR.equals(sysDictData.getDictLabel())).findFirst().get().getDictValue());;
 
        //计算总数
        for (Map.Entry<String, AreaStats> entry : areaStatsMap.entrySet()) {
            String key = entry.getKey();
            AreaStats value = entry.getValue();
            if (key.startsWith(ApiConstants.Province)) {
                provinceTotalSites += value.totalSites;
            } else {
                countyTotalSites += value.totalSites;
            }
        }
        //加权操作,补充同期抓拍量
        for (Map.Entry<String, AreaStats> entry : areaStatsMap.entrySet()) {
            String key = entry.getKey();
            AreaStats value = entry.getValue();
            //省厅
            if (key.startsWith(ApiConstants.Province)) {
                if (value.totalSites == 0) {
                    value.lastSnapCount = 0;
                } else {
                    value.lastSnapCount = (value.totalSites / provinceTotalSites) * lastProvinceSnap;
                }
            } else {
                //区县
                if (value.totalSites == 0) {
                    value.lastSnapCount = 0;
                } else {
                    value.lastSnapCount = (value.totalSites / countyTotalSites) * lastCountySnap;
                }
            }
        }
    }
 
    /**
     * 累计总点位数、离线数、总抓拍量
     */
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDataMonitorResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
 
        if (ApiConstants.HK_SnapCount_ResultType_Null != result.getResultType()) {
            stats.totalDataSum += result.getDataCount();
        }
 
    }
 
    /**
     * 车辆视图库对接稳定性
     */
    private CheckIndexCar createOrUpdateCheckIndexCar(String key, AreaStats stats, List<CheckIndexCar> checkIndexCarList) {
        CheckIndexCar checkIndexCar = getCheckIndex(key, checkIndexCarList, CheckIndexCar.class);
        if (checkIndexCar == null) {
            return null;
        }
 
        //视图库对接稳定性
        //Redis记录该区县当月无数据上传次数
        Integer noDateCount = (Integer) redisTemplate.opsForHash().get(RedisConstant.Check_Car_ViewConnect, key);
        // 如果值为null,则初始化为0
        if (noDateCount == null) {
            noDateCount = 0;
        }
        Double deductScore = 0.1 * noDateCount;
 
        if (stats.totalDataSum != 0) {
            Map<String, Object> viewConnectParam = new HashMap<>();
            viewConnectParam.put("totalDataSum", stats.totalDataSum);
            viewConnectParam.put("lastCount", new BigDecimal(stats.lastSnapCount).multiply(new BigDecimal(CheckConstants.MultiplyNum)).divide(new BigDecimal(LocalDate.now().getDayOfMonth()), 0, RoundingMode.HALF_UP));
            BigDecimal viewConnectStability = viewConnectStability(viewConnectParam);
            viewConnectStability = viewConnectStability.subtract(new BigDecimal(deductScore)).max(BigDecimal.ZERO).min(BigDecimal.ONE);
            checkIndexCar.setViewConnectStability(viewConnectStability);
        } else {
            noDateCount++;
        }
        // 将新的值放回Hash中
        redisTemplate.opsForHash().put(RedisConstant.Check_Car_ViewConnect, key, noDateCount);
        return checkIndexCar;
    }
}