/* Copyright 2011 Austin Wagner * * This file is part of Mobile Shuttle Tracker. * * Mobile Shuttle Tracker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Mobile Shuttle Tracker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mobile Shuttle Tracker. If not, see <http://www.gnu.org/licenses/>. */ package com.abstractedsheep.shuttletrackerworld; import java.util.*; import java.util.Map.Entry; import com.abstractedsheep.shuttletrackerworld.Netlink.RouteJson; import com.abstractedsheep.shuttletrackerworld.Netlink.StopJson; import com.abstractedsheep.shuttletrackerworld.Netlink.RouteJson.RouteCoordinateJson; import com.abstractedsheep.shuttletrackerworld.Netlink.StopJson.StopRouteJson; public class World { private static final long SHUTTLE_EXPIRATION_TIME = 60000; private final Map<Integer, Shuttle> shuttles; private final Map<Integer, Route> routes; private final Map<String, Stop> stops; private final List<Shuttle> shuttleList; private final List<Route> routeList; private final List<Stop> stopList; private final Map<Integer, Shuttle> ro_shuttles; private final Map<Integer, Route> ro_routes; private final Map<String, Stop> ro_stops; private final List<Shuttle> ro_shuttleList; private final List<Route> ro_routeList; private final List<Stop> ro_stopList; private World() { this.shuttles = Collections.synchronizedMap(new HashMap<Integer, Shuttle>()); this.routes = Collections.synchronizedMap(new HashMap<Integer, Route>()); this.stops = Collections.synchronizedMap(new HashMap<String, Stop>()); this.ro_shuttles = Collections.unmodifiableMap(shuttles); this.ro_routes = Collections.unmodifiableMap(routes); this.ro_stops = Collections.unmodifiableMap(stops); this.shuttleList = Collections.synchronizedList(new ArrayList<Shuttle>()); this.routeList = Collections.synchronizedList(new ArrayList<Route>()); this.stopList = Collections.synchronizedList(new ArrayList<Stop>()); this.ro_shuttleList = Collections.unmodifiableList(shuttleList); this.ro_routeList = Collections.unmodifiableList(routeList); this.ro_stopList = Collections.unmodifiableList(stopList); } /// <summary> /// Create a world object from a Netlink object. /// </summary> /// <param name="n">The Netlink class that represents the Netlink JSON.</param> /// <returns>A world generated from the Netlink.</returns> public static World generateWorld(Netlink n) { World w = new World(); for (RouteJson r : n.getRoutes()) { w.addRoute(r); } for (StopJson s : n.getStops()) { w.addStop(s); } return w; } /// <summary> /// Removes all shuttles older than SHUTTLE_EXPIRATION_TIME /// </summary> public void removeOldShuttles() { Set<Entry<Integer, Shuttle>> tempEntrySet = shuttles.entrySet(); synchronized (shuttleList) { for (Entry<Integer, Shuttle> e : tempEntrySet) { if (System.currentTimeMillis() - e.getValue().getLastUpdateTime() > SHUTTLE_EXPIRATION_TIME) shuttleList.remove(shuttles.remove(e.getKey())); } } } /// <summary> /// Adds a shuttle to the world or updates the position of an existing shuttle. /// </summary> /// <param name="shuttleId">The ID number of the shuttle.</param> /// <param name="location">The shuttle's current location.</param> /// <param name="name">The name of the shuttle.</param> /// <param name="bearing">The heading of the shuttle in degrees from north.</param> /// <param name="cardinalPoint">The heading of the shuttle as a cardinal direcation (e.g. Northwest).</param> /// <param name="speed">The speed of the shuttle in miles per hour.</param> /// <param name="route">The id of the shuttle route. -1 indicates that the shuttle is not on a route.</param> public void addOrUpdateShuttle(int shuttleId, Coordinate location, String name, int bearing, String cardinalPoint, int speed, int route) { Shuttle s = this.shuttles.get(shuttleId); Route r = this.routes.get(route); if (s == null) { s = new Shuttle(); s.id = shuttleId; s.location = location; s.name = name; s.bearing = bearing; s.cardinalPoint = cardinalPoint; s.setSpeed(speed); s.lastUpdateTime = System.currentTimeMillis(); this.shuttles.put(s.id, s); this.shuttleList.add(s); if (r != null) { s.currentRoute = r; r.shuttles.put(s.id, s); r.shuttleList.add(s); } s.snapToRoute(); } else { s.lastUpdateTime = System.currentTimeMillis(); s.location = location; s.setSpeed(speed); s.bearing = bearing; s.cardinalPoint = cardinalPoint; s.name = name; if (r == null && s.currentRoute != null) { s.currentRoute.shuttleList.remove(s.currentRoute.shuttles.remove(s.id)); s.currentRoute = null; } else if (r != null && s.currentRoute != null && s.currentRoute != r) { s.currentRoute.shuttleList.remove(s.currentRoute.shuttles.remove(s.id)); s.currentRoute = r; r.shuttles.put(s.id, s); r.shuttleList.add(s); } else if (r != null && s.currentRoute == null) { s.currentRoute = r; r.shuttles.put(s.id, s); r.shuttleList.add(s); } s.snapToRoute(); } } private void addRoute(RouteJson route) { List<Coordinate> coords = new ArrayList<Coordinate>(); for (RouteCoordinateJson rc : route.getCoords()) { coords.add(new Coordinate((int)(rc.getLatitude() * 1E6), (int)(rc.getLongitude() * 1E6))); } addRoute(route.getId(), route.getName(), route.getColorInt(), coords); } private void addRoute(int routeId, String name, int color, List<Coordinate> coords) { Route r = new Route(routeId, name, color, coords); this.routes.put(r.getId(), r); this.routeList.add(r); } private void addStop(StopJson stop) { List<Integer> routes = new ArrayList<Integer>(); for (StopRouteJson sj : stop.getRoutes()) { routes.add(sj.getId()); } addStop(stop.getShort_name(), new Coordinate((int)(stop.getLatitude() * 1E6), (int)(stop.getLongitude() * 1E6)), stop.getName(), routes); } private void addStop(String stopId, Coordinate location, String name, List<Integer> routes) { Stop s = new Stop(stopId, name, location); this.stops.put(s.getId(), s); this.stopList.add(s); for (Integer i : routes) { Route r = this.routes.get(i); s.routes.put(r.getId(), r); s.routeList.add(r); r.stops.put(s.getId(), s); r.stopList.add(s); s.snapToRoute(r); } } public Map<Integer, Shuttle> getShuttles() { return ro_shuttles; } public Map<Integer, Route> getRoutes() { return ro_routes; } public Map<String, Stop> getStops() { return ro_stops; } public List<Shuttle> getShuttleList() { return ro_shuttleList; } public List<Route> getRouteList() { return ro_routeList; } public List<Stop> getStopList() { return ro_stopList; } }