@BeforeClass
  public static void setUp() throws Exception {

    context = GtfsLibrary.readGtfs(new File(ConstantsForTests.FAKE_GTFS));
    graph = new Graph();

    GTFSPatternHopFactory factory = new GTFSPatternHopFactory(context);
    factory.run(graph);
    graph.putService(
        CalendarServiceData.class, GtfsLibrary.createCalendarServiceData(context.getDao()));

    patternIndex = new HashMap<AgencyAndId, TripPattern>();
    for (TransitStopDepart tsd : filter(graph.getVertices(), TransitStopDepart.class)) {
      for (TransitBoardAlight tba : filter(tsd.getOutgoing(), TransitBoardAlight.class)) {
        if (!tba.isBoarding()) continue;
        TripPattern pattern = tba.getPattern();
        for (Trip trip : pattern.getTrips()) {
          patternIndex.put(trip.getId(), pattern);
        }
      }
    }

    pattern = patternIndex.get(new AgencyAndId("agency", "1.1"));
    timetable = pattern.scheduledTimetable;
  }
  public void testBoardAlight() throws Exception {

    Vertex stop_a = graph.getVertex("agency_A_depart");
    Vertex stop_b_depart = graph.getVertex("agency_B_depart");

    assertEquals(1, stop_a.getDegreeOut());
    assertEquals(3, stop_b_depart.getDegreeOut());

    for (Edge e : stop_a.getOutgoing()) {
      assertEquals(TransitBoardAlight.class, e.getClass());
      assertTrue(((TransitBoardAlight) e).isBoarding());
    }

    // TODO: could this ever be a PatternAlight? I think not.
    TransitBoardAlight pb = (TransitBoardAlight) stop_a.getOutgoing().iterator().next();
    Vertex journey_a_1 = pb.getToVertex();

    assertEquals(1, journey_a_1.getDegreeIn());

    for (Edge e : journey_a_1.getOutgoing()) {
      if (e.getToVertex() instanceof TransitStop) {
        assertEquals(TransitBoardAlight.class, e.getClass());
        assertTrue(((TransitBoardAlight) e).isBoarding());
      } else {
        assertEquals(PatternHop.class, e.getClass());
      }
    }
  }
  public void setUp() throws Exception {

    context = GtfsLibrary.readGtfs(new File(ConstantsForTests.FAKE_GTFS));
    graph = new Graph();

    GTFSPatternHopFactory factory = new GTFSPatternHopFactory(context);
    factory.run(graph);
    graph.putService(
        CalendarServiceData.class, GtfsLibrary.createCalendarServiceData(context.getDao()));

    String[] stops = {
      "agency:A",
      "agency:B",
      "agency:C",
      "agency:D",
      "agency:E",
      "agency:entrance_a",
      "agency:entrance_b"
    };
    for (int i = 0; i < stops.length; ++i) {
      TransitStop stop = (TransitStop) (graph.getVertex(stops[i]));

      IntersectionVertex front =
          new IntersectionVertex(
              graph, "near_1_" + stop.getStopId(), stop.getX() + 0.0001, stop.getY() + 0.0001);
      IntersectionVertex back =
          new IntersectionVertex(
              graph, "near_2_" + stop.getStopId(), stop.getX() - 0.0001, stop.getY() - 0.0001);

      StreetEdge street1 =
          new StreetEdge(
              front,
              back,
              GeometryUtils.makeLineString(
                  stop.getX() + 0.0001,
                  stop.getY() + 0.0001,
                  stop.getX() - 0.0001,
                  stop.getY() - 0.0001),
              "street",
              100,
              StreetTraversalPermission.ALL,
              false);
      StreetEdge street2 =
          new StreetEdge(
              back,
              front,
              GeometryUtils.makeLineString(
                  stop.getX() - 0.0001,
                  stop.getY() - 0.0001,
                  stop.getX() + 0.0001,
                  stop.getY() + 0.0001),
              "street",
              100,
              StreetTraversalPermission.ALL,
              true);
    }

    NetworkLinker nl = new NetworkLinker(graph);
    nl.createLinkage();
  }
  /**
   * Get edges inside a bbox.
   *
   * @return
   */
  @Secured({"ROLE_USER"})
  @GET
  @Path("/edges")
  @Produces({MediaType.APPLICATION_JSON})
  public Object getEdges(
      @QueryParam("lowerLeft") String lowerLeft,
      @QueryParam("upperRight") String upperRight,
      @QueryParam("exactClass") String className,
      @QueryParam("skipTransit") boolean skipTransit,
      @QueryParam("skipStreets") boolean skipStreets,
      @QueryParam("skipNoGeometry") boolean skipNoGeometry) {

    initIndexes();

    Envelope envelope = getEnvelope(lowerLeft, upperRight);

    EdgeSet out = new EdgeSet();
    Graph graph = graphService.getGraph();

    @SuppressWarnings("unchecked")
    List<Edge> query = edgeIndex.query(envelope);
    out.edges = new ArrayList<WrappedEdge>();
    for (Edge e : query) {
      if (skipStreets && (e instanceof StreetEdge)) continue;
      if (skipTransit && !(e instanceof StreetEdge)) continue;
      if (skipNoGeometry && e.getGeometry() == null) continue;
      if (className != null && !e.getClass().getName().endsWith("." + className)) continue;
      out.edges.add(new WrappedEdge(e, graph.getIdForEdge(e)));
    }
    return out.withGraph(graph);
  }
  public RaptorStateSet getStateSet(RoutingRequest options) {

    final Graph graph;
    if (options.rctx == null) {
      graph = graphService.getGraph(options.getRouterId());
      options.setRoutingContext(graph);
      options.rctx.pathParsers =
          new PathParser[] {new BasicPathParser(), new NoThruTrafficPathParser()};
    } else {
      graph = options.rctx.graph;
    }

    RaptorData data = graph.getService(RaptorDataService.class).getData();

    // we multiply the initial walk distance to account for epsilon dominance.
    options.setMaxWalkDistance(options.getMaxWalkDistance() * WALK_EPSILON);

    RoutingRequest walkOptions = options.clone();
    walkOptions.rctx.pathParsers = new PathParser[0];
    TraverseModeSet modes = options.getModes().clone();
    modes.setTransit(false);
    walkOptions.setModes(modes);
    RaptorSearch search = new RaptorSearch(data, options);

    for (int i = 0; i < options.getMaxTransfers() + 2; ++i) {
      if (!round(data, options, walkOptions, search, i)) break;
    }
    RaptorStateSet result = new RaptorStateSet();
    result.statesByStop = search.statesByStop;
    return result;
  }
  @Secured({"ROLE_USER"})
  @GET
  @Path("/annotations")
  @Produces({MediaType.APPLICATION_JSON})
  public Object getAnnotations() {
    Graph graph = graphService.getGraph();
    List<GraphBuilderAnnotation> builderAnnotations = graph.getBuilderAnnotations();

    List<Annotation> out = new ArrayList<Annotation>();
    for (GraphBuilderAnnotation annotation : builderAnnotations) {
      Annotation outAnnotation = new Annotation();
      out.add(outAnnotation);
      outAnnotation.annotation = annotation.getVariety().name();
      Collection<Object> referencedObjects = annotation.getReferencedObjects();
      for (Object object : referencedObjects) {
        AnnotationObject annotationObj = new AnnotationObject();
        applyObjectToAnnotation(graph, annotationObj, object);
        outAnnotation.addObject(annotationObj);
      }
    }

    Annotations annotations = new Annotations();
    annotations.annotations = out;
    return annotations;
  }
 public synchronized void initIndexes() {
   if (vertexIndex != null) {
     return;
   }
   graphService.setLoadLevel(LoadLevel.DEBUG);
   Graph graph = graphService.getGraph();
   vertexIndex = new STRtree();
   edgeIndex = new STRtree();
   for (Vertex v : graph.getVertices()) {
     Envelope vertexEnvelope = new Envelope(v.getCoordinate());
     vertexIndex.insert(vertexEnvelope, v);
     for (Edge e : v.getOutgoing()) {
       Envelope envelope;
       Geometry geometry = e.getGeometry();
       if (geometry == null) {
         envelope = vertexEnvelope;
       } else {
         envelope = geometry.getEnvelopeInternal();
       }
       edgeIndex.insert(envelope, e);
     }
   }
   vertexIndex.build();
   edgeIndex.build();
 }
  public void testTransfers() throws Exception {
    TransferTable transferTable = graph.getTransferTable();

    // create dummy routes and trips
    Route fromRoute = new Route();
    fromRoute.setId(new AgencyAndId("agency", "1"));
    Trip fromTrip = new Trip();
    fromTrip.setId(new AgencyAndId("agency", "1.1"));
    fromTrip.setRoute(fromRoute);
    Route toRoute = new Route();
    toRoute.setId(new AgencyAndId("agency", "2"));
    Trip toTrip = new Trip();
    toTrip.setId(new AgencyAndId("agency", "2.1"));
    toTrip.setRoute(toRoute);
    Trip toTrip2 = new Trip();
    toTrip2.setId(new AgencyAndId("agency", "2.2"));
    toTrip2.setRoute(toRoute);

    // find stops
    Stop stopK = ((TransitStopArrive) graph.getVertex("agency_K_arrive")).getStop();
    Stop stopN = ((TransitStopDepart) graph.getVertex("agency_N_depart")).getStop();
    Stop stopM = ((TransitStopDepart) graph.getVertex("agency_M_depart")).getStop();

    assertTrue(transferTable.hasPreferredTransfers());
    assertEquals(
        StopTransfer.UNKNOWN_TRANSFER,
        transferTable.getTransferTime(stopN, stopM, fromTrip, toTrip));
    assertEquals(
        StopTransfer.FORBIDDEN_TRANSFER,
        transferTable.getTransferTime(stopK, stopM, fromTrip, toTrip));
    assertEquals(
        StopTransfer.PREFERRED_TRANSFER,
        transferTable.getTransferTime(stopN, stopK, toTrip, toTrip2));
    assertEquals(
        StopTransfer.TIMED_TRANSFER, transferTable.getTransferTime(stopN, stopK, fromTrip, toTrip));
    assertEquals(15, transferTable.getTransferTime(stopN, stopK, fromTrip, toTrip2));

    Vertex e_arrive = graph.getVertex("agency_E_arrive");
    Vertex f_depart = graph.getVertex("agency_F_depart");
    Edge edge = new TransferEdge(e_arrive, f_depart, 10000, 10000);

    long startTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 18, 0, 50, 0);
    Vertex stop_b = graph.getVertex("agency_B_depart");
    Vertex stop_g = graph.getVertex("agency_G_arrive");
    RoutingRequest options = new RoutingRequest();
    options.dateTime = startTime;
    options.setRoutingContext(graph, stop_b, stop_g);
    ShortestPathTree spt = aStar.getShortestPathTree(options);

    GraphPath path = spt.getPath(stop_g, false);
    assertNotNull(path);

    assertTrue(
        "expected to use much later trip due to min transfer time",
        path.getEndTime() - startTime > 4.5 * 60 * 60);

    /* cleanup */
    e_arrive.removeOutgoing(edge);
    f_depart.removeIncoming(edge);
  }
  public void testPickupDropoff() throws Exception {
    Vertex stop_o = graph.getVertex("agency_O_depart");
    Vertex stop_p = graph.getVertex("agency_P");
    int i = 0;
    for (@SuppressWarnings("unused") Edge e : stop_o.getOutgoing()) {
      ++i;
    }
    assertTrue(i == 3);

    long startTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 19, 12, 0, 0);
    RoutingRequest options = new RoutingRequest();
    options.dateTime = startTime;
    options.setRoutingContext(graph, stop_o, stop_p);
    ShortestPathTree spt = aStar.getShortestPathTree(options);
    GraphPath path = spt.getPath(stop_p, false);
    assertNotNull(path);
    long endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 19, 12, 10, 0);
    assertEquals(endTime, path.getEndTime());

    startTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 19, 12, 0, 1);
    options.dateTime = startTime;
    options.setRoutingContext(graph, stop_o, stop_p);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(stop_p, false);
    assertNotNull(path);
    endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 19, 15, 10, 0);
    assertEquals(endTime, path.getEndTime());
  }
  public void testRouting() throws Exception {

    Vertex stop_a = graph.getVertex("agency:A");
    Vertex stop_b = graph.getVertex("agency:B");
    Vertex stop_c = graph.getVertex("agency:C");
    Vertex stop_d = graph.getVertex("agency:D");
    Vertex stop_e = graph.getVertex("agency:E");

    RoutingRequest options = new RoutingRequest();
    // test feed is designed for instantaneous transfers
    options.transferSlack = (0);

    long startTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 0, 0, 0);
    options.dateTime = startTime;

    ShortestPathTree spt;
    GraphPath path;

    // A to B
    options.setRoutingContext(graph, stop_a, stop_b);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_b, false);
    assertNotNull(path);
    assertEquals(6, path.states.size());

    // A to C
    options.setRoutingContext(graph, stop_a, stop_c);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_c, false);
    assertNotNull(path);
    assertEquals(8, path.states.size());

    // A to D (change at C)
    options.setRoutingContext(graph, stop_a, stop_d);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_d, false);
    assertNotNull(path);
    // there are two paths of different lengths
    // both arrive at 40 minutes after midnight
    List<TransitStop> stops = extractStopVertices(path);
    assertEquals(stops.size(), 3);
    assertEquals(stops.get(1), stop_c);
    long endTime = startTime + 40 * 60;
    assertEquals(endTime, path.getEndTime());

    // A to E (change at C)
    options.setRoutingContext(graph, stop_a, stop_e);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(stop_e, false);
    assertNotNull(path);
    stops = extractStopVertices(path);
    assertEquals(stops.size(), 3);
    assertEquals(stops.get(1), stop_c);
    endTime = startTime + 70 * 60;
    assertEquals(endTime, path.getEndTime());
  }
  /** Make sure that stops are properly linked into the graph */
  @Test
  public void testStopLinking() throws Exception {
    AddTripPattern atp = getAddTripPattern(RouteSelector.BROAD_HIGH);
    atp.timetables.add(getTimetable(true));

    // get a graph
    Graph g = buildGraphNoTransit();
    link(g);
    g.index(new DefaultStreetVertexIndexFactory());

    // materialize the trip pattern
    atp.materialize(g);

    // there should be five stops because one point is not a stop
    assertEquals(5, atp.temporaryStops.length);

    // they should all be linked into the graph
    for (int i = 0; i < atp.temporaryStops.length; i++) {
      assertNotNull(atp.temporaryStops[i].sample);
      assertNotNull(atp.temporaryStops[i].sample.v0);
      assertNotNull(atp.temporaryStops[i].sample.v1);
    }

    // no services running: not needed for trips added on the fly.
    TimeWindow window = new TimeWindow(7 * 3600, 9 * 3600, new BitSet(), DayOfWeek.WEDNESDAY);

    Scenario scenario = new Scenario(0);
    scenario.modifications = Lists.newArrayList(atp);
    ProfileRequest req = new ProfileRequest();
    req.scenario = scenario;
    req.boardingAssumption = RaptorWorkerTimetable.BoardingAssumption.WORST_CASE;

    RaptorWorkerData data = new RaptorWorkerData(g, window, req);
    assertEquals(5, data.nStops);

    // make sure we can find the stops
    AStar aStar = new AStar();
    RoutingRequest rr = new RoutingRequest(TraverseMode.WALK);
    rr.from = new GenericLocation(39.963417, -82.980799);
    rr.batch = true;
    rr.setRoutingContext(g);
    rr.batch = true;

    ShortestPathTree spt = aStar.getShortestPathTree(rr);

    TIntIntMap stops = data.findStopsNear(spt, g);

    // we should have found stops
    assertFalse(stops.isEmpty());

    // ensure that the times made it into the data
    // This assumes worst-case departure, and the first worst departure is 10:30 after the service
    // starts running (dwell + headway)
    assertEquals(
        4 * 3600 + 600 + 30,
        data.timetablesForPattern.get(0).getFrequencyDeparture(0, 0, 39 * 360, -1, null));
  }
  public void testGetEdgesOneEdge() {
    Graph g = new Graph();
    Vertex a = new IntersectionVertex(g, "A", 5, 5);
    Vertex b = new IntersectionVertex(g, "B", 6, 6);
    FreeEdge ee = new FreeEdge(a, b);

    List<Edge> edges = new ArrayList<Edge>(g.getEdges());
    assertEquals(1, edges.size());
    assertEquals(ee, edges.get(0));
  }
  public void testWheelchairAccessible() throws Exception {
    Vertex near_a = graph.getVertex("near_1_agency_entrance_a");
    Vertex near_b = graph.getVertex("near_1_agency_entrance_b");
    Vertex near_c = graph.getVertex("near_1_agency_C");
    Vertex near_e = graph.getVertex("near_1_agency_E");

    Vertex stop_d = graph.getVertex("agency:D");
    Vertex split_d = null;
    for (StreetTransitLink e : Iterables.filter(stop_d.getOutgoing(), StreetTransitLink.class)) {
      split_d = e.getToVertex();
    }

    RoutingRequest options = new RoutingRequest();
    options.wheelchairAccessible = true;
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 18, 0, 0, 0);

    ShortestPathTree spt;
    GraphPath path;

    // stop B is accessible, so there should be a path.
    options.setRoutingContext(graph, near_a, near_b);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(near_b, false);
    assertNotNull(path);

    // stop C is not accessible, so there should be no path.
    options.setRoutingContext(graph, near_a, near_c);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(near_c, false);
    assertNull(path);

    // stop E has no accessibility information, but we should still be able to route to it.
    options.setRoutingContext(graph, near_a, near_e);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(near_e, false);
    assertNotNull(path);

    // from stop A to stop D would normally be trip 1.1 to trip 2.1, arriving at 00:30. But trip
    // 2 is not accessible, so we'll do 1.1 to 3.1, arriving at 01:00
    GregorianCalendar time = new GregorianCalendar(2009, 8, 18, 0, 0, 0);
    time.setTimeZone(TimeZone.getTimeZone("America/New_York"));
    options.dateTime = TestUtils.toSeconds(time);
    options.setRoutingContext(graph, near_a, split_d);
    spt = aStar.getShortestPathTree(options);

    time.add(Calendar.HOUR, 1);
    time.add(Calendar.SECOND, 1); // for the StreetTransitLink
    path = spt.getPath(split_d, false);
    assertNotNull(path);
    assertEquals(TestUtils.toSeconds(time), path.getEndTime());
  }
  /**
   * Return the graph for the given unique identifier for graph builder inputs on S3. If this is the
   * same as the last graph built, just return the pre-built graph. If not, build the graph from the
   * inputs, fetching them from S3 to the local cache as needed.
   */
  public synchronized Graph getGraph(String graphId) {

    LOG.info("Finding a graph for ID {}", graphId);

    if (graphId.equals(currGraphId)) {
      LOG.info("GraphID has not changed. Reusing the last graph that was built.");
      return currGraph;
    }

    // The location of the inputs that will be used to build this graph
    File graphDataDirectory = new File(GRAPH_CACHE_DIR, graphId);

    // If we don't have a local copy of the inputs, fetch graph data as a ZIP from S3 and unzip it
    if (!graphDataDirectory.exists() || graphDataDirectory.list().length == 0) {
      LOG.info("Downloading graph input files.");
      graphDataDirectory.mkdirs();
      S3Object graphDataZipObject = s3.getObject(graphBucket, graphId + ".zip");
      ZipInputStream zis = new ZipInputStream(graphDataZipObject.getObjectContent());
      try {
        ZipEntry entry;
        while ((entry = zis.getNextEntry()) != null) {
          File entryDestination = new File(graphDataDirectory, entry.getName());
          // Are both these mkdirs calls necessary?
          entryDestination.getParentFile().mkdirs();
          if (entry.isDirectory()) entryDestination.mkdirs();
          else {
            OutputStream entryFileOut = new FileOutputStream(entryDestination);
            IOUtils.copy(zis, entryFileOut);
            entryFileOut.close();
          }
        }
        zis.close();
      } catch (Exception e) {
        // TODO delete graph cache dir which is probably corrupted
        LOG.info("Error retrieving graph files", e);
      }
    } else {
      LOG.info("Graph input files were found locally. Using these files from the cache.");
    }

    // Now we have a local copy of these graph inputs. Make a graph out of them.
    CommandLineParameters params = new CommandLineParameters();
    params.build = new File(GRAPH_CACHE_DIR, graphId);
    params.inMemory = true;
    GraphBuilder graphBuilder = GraphBuilder.forDirectory(params, params.build);
    graphBuilder.run();
    Graph graph = graphBuilder.getGraph();
    graph.routerId = graphId;
    graph.index(new DefaultStreetVertexIndexFactory());
    graph.index.clusterStopsAsNeeded();
    this.currGraphId = graphId;
    this.currGraph = graph;
    return graph;
  }
  public void testShapeByLocation() throws Exception {
    Vertex stop_g = graph.getVertex("agency_G_depart");
    PatternHop hop = getHopOut(stop_g);
    Geometry geometry = hop.getGeometry();
    assertTrue(geometry.getLength() > 1.0);

    Vertex stop_a = graph.getVertex("agency_A_depart");
    hop = getHopOut(stop_a);
    geometry = hop.getGeometry();
    assertTrue(geometry.getLength() > 0.009999);
    assertTrue(geometry.getLength() < 0.010001);
  }
 /**
  * Get vertices inside a bbox.
  *
  * @return
  */
 @Secured({"ROLE_USER"})
 @GET
 @Path("/vertex")
 @Produces({MediaType.APPLICATION_JSON})
 public Object getVertex(@QueryParam("label") String label) {
   Graph graph = graphService.getGraph();
   Vertex vertex = graph.getVertex(label);
   if (vertex == null) {
     return null;
   }
   return new WrappedVertex(vertex).withGraph(graph);
 }
  public void testRouting() throws Exception {

    Vertex stop_a = graph.getVertex("agency_A");
    Vertex stop_b = graph.getVertex("agency_B");
    Vertex stop_c = graph.getVertex("agency_C");
    Vertex stop_d = graph.getVertex("agency_D");
    Vertex stop_e = graph.getVertex("agency_E");

    RoutingRequest options = new RoutingRequest();
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 0, 0, 0);

    ShortestPathTree spt;
    GraphPath path;

    // A to B
    options.setRoutingContext(graph, stop_a, stop_b);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_b, false);
    assertNotNull(path);
    assertEquals(extractStopVertices(path), Lists.newArrayList(stop_a, stop_b));

    // A to C
    options.setRoutingContext(graph, stop_a, stop_c);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_c, false);
    assertNotNull(path);
    assertEquals(extractStopVertices(path), Lists.newArrayList(stop_a, stop_c));

    // A to D
    options.setRoutingContext(graph, stop_a, stop_d);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_d, false);
    assertNotNull(path);
    assertEquals(extractStopVertices(path), Lists.newArrayList(stop_a, stop_c, stop_d));
    long endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 0, 0, 0) + 40 * 60;
    assertEquals(endTime, path.getEndTime());

    // A to E
    options.setRoutingContext(graph, stop_a, stop_e);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_e, false);
    assertNotNull(path);
    assertEquals(extractStopVertices(path), Lists.newArrayList(stop_a, stop_c, stop_e));
    endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 0, 0, 0) + 70 * 60;
    assertEquals(endTime, path.getEndTime());
  }
  public void testGetStreetEdgesNone() {
    Graph g = new Graph();
    Vertex a = new IntersectionVertex(g, "A", 5, 5);
    Vertex b = new IntersectionVertex(g, "B", 6, 6);
    Vertex c = new IntersectionVertex(g, "C", 3, 2);

    Set<Edge> allEdges = new HashSet<Edge>(4);
    allEdges.add(new FreeEdge(a, b));
    allEdges.add(new FreeEdge(b, c));
    allEdges.add(new FreeEdge(c, b));
    allEdges.add(new FreeEdge(c, a));

    Set<StreetEdge> edges = new HashSet<StreetEdge>(g.getStreetEdges());
    assertEquals(0, edges.size());
  }
  /** Build the weight table, parallelized according to the number of processors */
  public void buildTable() {
    ArrayList<TransitStop> stopVertices;

    LOG.debug("Number of vertices: " + g.getVertices().size());
    stopVertices = new ArrayList<TransitStop>();
    for (Vertex gv : g.getVertices())
      if (gv instanceof TransitStop) stopVertices.add((TransitStop) gv);
    int nStops = stopVertices.size();

    stopIndices = new IdentityHashMap<Vertex, Integer>(nStops);
    for (int i = 0; i < nStops; i++) stopIndices.put(stopVertices.get(i), i);
    LOG.debug("Number of stops: " + nStops);

    table = new float[nStops][nStops];
    for (float[] row : table) Arrays.fill(row, Float.POSITIVE_INFINITY);

    LOG.debug("Performing search at each transit stop.");

    int nThreads = Runtime.getRuntime().availableProcessors();
    LOG.debug("number of threads: " + nThreads);
    ArrayBlockingQueue<Runnable> taskQueue = new ArrayBlockingQueue<Runnable>(nStops);
    ThreadPoolExecutor threadPool =
        new ThreadPoolExecutor(nThreads, nThreads, 10, TimeUnit.SECONDS, taskQueue);
    GenericObjectPool heapPool =
        new GenericObjectPool(new PoolableBinHeapFactory<State>(g.getVertices().size()), nThreads);

    // make one heap and recycle it
    TraverseOptions options = new TraverseOptions();
    options.speed = maxWalkSpeed;
    final double MAX_WEIGHT = 60 * 60 * options.walkReluctance;
    final double OPTIMISTIC_BOARD_COST = options.boardCost;

    // create a task for each transit stop in the graph
    ArrayList<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
    for (TransitStop origin : stopVertices) {
      SPTComputer task =
          new SPTComputer(heapPool, options, MAX_WEIGHT, OPTIMISTIC_BOARD_COST, origin);
      tasks.add(task);
    }
    try {
      // invoke all of tasks.
      threadPool.invokeAll(tasks);
      threadPool.shutdown();
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
    floyd();
  }
    /**
     * The safest bike lane should have a safety weight no lower than the time weight of a flat
     * street. This method divides the safety lengths by the length ratio of the safest street,
     * ensuring this property.
     *
     * @param graph
     */
    private void applyBikeSafetyFactor(Graph graph) {
      _log.info(
          GraphBuilderAnnotation.register(
              graph,
              Variety.GRAPHWIDE,
              "Multiplying all bike safety values by " + (1 / bestBikeSafety)));
      HashSet<Edge> seenEdges = new HashSet<Edge>();
      for (Vertex vertex : graph.getVertices()) {
        for (Edge e : vertex.getOutgoing()) {
          if (!(e instanceof PlainStreetEdge)) {
            continue;
          }
          PlainStreetEdge pse = (PlainStreetEdge) e;

          if (!seenEdges.contains(e)) {
            seenEdges.add(e);
            pse.setBicycleSafetyEffectiveLength(
                pse.getBicycleSafetyEffectiveLength() / bestBikeSafety);
          }
        }
        for (Edge e : vertex.getIncoming()) {
          if (!(e instanceof PlainStreetEdge)) {
            continue;
          }
          PlainStreetEdge pse = (PlainStreetEdge) e;

          if (!seenEdges.contains(e)) {
            seenEdges.add(e);
            pse.setBicycleSafetyEffectiveLength(
                pse.getBicycleSafetyEffectiveLength() / bestBikeSafety);
          }
        }
      }
    }
  public void testGetStreetEdgesSeveral() {
    Graph g = new Graph();
    StreetVertex a = new IntersectionVertex(g, "A", 5, 5);
    StreetVertex b = new IntersectionVertex(g, "B", 6, 6);
    StreetVertex c = new IntersectionVertex(g, "C", 3, 2);

    Set<Edge> allStreetEdges = new HashSet<Edge>(4);
    allStreetEdges.add(edge(a, b, 1.0));
    allStreetEdges.add(edge(b, c, 1.0));
    allStreetEdges.add(edge(c, b, 1.0));
    allStreetEdges.add(edge(c, a, 1.0));

    Set<StreetEdge> edges = new HashSet<StreetEdge>(g.getStreetEdges());
    assertEquals(4, edges.size());
    assertEquals(allStreetEdges, edges);
  }
  public void testGetEdgesMultiple() {
    Graph g = new Graph();
    Vertex a = new IntersectionVertex(g, "A", 5, 5);
    Vertex b = new IntersectionVertex(g, "B", 6, 6);
    Vertex c = new IntersectionVertex(g, "C", 3, 2);

    Set<Edge> expectedEdges = new HashSet<Edge>(4);
    expectedEdges.add(new FreeEdge(a, b));
    expectedEdges.add(new FreeEdge(b, c));
    expectedEdges.add(new FreeEdge(c, b));
    expectedEdges.add(new FreeEdge(c, a));

    Set<Edge> edges = new HashSet<Edge>(g.getEdges());
    assertEquals(4, edges.size());
    assertEquals(expectedEdges, edges);
  }
  /**
   * Get vertices connected to an edge
   *
   * @return
   */
  @Secured({"ROLE_USER"})
  @GET
  @Path("/verticesForEdge")
  @Produces({MediaType.APPLICATION_JSON})
  public Object getVerticesForEdge(@QueryParam("edge") int edgeId) {

    Graph graph = graphService.getGraph();
    Edge edge = graph.getEdgeById(edgeId);

    VertexSet out = new VertexSet();
    out.vertices = new ArrayList<Vertex>(2);
    out.vertices.add(edge.getFromVertex());
    out.vertices.add(edge.getToVertex());

    return out.withGraph(graph);
  }
  private void run() {

    try {
      graph = Graph.load(new File(graphPath), Graph.LoadLevel.DEBUG);
    } catch (Exception e) {
      LOG.error("Exception while loading graph from " + graphPath);
      e.printStackTrace();
      return;
    }
    LOG.info("done loading graph.");

    if (outPath != null) {
      try {
        writer = new HTMLWriter(outPath);
      } catch (FileNotFoundException ex) {
        java.util.logging.Logger.getLogger(AnnotationsToHTML.class.getName())
            .log(Level.SEVERE, null, ex);
        LOG.error("Exception while opening output file {}:{}", outPath, ex.getMessage());
        return;
      }
    } else {
      writer = new HTMLWriter(System.out);
    }

    String command = jc.getParsedCommand();
    if (command.equals("annotate")) {
      annotationEndpoints.run();
    }

    if (outPath != null) {
      LOG.info("HTML is in {}", outPath);
    }

    writer.close();
  }
  public void testFewestTransfers() {
    Vertex stop_c = graph.getVertex("agency:C");
    Vertex stop_d = graph.getVertex("agency:D");
    RoutingRequest options = new RoutingRequest();
    options.optimize = OptimizeType.QUICK;
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 1, 16, 0, 0);
    options.setRoutingContext(graph, stop_c, stop_d);

    ShortestPathTree spt = aStar.getShortestPathTree(options);

    // when optimizing for speed, take the fast two-bus path
    GraphPath path = spt.getPath(stop_d, false);
    assertNotNull(path);
    assertEquals(
        TestUtils.dateInSeconds("America/New_York", 2009, 8, 1, 16, 20, 0), path.getEndTime());

    // when optimizing for fewest transfers, take the slow one-bus path
    options.transferPenalty = 1800;
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_d, false);
    assertNotNull(path);
    assertEquals(
        TestUtils.dateInSeconds("America/New_York", 2009, 8, 1, 16, 50, 0), path.getEndTime());
  }
 public void testShapeByDistance() throws Exception {
   Vertex stop_i = graph.getVertex("agency_I_depart");
   PatternHop hop = getHopOut(stop_i);
   Geometry geometry = hop.getGeometry();
   assertTrue(geometry.getLength() > 1.0);
   assertTrue(geometry.getLength() < 2.0);
 }
  public void testRoutingOverMidnight() throws Exception {
    // this route only runs on weekdays
    Vertex stop_g = graph.getVertex("agency:G_depart");
    Vertex stop_h = graph.getVertex("agency:H_arrive");

    ShortestPathTree spt;
    GraphPath path;
    RoutingRequest options = new RoutingRequest();

    // Friday evening
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 18, 23, 20, 0);
    options.setRoutingContext(graph, stop_g, stop_h);
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_h, false);
    assertNotNull(path);
    assertEquals(4, path.states.size());

    // Saturday morning
    long startTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 19, 0, 5, 0);
    options.dateTime = startTime;
    options.setRoutingContext(graph, stop_g.getLabel(), stop_h.getLabel());
    spt = aStar.getShortestPathTree(options);

    path = spt.getPath(stop_h, false);
    assertNotNull(path);
    assertEquals(4, path.states.size());
    long endTime = path.getEndTime();
    assertTrue(endTime < startTime + 60 * 60);
  }
  public void testFrequencies() {
    Vertex stop_u = graph.getVertex("agency_U_depart");
    Vertex stop_v = graph.getVertex("agency_V_arrive");

    ShortestPathTree spt;
    GraphPath path;

    RoutingRequest options = new RoutingRequest();
    options.setModes(new TraverseModeSet("TRANSIT"));
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 0, 0, 0);
    options.setRoutingContext(graph, stop_u, stop_v);

    // U to V - original stop times - shouldn't be used
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(stop_v, false);
    assertNotNull(path);
    assertEquals(4, path.states.size());
    long endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 6, 40, 0);
    assertEquals(endTime, path.getEndTime());

    // U to V - first frequency
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 7, 0, 0);
    options.setRoutingContext(graph, stop_u, stop_v);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(stop_v, false);
    assertNotNull(path);
    assertEquals(4, path.states.size());
    endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 7, 40, 0);
    assertEquals(endTime, path.getEndTime());

    // U to V - second frequency
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 14, 0, 0);
    options.setRoutingContext(graph, stop_u, stop_v);
    spt = aStar.getShortestPathTree(options);
    path = spt.getPath(stop_v, false);
    assertNotNull(path);
    assertEquals(4, path.states.size());
    endTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 7, 14, 40, 0);
    assertEquals(endTime, path.getEndTime());

    boolean boarded = false;
    for (FrequencyBoard e : filter(stop_u.getOutgoing(), FrequencyBoard.class)) {
      boarded = true;
      FrequencyBoard board = (FrequencyBoard) e;
      FrequencyBasedTripPattern pattern = board.getPattern();
      int previousArrivalTime = pattern.getPreviousArrivalTime(0, 0, false, false, false);
      assertTrue(previousArrivalTime < 0);

      previousArrivalTime = pattern.getPreviousArrivalTime(0, 60 * 60 * 7 - 1, false, false, false);
      assertEquals(60 * 60 * 6, previousArrivalTime);

      previousArrivalTime = pattern.getPreviousArrivalTime(0, 60 * 60 * 11, false, false, false);
      assertEquals(60 * 60 * 10, previousArrivalTime);

      previousArrivalTime = pattern.getPreviousArrivalTime(0, 60 * 60 * 18, false, false, false);
      assertEquals(60 * 60 * 16, previousArrivalTime);
    }
    assertTrue(boarded);
  }
 public void addEdges(Collection<Edge> newEdges, Graph graph) {
   if (edges == null) {
     edges = new ArrayList<WrappedEdge>();
   }
   for (Edge edge : newEdges) {
     edges.add(new WrappedEdge(edge, graph.getIdForEdge(edge)));
   }
 }
  public void testPathways() throws Exception {

    Vertex entrance = graph.getVertex("agency:entrance_a");
    assertNotNull(entrance);
    Vertex stop = graph.getVertex("agency:A");
    assertNotNull(stop);

    RoutingRequest options = new RoutingRequest();
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 1, 16, 0, 0);
    options.setRoutingContext(graph, entrance, stop);
    ShortestPathTree spt = aStar.getShortestPathTree(options);

    GraphPath path = spt.getPath(stop, false);
    assertNotNull(path);
    assertEquals(
        TestUtils.dateInSeconds("America/New_York", 2009, 8, 1, 16, 0, 34), path.getEndTime());
  }