예제 #1
0
class RouteOptimizer(object):
    def __init__(self, source, dest, optimization_type, depart_time):
        is_correct_type_or_err(source, BingLocation)
        is_correct_type_or_err(dest, BingLocation)
        is_correct_type_or_err(depart_time, BingDateTime)

        if optimization_type.lower() not in ["cost", "time"]:
            self.optimization_type = optimization_type

        self.origin_source = source
        self.final_dest = dest

        self.bing_maps = BingMaps()
        self.depart_time = depart_time

        self.uber_route = None
        self.lyft_route = None
        self._init_routes()

    def _init_routes(self):
        routes = RideShareRoute.from_source_dest(self.origin_source,
                                                 self.final_dest,
                                                 self.depart_time)
        self.uber_route = routes["uber"]
        self.lyft_route = routes["lyft"]

        transit_routes = self.bing_maps.get_transit_routes(
            self.origin_source.address_str, self.final_dest.address_str)
        self.basic_transit_routes = transit_routes

    def get_simple_hybrid(self):
        pass
예제 #2
0
    def __init__(self, source, dest, optimization_type, depart_time):
        is_correct_type_or_err(source, BingLocation)
        is_correct_type_or_err(dest, BingLocation)
        is_correct_type_or_err(depart_time, BingDateTime)

        if optimization_type.lower() not in ["cost", "time"]:
            self.optimization_type = optimization_type

        self.origin_source = source
        self.final_dest = dest

        self.bing_maps = BingMaps()
        self.depart_time = depart_time

        self.uber_route = None
        self.lyft_route = None
        self._init_routes()
예제 #3
0
    def get(self, query):
        address_list = []
        bing_map = BingMaps()

        try:
            address_list = bing_map.get_possible_locations_from_string(query)
        except BingApiError as e:
            handle_error(ex=e)

        duration_list = []
        for address in address_list:
            location = address[0]
            duration = dict()
            duration['address'] = location.address_str
            duration['lat'] = location.point_list[0]
            duration['long'] = location.point_list[1]
            duration_list.append(duration)
        return duration_list, 200
예제 #4
0
    def get(self, query):
        try:
            lat, long = query.split(",")
        except ValueError:
            msg = "Wrong lat,long format. Please supply latitude and longitude in the following format: 'lat,long'"
            handle_error(message=msg)

        bing_maps = BingMaps()

        try:
            location = bing_maps.get_location_from_point(
                lat.strip(), long.strip())
        except BingApiError as e:
            handle_error(ex=e)

        duration = dict()
        duration['address'] = location.address_str
        duration['lat'] = location.point_list[0]
        duration['long'] = location.point_list[1]

        return duration, 200
예제 #5
0
    def post(self):
        self.bing_maps = BingMaps()

        _request_body = request.json
        start = _request_body["start"]
        dest = _request_body["dest"]
        optimisation_type = _request_body["optimise_for"].lower()

        start_point = start.split(",")
        dest_point = dest.split(",")

        is_lat_long = True
        if len(start_point) != len(dest_point) or len(start_point) != 2:
            start_point = None
            dest_point = None
            is_lat_long = False

        if is_lat_long:
            start_location = self.bing_maps.get_location_from_point(
                start_point[0], start_point[1])
            dest_location = self.bing_maps.get_location_from_point(
                dest_point[0], dest_point[1])
        else:
            start_location = self.bing_maps.get_location_from_string(start)
            dest_location = self.bing_maps.get_location_from_string(dest)

        depart_time = BingDateTime.now()

        optimizer = RouteOptimizer(start_location, dest_location,
                                   optimisation_type, depart_time)

        response_list = []
        optimized_list = []

        uber_route = optimizer.uber_route
        lyft_route = optimizer.lyft_route
        transit_routes = optimizer.basic_transit_routes

        uber_route_dict = self._process_ride_share_route(uber_route)
        lyft_route_dict = self._process_ride_share_route(lyft_route)

        # largest cost should be the cheapest rideshare
        max_cost = min(uber_route_dict["cost"], lyft_route_dict["cost"])
        max_optimized_duration = None

        for t_route in transit_routes:
            transit_dict = self._process_transit_route(t_route)
            response_list.append(transit_dict)

            # longest duration should be that of a regular transit route
            max_optimized_duration = transit_dict[
                "duration"] if max_optimized_duration is None else min(
                    transit_dict["duration"], max_optimized_duration)

            complex_routes = optimizer.get_simple_hybrid(t_route)
            for cmp_route in complex_routes:
                optimized_list.append(self._process_complex_route(cmp_route))

        response_list.append(uber_route_dict)
        response_list.append(lyft_route_dict)

        max_optimized_duration = max(uber_route_dict["duration"],
                                     lyft_route_dict["duration"],
                                     max_optimized_duration)

        # filter suggested routes that are too slow or costly, sort by duration
        optimized_list = list(
            filter(
                lambda route: route["cost"] < max_cost and route["duration"] <
                max_optimized_duration, optimized_list))
        optimized_list = list(
            filter(_filter_routes_with_only_walk_rideshare, optimized_list))
        optimized_list = sorted(optimized_list,
                                key=lambda route: route["duration"])
        response_list.extend(optimized_list)

        return response_list
        """
        Dummy dictionary of the object [Route, Route....] 
        with one Route option.
        """
        routes_list = []
        route_dict = dict()
        segment_list = []
        segment_dict = dict()
        segment_dict["start"] = start
        segment_dict["dest"] = dest
        segment_dict["mode"] = "transit"
        segment_dict["duration"] = 600
        segment_dict["start_time"] = "07/23/2019 16:30"
        segment_dict["end_time"] = "07/23/2019 16:40"
        segment_dict["cost"] = 6.5
        segment_dict["description"] = "Take bus 545"
        segment_list.append(segment_dict)
        route_dict["segments"] = segment_dict
        route_dict["start"] = start
        route_dict["dest"] = dest
        route_dict["start_time"] = "07/23/2019 16:30"
        route_dict["end_time"] = "07/23/2019 16:40"
        route_dict["duration"] = 600
        route_dict["cost"] = 6.5
        routes_list.append(route_dict)

        return routes_list, 201
예제 #6
0
class Recommendations(Resource):
    def post(self):
        self.bing_maps = BingMaps()

        _request_body = request.json
        start = _request_body["start"]
        dest = _request_body["dest"]
        optimisation_type = _request_body["optimise_for"].lower()

        start_point = start.split(",")
        dest_point = dest.split(",")

        is_lat_long = True
        if len(start_point) != len(dest_point) or len(start_point) != 2:
            start_point = None
            dest_point = None
            is_lat_long = False

        if is_lat_long:
            start_location = self.bing_maps.get_location_from_point(
                start_point[0], start_point[1])
            dest_location = self.bing_maps.get_location_from_point(
                dest_point[0], dest_point[1])
        else:
            start_location = self.bing_maps.get_location_from_string(start)
            dest_location = self.bing_maps.get_location_from_string(dest)

        depart_time = BingDateTime.now()

        optimizer = RouteOptimizer(start_location, dest_location,
                                   optimisation_type, depart_time)

        response_list = []
        optimized_list = []

        uber_route = optimizer.uber_route
        lyft_route = optimizer.lyft_route
        transit_routes = optimizer.basic_transit_routes

        uber_route_dict = self._process_ride_share_route(uber_route)
        lyft_route_dict = self._process_ride_share_route(lyft_route)

        # largest cost should be the cheapest rideshare
        max_cost = min(uber_route_dict["cost"], lyft_route_dict["cost"])
        max_optimized_duration = None

        for t_route in transit_routes:
            transit_dict = self._process_transit_route(t_route)
            response_list.append(transit_dict)

            # longest duration should be that of a regular transit route
            max_optimized_duration = transit_dict[
                "duration"] if max_optimized_duration is None else min(
                    transit_dict["duration"], max_optimized_duration)

            complex_routes = optimizer.get_simple_hybrid(t_route)
            for cmp_route in complex_routes:
                optimized_list.append(self._process_complex_route(cmp_route))

        response_list.append(uber_route_dict)
        response_list.append(lyft_route_dict)

        max_optimized_duration = max(uber_route_dict["duration"],
                                     lyft_route_dict["duration"],
                                     max_optimized_duration)

        # filter suggested routes that are too slow or costly, sort by duration
        optimized_list = list(
            filter(
                lambda route: route["cost"] < max_cost and route["duration"] <
                max_optimized_duration, optimized_list))
        optimized_list = list(
            filter(_filter_routes_with_only_walk_rideshare, optimized_list))
        optimized_list = sorted(optimized_list,
                                key=lambda route: route["duration"])
        response_list.extend(optimized_list)

        return response_list
        """
        Dummy dictionary of the object [Route, Route....] 
        with one Route option.
        """
        routes_list = []
        route_dict = dict()
        segment_list = []
        segment_dict = dict()
        segment_dict["start"] = start
        segment_dict["dest"] = dest
        segment_dict["mode"] = "transit"
        segment_dict["duration"] = 600
        segment_dict["start_time"] = "07/23/2019 16:30"
        segment_dict["end_time"] = "07/23/2019 16:40"
        segment_dict["cost"] = 6.5
        segment_dict["description"] = "Take bus 545"
        segment_list.append(segment_dict)
        route_dict["segments"] = segment_dict
        route_dict["start"] = start
        route_dict["dest"] = dest
        route_dict["start_time"] = "07/23/2019 16:30"
        route_dict["end_time"] = "07/23/2019 16:40"
        route_dict["duration"] = 600
        route_dict["cost"] = 6.5
        routes_list.append(route_dict)

        return routes_list, 201

    def _process_ride_share_route(self, bing_ride_share):
        segment_dict = {}
        segment_dict["mode"] = "rideshare"
        segment_dict["duration"] = bing_ride_share.duration.total_seconds()

        segment_dict["start"] = bing_ride_share.source.address_dict()
        segment_dict["dest"] = bing_ride_share.dest.address_dict()

        segment_dict[
            "start_time"] = bing_ride_share.time_requested.date_time_str
        end_time = bing_ride_share.time_requested.date_time + bing_ride_share.duration
        segment_dict["end_time"] = BingDateTime(end_time).date_time_str

        segment_dict["cost"] = bing_ride_share.fare
        segment_dict[
            "description"] = "Use {} (factor in pickup/drop time).".format(
                bing_ride_share.type)

        result = {
            "segments": [segment_dict],
            "cost": segment_dict["cost"],
            "start": segment_dict["start"],
            "dest": segment_dict["dest"],
            "start_time": segment_dict["start_time"],
            "end_time": segment_dict["end_time"],
            "duration": segment_dict["duration"],
            "type": "only_ride_share"
        }

        return result

    def _process_transit_segment(self, bing_transit_segment):
        segment_dict = {}
        segment_dict["mode"] = "transit" if isinstance(
            bing_transit_segment, BingTransportSegment) else "walk"
        segment_dict["duration"] = bing_transit_segment.duration.total_seconds(
        )

        if isinstance(bing_transit_segment, BingTransportSegment):
            segment_dict[
                "start"] = bing_transit_segment.depart_details.coords.address_dict(
                )
            segment_dict[
                "dest"] = bing_transit_segment.arrive_details.coords.address_dict(
                )
        else:
            segment_dict[
                "start"] = bing_transit_segment.start_location.address_dict()
            segment_dict["dest"] = None

        if isinstance(bing_transit_segment, BingTransportSegment):
            segment_dict[
                "start_time"] = bing_transit_segment.depart_details.time.date_time_str
            segment_dict[
                "end_time"] = bing_transit_segment.arrive_details.time.date_time_str
        else:
            segment_dict["start_time"] = None
            segment_dict["end_time"] = None

        segment_dict["cost"] = bing_transit_segment.cost
        segment_dict["description"] = bing_transit_segment.text
        return segment_dict

    def _process_transit_route(self, bing_transit_route):
        segments = []

        for seg in bing_transit_route.segments:
            segments.append(self._process_transit_segment(seg))

        result = {
            "segments": segments,
            "cost": bing_transit_route.fare,
            "start": bing_transit_route.start_location.address_dict(),
            "dest": bing_transit_route.end_location.address_dict(),
            "start_time": bing_transit_route.start_time.date_time_str,
            "end_time": bing_transit_route.end_time.date_time_str,
            "duration": bing_transit_route.duration.total_seconds(),
            "type": "only_transit"
        }

        return result

    def _process_complex_route(self, bing_complex_route):
        total_duration = 0.0
        total_fare = 0
        segments = []

        complex_routes = []

        for route in bing_complex_route.routes:
            if isinstance(route, BingTransitRoute):
                route = self._process_transit_route(route)
            else:
                route = self._process_ride_share_route(route)

            total_duration += route["duration"]
            total_fare += route["cost"]
            segments.extend(route['segments'])

            # add the route_dict
            complex_routes.append(route)

        start_location = complex_routes[0]["start"]
        dest_location = complex_routes[-1]["dest"]

        start_time = complex_routes[0]["start_time"]
        end_time = complex_routes[-1]["end_time"]

        assert_equals_or_warn(start_location, segments[0]["start"])
        assert_equals_or_warn(dest_location, segments[-1]["dest"])
        assert_equals_or_warn(start_time, segments[0]["start_time"])
        assert_equals_or_warn(end_time, segments[-1]["end_time"])
        assert_equals_or_warn(
            total_duration, bing_complex_route.total_duration.total_seconds())

        result = {
            "start": start_location,
            "dest": dest_location,
            "start_time": start_time,
            "end_time": end_time,
            "cost": total_fare,
            "duration": total_duration,
            "segments": segments,
            "type": "complex"
        }

        return result
예제 #7
0
class RouteOptimizer(object):
    def __init__(self, source, dest, optimization_type, depart_time):
        is_correct_type_or_err(source, BingLocation)
        is_correct_type_or_err(dest, BingLocation)
        is_correct_type_or_err(depart_time, BingDateTime)

        if optimization_type.lower() not in ["cost", "time"]:
            self.optimization_type = optimization_type

        self.origin_source = source
        self.final_dest = dest

        self.bing_maps = BingMaps()
        self.depart_time = depart_time

        self.uber_route = None
        self.lyft_route = None
        self._init_routes()

    def _init_routes(self):
        routes = RideShareRoute.from_source_dest(self.origin_source,
                                                 self.final_dest,
                                                 self.depart_time)
        self.uber_route = routes["uber"]
        self.lyft_route = routes["lyft"]

        transit_routes = self.bing_maps.get_transit_routes(
            self.origin_source.address_str, self.final_dest.address_str)
        self.basic_transit_routes = transit_routes

    def get_simple_hybrid(self, transit_route):
        def _replace_simple_complex_route(last_segment,
                                          possible_complex_routes,
                                          transit_route):
            rs_source = last_segment.depart_details.coords
            rs_depart_time = last_segment.depart_details.time
            ride_share_route = RideShareRoute.from_source_dest(
                rs_source, self.final_dest, rs_depart_time)
            # possible_complex_routes.append(BingComplexRoute([transit_route, ride_share_route["lyft"]]))
            possible_complex_routes.append(
                BingComplexRoute([transit_route, ride_share_route["uber"]]))

        if len(transit_route.segments) <= 1:
            return []

        possible_complex_routes = []
        while len(transit_route.segments) > 1:
            # get last segment, this is the start of the rideshare.
            last_segment = transit_route.segments[-1]

            # update transit route by removing last segment
            transit_route = transit_route.get_route_without_last_segment()

            # if there is another transport segment beforehand
            if isinstance(last_segment, BingTransportSegment):
                _replace_simple_complex_route(last_segment,
                                              possible_complex_routes,
                                              transit_route)
            else:
                del last_segment
                # in this case last segment is walk segment... so use previous transit segment to determine departure time.
                try:
                    second_to_last_segment = transit_route.segments[-1]
                except IndexError:
                    continue
                if isinstance(second_to_last_segment, BingTransportSegment):
                    rs_source = second_to_last_segment.arrive_details.coords
                    rs_depart_time = second_to_last_segment.arrive_details.time
                    ride_share_route = RideShareRoute.from_source_dest(
                        rs_source, self.final_dest, rs_depart_time)
                    # possible_complex_routes.append(BingComplexRoute([transit_route, ride_share_route["lyft"]]))
                    possible_complex_routes.append(
                        BingComplexRoute(
                            [transit_route, ride_share_route["uber"]]))

        return possible_complex_routes
예제 #8
0
    def post(self):
        self.bing_maps = BingMaps()

        _request_body = request.json
        start = _request_body["start"]
        dest = _request_body["dest"]
        optimisation_type = _request_body["optimise_for"].lower()

        start_point = start.split(",")
        dest_point = dest.split(",")

        is_lat_long = True
        if len(start_point) != len(dest_point) or len(start_point) != 2:
            start_point = None
            dest_point = None
            is_lat_long = False

        if is_lat_long:
            start_location = self.bing_maps.get_location_from_point(
                start_point[0], start_point[1])
            dest_location = self.bing_maps.get_location_from_point(
                dest_point[0], dest_point[1])
        else:
            start_location = self.bing_maps.get_location_from_string(start)
            dest_location = self.bing_maps.get_location_from_string(dest)

        depart_time = BingDateTime.now()

        optimizer = RouteOptimizer(start_location, dest_location,
                                   optimisation_type, depart_time)

        response_list = []
        uber_route = optimizer.uber_route
        lyft_route = optimizer.lyft_route
        transit_routes = optimizer.basic_transit_routes

        uber_route_dict = self._process_ride_share_route(uber_route)
        lyft_route_dict = self._process_ride_share_route(lyft_route)

        for t_route in transit_routes:
            response_list.append(self._process_transit_route(t_route))

        response_list.append(uber_route_dict)
        response_list.append(lyft_route_dict)

        return response_list
        """
        Dummy dictionary of the object [Route, Route....] 
        with one Route option.
        """
        routes_list = []
        route_dict = dict()
        segment_list = []
        segment_dict = dict()
        segment_dict["start"] = start
        segment_dict["dest"] = dest
        segment_dict["mode"] = "transit"
        segment_dict["duration"] = 600
        segment_dict["start_time"] = "07/23/2019 16:30"
        segment_dict["end_time"] = "07/23/2019 16:40"
        segment_dict["cost"] = 6.5
        segment_dict["description"] = "Take bus 545"
        segment_list.append(segment_dict)
        route_dict["segment"] = segment_dict
        route_dict["start"] = start
        route_dict["dest"] = dest
        route_dict["start_time"] = "07/23/2019 16:30"
        route_dict["end_time"] = "07/23/2019 16:40"
        route_dict["duration"] = 600
        route_dict["cost"] = 6.5
        routes_list.append(route_dict)

        return routes_list, 201
예제 #9
0
class Recommendations(Resource):
    def post(self):
        self.bing_maps = BingMaps()

        _request_body = request.json
        start = _request_body["start"]
        dest = _request_body["dest"]
        optimisation_type = _request_body["optimise_for"].lower()

        start_point = start.split(",")
        dest_point = dest.split(",")

        is_lat_long = True
        if len(start_point) != len(dest_point) or len(start_point) != 2:
            start_point = None
            dest_point = None
            is_lat_long = False

        if is_lat_long:
            start_location = self.bing_maps.get_location_from_point(
                start_point[0], start_point[1])
            dest_location = self.bing_maps.get_location_from_point(
                dest_point[0], dest_point[1])
        else:
            start_location = self.bing_maps.get_location_from_string(start)
            dest_location = self.bing_maps.get_location_from_string(dest)

        depart_time = BingDateTime.now()

        optimizer = RouteOptimizer(start_location, dest_location,
                                   optimisation_type, depart_time)

        response_list = []
        uber_route = optimizer.uber_route
        lyft_route = optimizer.lyft_route
        transit_routes = optimizer.basic_transit_routes

        uber_route_dict = self._process_ride_share_route(uber_route)
        lyft_route_dict = self._process_ride_share_route(lyft_route)

        for t_route in transit_routes:
            response_list.append(self._process_transit_route(t_route))

        response_list.append(uber_route_dict)
        response_list.append(lyft_route_dict)

        return response_list
        """
        Dummy dictionary of the object [Route, Route....] 
        with one Route option.
        """
        routes_list = []
        route_dict = dict()
        segment_list = []
        segment_dict = dict()
        segment_dict["start"] = start
        segment_dict["dest"] = dest
        segment_dict["mode"] = "transit"
        segment_dict["duration"] = 600
        segment_dict["start_time"] = "07/23/2019 16:30"
        segment_dict["end_time"] = "07/23/2019 16:40"
        segment_dict["cost"] = 6.5
        segment_dict["description"] = "Take bus 545"
        segment_list.append(segment_dict)
        route_dict["segment"] = segment_dict
        route_dict["start"] = start
        route_dict["dest"] = dest
        route_dict["start_time"] = "07/23/2019 16:30"
        route_dict["end_time"] = "07/23/2019 16:40"
        route_dict["duration"] = 600
        route_dict["cost"] = 6.5
        routes_list.append(route_dict)

        return routes_list, 201

    def _process_ride_share_route(self, bing_ride_share):
        segment_dict = {}
        segment_dict["mode"] = "rideshare"
        segment_dict[
            "duration"] = bing_ride_share.travel_duration.total_seconds()

        segment_dict[
            "start"] = bing_ride_share.source.address_dict_from_bing_location(
            )
        segment_dict[
            "dest"] = bing_ride_share.dest.address_dict_from_bing_location()

        segment_dict[
            "start_time"] = bing_ride_share.time_requested.date_time_str
        end_time = bing_ride_share.time_requested.date_time + bing_ride_share.travel_duration
        segment_dict["end_time"] = BingDateTime(end_time).date_time_str

        segment_dict["cost"] = bing_ride_share.fare
        segment_dict[
            "description"] = "Use {} (factor in pickup/drop time).".format(
                bing_ride_share.type)

        result = {
            "segment": [segment_dict],
            "cost": segment_dict["cost"],
            "start": segment_dict["start"],
            "dest": segment_dict["dest"],
            "start_time": segment_dict["start_time"],
            "end_time": segment_dict["end_time"],
            "duration": segment_dict["duration"]
        }

        return result

    def _process_transit_segment(self, bing_transit_segment):
        segment_dict = {}
        segment_dict["mode"] = "transit" if isinstance(
            bing_transit_segment, BingTransportSegment) else "walk"
        segment_dict["duration"] = bing_transit_segment.duration.total_seconds(
        )

        if isinstance(bing_transit_segment, BingTransportSegment):
            segment_dict[
                "start"] = bing_transit_segment.depart_details.coords.address_dict_from_bing_location(
                )
            segment_dict[
                "dest"] = bing_transit_segment.arrive_details.coords.address_dict_from_bing_location(
                )
        else:
            segment_dict[
                "start"] = bing_transit_segment.start_location.address_dict_from_bing_location(
                )
            segment_dict["dest"] = None

        if isinstance(bing_transit_segment, BingTransportSegment):
            segment_dict[
                "start_time"] = bing_transit_segment.depart_details.time.date_time_str
            segment_dict[
                "end_time"] = bing_transit_segment.arrive_details.time.date_time_str
        else:
            segment_dict["start_time"] = None
            segment_dict["end_time"] = None

        segment_dict["cost"] = bing_transit_segment.cost
        segment_dict["description"] = bing_transit_segment.text
        return segment_dict

    def _process_transit_route(self, bing_transit_route):
        segments = []

        for seg in bing_transit_route.segments:
            segments.append(self._process_transit_segment(seg))

        result = {
            "segment": segments,
            "cost": bing_transit_route.fare,
            "start": segments[0]["start"],
            "dest": segments[-1]["dest"],
            "start_time": segments[0]["start"],
            "end_time": segments[-1]["dest"],
            "duration": bing_transit_route.duration
        }

        return result