/** 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)); }
/** * Finds all egress paths from to coordinate to end stop and adds routers to egressRouter * * @param request * @param egressRouter */ private void findEgressPaths(ProfileRequest request, Map<LegMode, StreetRouter> egressRouter) { // For egress // TODO: this must be reverse search for (LegMode mode : request.egressModes) { StreetRouter streetRouter = new StreetRouter(transportNetwork.streetLayer); streetRouter.transitStopSearch = true; streetRouter.dominanceVariable = StreetRouter.State.RoutingVariable.DURATION_SECONDS; if (egressUnsupportedModes.contains(mode)) { continue; } // TODO: add support for bike sharing streetRouter.streetMode = StreetMode.valueOf(mode.toString()); streetRouter.profileRequest = request; streetRouter.timeLimitSeconds = request.getTimeLimit(mode); if (streetRouter.setOrigin(request.toLat, request.toLon)) { streetRouter.route(); TIntIntMap stops = streetRouter.getReachedStops(); egressRouter.put(mode, streetRouter); LOG.info("Added {} edgres stops for mode {}", stops.size(), mode); } else { LOG.warn( "MODE:{}, Edge near the origin coordinate wasn't found. Routing didn't start!", mode); } } }
/** * Finds direct paths between from and to coordinates in request and adds them to option * * @param request * @param option */ private void findDirectPaths(ProfileRequest request, ProfileOption option) { // For direct modes for (LegMode mode : request.directModes) { StreetRouter streetRouter = new StreetRouter(transportNetwork.streetLayer); StreetPath streetPath; streetRouter.profileRequest = request; if (mode == LegMode.BICYCLE_RENT) { if (!transportNetwork.streetLayer.bikeSharing) { LOG.warn("Bike sharing trip requested but no bike sharing stations in the streetlayer"); continue; } streetRouter = findBikeRentalPath(request, streetRouter, true); if (streetRouter != null) { StreetRouter.State lastState = streetRouter.getState(request.toLat, request.toLon); if (lastState != null) { streetPath = new StreetPath(lastState, streetRouter, LegMode.BICYCLE_RENT, transportNetwork); } else { LOG.warn( "MODE:{}, Edge near the destination coordinate wasn't found. Routing didn't start!", mode); continue; } } else { LOG.warn("Not found path from cycle to end"); continue; } } else { streetRouter.streetMode = StreetMode.valueOf(mode.toString()); streetRouter.timeLimitSeconds = request.streetTime * 60; if (streetRouter.setOrigin(request.fromLat, request.fromLon)) { if (!streetRouter.setDestination(request.toLat, request.toLon)) { LOG.warn("Direct mode {} destination wasn't found!", mode); continue; } streetRouter.route(); StreetRouter.State lastState = streetRouter.getState(streetRouter.getDestinationSplit()); if (lastState == null) { LOG.warn("Direct mode {} last state wasn't found", mode); continue; } streetPath = new StreetPath(lastState, transportNetwork); } else { LOG.warn("Direct mode {} origin wasn't found!", mode); continue; } } StreetSegment streetSegment = new StreetSegment(streetPath, mode, transportNetwork.streetLayer); option.addDirect(streetSegment, request.getFromTimeDateZD()); } }
/** * Finds access paths from from coordinate in request and adds all routers with paths to * accessRouter map * * @param request * @param accessRouter */ private void findAccessPaths(ProfileRequest request, Map<LegMode, StreetRouter> accessRouter) { // Routes all access modes for (LegMode mode : request.accessModes) { StreetRouter streetRouter = new StreetRouter(transportNetwork.streetLayer); streetRouter.profileRequest = request; if (mode == LegMode.CAR_PARK) { streetRouter = findParkRidePath(request, streetRouter); if (streetRouter != null) { accessRouter.put(LegMode.CAR_PARK, streetRouter); } else { LOG.warn( "MODE:{}, Edge near the origin coordinate wasn't found. Routing didn't start!", mode); } } else if (mode == LegMode.BICYCLE_RENT) { if (!transportNetwork.streetLayer.bikeSharing) { LOG.warn("Bike sharing trip requested but no bike sharing stations in the streetlayer"); continue; } streetRouter = findBikeRentalPath(request, streetRouter, false); if (streetRouter != null) { accessRouter.put(LegMode.BICYCLE_RENT, streetRouter); } else { LOG.warn("Not found path from cycle to end"); } } else { streetRouter.streetMode = StreetMode.valueOf(mode.toString()); // Gets correct maxCar/Bike/Walk time in seconds for access leg based on mode since it // depends on the mode streetRouter.timeLimitSeconds = request.getTimeLimit(mode); streetRouter.transitStopSearch = true; streetRouter.dominanceVariable = StreetRouter.State.RoutingVariable.DURATION_SECONDS; if (streetRouter.setOrigin(request.fromLat, request.fromLon)) { streetRouter.route(); // Searching for access paths accessRouter.put(mode, streetRouter); } else { LOG.warn( "MODE:{}, Edge near the origin coordinate wasn't found. Routing didn't start!", mode); } } } }
// Does point to point routing with data from request public ProfileResponse getPlan(ProfileRequest request) { long startRouting = System.currentTimeMillis(); request.zoneId = transportNetwork.getTimeZone(); // Do the query and return result ProfileResponse profileResponse = new ProfileResponse(); ProfileOption option = new ProfileOption(); findDirectPaths(request, option); option.summary = option.generateSummary(); profileResponse.addOption(option); if (request.hasTransit()) { Map<LegMode, StreetRouter> accessRouter = new HashMap<>(request.accessModes.size()); Map<LegMode, StreetRouter> egressRouter = new HashMap<>(request.egressModes.size()); // This map saves which access mode was used to access specific stop in access mode TIntObjectMap<LegMode> stopModeAccessMap = new TIntObjectHashMap<>(); // This map saves which egress mode was used to access specific stop in egress mode TIntObjectMap<LegMode> stopModeEgressMap = new TIntObjectHashMap<>(); findAccessPaths(request, accessRouter); findEgressPaths(request, egressRouter); // fold access and egress times into single maps TIntIntMap accessTimes = combineMultimodalRoutingAccessTimes(accessRouter, stopModeAccessMap, request); TIntIntMap egressTimes = combineMultimodalRoutingAccessTimes(egressRouter, stopModeEgressMap, request); McRaptorSuboptimalPathProfileRouter router = new McRaptorSuboptimalPathProfileRouter( transportNetwork, request, accessTimes, egressTimes); List<PathWithTimes> usefullpathList = new ArrayList<>(); // getPaths actually returns a set, which is important so that things are deduplicated. // However we need a list // so we can sort it below. usefullpathList.addAll(router.getPaths()); // This sort is necessary only for text debug output so it will be disabled when it is // finished /** * Orders first no transfers then one transfers 2 etc - then orders according to first trip: - * board stop - alight stop - alight time - same for one transfer trip */ usefullpathList.sort( (o1, o2) -> { int c; c = Integer.compare(o1.patterns.length, o2.patterns.length); if (c == 0) { c = Integer.compare(o1.boardStops[0], o2.boardStops[0]); } if (c == 0) { c = Integer.compare(o1.alightStops[0], o2.alightStops[0]); } if (c == 0) { c = Integer.compare(o1.alightTimes[0], o2.alightTimes[0]); } if (c == 0 && o1.patterns.length == 2) { c = Integer.compare(o1.boardStops[1], o2.boardStops[1]); if (c == 0) { c = Integer.compare(o1.alightStops[1], o2.alightStops[1]); } if (c == 0) { c = Integer.compare(o1.alightTimes[1], o2.alightTimes[1]); } } return c; }); LOG.info("Usefull paths:{}", usefullpathList.size()); int seen_paths = 0; int boardStop = -1, alightStop = -1; for (PathWithTimes path : usefullpathList) { profileResponse.addTransitPath( accessRouter, egressRouter, stopModeAccessMap, stopModeEgressMap, path, transportNetwork, request.getFromTimeDateZD()); // LOG.info("Num patterns:{}", path.patterns.length); // ProfileOption transit_option = new ProfileOption(); /*if (path.patterns.length == 1) { continue; }*/ /*if (seen_paths > 20) { break; }*/ if (LOG.isDebugEnabled()) { LOG.debug(" "); for (int i = 0; i < path.patterns.length; i++) { // TransitSegment transitSegment = new TransitSegment(transportNetwork.transitLayer, // path.boardStops[i], path.alightStops[i], path.patterns[i]); if (!(((boardStop == path.boardStops[i] && alightStop == path.alightStops[i])))) { LOG.debug( " BoardStop: {} pattern: {} allightStop: {}", path.boardStops[i], path.patterns[i], path.alightStops[i]); } TripPattern pattern = transportNetwork.transitLayer.tripPatterns.get(path.patterns[i]); if (pattern.routeIndex >= 0) { RouteInfo routeInfo = transportNetwork.transitLayer.routes.get(pattern.routeIndex); LOG.debug( " Pattern:{} on route:{} ({}) with {} stops", path.patterns[i], routeInfo.route_long_name, routeInfo.route_short_name, pattern.stops.length); } LOG.debug( " {}->{} ({}:{})", transportNetwork.transitLayer.stopNames.get(path.boardStops[i]), transportNetwork.transitLayer.stopNames.get(path.alightStops[i]), path.alightTimes[i] / 3600, path.alightTimes[i] % 3600 / 60); // transit_option.addTransit(transitSegment); } boardStop = path.boardStops[0]; alightStop = path.alightStops[0]; } seen_paths++; } profileResponse.generateStreetTransfers(transportNetwork, request); } LOG.info("Returned {} options", profileResponse.getOptions().size()); LOG.info("Took {} ms", System.currentTimeMillis() - startRouting); return profileResponse; }
/** Test the full routing */ @Test public void integrationTest() throws Exception { Graph g = buildGraphNoTransit(); addTransit(g); link(g); ProfileRequest pr1 = new ProfileRequest(); pr1.date = new LocalDate(2015, 6, 10); pr1.fromTime = 7 * 3600; pr1.toTime = 9 * 3600; pr1.fromLat = pr1.toLat = 39.9621; pr1.fromLon = pr1.toLon = -83.0007; RepeatedRaptorProfileRouter rrpr1 = new RepeatedRaptorProfileRouter(g, pr1); rrpr1.route(); ProfileRequest pr2 = new ProfileRequest(); pr2.date = new LocalDate(2015, 6, 10); pr2.fromTime = 7 * 3600; pr2.toTime = 9 * 3600; pr2.fromLat = pr2.toLat = 39.9621; pr2.fromLon = pr2.toLon = -83.0007; AddTripPattern atp = getAddTripPattern(RouteSelector.BROAD_HIGH); atp.timetables.add(getTimetable(true)); pr2.scenario = new Scenario(0); pr2.scenario.modifications = Arrays.asList(atp); RepeatedRaptorProfileRouter rrpr2 = new RepeatedRaptorProfileRouter(g, pr2); rrpr2.route(); boolean foundDecrease = false; // make sure that travel time did not increase for (TObjectIntIterator<Vertex> vit = rrpr1.timeSurfaceRangeSet.min.times.iterator(); vit.hasNext(); ) { vit.advance(); int time2 = rrpr2.timeSurfaceRangeSet.min.getTime(vit.key()); assertTrue(time2 <= vit.value()); if (time2 < vit.value()) foundDecrease = true; } assertTrue("found decreases in travel time due to adding route", foundDecrease); }
/** Make sure that transfers work */ @Test public void testTransfers() throws Exception { AddTripPattern atp = getAddTripPattern(RouteSelector.BROAD_HIGH); atp.timetables.add(getTimetable(false)); AddTripPattern atp2 = getAddTripPattern(RouteSelector.BEXLEY_CMH); atp2.timetables.add(getTimetable(true)); // get a graph Graph g = buildGraphNoTransit(); addTransit(g); link(g); g.index(new DefaultStreetVertexIndexFactory()); // materialize the trip pattern atp.materialize(g); atp2.materialize(g); TimeWindow window = new TimeWindow( 7 * 3600, 9 * 3600, g.index.servicesRunning(new LocalDate(2015, 6, 10)), DayOfWeek.WEDNESDAY); Scenario scenario = new Scenario(0); scenario.modifications = Lists.newArrayList(atp, atp2); ProfileRequest req = new ProfileRequest(); req.scenario = scenario; req.boardingAssumption = RaptorWorkerTimetable.BoardingAssumption.WORST_CASE; RaptorWorkerData data = new RaptorWorkerData(g, window, req); // make sure that we have transfers a) between the new lines b) from the new lines // to the existing lines c) from the existing lines to the new lines // stop IDs in the data will be 0 and 1 for existing stops, 2 - 6 for Broad/High and 7 - 11 for // Bexley/CMH int[] txFromExisting = data.transfersForStop.get(0); if (txFromExisting.length == 0) txFromExisting = data.transfersForStop.get(1); // make sure there's a transfer to stop 4 (Broad/High) // the AddTripPattern instructions are processed in order // also recall that each transfer has two ints in the array as it's a jagged array of // dest_pattern, distance assertTrue(txFromExisting.length > 0); boolean foundTx = false; for (int i = 0; i < txFromExisting.length; i += 2) { if (txFromExisting[i] == 4) { foundTx = true; break; } } assertTrue("transfer from existing to new", foundTx); // Check that there are transfers from the new route to the existing route // This is the stop at Broad and High int[] txToExisting = data.transfersForStop.get(4); assertTrue(txToExisting.length > 0); foundTx = false; for (int i = 0; i < txToExisting.length; i += 2) { if (txToExisting[i] == 0 || txToExisting[i] == 1) { // stop from existing route foundTx = true; break; } } assertTrue("transfer from new to existing", foundTx); // Check that there are transfers between the new routes int[] txBetweenNew = data.transfersForStop.get(7); assertTrue(txBetweenNew.length > 0); foundTx = false; for (int i = 0; i < txBetweenNew.length; i += 2) { if (txBetweenNew[i] == 2) { foundTx = true; break; } } assertTrue(foundTx); }
public boolean updateProfile(StatusResponse currentStatus, ProfileRequest data) { if (data.getUsername() != null) { if (!data.getUsername().equals(currentStatus.getProfile().getUsername())) { if (data.getUsername().length() == 0) { currentStatus.getResponses().put("username", "username_empty"); } else if (!usernameIsAvailable(data.getUsername())) { currentStatus.getResponses().put("username", "username_not_available"); } else { context .getUserProfileDao() .updateUsername(currentStatus.getProfile(), data.getUsername()); } } } if (!data.getEmail().isEmpty() && !data.getEmail().equals(currentStatus.getProfile().getEmail())) { context.getUserProfileDao().updateEmail(currentStatus.getProfile(), data.getEmail()); } if (!data.getNotify1().equals(currentStatus.getProfile().getNotify1())) { context.getUserProfileDao().updateNotify1(currentStatus.getProfile(), data.getNotify1()); } if (!data.getNotify2().equals(currentStatus.getProfile().getNotify2())) { context.getUserProfileDao().updateNotify2(currentStatus.getProfile(), data.getNotify2()); } if (!data.getNotify3().equals(currentStatus.getProfile().getNotify3())) { context.getUserProfileDao().updateNotify3(currentStatus.getProfile(), data.getNotify3()); } if (!data.getNotify4().equals(currentStatus.getProfile().getNotify4())) { context.getUserProfileDao().updateNotify4(currentStatus.getProfile(), data.getNotify4()); } if (!data.getNotify5().equals(currentStatus.getProfile().getNotify5())) { context.getUserProfileDao().updateNotify5(currentStatus.getProfile(), data.getNotify5()); } context .getUserProfileDao() .updateUserInformation( currentStatus.getProfile(), data.getMetadata(), data.getVisibility()); return true; }