VehicleViolationsServiceImpl.java 16.9 KB
package com.objecteye.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.objecteye.entity.*;
import com.objecteye.pojo.RabbitMQVehicle;
import com.objecteye.pojo.RabbitMqVehicleViolation;
import com.objecteye.service.IVehicleViolationsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 车辆违规模块
 *
 * @author liuhaoyu
 */
@Component
public class VehicleViolationsServiceImpl implements IVehicleViolationsService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MongoTemplate mongoTemplate;

    private static Map<Integer, String> WEEK_MAP = new HashMap<>();

    static {
        WEEK_MAP.put(1, "周一");
        WEEK_MAP.put(2, "周二");
        WEEK_MAP.put(3, "周三");
        WEEK_MAP.put(4, "周四");
        WEEK_MAP.put(5, "周五");
        WEEK_MAP.put(6, "周六");
        WEEK_MAP.put(7, "周日");
    }

    /**
     * 特殊车辆确认置信度下限
     */
    private final double SPECIAL_VEHICLE_TYPE_LOWER_SCORS = 0.7;
    /**
     * 车辆违规置信度下限
     */
    private final double ILLEGAL_CONFIRM_LIMMIT = 0.9;

    /**
     * 禁行任务查询接口
     *
     * @param currentpage 页码
     * @param pagevolume  页码容量
     * @param name        名称(非必填)
     * @return 结果集
     */
    @Override
    public PageResult forbiddenTaskQueryByPage(Integer currentpage, Integer pagevolume, String name) {
        Criteria criteria = new Criteria();
        if (null != name && !"".equals(name)) {
            criteria.and("name").regex(".*" + name + ".*");
        }

        List<SyVehicleForbidenTask> tempList = mongoTemplate.find(Query.query(criteria)
                .skip((currentpage - 1) * pagevolume).limit(pagevolume), SyVehicleForbidenTask.class);
        long count = mongoTemplate.count(Query.query(criteria), SyVehicleForbidenTask.class);
        // 一次查询所有任务id对应的报警数
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.project("taskId"),
                Aggregation.group("taskId").count().as("count"),
                Aggregation.project("taskId", "count"));
        AggregationResults<JSONObject> vehicleViolationAgg = mongoTemplate.aggregate(aggregation, "rabbitMqVehicleViolation", JSONObject.class);
        List<JSONObject> taskWarningNumList = vehicleViolationAgg.getMappedResults();
        Map<String, String> taskWarningNumMap = new HashMap<>();
        for (JSONObject jsonObject : taskWarningNumList) {
            if (null == jsonObject) {
                continue;
            }
            taskWarningNumMap.put(jsonObject.getString("_id"), jsonObject.getString("count"));
        }

        List<SyVehicleForbiddenTaskOutput> resultList = new ArrayList<>();
        // 拼接返回数据格式
        for (SyVehicleForbidenTask forbiddenTask : tempList) {
            if (null == forbiddenTask) {
                continue;
            }
            SyVehicleForbiddenTaskOutput output = new SyVehicleForbiddenTaskOutput();
            output.setId(forbiddenTask.getId());
            output.setName(forbiddenTask.getName());
            output.setDescription(forbiddenTask.getDescription());
            output.setStatus(null != forbiddenTask.getStatus() && 1 == forbiddenTask.getStatus() ? "工作中" : "已撤销");
            output.setEffectStartTime(DateUtil.format(new Date(forbiddenTask.getEffectStartTime()), "yyyy-MM-dd HH:mm:ss"));
            output.setVehicleType(forbiddenTask.getVehicleType().replaceAll("1", "危化品车").replaceAll("2", "渣土车"));
            JSONObject forbiddenDetailObj = JSON.parseObject(forbiddenTask.getForbiddenDetailTime());
            if (null != forbiddenDetailObj) {
                List<String> forbiddenTimeList = new ArrayList<>();
                for (int i = 1; i <= WEEK_MAP.size(); i++) {
                    if (forbiddenDetailObj.containsKey(String.valueOf(i))) {
                        forbiddenTimeList.add(WEEK_MAP.get(i) + " " + forbiddenDetailObj.getString(String.valueOf(i)));
                    }
                }
                output.setForbiddenDetailTime(String.join(",", forbiddenTimeList));
            }
            String warningNumber = taskWarningNumMap.getOrDefault(String.valueOf(forbiddenTask.getId()), "0");
            output.setWarningNumber(warningNumber);
            resultList.add(output);
        }
        return new PageResult<>((long) Math.ceil((double) count / pagevolume), resultList);
    }

    /**
     * 禁行任务查询明细
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    public SyVehicleForbidenTask forbiddenTaskDetail(String id) {
        return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)), SyVehicleForbidenTask.class);
    }

    /**
     * 禁行任务维护- 新增接口
     *
     * @param syVehicleForbidenTask 请求参数
     * @return 结果集
     */
    @Override
    public int forbiddenTaskAdd(SyVehicleForbidenTask syVehicleForbidenTask) {
        syVehicleForbidenTask.setEffectStartTime(System.currentTimeMillis());
        if (syVehicleForbidenTask.getStatus() == null) {
            syVehicleForbidenTask.setStatus(1);
        }
        mongoTemplate.insert(syVehicleForbidenTask);
        return 1;
    }

    /**
     * 禁行任务维护- 修改接口
     *
     * @param syVehicleForbidenTask 请求参数
     * @return 结果集
     */
    @Override
    public int forbiddenTaskUpdate(SyVehicleForbidenTask syVehicleForbidenTask) {
        mongoTemplate.save(syVehicleForbidenTask);
        return 1;
    }

    /**
     * 禁行任务维护- 删除接口
     *
     * @param ids 请求参数
     * @return 结果集
     */
    @Override
    public int forbiddenTaskDelete(List<String> ids) {
        int effectNum = 0;
        for (String id : ids) {
            if (null == id || "".equals(id)) {
                continue;
            }
            // 删除历史数据
            mongoTemplate.remove(Query.query(Criteria.where("taskId").is(id)), RabbitMqVehicleViolation.class);
            // 删除任务
            mongoTemplate.remove(Query.query(Criteria.where("id").is(id)), SyVehicleForbidenTask.class);
            effectNum++;
        }
        return effectNum;
    }

    /**
     * 布控任务监控
     *
     * @param rabbitMqVehicle mq消息
     */
    @Override
    public void taskListener(RabbitMQVehicle rabbitMqVehicle) {
        RabbitMqVehicleViolation rabbitMqVehicleViolation = JSON.parseObject(JSON.toJSONString(rabbitMqVehicle), RabbitMqVehicleViolation.class);
        rabbitMqVehicleViolation.setBaseId(rabbitMqVehicleViolation.getId());
        double specialScore = rabbitMqVehicleViolation.getVehicle_special_score();
        // 非特殊车辆
        if (specialScore >= SPECIAL_VEHICLE_TYPE_LOWER_SCORS) {
            // 特殊车辆处理
            int specialType = rabbitMqVehicleViolation.getVehicle_special_type();
            // 对激活的任务做判断
            List<SyVehicleForbidenTask> availableForbiddenTasks = mongoTemplate.find(Query.query(Criteria.where("status").ne(0)), SyVehicleForbidenTask.class);
            if (availableForbiddenTasks.size() != 0) {
                // 检测是否违规, 违规一次即跳出循环
                for (SyVehicleForbidenTask forbiddenTask : availableForbiddenTasks) {
                    List<String> vehicleType = Arrays.stream(forbiddenTask.getVehicleType().split(",")).collect(Collectors.toList());
                    if (vehicleType.contains(String.valueOf(specialType))) {
                        // 是否检测时间段内
                        String pictime = DateUtil.format(new Date(rabbitMqVehicleViolation.getPictime()), "yyyy-MM-dd HH:mm:ss");
                        JSONObject forbiddenDetail = JSON.parseObject(forbiddenTask.getForbiddenDetailTime());
                        int dayOfWeek = DateUtil.dayOfWeek(new Date(rabbitMqVehicleViolation.getPictime()));
                        String week = String.valueOf(dayOfWeek == 1 ? 7 : dayOfWeek - 1);
                        String forbiddenDayDetail = forbiddenDetail.getString(week);
                        if (null != forbiddenDayDetail) {
                            String[] timeScopeArr = forbiddenDayDetail.split(",");
                            for (String timeScope : timeScopeArr) {
                                String startTime = pictime.split(" ")[0] + " " + timeScope.split("-")[0];
                                String endTime = pictime.split(" ")[0] + " " + timeScope.split("-")[1];

                                if (betweenMs(pictime, startTime) < 0 && betweenMs(pictime, endTime) > 0) {
                                    rabbitMqVehicleViolation.setId(UUID.randomUUID().toString());
                                    rabbitMqVehicleViolation.setTaskId(forbiddenTask.getId());
                                    mongoTemplate.insert(rabbitMqVehicleViolation);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取时间差值 带正负
     *
     * @param beginDate 开始时间
     * @param endDate   结束时间
     * @return 时间差值
     */
    private long betweenMs(String beginDate, String endDate) {
        return DateUtil.between(DateUtil.parse(beginDate), DateUtil.parse(endDate), DateUnit.MS, false);
    }

    /**
     * 车辆违规查询
     *
     * @param params            请求参数
     * @param useViolationTable 是否是查询禁行违规
     * @return 结果集
     */
    @Override
    public PageResult vehicleViolationQueryByPage(VehicleViolationsForbidenTaskQueryParams params, boolean useViolationTable) {
        int pageNum = params.getCurrentpage();
        int pageSize = params.getPagevolume();
        boolean ifNoCheckStatus = true;

        Criteria criteria = new Criteria();
        Long startTime = params.getStartTime();
        Long endTime = params.getEndTime();
        if (null == startTime) {
            if (null != endTime) {
                criteria.and("pictime").lte(endTime);
            }
        } else if (null == endTime) {
            criteria.and("pictime").gte(startTime);
        } else {
            criteria.andOperator(Criteria.where("pictime").gte(startTime), Criteria.where("pictime").lte(endTime));
        }
        List<Criteria> orCriteriaList = new ArrayList<>();
        if (null != params.getIfNoPlate() && 1 == params.getIfNoPlate()) {
            orCriteriaList.add(Criteria.where("vehicleplatedetectscore").is(0));
            ifNoCheckStatus = false;
        }
        if (null != params.getIfStainedPlate() && 1 == params.getIfStainedPlate()) {
            String regex = "^.*\\*.*$";
            Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
            orCriteriaList.add(Criteria.where("vehicle_plate_hphm").regex(pattern));
            ifNoCheckStatus = false;
        }
        if (null != params.getIfDriverNoBelt() && 1 == params.getIfDriverNoBelt()) {
            orCriteriaList.add(Criteria.where("vehicle_illegal_driver_belt_status").is(1000)
                    .and("vehicle_illegal_driver_belt_confidence").gte(ILLEGAL_CONFIRM_LIMMIT));
            ifNoCheckStatus = false;
        }
        if (null != params.getIfCopilotNoBelt() && 1 == params.getIfCopilotNoBelt()) {
            orCriteriaList.add(Criteria.where("vehicle_illegal_copilot_belt_status").is(1000)
                    .and("vehicle_illegal_copilot_belt_confidence").gte(ILLEGAL_CONFIRM_LIMMIT));
            ifNoCheckStatus = false;
        }
        if (null != params.getIfPhone() && 1 == params.getIfPhone()) {
            orCriteriaList.add(Criteria.where("vehicle_illegal_driver_phone_status").is(1000)
                    .and("vehicle_illegal_driver_phone_confidence").gte(ILLEGAL_CONFIRM_LIMMIT));
            ifNoCheckStatus = false;
        }
        if (null != params.getIfSmoke() && 1 == params.getIfSmoke()) {
            orCriteriaList.add(Criteria.where("vehicle_illegal_driver_smoke_status").is(1000)
                    .and("vehicle_illegal_driver_smoke_confidence").gte(ILLEGAL_CONFIRM_LIMMIT));
            ifNoCheckStatus = false;
        }

        boolean ifMuckCar = null != params.getIfMuckCar() && 1 == params.getIfMuckCar();
        boolean ifDangerousChemicals = null != params.getIfDangerousChemicals() && 1 == params.getIfDangerousChemicals();
        if (ifMuckCar) {
            orCriteriaList.add(Criteria.where("vehicle_special_type").is(2)
                    .and("vehicle_special_score").gte(SPECIAL_VEHICLE_TYPE_LOWER_SCORS));
            ifNoCheckStatus = false;
        }
        if (ifDangerousChemicals) {
            orCriteriaList.add(Criteria.where("vehicle_special_type").is(1)
                    .and("vehicle_special_score").gte(SPECIAL_VEHICLE_TYPE_LOWER_SCORS));
            ifNoCheckStatus = false;
        }

        criteria.orOperator(orCriteriaList.stream().toArray(Criteria[]::new));

        Query query = Query.query(criteria).limit(pageSize).skip((pageNum - 1) * pageSize);
        query.fields().include("id");
        query.fields().include("baseId");
        query.fields().include("pictime");
        query.fields().include("snapshoturl");
        query.fields().include("personUrl");
        query.fields().include("vehicle_plate_hphm");
        query.fields().include("equipmentName");
        return getVehicleViolationQueryResult(query, useViolationTable, ifNoCheckStatus, pageSize);
    }

    /**
     * 车辆违规查询- 获得查询结果
     *
     * @param query             过滤条件
     * @param useViolationTable 是否是使用违规车辆表
     * @param ifNoCheckStatus   是否无勾选项
     * @return 结果集
     */
    private PageResult getVehicleViolationQueryResult(Query query, boolean useViolationTable, boolean ifNoCheckStatus, int pageSize) {
        if (ifNoCheckStatus) {
            return new PageResult<>(0, new ArrayList<>());
        }
        if (useViolationTable) {
            List<RabbitMqVehicleViolation> vehicleViolations = mongoTemplate.find(query, RabbitMqVehicleViolation.class);

            List<VehicleSimpleResult> resultList = new ArrayList<>();
            for (RabbitMqVehicleViolation rabbitMqVehicleViolation : vehicleViolations) {
                if (null == rabbitMqVehicleViolation) {
                    continue;
                }
                VehicleSimpleResult vehicleSimpleResult = new VehicleSimpleResult();
                vehicleSimpleResult.setPicurl(rabbitMqVehicleViolation.getSnapshoturl());
                vehicleSimpleResult.setId(rabbitMqVehicleViolation.getBaseId());
                vehicleSimpleResult.setPersonUrl(rabbitMqVehicleViolation.getPersonUrl());
                vehicleSimpleResult.setPictime(DateUtil.format(new Date(rabbitMqVehicleViolation.getPictime()), "yyyy-MM-dd HH:mm:ss"));
                vehicleSimpleResult.setPlateNumber(rabbitMqVehicleViolation.getVehicle_plate_hphm());
                resultList.add(vehicleSimpleResult);
            }
            long total = mongoTemplate.count(query, RabbitMqVehicleViolation.class);
            int totalPage = (int) Math.ceil((double) total / pageSize);

            return new PageResult<>(totalPage, resultList);
        } else {
            List<RabbitMQVehicle> rabbitMqVehicles = mongoTemplate.find(query, RabbitMQVehicle.class);

            List<VehicleSimpleResult> resultList = new ArrayList<>();
            for (RabbitMQVehicle rabbitMqVehicle : rabbitMqVehicles) {
                if (null == rabbitMqVehicle) {
                    continue;
                }
                VehicleSimpleResult vehicleSimpleResult = new VehicleSimpleResult();
                vehicleSimpleResult.setId(rabbitMqVehicle.getId());
                vehicleSimpleResult.setPicurl(rabbitMqVehicle.getSnapshoturl());
                vehicleSimpleResult.setPersonUrl(rabbitMqVehicle.getPersonUrl());
                vehicleSimpleResult.setPictime(DateUtil.format(new Date(rabbitMqVehicle.getPictime()), "yyyy-MM-dd HH:mm:ss"));
                vehicleSimpleResult.setPlateNumber(rabbitMqVehicle.getVehicle_plate_hphm());
                resultList.add(vehicleSimpleResult);
            }
            long total = mongoTemplate.count(query, RabbitMQVehicle.class);
            int totalPage = (int) Math.ceil((double) total / pageSize);
            return new PageResult<>(totalPage, resultList);
        }
    }
}