GpsCacheData.java 5.04 KB
package com.bsth.data.gps;

import com.bsth.data.geo.GeoCacheData;
import com.bsth.data.gps.util.CircleQueue;
import com.bsth.data.history.HistoryConsumeTimeDataHandler;
import com.bsth.entity.GpsEntity;
import com.bsth.entity.StationRoute;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * GPS 历史缓存 和 实时对照缓存
 */
public class GpsCacheData {

    /**
     * 每个设备缓存最后 200 个 GPS 点位
     */
    private static final int MAX_CACHE_SIZE = 200;
    private static ConcurrentMap<String, CircleQueue> prevMap;

    /**
     * 实时gps对照 K: 设备号
     */
    private static ConcurrentMap<String, GpsEntity> realMap;

    /**
     * 线路索引的设备号K:lineCode_upDown
     */
    private static ListMultimap<String, String> lineRealMap;

    static {
        prevMap = new ConcurrentHashMap<>();
        realMap = new ConcurrentHashMap<>();
        lineRealMap = Multimaps.synchronizedListMultimap(ArrayListMultimap.create());
    }

    public static void put(GpsEntity gps) {
        String device = gps.getDeviceId();
        GpsEntity prev = realMap.get(device);

        if (null != prev) {
            if (!prev.getCode().equals(gps.getCode())) {
                lineRealMap.remove(prev.getCode(), prev.getDeviceId());
                lineRealMap.put(gps.getCode(), gps.getDeviceId());
            }
            putPrev(prev);
        } else
            lineRealMap.put(gps.getCode(), gps.getDeviceId());


        realMap.put(device, gps);
    }

    private static void putPrev(GpsEntity prev) {
        String device = prev.getDeviceId();
        CircleQueue queue = prevMap.get(device);

        if (null == queue) {
            queue = new CircleQueue(MAX_CACHE_SIZE);
            prevMap.put(device, queue);
        }

        queue.add(prev);
    }

    /**
     * 获取指定时间之前的轨迹数据
     *
     * @param device
     * @param maxSecond
     * @param minSecond
     * @return 如果数据不满足 < minSecond ,则返回空list
     */
    public static List<GpsEntity> prev(String device, long maxSecond, long minSecond) {
        List<GpsEntity> rs = new ArrayList<>();
        CircleQueue queue = prevMap.get(device);

        if (null == queue)
            return rs;

        long t = System.currentTimeMillis();
        minSecond = t - (minSecond * 1000);
        maxSecond = t - (maxSecond * 1000);

        GpsEntity[] array = queue.getQueue();

        if (t - array[0].getTimestamp() < minSecond)
            return rs;

        for (int i = array.length - 1; i > 0; i--) {
            if (t - array[i].getTimestamp() > maxSecond)
                break;
            rs.add(array[i]);
        }
        return rs;
    }

    public static GpsEntity findOne(String device) {
        return realMap.get(device);
    }

    public static Map<String, Object> find(String lineCode, int upDown) {
        List<String> ds = lineRealMap.get(lineCode + "_" + upDown);

        long t = System.currentTimeMillis();
        List<GpsEntity> list = new ArrayList<>(ds.size());
        GpsEntity gps;
        for (String d : ds) {
            gps = findOne(d);
            if(gps.getNbbm().equals("W1F-052"))
                System.out.println("aaaa");
            gps.smoothTransition(t);
            list.add(gps);
        }

        Map<String, Object> rs = new HashMap<>();
        rs.put("list", list);
        rs.put("forecast", HistoryConsumeTimeDataHandler.forecastEnd(list, null));//终点时间预测
        return rs;
    }

    /**
     * 上一个进出的站点
     *
     * @param gps
     * @return
     */
    public static StationRoute prevInStation(GpsEntity gps) {
        CircleQueue queue = prevMap.get(gps.getDeviceId());

        if (null == queue || queue.size() == 0)
            return null;

        GpsEntity[] array = queue.getQueue();

        GpsEntity prev;
        for (int i = array.length - 1; i > 0; i--) {
            prev = array[i];

            if (prev.getInOut() > 0
                    && !prev.getStationCode().equals(gps.getStationCode())) {
                return GeoCacheData.findByCode(prev);
            }
        }
        return null;
    }

    public static void clear(String deviceId) {
        CircleQueue queue = prevMap.get(deviceId);
        if (null != queue) {
            queue = null;
            prevMap.remove(deviceId);
        }
    }

    public static List<GpsEntity> findList(String lineCode, int upDown) {
        List<String> ds = lineRealMap.get(lineCode + "_" + upDown);

        List<GpsEntity> list = new ArrayList<>(ds.size());
        for (String d : ds) {
            list.add(findOne(d));
        }

        return list;
    }
}