def _get_route_combinations(start: tuple, destination: tuple, departure: str) -> List[dict]: """ retrieves all possible routes for a specific start and destination address """ public_transport_stops = public_transport_connection_finder.get_public_transport_stops( start) routes = [] for public_transport_stop_uic_ref, public_transport_stop_position in public_transport_stops.items( ): logger.debug( f'retrieve route with start at public transport stop: {public_transport_stop_uic_ref}' ) public_transport_departure = _calc_public_transport_departure( departure, start, public_transport_stop_position) try: public_transport_connection = \ public_transport_connection_finder.get_public_transport_connection(public_transport_stop_uic_ref, destination, public_transport_departure) except ValidationError: """ Happens if the configured lookup radius is too high and the destination is used as a start public transport stop. So both the start and destination value will be the same. We'are able to skip the connection and try the next one. """ continue except RuntimeError: """ Happens if no connection was found for the given parameters. We'are able to skip the connection and try the next one. """ continue if not public_transport_connection['path']: continue # skip empty paths, this happens if the path only consists of walking legs public_transport_connection_start = tuple( public_transport_connection['path'][0]['start_position']) start_walking_route = walking_route_finder.get_walking_route( start, public_transport_connection_start) public_transport_connection_destination = tuple( public_transport_connection['path'][-1]['exit_position']) end_walking_route = walking_route_finder.get_walking_route( public_transport_connection_destination, destination) routes.append( _generate_route_combination(start_walking_route, public_transport_connection, end_walking_route)) return routes
def _calc_public_transport_departure(departure: str, start: tuple, destination: tuple) -> str: """ Adds the duration that it takes to get from start to destination to the provided departure time. The destination should be a public transport stop to make sure that the pedestrian has enough time to catch the public transport. """ walking_route = walking_route_finder.get_walking_route(start, destination) initial_departure = datetime.strptime(departure, DEPARTURE_FORMAT) public_transport_departure = initial_departure + timedelta( seconds=walking_route['duration']) return '{:%H:%M}'.format(public_transport_departure)
def _optimize_route_combination(route_combination: dict, start: tuple, destination: tuple) -> dict: """ retrieves accurate coordinates for the public transport stops and thus new walking routes will be generated """ logger.debug("optimize route") public_transport_connection = route_combination[ 'public_transport_connection'] optimized_public_transport_connection = \ public_transport_connection_finder.optimize_public_transport_connection(public_transport_connection) public_transport_connection_start = tuple( optimized_public_transport_connection['path'][0]['start_position']) start_walking_route = walking_route_finder.get_walking_route( start, public_transport_connection_start) public_transport_connection_destination = tuple( optimized_public_transport_connection['path'][-1]['exit_position']) end_walking_route = walking_route_finder.get_walking_route( public_transport_connection_destination, destination) return _generate_route_combination(start_walking_route, public_transport_connection, end_walking_route)
def find_route(start: str, destination: str, departure: str, precise_public_transport_stops: bool) -> dict: logger.info(f'route from {start} to {destination}') start = _parse_location(start) destination = _parse_location(destination) departure = _parse_departure(departure) overall_walking_route = walking_route_finder.get_walking_route( start, destination) if overall_walking_route['duration'] <= MAX_WALKING_DURATION: logger.info( "Walking is faster than using public transport, return walking only route" ) return _convert_walking_route_to_overall_response( overall_walking_route) route_combinations = _get_route_combinations(start, destination, departure) if not route_combinations: logger.info( "No public transport route was returned because the path consists only of walking legs" ) return _convert_walking_route_to_overall_response( overall_walking_route) best_route_combination = _get_best_route_combination(route_combinations) if _is_walking_faster_than_route_combination(overall_walking_route, best_route_combination, departure): return _convert_walking_route_to_overall_response( overall_walking_route) if precise_public_transport_stops: best_route_combination = _optimize_route_combination( best_route_combination, start, destination) return best_route_combination