fuliqi
2024-09-09 d5c2dc44df6e6442b3bb5033cd9ca116777aecbc
考核指标代码调整
24个文件已修改
1个文件已添加
1341 ■■■■■ 已修改文件
ycl-pojo/src/main/java/com/ycl/platform/domain/result/BaseResult.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarClockAccuracyCalculation.java 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarConsistentCalculation.java 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarDataIntegrityCalculation.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarDeviceSampleCalculation.java 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarInFoAccuracyCalculation.java 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarSnapshopDataCalculation.java 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/CarSnapshotDelayCalculation.java 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/FaceClockAccuracyCalculation.java 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/FaceConsistentCalculation.java 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/FaceDeviceSampleCalculation.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/FaceInFoAccuracyCalculation.java 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/FaceSnapshotDataCalculation.java 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/FaceSnapshotDelayCalculation.java 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/IndexCalculationServe.java 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/IndexCalculationUtils.java 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/MonitorQualifyCalculation.java 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/MonitorRegistrationCalculation.java 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/PlatformOnlineCalculation.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/VideoOnlineCalculation.java 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/VideoOsdCalculation.java 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/calculate/VideoUsabilityCalculation.java 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/YwPointServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/CarTask.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/application-dev.yml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/result/BaseResult.java
@@ -8,6 +8,8 @@
import java.time.LocalDate;
import java.util.Date;
//deptId不做记录,如果更换区域,国标码前8位会改,等于一个新设备不会影响历史数据
@Data
public class BaseResult {
    @Id
ycl-server/src/main/java/com/ycl/calculate/CarClockAccuracyCalculation.java
@@ -39,7 +39,7 @@
 */
@Component
@Slf4j
public class CarClockAccuracyCalculation extends IndexCalculationServe implements CalculationStrategy<VehicleDeviceInspectionResult> {
public class CarClockAccuracyCalculation extends IndexCalculationServe<VehicleDeviceInspectionResult, CarClockAccuracyCalculation.AreaStats> implements CalculationStrategy<VehicleDeviceInspectionResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
@@ -48,38 +48,16 @@
    private ICheckIndexCarService checkIndexCarService;
    //区域车辆时钟准确性的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int accuracySites = 0;
    }
    @Override
    public void calculate(List<VehicleDeviceInspectionResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(VehicleDeviceInspectionResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (VehicleDeviceInspectionResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province  + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
@@ -99,7 +77,8 @@
    /**
     * 累计时钟合格设备
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, VehicleDeviceInspectionResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, VehicleDeviceInspectionResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
ycl-server/src/main/java/com/ycl/calculate/CarConsistentCalculation.java
@@ -4,6 +4,8 @@
import com.ycl.platform.domain.entity.CheckIndexCar;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.result.HK.DataIntegrityMonitoringResult;
import com.ycl.platform.domain.result.HK.VehicleDeviceInspectionResult;
import com.ycl.platform.domain.result.UY.MonitorQualifyResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexCarMapper;
import com.ycl.platform.mapper.TMonitorMapper;
@@ -34,7 +36,7 @@
 */
@Component
@Slf4j
public class CarConsistentCalculation extends IndexCalculationServe implements CalculationStrategy<TMonitorVO> {
public class CarConsistentCalculation extends IndexCalculationServe<MonitorQualifyResult, CarConsistentCalculation.AreaStats> implements CalculationStrategy<MonitorQualifyResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
@@ -44,48 +46,17 @@
    @Autowired
    private RedisTemplate redisTemplate;
    //区域车辆信息采集准确率的内部类
    private static class AreaStats {
    //区域车辆目录一致率的内部类
    protected static class AreaStats {
        int totalSites = 0;
        int newSites = 0;
    }
    @Override
    public void calculate(List<TMonitorVO> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(list)){
            monitorMap = list.stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        }
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //未注册车辆设备
        Map<String,TMonitor> newMonitorMap = new HashMap<>();
        //Mongo一机一档同步Mysql时放入Redis 筛选出车辆档案
        String json = (String) redisTemplate.opsForValue().get(RedisConstant.New_Monitor_Set);
        if (!StringUtils.isEmpty(json)) {
            List<TMonitor> newMonitors = JSONArray.parseArray(json, TMonitor.class);
            if(!CollectionUtils.isEmpty(newMonitors)){
                newMonitorMap = newMonitors.stream().filter(tMonitor -> tMonitor.getCameraFunType().contains(CheckConstants.Rule_Category_Car+"")).collect(Collectors.toMap(TMonitor::getSerialNumber, Function.identity()));
            }
        }
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (TMonitorVO result : list) {
            TMonitorVO monitor = monitorMap.get(result.getSerialNumber());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result,newMonitorMap);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result,newMonitorMap);
            }
        }
    public void calculate(List<MonitorQualifyResult> list) {
        //获取分区域的指标数量
        Map<String, AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
@@ -98,18 +69,19 @@
                }
            }
        });
        checkIndexCarService.saveOrUpdateBatch(checkIndexCars);
    }
    /**
     * 累计车辆目录一致率
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, TMonitorVO result,Map<String,TMonitor> newMonitorMap) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitorQualifyResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
        if(newMonitorMap.containsKey(result.getSerialNumber())){
        if(result.getNewDevice()!=null && result.getNewDevice()){
            stats.newSites++;
        }
    }
ycl-server/src/main/java/com/ycl/calculate/CarDataIntegrityCalculation.java
@@ -29,7 +29,7 @@
 */
@Component
@Slf4j
public class CarDataIntegrityCalculation extends IndexCalculationServe implements CalculationStrategy<DataIntegrityMonitoringResult> {
public class CarDataIntegrityCalculation extends IndexCalculationServe<DataIntegrityMonitoringResult, CarDataIntegrityCalculation.AreaStats> implements CalculationStrategy<DataIntegrityMonitoringResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
@@ -38,7 +38,7 @@
    private ICheckIndexCarService checkIndexCarService;
    //区域车辆信息采集准确率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int importantTotalSites = 0;
        int integritySites = 0;
@@ -47,30 +47,9 @@
    @Override
    public void calculate(List<DataIntegrityMonitoringResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(DataIntegrityMonitoringResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //获取重点点位集合
        List<String> importantIds = getImportant();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (DataIntegrityMonitoringResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result, importantIds);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result, importantIds);
            }
        }
        //获取分区域的指标数量
        Map<String, CarDataIntegrityCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
@@ -90,7 +69,8 @@
    /**
     * 累计抓拍数据完整设备数和设备总数,区分重点点位
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, DataIntegrityMonitoringResult result, List<String> importantIds) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, DataIntegrityMonitoringResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
@@ -99,7 +79,7 @@
            stats.integritySites++;
        }
        //重点点位为六项属性完整
        if (importantIds.contains(result.getExternalIndexCode())) {
        if (result.getImportantTag()!=null && result.getImportantTag()) {
            stats.importantTotalSites++;
            if (result.getNoIntegrityPercent() <= 0.1) {
                stats.importantIntegritySites++;
ycl-server/src/main/java/com/ycl/calculate/CarDeviceSampleCalculation.java
@@ -30,7 +30,7 @@
 */
@Component
@Slf4j
public class CarDeviceSampleCalculation extends IndexCalculationServe implements CalculationStrategy<VehicleDeviceSamplingResult> {
public class CarDeviceSampleCalculation extends IndexCalculationServe<VehicleDeviceSamplingResult, CarDeviceSampleCalculation.AreaStats> implements CalculationStrategy<VehicleDeviceSamplingResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
@@ -39,7 +39,7 @@
    private ICheckIndexCarService checkIndexCarService;
    //区域车辆抽检指标
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int importantTotalSites = 0;
        //属性识别准确的点位数
@@ -54,30 +54,9 @@
    @Override
    public void calculate(List<VehicleDeviceSamplingResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(VehicleDeviceSamplingResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //获取重点点位集合
        List<String> importantIds = getImportant();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (VehicleDeviceSamplingResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result, importantIds);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result, importantIds);
            }
        }
        //获取分区域的指标数量
        Map<String, CarDeviceSampleCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
@@ -97,7 +76,8 @@
    /**
     * 累计抓拍数据准确设备数和设备总数,区分重点点位
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, VehicleDeviceSamplingResult result, List<String> importantIds) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, VehicleDeviceSamplingResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        VehicleDeviceSamplingResult.VehicleDifference vehDiff = result.getVehDiff();
@@ -108,7 +88,7 @@
            stats.accuracySites++;
        }
        //重点点位为六项属性
        if (importantIds.contains(result.getExternalIndexCode())) {
        if (result.getImportantTag() != null && result.getImportantTag()) {
            stats.importantTotalSites++;
            if (vehDiff.getImportantConPercent() >= 0.9) {
                stats.importantAccuracySites++;
@@ -138,7 +118,7 @@
        if (checkIndexCar == null) {
            return null;
        }
        log.info("key:{},车辆抓拍数据准确性:totalSites:{},importantTotalSites:{},accuracySites:{},importantAccuracySites:{}",key,stats.totalSites,stats.importantTotalSites,stats.accuracySites,stats.importantAccuracySites);
        log.info("key:{},车辆抓拍数据准确性:totalSites:{},importantTotalSites:{},accuracySites:{},importantAccuracySites:{}", key, stats.totalSites, stats.importantTotalSites, stats.accuracySites, stats.importantAccuracySites);
        //调用车辆抓拍数据准确性计算方法
        Map<String, Object> accuracyParam = new HashMap<>();
        accuracyParam.put("totalSites", stats.totalSites);
@@ -147,14 +127,14 @@
        accuracyParam.put("importantAccuracySites", stats.importantAccuracySites);
        BigDecimal dataAccuracy = dataAccuracy(accuracyParam);
        checkIndexCar.setVehicleCaptureAccuracy(dataAccuracy);
        log.info("url可用性: totalSites:{},urlQualifySites:{}",stats.totalSites,stats.urlUsabilitySites);
        log.info("url可用性: totalSites:{},urlQualifySites:{}", stats.totalSites, stats.urlUsabilitySites);
        //调用url可用性计算方法
        Map<String, Object> urlParam = new HashMap<>();
        urlParam.put("totalSites", stats.totalSites);
        urlParam.put("urlQualifySites", stats.urlUsabilitySites);
        BigDecimal urlUsability = urlUsability(urlParam);
        checkIndexCar.setVehicleUrlAvailability(urlUsability);
        log.info("大图可用性: totalSites:{},picUsabilitySites:{}",stats.totalSites,stats.picUsabilitySites);
        log.info("大图可用性: totalSites:{},picUsabilitySites:{}", stats.totalSites, stats.picUsabilitySites);
        //调用大图可用性计算方法
        Map<String, Object> usabilityParam = new HashMap<>();
        usabilityParam.put("totalSites", stats.totalSites);
ycl-server/src/main/java/com/ycl/calculate/CarInFoAccuracyCalculation.java
@@ -36,7 +36,7 @@
 */
@Component
@Slf4j
public class CarInFoAccuracyCalculation extends IndexCalculationServe implements CalculationStrategy<CrossDetailResult> {
public class CarInFoAccuracyCalculation extends IndexCalculationServe<CrossDetailResult, CarInFoAccuracyCalculation.AreaStats> implements CalculationStrategy<CrossDetailResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
@@ -45,38 +45,16 @@
    private ICheckIndexCarService checkIndexCarService;
    //区域车辆信息采集准确率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int qualifySite = 0;
    }
    @Override
    public void calculate(List<CrossDetailResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(CrossDetailResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (CrossDetailResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, CarInFoAccuracyCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
@@ -97,7 +75,8 @@
    /**
     * 累计总点位数、标注异常点位数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, CrossDetailResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, CrossDetailResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
ycl-server/src/main/java/com/ycl/calculate/CarSnapshopDataCalculation.java
@@ -2,31 +2,26 @@
import com.ycl.platform.domain.entity.CheckIndexCar;
import com.ycl.platform.domain.result.HK.SnapshotDataMonitorResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexCarMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexCarService;
import com.ycl.system.entity.SysDictData;
import com.ycl.system.mapper.SysConfigMapper;
import com.ycl.system.mapper.SysDeptMapper;
import com.ycl.system.mapper.SysDictDataMapper;
import com.ycl.system.mapper.SysDictTypeMapper;
import com.ycl.utils.DateUtils;
import constant.*;
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 org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算车辆点位在线率、视图库对接稳定性
@@ -37,13 +32,9 @@
 */
@Component
@Slf4j
public class CarSnapshopDataCalculation extends IndexCalculationServe implements CalculationStrategy<SnapshotDataMonitorResult> {
public class CarSnapshopDataCalculation extends IndexCalculationServe<SnapshotDataMonitorResult, CarSnapshopDataCalculation.AreaStats> implements CalculationStrategy<SnapshotDataMonitorResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexCarService checkIndexCarService;
    @Autowired
@@ -51,7 +42,7 @@
    @Autowired
    private SysDictDataMapper dictDataMapper;
    //区域车辆点位在线指标的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int onlineSites = 0;
        int totalDataSum = 0;
@@ -59,18 +50,10 @@
    @Override
    public void calculate(List<SnapshotDataMonitorResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获取分区域的指标数量
        Map<String, CarSnapshopDataCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(SnapshotDataMonitorResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取本月的第一天
@@ -80,23 +63,6 @@
            // 如果是,则清除Redis中记录中断次数的数据
            redisTemplate.delete(RedisConstant.Check_Car_ViewConnect);
        }
        for (SnapshotDataMonitorResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
//        //获取2022同期抓拍平均值 省厅、市局
//        BigDecimal cityCountAvg = getAverageCount(CheckSnapCountConstants.Car_City);
//        BigDecimal countyCountAvg = getAverageCount(CheckSnapCountConstants.Car_County);
        //从字典获取同期抓拍量
        List<SysDictData> carSnap = dictDataMapper.selectDictDataByType(CheckConstants.DICT_CAR_SNAP);
        // 查询是否index表已经存在今日数据
@@ -117,7 +83,8 @@
    /**
     * 累计总点位数、离线数、总抓拍量
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDataMonitorResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDataMonitorResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
ycl-server/src/main/java/com/ycl/calculate/CarSnapshotDelayCalculation.java
@@ -1,31 +1,20 @@
package com.ycl.calculate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ycl.platform.domain.entity.CheckIndexCar;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.result.HK.SnapshotDataMonitorResult;
import com.ycl.platform.domain.result.HK.SnapshotDelayMonitorResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexCarMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexCarService;
import com.ycl.platform.service.ITMonitorService;
import com.ycl.system.mapper.SysConfigMapper;
import constant.ApiConstants;
import constant.CheckConstants;
import constant.CheckSnapCountConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 计算车辆备抓拍数据上传及时性
@@ -36,16 +25,14 @@
 */
@Component
@Slf4j
public class CarSnapshotDelayCalculation extends IndexCalculationServe implements CalculationStrategy<SnapshotDelayMonitorResult> {
public class CarSnapshotDelayCalculation extends IndexCalculationServe<SnapshotDelayMonitorResult, CarSnapshotDelayCalculation.AreaStats> implements CalculationStrategy<SnapshotDelayMonitorResult> {
    @Autowired
    private CheckIndexCarMapper checkIndexCarMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexCarService checkIndexCarService;
    //区域车辆点位在线指标的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalCount = 0;
        int delayCount = 0;
        //0-180s
@@ -58,31 +45,9 @@
    @Override
    public void calculate(List<SnapshotDelayMonitorResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(SnapshotDelayMonitorResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (SnapshotDelayMonitorResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, CarSnapshotDelayCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexCar> checkIndexCarList = checkIndexCarMapper.selectToday(DateUtils.getDate());
@@ -102,7 +67,8 @@
    /**
     * 累计总数据量、延迟数据量
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDelayMonitorResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDelayMonitorResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalCount += result.getDataCount();
ycl-server/src/main/java/com/ycl/calculate/FaceClockAccuracyCalculation.java
@@ -35,47 +35,23 @@
 */
@Component
@Slf4j
public class FaceClockAccuracyCalculation extends IndexCalculationServe implements CalculationStrategy<FaceDeviceInspectionResult> {
public class FaceClockAccuracyCalculation extends IndexCalculationServe<FaceDeviceInspectionResult, FaceClockAccuracyCalculation.AreaStats> implements CalculationStrategy<FaceDeviceInspectionResult> {
    @Autowired
    private CheckIndexFaceMapper CheckIndexFaceMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexFaceService checkIndexFaceService;
    //区域车辆时钟准确性的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int accuracySites = 0;
    }
    @Override
    public void calculate(List<FaceDeviceInspectionResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(FaceDeviceInspectionResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (FaceDeviceInspectionResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, FaceClockAccuracyCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexFace> checkIndexFaceList = CheckIndexFaceMapper.selectToday(DateUtils.getDate());
@@ -95,7 +71,8 @@
    /**
     * 累计时钟合格设备
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, FaceDeviceInspectionResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, FaceDeviceInspectionResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
ycl-server/src/main/java/com/ycl/calculate/FaceConsistentCalculation.java
@@ -1,30 +1,19 @@
package com.ycl.calculate;
import com.alibaba.fastjson2.JSONArray;
import com.ycl.platform.domain.entity.CheckIndexFace;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.domain.result.UY.MonitorQualifyResult;
import com.ycl.platform.mapper.CheckIndexFaceMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexFaceService;
import constant.ApiConstants;
import constant.CheckConstants;
import constant.RedisConstant;
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 org.springframework.util.CollectionUtils;
import utils.DateUtils;
import utils.StringUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算人脸目录一致率
@@ -33,58 +22,23 @@
 */
@Component
@Slf4j
public class FaceConsistentCalculation extends IndexCalculationServe implements CalculationStrategy<TMonitorVO> {
public class FaceConsistentCalculation extends IndexCalculationServe<MonitorQualifyResult, FaceConsistentCalculation.AreaStats> implements CalculationStrategy<MonitorQualifyResult> {
    @Autowired
    private CheckIndexFaceMapper checkIndexFaceMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexFaceService checkIndexFaceService;
    @Autowired
    private RedisTemplate redisTemplate;
    //区域车辆信息采集准确率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int newSites = 0;
    }
    @Override
    public void calculate(List<TMonitorVO> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(list)){
            monitorMap = list.stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        }
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //未注册人脸设备
        Map<String,TMonitor> newMonitorMap = new HashMap<>();
        //Mongo一机一档同步Mysql时放入Redis 筛选出车辆档案
        String json = (String) redisTemplate.opsForValue().get(RedisConstant.New_Monitor_Set);
        if (!StringUtils.isEmpty(json)) {
            List<TMonitor> newMonitors = JSONArray.parseArray(json, TMonitor.class);
            if(!CollectionUtils.isEmpty(newMonitors)){
                newMonitorMap = newMonitors.stream().filter(tMonitor -> tMonitor.getCameraFunType().contains(CheckConstants.Rule_Category_Face+"")).collect(Collectors.toMap(TMonitor::getSerialNumber, Function.identity()));
            }
        }
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (TMonitorVO result : list) {
            TMonitorVO monitor = monitorMap.get(result.getSerialNumber());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result,newMonitorMap);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result,newMonitorMap);
            }
        }
    public void calculate(List<MonitorQualifyResult> list) {
        //获取分区域的指标数量
        Map<String, FaceConsistentCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexFace> checkIndexFaceList = checkIndexFaceMapper.selectToday(DateUtils.getDate());
@@ -104,11 +58,12 @@
    /**
     * 累计人脸目录一致率
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, TMonitorVO result,Map<String,TMonitor> newMonitorMap) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitorQualifyResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
        if(newMonitorMap.containsKey(result.getSerialNumber())){
        if(result.getNewDevice()!=null && result.getNewDevice()){
            stats.newSites++;
        }
    }
ycl-server/src/main/java/com/ycl/calculate/FaceDeviceSampleCalculation.java
@@ -29,7 +29,7 @@
 */
@Component
@Slf4j
public class FaceDeviceSampleCalculation extends IndexCalculationServe implements CalculationStrategy<FaceDeviceSamplingResult> {
public class FaceDeviceSampleCalculation extends IndexCalculationServe<FaceDeviceSamplingResult, FaceDeviceSampleCalculation.AreaStats> implements CalculationStrategy<FaceDeviceSamplingResult> {
    @Autowired
    private CheckIndexFaceMapper checkIndexFaceMapper;
    @Autowired
@@ -38,7 +38,7 @@
    private ICheckIndexFaceService checkIndexFaceService;
    //区域车辆抽检指标
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        //图片合格的点位数
        int picQualifySites = 0;
@@ -48,28 +48,9 @@
    @Override
    public void calculate(List<FaceDeviceSamplingResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(FaceDeviceSamplingResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (FaceDeviceSamplingResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, FaceDeviceSampleCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexFace> checkIndexFaceList = checkIndexFaceMapper.selectToday(DateUtils.getDate());
@@ -89,7 +70,8 @@
    /**
     * 累计抓拍数据准确设备数和设备总数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, FaceDeviceSamplingResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, FaceDeviceSamplingResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        FaceDeviceSamplingResult.BigUsefulness bigUseful = result.getBigUseful();
ycl-server/src/main/java/com/ycl/calculate/FaceInFoAccuracyCalculation.java
@@ -1,29 +1,20 @@
package com.ycl.calculate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ycl.platform.domain.entity.CheckIndexCar;
import com.ycl.platform.domain.entity.CheckIndexFace;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.result.HK.FaceDeviceSamplingResult;
import com.ycl.platform.domain.result.HK.MonitoringDetailResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexFaceMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexFaceService;
import com.ycl.platform.service.ITMonitorService;
import com.ycl.system.mapper.SysConfigMapper;
import constant.ApiConstants;
import constant.CheckConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 人脸卡口信息采集准确率  设备编码、行政区划代码、安装位置、坐标经纬度信息完整准确
@@ -33,47 +24,23 @@
 */
@Component
@Slf4j
public class FaceInFoAccuracyCalculation extends IndexCalculationServe implements CalculationStrategy<MonitoringDetailResult> {
public class FaceInFoAccuracyCalculation extends IndexCalculationServe<MonitoringDetailResult, FaceInFoAccuracyCalculation.AreaStats> implements CalculationStrategy<MonitoringDetailResult> {
    @Autowired
    private CheckIndexFaceMapper checkIndexFaceMapper;
    @Autowired
    private ICheckIndexFaceService checkIndexFaceService;
    @Autowired
    private TMonitorMapper monitorMapper;
    //区域车辆信息采集准确率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int qualifySite = 0;
    }
    @Override
    public void calculate(List<MonitoringDetailResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(MonitoringDetailResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (MonitoringDetailResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, FaceInFoAccuracyCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexFace> checkIndexFaceList = checkIndexFaceMapper.selectToday(DateUtils.getDate());
@@ -94,7 +61,8 @@
    /**
     * 累计总点位数、标注异常点位数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitoringDetailResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitoringDetailResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
ycl-server/src/main/java/com/ycl/calculate/FaceSnapshotDataCalculation.java
@@ -39,7 +39,7 @@
 */
@Component
@Slf4j
public class FaceSnapshotDataCalculation extends IndexCalculationServe implements CalculationStrategy<SnapshotDataMonitorResult> {
public class FaceSnapshotDataCalculation extends IndexCalculationServe<SnapshotDataMonitorResult, FaceSnapshotDataCalculation.AreaStats> implements CalculationStrategy<SnapshotDataMonitorResult> {
    @Autowired
    private CheckIndexFaceMapper checkIndexFaceMapper;
    @Autowired
@@ -53,7 +53,7 @@
    @Autowired
    private SysDictDataMapper dictDataMapper;
    //区域人脸点位在线指标的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int onlineSites = 0;
        int totalDataSum = 0;
@@ -61,17 +61,10 @@
    @Override
    public void calculate(List<SnapshotDataMonitorResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(SnapshotDataMonitorResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //获取分区域的指标数量
        Map<String, FaceSnapshotDataCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取本月的第一天
@@ -81,23 +74,6 @@
            // 如果是,则清除Redis中记录中断次数的数据
            redisTemplate.delete(RedisConstant.Check_Face_ViewConnect);
        }
        for (SnapshotDataMonitorResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
//        //获取2022同期抓拍平均值 省厅、市局
//        BigDecimal cityCountAvg = getAverageCount(CheckSnapCountConstants.Face_City);
//        BigDecimal countyCountAvg = getAverageCount(CheckSnapCountConstants.Face_County);
        //从字典获取同期抓拍量
        List<SysDictData> faceSnap = dictDataMapper.selectDictDataByType(CheckConstants.DICT_FACE_SNAP);
        // 查询今日数据
@@ -116,7 +92,8 @@
    }
    //累计总点位数、离线数、总抓拍量
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDataMonitorResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDataMonitorResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
@@ -126,14 +103,6 @@
        }
    }
//    //获取2022同期抓拍平均值
//    private BigDecimal getAverageCount(String configKey) {
//        String count = sysConfigMapper.checkConfigKeyUnique(configKey).getConfigValue();
//        return new BigDecimal(count)
//                .multiply(new BigDecimal(CheckSnapCountConstants.Multiply))
//                .divide(new BigDecimal(CheckSnapCountConstants.CountyNum), 10, RoundingMode.HALF_UP)
//                .divide(new BigDecimal(LocalDate.now().getDayOfMonth()), 0, RoundingMode.HALF_UP);
//    }
    //车辆点位在线率和视图库对接稳定性
    private CheckIndexFace createOrUpdateCheckIndexFace(String key, AreaStats stats, List<CheckIndexFace> checkIndexFaceList,List<SysDictData> faceSnap) {
ycl-server/src/main/java/com/ycl/calculate/FaceSnapshotDelayCalculation.java
@@ -2,16 +2,11 @@
import com.ycl.platform.domain.entity.CheckIndexFace;
import com.ycl.platform.domain.result.HK.SnapshotDelayMonitorResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexFaceMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexFaceService;
import constant.ApiConstants;
import constant.CheckConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
@@ -19,8 +14,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算人脸设备抓拍数据上传及时性
@@ -31,16 +24,14 @@
 */
@Component
@Slf4j
public class FaceSnapshotDelayCalculation extends IndexCalculationServe implements CalculationStrategy<SnapshotDelayMonitorResult> {
public class FaceSnapshotDelayCalculation extends IndexCalculationServe<SnapshotDelayMonitorResult, FaceSnapshotDelayCalculation.AreaStats> implements CalculationStrategy<SnapshotDelayMonitorResult> {
    @Autowired
    private CheckIndexFaceMapper checkIndexFaceMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexFaceService checkIndexFaceService;
    //区域人脸数据上传延迟指标的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalCount = 0;
        int delayCount = 0;
        //0-180s
@@ -53,31 +44,9 @@
    @Override
    public void calculate(List<SnapshotDelayMonitorResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(SnapshotDelayMonitorResult::getExternalIndexCode).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (SnapshotDelayMonitorResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getExternalIndexCode());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, FaceSnapshotDelayCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexFace> checkIndexFaceList = checkIndexFaceMapper.selectToday(DateUtils.getDate());
@@ -97,7 +66,8 @@
    /**
     * 累计总数据量、延迟数据量
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDelayMonitorResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, SnapshotDelayMonitorResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalCount += result.getDataCount();
ycl-server/src/main/java/com/ycl/calculate/IndexCalculationServe.java
@@ -1,249 +1,54 @@
package com.ycl.calculate;
import com.ycl.platform.base.CheckIndex;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.entity.YwPoint;
import com.ycl.platform.domain.result.UY.MonitorQualifyResult;
import com.ycl.platform.domain.result.BaseResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.mapper.YwPointMapper;
import com.ycl.utils.DateUtils;
import constant.ApiConstants;
import constant.CheckConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算公式
 * 抽出各区域统计数量方法
 */
@Component
@Slf4j
public class IndexCalculationServe {
    @Autowired
    private YwPointMapper pointMapper;
public abstract class IndexCalculationServe <T extends BaseResult, S> extends IndexCalculationUtils {
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private MongoTemplate mongoTemplate;
    //抽象方法,由子类编写具体逻辑算法
    protected abstract void updateAreaStats(Map<String, S> areaStatsMap, String key, T result);
    //一机一档合格率
    public BigDecimal monitorQualify(Map<String, Object> param) {
        BigDecimal totalMonitors = new BigDecimal((Integer) param.get("totalMonitors"));
        BigDecimal qualifyMonitor = new BigDecimal((Integer) param.get("qualifyMonitor"));
        return BigDecimal.ZERO.compareTo(totalMonitors) == 0 ? BigDecimal.ZERO : qualifyMonitor.divide(totalMonitors, 4, RoundingMode.HALF_UP);
    }
    //一机一档注册率率
    public BigDecimal monitorRegistration(Map<String, Object> param) {
        //新+正在用的档案数
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        //正在用的档案数
        BigDecimal useSites = new BigDecimal((Integer) param.get("totalSites") - (Integer) param.get("newSites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : useSites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //档案考核比
    public BigDecimal archivesRate(Map<String, Object> param) {
        BigDecimal allFiles = new BigDecimal((Integer) param.get("allFiles"));
        BigDecimal todayFiles = new BigDecimal((Integer) param.get("todayFiles"));
        return BigDecimal.ZERO.compareTo(todayFiles) == 0 ? BigDecimal.ZERO : todayFiles.divide(allFiles, 4, RoundingMode.HALF_UP);
    }
    //点位在线率
    public BigDecimal siteOnline(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal onlineSites = new BigDecimal((Integer) param.get("onlineSites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : onlineSites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //视频Osd准确率
    public BigDecimal osdAccuracy(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal osdAccuracySites = new BigDecimal((Integer) param.get("osdAccuracySites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : osdAccuracySites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //视频时间合格率
    public BigDecimal osdTimeAccuracy(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal timeAccuracySites = new BigDecimal((Integer) param.get("timeAccuracySites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : timeAccuracySites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //目录一致率,每超过百分之1扣10%
    public BigDecimal directoryConstant(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal newSites = new BigDecimal((Integer) param.get("newSites"));
        // 计算newSites占totalSites的百分比倍数
        BigDecimal percentage = newSites.divide(totalSites, 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100));
        BigDecimal result = BigDecimal.ONE;
        //超过百分之1没,超过了才扣分
        if (BigDecimal.ONE.compareTo(percentage) <= 0) {
            result = result.subtract(percentage.multiply(new BigDecimal("0.1")));
    protected Map<String, S> getAreaStatsMap(List<T> list){
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return null;
        }
        return result.max(BigDecimal.ZERO);
    }
        //返回以国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(BaseResult::getNo).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        Map<String, S> areaStatsMap = new HashMap<>();
    //视图库对接稳定性
    public BigDecimal viewConnectStability(Map<String, Object> param) {
        BigDecimal totalDataSum = new BigDecimal((Integer) param.get("totalDataSum"));
        BigDecimal avgCount = (BigDecimal) param.get("avgCount");
        log.info("视图库对接稳定性,totalDataSum:{},avgCount:{}",totalDataSum,avgCount);
        return BigDecimal.ZERO.compareTo(totalDataSum) == 0 ? BigDecimal.ZERO : avgCount.divide(totalDataSum, 4, RoundingMode.HALF_UP);
    }
        for (T result : list) {
            //获取设备所属部门
            TMonitorVO monitor = monitorMap.get(result.getNo());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
    //标注正确率
    public BigDecimal infoAccuracy(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal qualifySiteCount = new BigDecimal((Integer) param.get("qualifySite"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : qualifySiteCount.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //数据上传及时性
    public BigDecimal snapshopDelay(Map<String, Object> param) {
        BigDecimal totalCount = new BigDecimal((Integer) param.get("totalCount"));
        BigDecimal delayCount = new BigDecimal((Integer) param.get("delayCount"));
        BigDecimal delayCount1 = new BigDecimal((Integer) param.get("delayCount1"));
        BigDecimal delayCount2 = new BigDecimal((Integer) param.get("delayCount2"));
        BigDecimal delayCount3 = new BigDecimal((Integer) param.get("delayCount3"));
        BigDecimal result = BigDecimal.ZERO.compareTo(totalCount) == 0 ? BigDecimal.ZERO :
                totalCount.subtract(delayCount).divide(totalCount, 10, RoundingMode.HALF_UP).multiply(BigDecimal.ONE)
                        .add(delayCount1.divide(totalCount, 10, RoundingMode.HALF_UP).multiply(BigDecimal.ONE))
                        .add(delayCount2.divide(totalCount, 10, RoundingMode.HALF_UP).multiply(new BigDecimal("0.8")))
                        .add(delayCount3.divide(totalCount, 10, RoundingMode.HALF_UP).multiply(new BigDecimal("0.6")));
        return result.setScale(4, RoundingMode.HALF_UP);
    }
    //车辆数据完整性
    public BigDecimal dataIntegrity(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal importantTotalSites = new BigDecimal((Integer) param.get("importantTotalSites"));
        BigDecimal integritySites = new BigDecimal((Integer) param.get("integritySites"));
        BigDecimal importantIntegritySites = new BigDecimal((Integer) param.get("importantIntegritySites"));
        BigDecimal total = BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : integritySites.divide(totalSites, 10, RoundingMode.HALF_UP);
        BigDecimal important = BigDecimal.ZERO.compareTo(importantTotalSites) == 0 ? BigDecimal.ZERO : importantIntegritySites.divide(importantTotalSites, 10, RoundingMode.HALF_UP);
        return total.multiply(important).setScale(4, RoundingMode.HALF_UP);
    }
    //车辆数据完整性
    public BigDecimal dataAccuracy(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal importantTotalSites = new BigDecimal((Integer) param.get("importantTotalSites"));
        BigDecimal accuracySites = new BigDecimal((Integer) param.get("accuracySites"));
        BigDecimal importantAccuracySites = new BigDecimal((Integer) param.get("importantAccuracySites"));
        BigDecimal total = BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : accuracySites.divide(totalSites, 10, RoundingMode.HALF_UP);
        BigDecimal important = BigDecimal.ZERO.compareTo(importantTotalSites) == 0 ? BigDecimal.ZERO : importantAccuracySites.divide(importantTotalSites, 10, RoundingMode.HALF_UP);
        return total.multiply(important).setScale(4, RoundingMode.HALF_UP);
    }
    //时钟准确性
    public BigDecimal clockAccuracy(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal accuracySites = new BigDecimal((Integer) param.get("accuracySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : accuracySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //url可用性
    public BigDecimal urlUsability(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal urlQualifySites = new BigDecimal((Integer) param.get("urlQualifySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : urlQualifySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //大图可用性
    public BigDecimal picUsability(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal picUsabilitySites = new BigDecimal((Integer) param.get("picUsabilitySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : picUsabilitySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //图片合格率
    public BigDecimal dataQualify(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal picQualifySites = new BigDecimal((Integer) param.get("picQualifySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : picQualifySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //录像可用率
    public BigDecimal videoUsability(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal usabilitySites = new BigDecimal((Integer) param.get("usabilitySites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : usabilitySites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //返回省厅国标码集合
    public List<String> getProvince() {
        List<YwPoint> province = pointMapper.selectByTag(null, Boolean.TRUE, null, null);
        return CollectionUtils.isEmpty(province) ? new ArrayList<>() : province.stream().map(YwPoint::getSerialNumber).collect(Collectors.toList());
    }
    //返回重点点位集合
    public List<String> getImportant() {
        List<YwPoint> important = pointMapper.selectByTag(Boolean.TRUE, null, null, null);
        return CollectionUtils.isEmpty(important) ? new ArrayList<>() : important.stream().map(YwPoint::getSerialNumber).collect(Collectors.toList());
    }
    //返回重点指挥图像集合
    public List<String> getCommandImage() {
        List<YwPoint> commandImages = pointMapper.selectByTag(null, null, Boolean.TRUE, null);
        return CollectionUtils.isEmpty(commandImages) ? new ArrayList<>() : commandImages.stream().map(YwPoint::getSerialNumber).collect(Collectors.toList());
    }
    //返回部级点位集合
    public List<String> getDeptTag() {
        List<YwPoint> commandImages = pointMapper.selectByTag(null, null, null, Boolean.TRUE);
        return CollectionUtils.isEmpty(commandImages) ? new ArrayList<>() : commandImages.stream().map(YwPoint::getSerialNumber).collect(Collectors.toList());
    }
    //返回monitor
    public List<String> getMonitorFromMongo() {
        Date yesterday = DateUtils.addDays(new Date(), -1);
        Query query = new Query(Criteria.where("mongoCreateTime").gte(DateUtils.getDayStart(yesterday)).lt(DateUtils.getDayEnd(yesterday)));
        List<MonitorQualifyResult> oneMachineFileResults = mongoTemplate.find(query, MonitorQualifyResult.class);
        return CollectionUtils.isEmpty(oneMachineFileResults) ? new ArrayList<>() : oneMachineFileResults.stream().map(result -> result.getSerialNumber().getValue()).collect(Collectors.toList());
    }
    //检查是否存在当日数据
    public <T extends CheckIndex> T getCheckIndex(String key, List<T> checkIndexList, Class<T> clazz) {
        T checkIndex;
        // 检查是否已存在今日数据
        Optional<T> existingIndex = checkIndexList.stream()
                .filter(index -> key.startsWith(ApiConstants.Province) ?
                        CheckConstants.Examine_Tag_Province.equals(index.getExamineTag()) && key.split("_")[1].equals(index.getDeptId().toString())
                        : CheckConstants.Examine_Tag_County.equals(index.getExamineTag()) && key.equals(index.getDeptId().toString()))
                .findFirst();
        if (existingIndex.isPresent()) {
            checkIndex = existingIndex.get();
        } else {
            try {
                checkIndex = clazz.getDeclaredConstructor().newInstance();
                checkIndex.setDeptId(key.startsWith(ApiConstants.Province) ? Long.parseLong(key.split("_")[1]) : Long.parseLong(key));
                checkIndex.setExamineTag(key.startsWith(ApiConstants.Province) ? CheckConstants.Examine_Tag_Province : CheckConstants.Examine_Tag_County);
                checkIndex.setCreateTime(new Date());
            } catch (Exception e) {
                checkIndex = null;
                log.error("无法创建 checkIndex 实例", e);
            // 处理省厅数据
            if (result.getProvinceTag()!=null && result.getProvinceTag()) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        return checkIndex;
        return areaStatsMap;
    }
}
ycl-server/src/main/java/com/ycl/calculate/IndexCalculationUtils.java
New file
@@ -0,0 +1,193 @@
package com.ycl.calculate;
import com.ycl.platform.base.CheckIndex;
import constant.ApiConstants;
import constant.CheckConstants;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Slf4j
public class IndexCalculationUtils {
    //检查是否存在当日数据
    public <I extends CheckIndex> I getCheckIndex(String key, List<I> checkIndexList, Class<I> clazz) {
        I checkIndex;
        // 检查是否已存在今日数据
        Optional<I> existingIndex = checkIndexList.stream()
                .filter(index -> key.startsWith(ApiConstants.Province) ?
                        CheckConstants.Examine_Tag_Province.equals(index.getExamineTag()) && key.split("_")[1].equals(index.getDeptId().toString())
                        : CheckConstants.Examine_Tag_County.equals(index.getExamineTag()) && key.equals(index.getDeptId().toString()))
                .findFirst();
        if (existingIndex.isPresent()) {
            checkIndex = existingIndex.get();
        } else {
            try {
                checkIndex = clazz.getDeclaredConstructor().newInstance();
                checkIndex.setDeptId(key.startsWith(ApiConstants.Province) ? Long.parseLong(key.split("_")[1]) : Long.parseLong(key));
                checkIndex.setExamineTag(key.startsWith(ApiConstants.Province) ? CheckConstants.Examine_Tag_Province : CheckConstants.Examine_Tag_County);
                checkIndex.setCreateTime(new Date());
            } catch (Exception e) {
                checkIndex = null;
                log.error("无法创建 checkIndex 实例", e);
            }
        }
        return checkIndex;
    }
    /** --------指标算法---------*/
    //一机一档合格率
    public BigDecimal monitorQualify(Map<String, Object> param) {
        BigDecimal totalMonitors = new BigDecimal((Integer) param.get("totalMonitors"));
        BigDecimal qualifyMonitor = new BigDecimal((Integer) param.get("qualifyMonitor"));
        return BigDecimal.ZERO.compareTo(totalMonitors) == 0 ? BigDecimal.ZERO : qualifyMonitor.divide(totalMonitors, 4, RoundingMode.HALF_UP);
    }
    //一机一档注册率率
    public BigDecimal monitorRegistration(Map<String, Object> param) {
        //新+正在用的档案数
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        //正在用的档案数
        BigDecimal useSites = new BigDecimal((Integer) param.get("totalSites") - (Integer) param.get("newSites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : useSites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //档案考核比
    public BigDecimal archivesRate(Map<String, Object> param) {
        BigDecimal allFiles = new BigDecimal((Integer) param.get("allFiles"));
        BigDecimal todayFiles = new BigDecimal((Integer) param.get("todayFiles"));
        return BigDecimal.ZERO.compareTo(todayFiles) == 0 ? BigDecimal.ZERO : todayFiles.divide(allFiles, 4, RoundingMode.HALF_UP);
    }
    //点位在线率
    public BigDecimal siteOnline(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal onlineSites = new BigDecimal((Integer) param.get("onlineSites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : onlineSites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //视频Osd准确率
    public BigDecimal osdAccuracy(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal osdAccuracySites = new BigDecimal((Integer) param.get("osdAccuracySites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : osdAccuracySites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //视频时间合格率
    public BigDecimal osdTimeAccuracy(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal timeAccuracySites = new BigDecimal((Integer) param.get("timeAccuracySites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : timeAccuracySites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
    //目录一致率,每超过百分之1扣10%
    public BigDecimal directoryConstant(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal newSites = new BigDecimal((Integer) param.get("newSites"));
        // 计算newSites占totalSites的百分比倍数
        BigDecimal percentage = newSites.divide(totalSites, 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100));
        BigDecimal result = BigDecimal.ONE;
        //超过百分之1没,超过了才扣分
        if (BigDecimal.ONE.compareTo(percentage) <= 0) {
            result = result.subtract(percentage.multiply(new BigDecimal("0.1")));
        }
        return result.max(BigDecimal.ZERO);
    }
    //视图库对接稳定性
    public BigDecimal viewConnectStability(Map<String, Object> param) {
        BigDecimal totalDataSum = new BigDecimal((Integer) param.get("totalDataSum"));
        BigDecimal avgCount = (BigDecimal) param.get("avgCount");
        log.info("视图库对接稳定性,totalDataSum:{},avgCount:{}",totalDataSum,avgCount);
        return BigDecimal.ZERO.compareTo(totalDataSum) == 0 ? BigDecimal.ZERO : avgCount.divide(totalDataSum, 4, RoundingMode.HALF_UP);
    }
    //标注正确率
    public BigDecimal infoAccuracy(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal qualifySiteCount = new BigDecimal((Integer) param.get("qualifySite"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : qualifySiteCount.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //数据上传及时性
    public BigDecimal snapshopDelay(Map<String, Object> param) {
        BigDecimal totalCount = new BigDecimal((Integer) param.get("totalCount"));
        BigDecimal delayCount = new BigDecimal((Integer) param.get("delayCount"));
        BigDecimal delayCount1 = new BigDecimal((Integer) param.get("delayCount1"));
        BigDecimal delayCount2 = new BigDecimal((Integer) param.get("delayCount2"));
        BigDecimal delayCount3 = new BigDecimal((Integer) param.get("delayCount3"));
        BigDecimal result = BigDecimal.ZERO.compareTo(totalCount) == 0 ? BigDecimal.ZERO :
                totalCount.subtract(delayCount).divide(totalCount, 10, RoundingMode.HALF_UP).multiply(BigDecimal.ONE)
                        .add(delayCount1.divide(totalCount, 10, RoundingMode.HALF_UP).multiply(BigDecimal.ONE))
                        .add(delayCount2.divide(totalCount, 10, RoundingMode.HALF_UP).multiply(new BigDecimal("0.8")))
                        .add(delayCount3.divide(totalCount, 10, RoundingMode.HALF_UP).multiply(new BigDecimal("0.6")));
        return result.setScale(4, RoundingMode.HALF_UP);
    }
    //车辆数据完整性
    public BigDecimal dataIntegrity(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal importantTotalSites = new BigDecimal((Integer) param.get("importantTotalSites"));
        BigDecimal integritySites = new BigDecimal((Integer) param.get("integritySites"));
        BigDecimal importantIntegritySites = new BigDecimal((Integer) param.get("importantIntegritySites"));
        BigDecimal total = BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : integritySites.divide(totalSites, 10, RoundingMode.HALF_UP);
        BigDecimal important = BigDecimal.ZERO.compareTo(importantTotalSites) == 0 ? BigDecimal.ZERO : importantIntegritySites.divide(importantTotalSites, 10, RoundingMode.HALF_UP);
        return total.multiply(important).setScale(4, RoundingMode.HALF_UP);
    }
    //车辆数据完整性
    public BigDecimal dataAccuracy(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal importantTotalSites = new BigDecimal((Integer) param.get("importantTotalSites"));
        BigDecimal accuracySites = new BigDecimal((Integer) param.get("accuracySites"));
        BigDecimal importantAccuracySites = new BigDecimal((Integer) param.get("importantAccuracySites"));
        BigDecimal total = BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : accuracySites.divide(totalSites, 10, RoundingMode.HALF_UP);
        BigDecimal important = BigDecimal.ZERO.compareTo(importantTotalSites) == 0 ? BigDecimal.ZERO : importantAccuracySites.divide(importantTotalSites, 10, RoundingMode.HALF_UP);
        return total.multiply(important).setScale(4, RoundingMode.HALF_UP);
    }
    //时钟准确性
    public BigDecimal clockAccuracy(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal accuracySites = new BigDecimal((Integer) param.get("accuracySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : accuracySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //url可用性
    public BigDecimal urlUsability(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal urlQualifySites = new BigDecimal((Integer) param.get("urlQualifySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : urlQualifySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //大图可用性
    public BigDecimal picUsability(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal picUsabilitySites = new BigDecimal((Integer) param.get("picUsabilitySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : picUsabilitySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //图片合格率
    public BigDecimal dataQualify(Map<String, Object> param) {
        BigDecimal totalSitesCount = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal picQualifySites = new BigDecimal((Integer) param.get("picQualifySites"));
        return BigDecimal.ZERO.compareTo(totalSitesCount) == 0 ? BigDecimal.ZERO : picQualifySites.divide(totalSitesCount, 4, RoundingMode.HALF_UP);
    }
    //录像可用率
    public BigDecimal videoUsability(Map<String, Object> param) {
        BigDecimal totalSites = new BigDecimal((Integer) param.get("totalSites"));
        BigDecimal usabilitySites = new BigDecimal((Integer) param.get("usabilitySites"));
        return BigDecimal.ZERO.compareTo(totalSites) == 0 ? BigDecimal.ZERO : usabilitySites.divide(totalSites, 4, RoundingMode.HALF_UP);
    }
}
ycl-server/src/main/java/com/ycl/calculate/MonitorQualifyCalculation.java
@@ -2,16 +2,11 @@
import com.ycl.platform.domain.entity.CheckIndexVideo;
import com.ycl.platform.domain.result.UY.MonitorQualifyResult;
import com.ycl.platform.domain.result.UY.QueryVqdResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexVideoMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexVideoService;
import constant.ApiConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
@@ -19,8 +14,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算一机一档合格率
@@ -30,16 +23,14 @@
 */
@Component
@Slf4j
public class MonitorQualifyCalculation extends IndexCalculationServe implements CalculationStrategy<MonitorQualifyResult> {
public class MonitorQualifyCalculation extends IndexCalculationServe<MonitorQualifyResult, MonitorQualifyCalculation.AreaStats> implements CalculationStrategy<MonitorQualifyResult> {
    @Autowired
    private CheckIndexVideoMapper checkIndexVideoMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexVideoService checkIndexVideoService;
    //区域视频在线率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        //总档案数
        int totalMonitors = 0;
        //合格档案数
@@ -48,31 +39,9 @@
    @Override
    public void calculate(List<MonitorQualifyResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(result -> result.getSerialNumber().getValue()).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (MonitorQualifyResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getSerialNumber().getValue());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result);
            }
        }
        //获取分区域的指标数量
        Map<String, MonitorQualifyCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexVideo> checkIndexVideoList = checkIndexVideoMapper.selectToday(DateUtils.getDate());
@@ -92,7 +61,8 @@
    /**
     * 累计总档案数和合格档案数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitorQualifyResult result) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitorQualifyResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalMonitors++;
ycl-server/src/main/java/com/ycl/calculate/MonitorRegistrationCalculation.java
@@ -1,29 +1,21 @@
package com.ycl.calculate;
import com.alibaba.fastjson2.JSONArray;
import com.ycl.platform.domain.entity.CheckIndexVideo;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.entity.YwPoint;
import com.ycl.platform.domain.result.UY.VideoOnlineResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.domain.result.UY.MonitorQualifyResult;
import com.ycl.platform.mapper.CheckIndexVideoMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexVideoService;
import constant.ApiConstants;
import constant.CheckThreadConstants;
import constant.RedisConstant;
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 org.springframework.util.CollectionUtils;
import utils.DateUtils;
import utils.StringUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 计算一机一档注册率、档案考核比
@@ -32,16 +24,16 @@
 */
@Component
@Slf4j
public class MonitorRegistrationCalculation extends IndexCalculationServe implements CalculationStrategy<TMonitorVO> {
public class MonitorRegistrationCalculation extends IndexCalculationServe<MonitorQualifyResult, MonitorRegistrationCalculation.AreaStats> implements CalculationStrategy<MonitorQualifyResult> {
    @Autowired
    private CheckIndexVideoMapper checkIndexVideoMapper;
    @Autowired
    private ICheckIndexVideoService checkIndexVideoService;
    @Autowired
    private RedisTemplate redisTemplate;
    private TMonitorMapper monitorMapper;
    //区域视频在线率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        //资产库登记在用数
        int totalSites = 0;
        //未注册的数量
@@ -51,46 +43,12 @@
        //当日档案数(凌晨计算的,实际取得是昨日的一机一档数量)
        int todayFiles = 0;
    }
    //TODO:改为MonitorQualifyResult,算法优化
    @Override
    public void calculate(List<TMonitorVO> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(list)) {
            monitorMap = list.stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        }
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //未注册设备
        Map<String, TMonitor> newMonitorMap = new HashMap<>();
        //Mongo一机一档同步Mysql时放入Redis
        String json = (String) redisTemplate.opsForValue().get(RedisConstant.New_Monitor_Set);
        if (!StringUtils.isEmpty(json)) {
            List<TMonitor> newMonitors = JSONArray.parseArray(json, TMonitor.class);
            if (!CollectionUtils.isEmpty(newMonitors)) {
                newMonitorMap = newMonitors.stream().collect(Collectors.toMap(TMonitor::getSerialNumber, Function.identity()));
            }
        }
        //获取昨日mongo一机一档数量
        List<String> todayMonitor = getMonitorFromMongo();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (TMonitorVO result : list) {
            TMonitorVO monitor = monitorMap.get(result.getSerialNumber());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result, newMonitorMap, todayMonitor);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result, newMonitorMap, todayMonitor);
            }
        }
    public void calculate(List<MonitorQualifyResult> list) {
        //获取分区域的指标数量
        Map<String, MonitorRegistrationCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexVideo> checkIndexVideoList = checkIndexVideoMapper.selectToday(DateUtils.getDate());
@@ -110,16 +68,14 @@
    /**
     * 累计总点位数、在线点位数、重点点位数、重点点位在线数、指挥图像数、指挥图像在线数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, TMonitorVO result, Map<String, TMonitor> newMonitors, List<String> yesterdayMonitor) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, MonitorQualifyResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
        stats.allFiles++;
        if (newMonitors.containsKey(result.getSerialNumber())) {
        if (result.getNewDevice()!=null && result.getNewDevice()) {
            stats.newSites++;
        }
        if (yesterdayMonitor.contains(result.getSerialNumber())) {
            stats.todayFiles++;
        }
    }
ycl-server/src/main/java/com/ycl/calculate/PlatformOnlineCalculation.java
@@ -1,7 +1,10 @@
package com.ycl.calculate;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.ycl.platform.domain.entity.CheckIndexVideo;
import com.ycl.platform.domain.result.BaseResult;
import com.ycl.platform.domain.result.UY.QueryVqdResult;
import com.ycl.platform.domain.result.UY.VideoOnlineResult;
import com.ycl.platform.domain.vo.PlatformOnlineVO;
import com.ycl.platform.mapper.CheckIndexVideoMapper;
import com.ycl.platform.service.ICheckIndexVideoService;
@@ -28,7 +31,7 @@
 */
@Component
@Slf4j
public class PlatformOnlineCalculation extends IndexCalculationServe implements CalculationStrategy<PlatformOnlineVO> {
public class PlatformOnlineCalculation extends IndexCalculationUtils implements CalculationStrategy<PlatformOnlineVO> {
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
@@ -71,4 +74,5 @@
            log.info("数据为空");
        }
    }
}
ycl-server/src/main/java/com/ycl/calculate/VideoOnlineCalculation.java
@@ -1,23 +1,15 @@
package com.ycl.calculate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ycl.platform.domain.entity.CheckIndexVideo;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.result.HK.SnapshotDelayMonitorResult;
import com.ycl.platform.domain.result.UY.QueryVqdResult;
import com.ycl.platform.domain.result.UY.VideoOnlineResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexVideoMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexFaceService;
import com.ycl.platform.service.ICheckIndexVideoService;
import com.ycl.platform.service.ITMonitorService;
import constant.ApiConstants;
import constant.CheckThreadConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
@@ -25,8 +17,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算视频设备点位在线率、重点点位在线率、重点指挥图像在线率、部级点位在线率
@@ -37,7 +27,7 @@
 */
@Component
@Slf4j
public class VideoOnlineCalculation extends IndexCalculationServe implements CalculationStrategy<VideoOnlineResult> {
public class VideoOnlineCalculation extends IndexCalculationServe<VideoOnlineResult, VideoOnlineCalculation.AreaStats> implements CalculationStrategy<VideoOnlineResult> {
    @Autowired
    private CheckIndexVideoMapper checkIndexVideoMapper;
    @Autowired
@@ -46,7 +36,7 @@
    private ICheckIndexVideoService checkIndexVideoService;
    //区域视频在线率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int onlineSites = 0;
        int importantSites = 0;
@@ -59,37 +49,9 @@
    @Override
    public void calculate(List<VideoOnlineResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(VideoOnlineResult::getDeviceId).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //重点点位集合
        List<String> important = getImportant();
        //重点指挥图像集合
        List<String> commandImage = getCommandImage();
        //获取部级点位集合
        List<String> deptTag = getDeptTag();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (VideoOnlineResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getDeviceId());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result, important,commandImage,deptTag);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province  + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result, important,commandImage,deptTag);
            }
        }
        //获取分区域的指标数量
        Map<String, VideoOnlineCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexVideo> checkIndexVideoList = checkIndexVideoMapper.selectToday(DateUtils.getDate());
@@ -109,30 +71,31 @@
    /**
     * 累计总点位数、在线点位数、重点点位数、重点点位在线数、指挥图像数、指挥图像在线数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, VideoOnlineResult result, List<String> important, List<String>  commandImage,List<String> deptTag) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, VideoOnlineResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
        //重点点位
        if(important.contains(result.getDeviceId())){
        if(result.getImportantTag()!=null && result.getImportantTag()){
            stats.importantSites++;
        }
        //指挥图像点位
        if(commandImage.contains(result.getDeviceId())){
        if(result.getImportantCommandImageTag()!=null && result.getImportantCommandImageTag()){
            stats.commandSites++;
        }
        if(deptTag.contains(result.getDeviceId())){
        if(result.getDeptTag()!=null && result.getDeptTag()){
            stats.deptSites++;
        }
        if (ApiConstants.UY_OnlineSite_Online.equals(result.getStatus())){
            stats.onlineSites++;
            if(important.contains(result.getDeviceId())){
            if(result.getImportantTag()!=null && result.getImportantTag()){
                stats.importantOnlineSites++;
            }
            if(commandImage.contains(result.getDeviceId())){
            if(result.getImportantCommandImageTag()!=null && result.getImportantCommandImageTag()){
                stats.commandOnlineSites++;
            }
            if(deptTag.contains(result.getDeviceId())){
            if(result.getDeptTag()!=null && result.getDeptTag()){
                stats.deptOnlineSites++;
            }
        }
ycl-server/src/main/java/com/ycl/calculate/VideoOsdCalculation.java
@@ -2,27 +2,19 @@
import com.ycl.platform.domain.entity.CheckIndexVideo;
import com.ycl.platform.domain.result.UY.OsdCheckResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexVideoMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexVideoService;
import constant.ApiConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算视频设备Osd标注信息、时间准确信息
@@ -31,16 +23,14 @@
 */
@Component
@Slf4j
public class VideoOsdCalculation extends IndexCalculationServe implements CalculationStrategy<OsdCheckResult> {
public class VideoOsdCalculation extends IndexCalculationServe<OsdCheckResult, VideoOsdCalculation.AreaStats> implements CalculationStrategy<OsdCheckResult> {
    @Autowired
    private CheckIndexVideoMapper checkIndexVideoMapper;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private ICheckIndexVideoService checkIndexVideoService;
    //区域视频在线率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int importantTotalSites = 0;
        int importantOsdAccuracySites = 0;
@@ -49,33 +39,9 @@
    @Override
    public void calculate(List<OsdCheckResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(OsdCheckResult::getDeviceNo).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //重点点位集合
        List<String> important = getImportant();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (OsdCheckResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getDeviceNo());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result, important);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result, important);
            }
        }
        //获取分区域的指标数量
        Map<String, VideoOsdCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexVideo> checkIndexVideoList = checkIndexVideoMapper.selectToday(DateUtils.getDate());
@@ -95,13 +61,14 @@
    /**
     * 累计osd合格数、时间偏差合格数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, OsdCheckResult result, List<String> important) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, OsdCheckResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
        //重点点位
        if (important.contains(result.getDeviceNo())) {
        if (result.getImportantTag()) {
            stats.importantTotalSites++;
            if (checkOsd(result)) {
                stats.importantOsdAccuracySites++;
ycl-server/src/main/java/com/ycl/calculate/VideoUsabilityCalculation.java
@@ -1,21 +1,14 @@
package com.ycl.calculate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ycl.platform.domain.entity.CheckIndexVideo;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.param.UY.RecordMetaDSumParam;
import com.ycl.platform.domain.result.UY.QueryVqdResult;
import com.ycl.platform.domain.result.UY.RecordMetaDSumResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.CheckIndexVideoMapper;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.service.ICheckIndexVideoService;
import com.ycl.platform.service.ITMonitorService;
import constant.ApiConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import utils.DateUtils;
import java.math.BigDecimal;
@@ -23,8 +16,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 计算视频设备录像可用率
@@ -35,7 +26,7 @@
 */
@Component
@Slf4j
public class VideoUsabilityCalculation extends IndexCalculationServe implements CalculationStrategy<RecordMetaDSumResult> {
public class VideoUsabilityCalculation extends IndexCalculationServe<RecordMetaDSumResult, VideoUsabilityCalculation.AreaStats> implements CalculationStrategy<RecordMetaDSumResult> {
    @Autowired
    private CheckIndexVideoMapper checkIndexVideoMapper;
    @Autowired
@@ -44,7 +35,7 @@
    private ICheckIndexVideoService checkIndexVideoService;
    //区域视频在线率的内部类
    private static class AreaStats {
    protected static class AreaStats {
        int totalSites = 0;
        int usabilitySites = 0;
        int importantSites = 0;
@@ -55,33 +46,9 @@
    @Override
    public void calculate(List<RecordMetaDSumResult> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return;
        }
        //获得国标码为key的设备map
        Map<String, TMonitorVO> monitorMap = monitorMapper.selectListByIds(list.stream().map(RecordMetaDSumResult::getDeviceId).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(TMonitorVO::getSerialNumber, Function.identity()));
        //获取省厅国标码集合
        List<String> provinceIds = getProvince();
        //重点点位集合
        List<String> important = getImportant();
        List<String> deptTag = getDeptTag();
        Map<String, AreaStats> areaStatsMap = new HashMap<>();
        for (RecordMetaDSumResult result : list) {
            TMonitorVO monitor = monitorMap.get(result.getDeviceId());
            if (monitor == null) continue;
            String deptId = monitor.getDeptId().toString();
            updateAreaStats(areaStatsMap, deptId, result, important,deptTag);
            // 处理省厅数据
            if (!CollectionUtils.isEmpty(provinceIds) && provinceIds.contains(monitor.getSerialNumber())) {
                String provinceKey = ApiConstants.Province + deptId;
                updateAreaStats(areaStatsMap, provinceKey, result, important,deptTag);
            }
        }
        //获取分区域的指标数量
        Map<String, VideoUsabilityCalculation.AreaStats> areaStatsMap = getAreaStatsMap(list);
        if (areaStatsMap == null) return;
        // 查询是否index表已经存在今日数据
        List<CheckIndexVideo> checkIndexVideoList = checkIndexVideoMapper.selectToday(DateUtils.getDate());
@@ -101,22 +68,23 @@
    /**
     * 累计总点位数、在线点位数、重点点位数、重点点位在线数
     */
    private void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, RecordMetaDSumResult result, List<String> important,List<String> deptTag) {
    @Override
    public void updateAreaStats(Map<String, AreaStats> areaStatsMap, String key, RecordMetaDSumResult result) {
        //返回对象的引用,如果不存在会放入新的key,value
        AreaStats stats = areaStatsMap.computeIfAbsent(key, k -> new AreaStats());
        stats.totalSites++;
        if(important.contains(result.getDeviceId())){
        if(result.getImportantTag()!=null && result.getImportantTag()){
            stats.importantSites++;
        }
        if(deptTag.contains(result.getDeviceId())){
        if(result.getDeptTag()!=null && result.getDeptTag()){
            stats.deptSite++;
        }
        if (ApiConstants.UY_RecordStatus_Integrity.equals(result.getRecordStatus())){
            stats.usabilitySites++;
            if(important.contains(result.getDeviceId())){
            if(result.getImportantTag()!=null && result.getImportantTag()){
                stats.importantUsabilitySites++;
            }
            if(deptTag.contains(result.getDeviceId())){
            if(result.getDeptTag()!=null && result.getDeptTag()){
                stats.depteUsabilitySites++;
            }
        }
ycl-server/src/main/java/com/ycl/platform/service/impl/YwPointServiceImpl.java
@@ -329,4 +329,5 @@
            baseResult.setNewDevice(!dbGBList.contains(s));
        }
    }
}
ycl-server/src/main/java/com/ycl/task/CarTask.java
@@ -4,6 +4,7 @@
import com.ycl.calculate.CalculationStrategy;
import com.ycl.factory.IndexCalculationFactory;
import com.ycl.platform.domain.result.HK.*;
import com.ycl.platform.domain.result.UY.MonitorQualifyResult;
import com.ycl.platform.domain.vo.TMonitorVO;
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.utils.DateUtils;
@@ -20,6 +21,7 @@
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@@ -116,10 +118,16 @@
    public void directConsistentTask() {
        log.info("开始计算车辆目录一致率");
        //车辆目录一致率
        List<TMonitorVO> tMonitorVOS = monitorMapper.selectMonitorVOList();
        List<TMonitorVO> list = tMonitorVOS.stream().filter(tMonitorVO -> !StringUtils.isEmpty(tMonitorVO.getCameraFunType()) && tMonitorVO.getCameraFunType().contains(CheckConstants.Rule_Category_Car + "")).collect(Collectors.toList());
        Date yesterday = DateUtils.addDays(new Date(), -1);
        Query query = new Query();
        query.addCriteria(Criteria
                .where("mongoCreateTime").gte(DateUtils.getDayStart(yesterday)).lt(DateUtils.getDayEnd(yesterday)));
        // .*表示任意数量字符 1/2/3 视频/车辆/人脸
        Pattern pattern = Pattern.compile(".*2.*");
        query.addCriteria(Criteria.where("sxjgnlx.value").regex(pattern));
        List<MonitorQualifyResult> results = mongoTemplate.find(query, MonitorQualifyResult.class);
        CalculationStrategy calculator = IndexCalculationFactory.getCalculator(CalculationStrategyConstants.Car_DirectConsistent);
        calculator.calculate(list);
        calculator.calculate(results);
        log.info("结束计算车辆目录一致率");
    }
ycl-server/src/main/resources/application-dev.yml
@@ -37,9 +37,9 @@
spring:
  # 数据源配置
  datasource:
    url: jdbc:mysql://101.35.247.188/zgyw?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true&allowPublicKeyRetrieval=true
    url: jdbc:mysql://localhost:3306/zgyw?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true&allowPublicKeyRetrieval=true
    username: root
    password: ycl@202466
    password: 1234
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
@@ -126,7 +126,7 @@
spring:
  data:
    mongodb:
      uri: mongodb://root1:yunwei%402024@127.0.0.1:27017/zgyw?authSource=admin
      uri: mongodb://root1:yunwei%402024@192.168.3.88:27017/zgyw?authSource=admin
# 拉取数据请求配置
request: