Пример #1
0
    def _do_request(self):
        logger = logging.getLogger(__name__)
        logger.debug(
            "requesting %s direct path from %s to %s by %s",
            self._path_type,
            self._orig_obj.uri,
            self._dest_obj.uri,
            self._mode,
        )

        dp = self._direct_path_with_fp(self._instance)

        if getattr(dp, "journeys", None):
            if self._mode == "ridesharing":
                switch_back_to_ridesharing(dp, True)
            dp.journeys[0].internal_id = str(utils.generate_id())

        logger.debug(
            "finish %s direct path from %s to %s by %s",
            self._path_type,
            self._orig_obj.uri,
            self._dest_obj.uri,
            self._mode,
        )
        return dp
Пример #2
0
def _create_crowfly(pt_journey, crowfly_origin, crowfly_destination, begin, end, mode):
    section = response_pb2.Section()
    section.type = response_pb2.CROW_FLY
    section.origin.CopyFrom(crowfly_origin)
    section.destination.CopyFrom(crowfly_destination)
    section.duration = end - begin
    pt_journey.durations.total += section.duration
    pt_journey.duration += section.duration
    section.begin_date_time = begin
    section.end_date_time = end
    if section.duration > 0:
        section.street_network.mode = MODE_TO_PB_MODE.get(mode)
    # mode is always walking for a teleportation crow_fly
    else:
        section.street_network.mode = response_pb2.Walking

    # Calculate section length
    from_coord = get_pt_object_coord(section.origin)
    to_coord = get_pt_object_coord(section.destination)
    section.length = int(crowfly_distance_between(from_coord, to_coord))

    # The section "distances" and "durations" in the response needs to be updated according to the mode.
    # only if it isn't a 'free' crow_fly
    if section.duration > 0:
        setattr(pt_journey.distances, mode, (getattr(pt_journey.distances, mode) + section.length))
        setattr(pt_journey.durations, mode, (getattr(pt_journey.durations, mode) + section.duration))

    section.id = six.text_type(generate_id())
    return section
Пример #3
0
    def _do_isochrone_common_request(self):
        logger = logging.getLogger(__name__)
        fallback_durations_pool = (self._orig_fallback_durtaions_pool
                                   if self._orig_fallback_durtaions_pool
                                   is not None else
                                   self._dest_fallback_durations_pool)
        mode = self._dep_mode if self._orig_fallback_durtaions_pool is not None else self._arr_mode
        self._logger.debug("waiting for fallback durations with %s", mode)
        fallback_duration_status = fallback_durations_pool.wait_and_get(mode)

        self._logger.debug(
            "requesting public transport journey with dep_mode: %s", mode)

        fallback_durations = {
            k: v.duration
            for k, v in fallback_duration_status.items()
        }

        if not fallback_durations or not self._request.get('max_duration', 0):
            return None

        if self._orig_fallback_durtaions_pool is not None:
            orig_and_dest_fallback_durations = {
                "orig_fallback_durations": fallback_durations,
                "dest_fallback_durations": {},
            }
        else:
            orig_and_dest_fallback_durations = {
                "orig_fallback_durations": {},
                "dest_fallback_durations": fallback_durations,
            }

        if self._request_type == type_pb2.ISOCHRONE:
            resp = self._journeys(self._instance.planner,
                                  **orig_and_dest_fallback_durations)
        else:
            resp = self._graphical_isochrone(
                self._instance.planner, **orig_and_dest_fallback_durations)

        for j in resp.journeys:
            j.internal_id = str(utils.generate_id())

        if resp.HasField(six.text_type("error")):
            logger.debug("pt journey has error mode: %s", mode)
            # Here needs to modify error message of no_solution
            if not fallback_durations:
                if self._orig_fallback_durtaions_pool is not None:
                    resp.error.id = response_pb2.Error.no_origin
                    resp.error.message = "no origin point"
                else:
                    resp.error.id = response_pb2.Error.no_destination
                    resp.error.message = "no destination point"

        logger.debug("finish public transport journey with mode: %s", mode)
        return resp
Пример #4
0
    def _do_request(self):
        logger = logging.getLogger(__name__)
        logger.debug("waiting for orig fallback durations with %s",
                     self._dep_mode)
        orig_fallback_duration_status = self._orig_fallback_durtaions_pool.wait_and_get(
            self._dep_mode)
        logger.debug("waiting for dest fallback durations with %s",
                     self._arr_mode)
        dest_fallback_duration_status = self._dest_fallback_durations_pool.wait_and_get(
            self._arr_mode)

        logger.debug(
            "requesting public transport journey with dep_mode: %s and arr_mode: %s",
            self._dep_mode,
            self._arr_mode,
        )

        orig_fallback_durations = {
            k: v.duration
            for k, v in orig_fallback_duration_status.items()
        }
        dest_fallback_durations = {
            k: v.duration
            for k, v in dest_fallback_duration_status.items()
        }

        if (not orig_fallback_durations or not dest_fallback_durations
                or not self._request.get('max_duration', 0)):
            return None

        resp = self._journeys(self._instance.planner, orig_fallback_durations,
                              dest_fallback_durations)

        for j in resp.journeys:
            j.internal_id = str(utils.generate_id())

        if resp.HasField(b"error"):
            logger.debug("pt journey has error dep_mode: %s and arr_mode: %s",
                         self._dep_mode, self._arr_mode)
            # Here needs to modify error message of no_solution
            if not orig_fallback_durations:
                resp.error.id = response_pb2.Error.no_origin
                resp.error.message = "no origin point"
            elif not dest_fallback_durations:
                resp.error.id = response_pb2.Error.no_destination
                resp.error.message = "no destination point"

        logger.debug(
            "finish public transport journey with dep_mode: %s and arr_mode: %s",
            self._dep_mode, self._arr_mode)
        return resp
Пример #5
0
    def _do_request(self):
        logger = logging.getLogger(__name__)
        logger.debug("requesting %s direct path from %s to %s by %s",
                     self._path_type, self._orig_obj.uri, self._dest_obj.uri,
                     self._mode)

        dp = self._instance.direct_path(self._mode, self._orig_obj,
                                        self._dest_obj,
                                        self._fallback_extremity,
                                        self._request, self._path_type)
        if getattr(dp, "journeys", None):
            dp.journeys[0].internal_id = str(utils.generate_id())

        logger.debug("finish %s direct path from %s to %s by %s",
                     self._path_type, self._orig_obj.uri, self._dest_obj.uri,
                     self._mode)
        return dp
Пример #6
0
    def _do_journeys_request(self):

        self._logger.debug(
            "requesting public transport journey with dep_mode: %s and arr_mode: %s",
            self._dep_mode,
            self._arr_mode,
        )

        orig_fallback_durations = self._orig_fallback_durtaions_pool.get_best_fallback_durations(
            self._dep_mode)
        dest_fallback_durations = self._dest_fallback_durations_pool.get_best_fallback_durations(
            self._arr_mode)

        if (not orig_fallback_durations or not dest_fallback_durations
                or not self._request.get('max_duration', 0)):
            return None

        resp = self._journeys(self._instance.planner, orig_fallback_durations,
                              dest_fallback_durations)

        for j in resp.journeys:
            j.internal_id = str(utils.generate_id())

        if resp.HasField(str("error")):
            self._logger.debug(
                "pt journey has error dep_mode: %s and arr_mode: %s",
                self._dep_mode, self._arr_mode)
            # Here needs to modify error message of no_solution
            if not orig_fallback_durations:
                resp.error.id = response_pb2.Error.no_origin
                resp.error.message = "no origin point"
            elif not dest_fallback_durations:
                resp.error.id = response_pb2.Error.no_destination
                resp.error.message = "no destination point"

        self._logger.debug(
            "finish public transport journey with dep_mode: %s and arr_mode: %s",
            self._dep_mode, self._arr_mode)
        return resp
Пример #7
0
    def _do_request(self):
        self._logger.debug(
            "requesting %s direct path from %s to %s by %s",
            self._path_type,
            self._orig_obj.uri,
            self._dest_obj.uri,
            self._mode,
        )

        dp = self._direct_path_with_fp(self._streetnetwork_service)

        if getattr(dp, "journeys", None):
            dp.journeys[0].internal_id = str(utils.generate_id())

        self._logger.debug(
            "finish %s direct path from %s to %s by %s",
            self._path_type,
            self._orig_obj.uri,
            self._dest_obj.uri,
            self._mode,
        )
        return dp
Пример #8
0
def _create_crowfly(pt_journey, crowfly_origin, crowfly_destination, begin, end, mode):
    section = response_pb2.Section()
    section.type = response_pb2.CROW_FLY
    section.origin.CopyFrom(crowfly_origin)
    section.destination.CopyFrom(crowfly_destination)
    section.duration = end - begin
    pt_journey.durations.total += section.duration
    pt_journey.duration += section.duration
    section.begin_date_time = begin
    section.end_date_time = end
    if section.duration > 0:
        section.street_network.mode = FallbackModes[mode].value
    # mode is always walking for a teleportation crow_fly
    else:
        section.street_network.mode = response_pb2.Walking

    # Calculate section length
    from_coord = get_pt_object_coord(section.origin)
    to_coord = get_pt_object_coord(section.destination)
    section.length = int(crowfly_distance_between(from_coord, to_coord))

    section.id = six.text_type(generate_id())
    return section
Пример #9
0
def _rename_fallback_sections_ids(sections):
    for s in sections:
        s.id = six.text_type(generate_id())
Пример #10
0
def build_ridesharing_journeys(from_pt_obj, to_pt_obj, period_extremity,
                               instance):
    from_coord = get_pt_object_coord(from_pt_obj)
    to_coord = get_pt_object_coord(to_pt_obj)
    from_str = "{},{}".format(from_coord.lat, from_coord.lon)
    to_str = "{},{}".format(to_coord.lat, to_coord.lon)
    try:
        rsjs, fps = instance.get_ridesharing_journeys_with_feed_publishers(
            from_str, to_str, period_extremity)
    except Exception as e:
        logging.exception(
            'Error while retrieving ridesharing ads and feed_publishers from %s to %s: {}',
            from_str, to_str)
        new_relic.record_custom_event('ridesharing_internal_failure',
                                      {'message': str(e)})
        rsjs = []
        fps = []

    pb_rsjs = []
    pb_tickets = []
    pb_feed_publishers = [_make_pb_fp(fp) for fp in fps if fp is not None]

    for rsj in rsjs:
        pb_rsj = response_pb2.Journey()
        pb_rsj_pickup = instance.georef.place("{};{}".format(
            rsj.pickup_place.lon, rsj.pickup_place.lat))
        pb_rsj_dropoff = instance.georef.place("{};{}".format(
            rsj.dropoff_place.lon, rsj.dropoff_place.lat))
        pickup_coord = get_pt_object_coord(pb_rsj_pickup)
        dropoff_coord = get_pt_object_coord(pb_rsj_dropoff)

        pb_rsj.requested_date_time = period_extremity.datetime
        pb_rsj.departure_date_time = rsj.pickup_date_time
        pb_rsj.arrival_date_time = rsj.dropoff_date_time
        pb_rsj.tags.append('ridesharing')

        # start teleport section
        start_teleport_section = pb_rsj.sections.add()
        start_teleport_section.id = "section_{}".format(
            six.text_type(generate_id()))
        start_teleport_section.type = response_pb2.CROW_FLY
        start_teleport_section.street_network.mode = response_pb2.Walking
        start_teleport_section.origin.CopyFrom(from_pt_obj)
        start_teleport_section.destination.CopyFrom(pb_rsj_pickup)
        start_teleport_section.length = int(
            crowfly_distance_between(from_coord, pickup_coord))
        start_teleport_section.duration = 0
        start_teleport_section.shape.extend([from_coord, pickup_coord])
        start_teleport_section.begin_date_time = rsj.pickup_date_time
        start_teleport_section.end_date_time = rsj.pickup_date_time
        # report value to journey
        pb_rsj.distances.walking += start_teleport_section.length

        # real ridesharing section
        rs_section = pb_rsj.sections.add()
        rs_section.id = "section_{}".format(six.text_type(generate_id()))
        rs_section.type = response_pb2.RIDESHARING
        rs_section.origin.CopyFrom(pb_rsj_pickup)
        rs_section.destination.CopyFrom(pb_rsj_dropoff)
        rs_section.additional_informations.append(
            response_pb2.HAS_DATETIME_ESTIMATED)

        rs_section.ridesharing_information.operator = rsj.metadata.system_id
        rs_section.ridesharing_information.network = rsj.metadata.network
        if rsj.available_seats is not None:
            rs_section.ridesharing_information.seats.available = rsj.available_seats
        if rsj.total_seats is not None:
            rs_section.ridesharing_information.seats.total = rsj.total_seats
        if rsj.driver.alias:
            rs_section.ridesharing_information.driver.alias = rsj.driver.alias
        if rsj.driver.image:
            rs_section.ridesharing_information.driver.image = rsj.driver.image
        if rsj.driver.gender is not None:
            if rsj.driver.gender == Gender.MALE:
                rs_section.ridesharing_information.driver.gender = response_pb2.MALE
            elif rsj.driver.gender == Gender.FEMALE:
                rs_section.ridesharing_information.driver.gender = response_pb2.FEMALE
        if rsj.driver.rate is not None and rsj.driver.rate_count:
            rs_section.ridesharing_information.driver.rating.value = rsj.driver.rate
        if rsj.driver.rate_count:
            rs_section.ridesharing_information.driver.rating.count = rsj.driver.rate_count
        if rsj.metadata.rating_scale_min is not None and rsj.metadata.rating_scale_max is not None:
            rs_section.ridesharing_information.driver.rating.scale_min = rsj.metadata.rating_scale_min
            rs_section.ridesharing_information.driver.rating.scale_max = rsj.metadata.rating_scale_max

        if rsj.ridesharing_ad:
            l = rs_section.ridesharing_information.links.add()
            l.key = "ridesharing_ad"
            l.href = rsj.ridesharing_ad

        # TODO CO2 = length * coeffCar / (totalSeats  + 1)
        rs_section.length = rsj.distance

        rs_section.shape.extend(rsj.shape)

        rs_section.duration = rsj.dropoff_date_time - rsj.pickup_date_time
        rs_section.begin_date_time = rsj.pickup_date_time
        rs_section.end_date_time = rsj.dropoff_date_time
        # report values to journey
        pb_rsj.distances.ridesharing += rs_section.length
        pb_rsj.duration += rs_section.duration
        pb_rsj.durations.total += rs_section.duration
        pb_rsj.durations.ridesharing += rs_section.duration

        # end teleport section
        end_teleport_section = pb_rsj.sections.add()
        end_teleport_section.id = "section_{}".format(
            six.text_type(generate_id()))
        end_teleport_section.type = response_pb2.CROW_FLY
        end_teleport_section.street_network.mode = response_pb2.Walking
        end_teleport_section.origin.CopyFrom(pb_rsj_dropoff)
        end_teleport_section.destination.CopyFrom(to_pt_obj)
        end_teleport_section.length = int(
            crowfly_distance_between(dropoff_coord, to_coord))
        end_teleport_section.duration = 0
        end_teleport_section.shape.extend([dropoff_coord, to_coord])
        end_teleport_section.begin_date_time = rsj.dropoff_date_time
        end_teleport_section.end_date_time = rsj.dropoff_date_time
        # report value to journey
        pb_rsj.distances.walking += end_teleport_section.length

        # create ticket associated
        ticket = response_pb2.Ticket()
        ticket.id = "ticket_{}".format(six.text_type(generate_id()))
        ticket.name = "ridesharing_price_{}".format(ticket.id)
        ticket.found = True
        ticket.comment = "Ridesharing price for section {}".format(
            rs_section.id)
        ticket.section_id.extend([rs_section.id])
        # also add fare to journey
        ticket.cost.value = rsj.price
        pb_rsj.fare.total.value = ticket.cost.value
        ticket.cost.currency = rsj.currency
        pb_rsj.fare.total.currency = rsj.currency
        pb_rsj.fare.found = True
        pb_rsj.fare.ticket_id.extend([ticket.id])

        pb_tickets.append(ticket)
        pb_rsjs.append(pb_rsj)

    return pb_rsjs, pb_tickets, pb_feed_publishers
Пример #11
0
    def call_kraken(self, request_type, request, instance, krakens_call):
        """
        For all krakens_call, call the kraken and aggregate the responses

        return the list of all responses
        """
        logger = logging.getLogger(__name__)
        logger.debug('datetime: %s', request['datetime'])

        # odt_stop_points is a set of stop_point.uri with is_zonal = true used to manage tad_zonal
        odt_stop_points = set()

        # crowfly_stop_points is a set of stop_point.uri used to create a crowfly section.
        crowfly_stop_points = set()

        if not g.requested_origin:
            g.requested_origin = instance.georef.place(request['origin'])
            if not g.requested_origin:
                r = self._make_error_response(
                    "The entry point: {} is not valid".format(
                        request['origin']), response_pb2.Error.unknown_object)
                return [r]

        if not g.requested_destination:
            g.requested_destination = instance.georef.place(
                request['destination'])
            if not g.requested_destination:
                r = self._make_error_response(
                    "The entry point: {} is not valid".format(
                        request['destination']),
                    response_pb2.Error.unknown_object)
                return [r]

        worker = AsyncWorker(instance, krakens_call, request)

        resp = []

        # Now we compute the direct path with all requested departure
        # mode their time will be used to initialized our PT calls and
        # to bound the fallback duration of the first section.
        futures = worker.get_direct_path_futures(
            g.fallback_direct_path, g.requested_origin,
            g.requested_destination, request['datetime'], request['clockwise'],
            False, {mode
                    for mode, _ in krakens_call})
        for future in gevent.iwait(futures):
            resp_key, resp_direct_path = future.get()
            g.fallback_direct_path[resp_key] = resp_direct_path
            if resp_direct_path.journeys:
                resp_direct_path.journeys[0].internal_id = str(generate_id())
                resp.append(resp_direct_path)

        if request.get('max_duration', 0):
            direct_path_duration_by_mode = make_direct_path_duration_by_mode(
                g.fallback_direct_path)

            # Get all stop_points around the requested origin within a crowfly range
            # Calls on origins and destinations are asynchronous
            orig_futures, dest_futures = worker.get_crowfly_futures(
                g.requested_origin, g.requested_destination,
                direct_path_duration_by_mode)
            gevent.joinall(orig_futures + dest_futures)
            for future in orig_futures:
                g.origins_places_crowfly.update(future.get())
            for future in dest_futures:
                g.destinations_places_crowfly.update(future.get())

            # Once we get crow fly stop points with origins and destinations, we start
            # the computation NM: the fallback matrix which contains the arrival duration for crowfly stop_points
            # from origin/destination
            # Ex:
            #                    stop_point1   stop_point2  stop_point3
            # request_origin_1     86400(s)      43200(s)     21600(s)
            # As a side note this won't work the day when our ETA will be impacted by the datetime of the journey,
            # at least for the arrival when doing a "departure after" request.
            orig_futures, dest_futures = worker.get_routing_matrix_futures(
                g.requested_origin, g.requested_destination,
                g.origins_places_crowfly, g.destinations_places_crowfly,
                direct_path_duration_by_mode)
            gevent.joinall(orig_futures + dest_futures)
            for future in orig_futures:
                g.origins_fallback.update(future.get())
            for future in dest_futures:
                g.destinations_fallback.update(future.get())

            # In Some special cases, like "odt" or "departure(arrive) from(to) a stop_area",
            # the first(last) section should be treated differently
            orig_futures, dest_futures = worker.get_update_crowfly_duration_futures(
            )
            gevent.joinall(orig_futures + dest_futures)

            def _updater(_futures, fb, crowfly_stop_points, odt_stop_points):
                for f in _futures:
                    crowfly_res, odt_res, fb_res = f.get()
                    crowfly_stop_points |= crowfly_res
                    odt_stop_points |= odt_res
                    for mode in (mode for mode in fb_res if mode in fb):
                        fb.merge_reached_values(mode, fb_res[mode])

            _updater(orig_futures, g.origins_fallback, crowfly_stop_points,
                     odt_stop_points)
            _updater(dest_futures, g.destinations_fallback,
                     crowfly_stop_points, odt_stop_points)

            # We update the fallback duration matrix if the requested origin/destination is also
            # present in the fallback duration matrix, which means from stop_point_1 to itself, it takes 0 second
            # Ex:
            #                stop_point1   stop_point2  stop_point3
            # stop_point_1         0(s)       ...          ...
            for dep_mode, arr_mode in krakens_call:
                g.origins_fallback.reset_if_exist(dep_mode,
                                                  g.requested_origin.uri)
                g.destinations_fallback.reset_if_exist(
                    arr_mode, g.requested_destination.uri)

        # Here starts the computation for pt journey
        journey_parameters = create_parameters(request)
        futures = worker.get_pt_journey_futures(g.requested_origin,
                                                g.requested_destination,
                                                g.fallback_direct_path,
                                                g.origins_fallback,
                                                g.destinations_fallback,
                                                journey_parameters)

        response_tuples = []
        for future in gevent.iwait(futures):
            dep_mode, arr_mode, local_resp = future.get()
            if local_resp is None:
                continue
            dp_key = make_direct_path_key(dep_mode, g.requested_origin.uri,
                                          g.requested_destination.uri,
                                          request['datetime'],
                                          request['clockwise'], False)
            direct_path = g.fallback_direct_path.get(dp_key)

            if local_resp.HasField(b"error") and local_resp.error.id == response_pb2.Error.error_id.Value('no_solution') \
                    and direct_path.journeys:
                local_resp.ClearField(b"error")
            if local_resp.HasField(b"error"):
                #Here needs to modify error message of no_solution
                if len(g.origins_fallback[dep_mode]) == 0:
                    self.update_error_message(local_resp,
                                              response_pb2.Error.no_origin,
                                              "no origin point")
                elif len(g.destinations_fallback[arr_mode]) == 0:
                    self.update_error_message(
                        local_resp, response_pb2.Error.no_destination,
                        "no destination point")

                return [local_resp]

            # for log purpose we put and id in each journeys
            for j in local_resp.journeys:
                j.internal_id = str(generate_id())
                response_tuples.append((dep_mode, arr_mode, j))
            resp.append(local_resp)

        # Once the pt journey is found, we need to reconstruct the whole journey with fallback regarding the mode

        # For the sake of performance, we compute at first all fallback direct path asynchronously
        # then we update the pool of direct paths
        futures = worker.get_fallback_direct_path_futures(
            response_tuples, crowfly_stop_points, odt_stop_points)
        for future in gevent.iwait(futures):
            resp_key, resp_direct_path = future.get()
            g.fallback_direct_path[resp_key] = resp_direct_path

        # Now we construct the whole journey by concatenating the fallback direct path with the pt journey
        worker.build_journeys(response_tuples, crowfly_stop_points,
                              odt_stop_points)

        #If resp doesn't contain any response we have to add an error message
        if len(resp) == 0:
            if len(g.origins_fallback[dep_mode]) == 0 and len(
                    g.destinations_fallback[arr_mode]) == 0:
                resp.append(
                    self._make_error_response(
                        "no origin point nor destination point",
                        response_pb2.Error.no_origin_nor_destination))
            elif len(g.origins_fallback[dep_mode]) == 0:
                resp.append(
                    self._make_error_response("no origin point",
                                              response_pb2.Error.no_origin))
            elif len(g.destinations_fallback[arr_mode]) == 0:
                resp.append(
                    self._make_error_response(
                        "no destination point",
                        response_pb2.Error.no_destination))
            return resp
        for r in resp:
            fill_uris(r)
        return resp