public List<TransferPerformanceSummary> getTransferPerformance (String stop_id, LocalDate date) {
        List<StopTime> stopTimes = feed.getStopTimesForStop(stop_id);

        Map<String, List<StopTime>> routeStopTimeMap  = new HashMap<>();
        List<TransferPerformanceSummary> transferPerformanceMap = new ArrayList<>();
        // TODO: do we need to handle interpolated stop times???

        // first stream stopTimes for stop into route -> list of stopTimes map
        stopTimes.stream()
                .forEach(st -> {
                    Trip trip = feed.trips.get(st.trip_id);
                    Service service = feed.services.get(trip.service_id);
                    // only add to map if trip is active on given date
                    if (service != null && service.activeOn(date)) {
                        Route route = feed.routes.get(trip.route_id);

                        List<StopTime> times = new ArrayList<>();
                        if (routeStopTimeMap.containsKey(route.route_id)) {
                            times.addAll(routeStopTimeMap.get(route.route_id));
                        }
                        times.add(st);
                        routeStopTimeMap.put(route.route_id, times);
                    }
                });
        Map<Fun.Tuple2<String, String>, TIntList> waitTimesByRoute = new HashMap<>();
        Map<Fun.Tuple2<String, String>, Set<Fun.Tuple2<StopTime, StopTime>>> missedTransfers = new HashMap<>();
        // iterate over every entry in route -> list of stopTimes map
        for (Map.Entry<String, List<StopTime>> entry : routeStopTimeMap.entrySet()) {
            final int MISSED_TRANSFER_THRESHOLD = 60 * 10;
            List<StopTime> currentTimes = entry.getValue();

            String currentRoute = entry.getKey();

            for (StopTime currentTime : currentTimes) {
                if (currentTime.arrival_time > 0) {
                    // cycle through all other routes that stop here.
                    for (Map.Entry<String, List<StopTime>> entry2 : routeStopTimeMap.entrySet()) {

                        List<StopTime> compareTimes = entry2.getValue();
                        String compareRoute = entry2.getKey();
                        Fun.Tuple2<String, String> routeKey = new Fun.Tuple2(currentRoute, compareRoute);
                        if (compareRoute.equals(currentRoute)) {
                            continue;
                        }
                        if (!waitTimesByRoute.containsKey(routeKey)) {
                            waitTimesByRoute.put(routeKey, new TIntArrayList());
                        }

                        int shortestWait = Integer.MAX_VALUE;
                        // compare current time against departure times for route
                        for (StopTime compareTime : compareTimes) {
                            if (compareTime.departure_time > 0) {
                                int waitTime = compareTime.departure_time - currentTime.arrival_time;

                                // if non-negative and shortest, save for later
                                if (waitTime >= 0 && waitTime < shortestWait){
                                    shortestWait = waitTime;
                                }
                                // otherwise, check for missed near-transfer opportunities
                                else {
                                    if (waitTime < 0 && waitTime * -1 <= MISSED_TRANSFER_THRESHOLD) {
                                        Fun.Tuple2<StopTime, StopTime> missedTransfer = new Fun.Tuple2(compareTime, currentTime);
//                                        missedTransfer.add(currentTime);
//                                        missedTransfer.add(compareTime);
                                        if (!missedTransfers.containsKey(routeKey)) {
                                            missedTransfers.put(routeKey, new HashSet<>());
                                        }
                                        missedTransfers.get(routeKey).add(missedTransfer);
                                    }
                                }
                            }
                        }
                        // add shortestWait for currentTime to map
                        if (shortestWait < Integer.MAX_VALUE)
                            waitTimesByRoute.get(routeKey).add(shortestWait);
                    }
                }
            }
        }
        for (Map.Entry<Fun.Tuple2<String, String>, TIntList> entry : waitTimesByRoute.entrySet()) {
            Fun.Tuple2<String, String> routeKey = entry.getKey();
            TIntList waitTimes = entry.getValue();
            if (waitTimes.isEmpty()) {
                continue;
            }
            int min = waitTimes.min();
            int max = waitTimes.max();
            waitTimes.sort();
            int median = waitTimes.get(waitTimes.size() / 2);
            TransferPerformanceSummary routeTransferPerformance = new TransferPerformanceSummary(routeKey.a, routeKey.b, min, max, median, missedTransfers.get(routeKey));
            transferPerformanceMap.add(routeTransferPerformance);
        }

        return transferPerformanceMap;
    }
public List<TransferPerformanceSummary> getTransferPerformance (String stop_id, LocalDate date) {
        List<StopTime> stopTimes = feed.getStopTimesForStop(stop_id);

        Map<String, List<StopTime>> routeStopTimeMap  = new HashMap<>();
        List<TransferPerformanceSummary> transferPerformanceMap = new ArrayList<>();
        

        
        stopTimes.stream()
                .forEach(st -> {
                    Trip trip = feed.trips.get(st.trip_id);
                    Service service = feed.services.get(trip.service_id);
                    
                    if (service != null && service.activeOn(date)) {
                        Route route = feed.routes.get(trip.route_id);

                        List<StopTime> times = new ArrayList<>();
                        if (routeStopTimeMap.containsKey(route.route_id)) {
                            times.addAll(routeStopTimeMap.get(route.route_id));
                        }
                        times.add(st);
                        routeStopTimeMap.put(route.route_id, times);
                    }
                });
        Map<Fun.Tuple2<String, String>, TIntList> waitTimesByRoute = new HashMap<>();
        Map<Fun.Tuple2<String, String>, Set<Fun.Tuple2<StopTime, StopTime>>> missedTransfers = new HashMap<>();
        
        for (Map.Entry<String, List<StopTime>> entry : routeStopTimeMap.entrySet()) {
            final int MISSED_TRANSFER_THRESHOLD = 60 * 10;
            List<StopTime> currentTimes = entry.getValue();

            String currentRoute = entry.getKey();

            for (StopTime currentTime : currentTimes) {
                if (currentTime.arrival_time > 0) {
                    
                    for (Map.Entry<String, List<StopTime>> entry2 : routeStopTimeMap.entrySet()) {

                        List<StopTime> compareTimes = entry2.getValue();
                        String compareRoute = entry2.getKey();
                        Fun.Tuple2<String, String> routeKey = new Fun.Tuple2(currentRoute, compareRoute);
                        if (compareRoute.equals(currentRoute)) {
                            continue;
                        }
                        if (!waitTimesByRoute.containsKey(routeKey)) {
                            waitTimesByRoute.put(routeKey, new TIntArrayList());
                        }

                        int shortestWait = Integer.MAX_VALUE;
                        
                        for (StopTime compareTime : compareTimes) {
                            if (compareTime.departure_time > 0) {
                                int waitTime = compareTime.departure_time - currentTime.arrival_time;

                                
                                if (waitTime >= 0 && waitTime < shortestWait){
                                    shortestWait = waitTime;
                                }
                                
                                else {
                                    if (waitTime < 0 && waitTime * -1 <= MISSED_TRANSFER_THRESHOLD) {
                                        Fun.Tuple2<StopTime, StopTime> missedTransfer = new Fun.Tuple2(compareTime, currentTime);


                                        if (!missedTransfers.containsKey(routeKey)) {
                                            missedTransfers.put(routeKey, new HashSet<>());
                                        }
                                        missedTransfers.get(routeKey).add(missedTransfer);
                                    }
                                }
                            }
                        }
                        
                        if (shortestWait < Integer.MAX_VALUE)
                            waitTimesByRoute.get(routeKey).add(shortestWait);
                    }
                }
            }
        }
        for (Map.Entry<Fun.Tuple2<String, String>, TIntList> entry : waitTimesByRoute.entrySet()) {
            Fun.Tuple2<String, String> routeKey = entry.getKey();
            TIntList waitTimes = entry.getValue();
            if (waitTimes.isEmpty()) {
                continue;
            }
            int min = waitTimes.min();
            int max = waitTimes.max();
            waitTimes.sort();
            int median = waitTimes.get(waitTimes.size() / 2);
            TransferPerformanceSummary routeTransferPerformance = new TransferPerformanceSummary(routeKey.a, routeKey.b, min, max, median, missedTransfers.get(routeKey));
            transferPerformanceMap.add(routeTransferPerformance);
        }

        return transferPerformanceMap;
    }
public List < TransferPerformanceSummary > getTransferPerformance ( String stop_id , LocalDate date ) { List < StopTime > stopTimes = feed . getStopTimesForStop ( stop_id ) ; Map < String , List < StopTime > > routeStopTimeMap = new HashMap <> ( ) ; List < TransferPerformanceSummary > transferPerformanceMap = new ArrayList <> ( ) ; // TODO: do we need to handle interpolated stop times??? // first stream stopTimes for stop into route -> list of stopTimes map stopTimes . stream ( ) . forEach ( st -> { Trip trip = feed . trips . get ( st . trip_id ) ; Service service = feed . services . get ( trip . service_id ) ; // only add to map if trip is active on given date if ( service != null && service . activeOn ( date ) ) { Route route = feed . routes . get ( trip . route_id ) ; List < StopTime > times = new ArrayList <> ( ) ; if ( routeStopTimeMap . containsKey ( route . route_id ) ) { times . addAll ( routeStopTimeMap . get ( route . route_id ) ) ; } times . add ( st ) ; routeStopTimeMap . put ( route . route_id , times ) ; } } ) ; Map < Fun . Tuple2 < String , String > , TIntList > waitTimesByRoute = new HashMap <> ( ) ; Map < Fun . Tuple2 < String , String > , Set < Fun . Tuple2 < StopTime , StopTime > > > missedTransfers = new HashMap <> ( ) ; // iterate over every entry in route -> list of stopTimes map for ( Map . Entry < String , List < StopTime > > entry : routeStopTimeMap . entrySet ( ) ) { final int MISSED_TRANSFER_THRESHOLD = 60 * 10 ; List < StopTime > currentTimes = entry . getValue ( ) ; String currentRoute = entry . getKey ( ) ; for ( StopTime currentTime : currentTimes ) { if ( currentTime . arrival_time > 0 ) { // cycle through all other routes that stop here. for ( Map . Entry < String , List < StopTime > > entry2 : routeStopTimeMap . entrySet ( ) ) { List < StopTime > compareTimes = entry2 . getValue ( ) ; String compareRoute = entry2 . getKey ( ) ; Fun . Tuple2 < String , String > routeKey = new Fun . Tuple2 ( currentRoute , compareRoute ) ; if ( compareRoute . equals ( currentRoute ) ) { continue ; } if ( ! waitTimesByRoute . containsKey ( routeKey ) ) { waitTimesByRoute . put ( routeKey , new TIntArrayList ( ) ) ; } int shortestWait = Integer . MAX_VALUE ; // compare current time against departure times for route for ( StopTime compareTime : compareTimes ) { if ( compareTime . departure_time > 0 ) { int waitTime = compareTime . departure_time - currentTime . arrival_time ; // if non-negative and shortest, save for later if ( waitTime >= 0 && waitTime < shortestWait ) { shortestWait = waitTime ; } // otherwise, check for missed near-transfer opportunities else { if ( waitTime < 0 && waitTime * - 1 <= MISSED_TRANSFER_THRESHOLD ) { Fun . Tuple2 < StopTime , StopTime > missedTransfer = new Fun . Tuple2 ( compareTime , currentTime ) ; //                                        missedTransfer.add(currentTime); //                                        missedTransfer.add(compareTime); if ( ! missedTransfers . containsKey ( routeKey ) ) { missedTransfers . put ( routeKey , new HashSet <> ( ) ) ; } missedTransfers . get ( routeKey ) . add ( missedTransfer ) ; } } } } // add shortestWait for currentTime to map if ( shortestWait < Integer . MAX_VALUE ) waitTimesByRoute . get ( routeKey ) . add ( shortestWait ) ; } } } } for ( Map . Entry < Fun . Tuple2 < String , String > , TIntList > entry : waitTimesByRoute . entrySet ( ) ) { Fun . Tuple2 < String , String > routeKey = entry . getKey ( ) ; TIntList waitTimes = entry . getValue ( ) ; if ( waitTimes . isEmpty ( ) ) { continue ; } int min = waitTimes . min ( ) ; int max = waitTimes . max ( ) ; waitTimes . sort ( ) ; int median = waitTimes . get ( waitTimes . size ( ) / 2 ) ; TransferPerformanceSummary routeTransferPerformance = new TransferPerformanceSummary ( routeKey . a , routeKey . b , min , max , median , missedTransfers . get ( routeKey ) ) ; transferPerformanceMap . add ( routeTransferPerformance ) ; } return transferPerformanceMap ; }
Returns a list of transfer performance summaries (max, min, and median wait times between routes)
for each route pair at a stop for the specified date of service.
@param stop_id
@param date
@return
Returns a list of transfer performance summaries ( max min and median wait times between routes ) for each route pair at a stop for the specified date of service .