Exemple #1
0
 def display_trip_economics(self, trip):
     print (trip.user_id,"|",trip.id, ",", trip.plan_id, \
           "|", trip.multimodal_summary, \
           "|", DateTime_to_Text(trip.starttime), "to", DateTime_to_Text(trip.endtime), \
           "| from ", pointRow_to_geoText(trip.origin), "--> to", pointRow_to_geoText(trip.destination), \
           "| time:", DateTimeDelta_to_Text(trip.duration), "| cost:", round(trip.cost, 2), round_dict_values(trip.cost_by_mode, 2), \
           "| cals:", int(round(trip.calories)), round_dict_values(trip.calories_by_mode, 0), \
           "| emission:", int(round(trip.emission)), round_dict_values(trip.emission_by_mode, 0), \
           "| comfort:", trip.comfort, "| distance: ", int(round(trip.distance)), round_dict_values(trip.distance_by_mode, 0)
           )
Exemple #2
0
 def display_trip_economics_csv(self, trip):
     print (trip.user_id,"|", trip.device_id,"|", trip.id, "|", trip.plan_id, \
           "|", trip.multimodal_summary, \
           "|", DateTime_to_Text(trip.starttime), "|", DateTime_to_Text(trip.endtime), \
           "|", DateTimeDelta_to_Text(trip.duration), "|", round(trip.cost, 2), \
           "|", int(round(trip.calories)), "|", round(trip.emission/1000.0, 1), \
           "|", trip.comfort, "|", round(trip.distance/1000.0, 1), \
           "||", pointRow_to_geoText(trip.origin), "|", pointRow_to_geoText(trip.destination),\
           "||", round_dict_values(trip.cost_by_mode, 2), "|", round_dict_values(trip.calories_by_mode, 0), \
           "|", round_dict_values(trip.emission_by_mode, 0),"|", round_dict_values(trip.distance_by_mode, 0)
           )
Exemple #3
0
    def _query_a_trip_plan(self, desired_trip, desired_transport_mode,
                           num_of_itineraries, max_walk_distance,
                           show_intermediate_stops):
        log("")
        log(["_query_a_trip_plan::Requesting to OTP journey planner:"])
        log([
            "Input desired_trip:", desired_trip.starttime, ",",
            desired_transport_mode
        ])

        # Send our query to OTP journey planner:
        # Example:
        #   querystr = "fromPlace=60.170718,24.930221&toPlace=60.250214,25.009566&date=2016/4/22&time=17:18:00&numItineraries=3&maxTransfers=3&maxWalkDistance=1500"

        if desired_transport_mode == 'PUBLIC_TRANSPORT' or desired_transport_mode in PublicTransportModesTemplate:
            querystr = """fromPlace={0}&toPlace={1}&date={2}&time={3}&numItineraries={4}&maxWalkDistance={5}&showIntermediateStops={6}""".format(
                pointRow_to_geoText(desired_trip.origin),
                pointRow_to_geoText(desired_trip.destination),
                desired_trip.starttime.date().isoformat(),
                desired_trip.starttime.time().isoformat(), num_of_itineraries,
                max_walk_distance, show_intermediate_stops)
        else:
            querystr = """fromPlace={0}&toPlace={1}&date={2}&time={3}&numItineraries={4}&mode={5}""".format(
                pointRow_to_geoText(desired_trip.origin),
                pointRow_to_geoText(desired_trip.destination),
                desired_trip.starttime.date().isoformat(),
                desired_trip.starttime.time().isoformat(), num_of_itineraries,
                desired_transport_mode)

        webres, response_content_str = self.webnet.send_http_get(
            self.api_url, querystr)

        if type(response_content_str) == bytes:
            response_content_str = response_content_str.decode()

        return self._parse_webnet_response(webres, response_content_str)
Exemple #4
0
    def plan_a_trip_new(self, reference_trip, desired_transport_mode,
                        num_of_itineraries, max_walk_distance,
                        show_intermediate_stops):
        log("")
        log(["plan_a_trip::Input reference trip: ", reference_trip.starttime, \
              ":  from ", pointRow_to_geoText(reference_trip.origin), "--> to", pointRow_to_geoText(reference_trip.destination)])

        desired_trip = deepcopy(
            reference_trip
        )  # keep a copy, in order to not change the input params in the caller's scope

        # query journey planner --------------:
        is_desired_trip_date_shifted = False
        shifted_starttime = None

        plan = None
        res = 0
        error = None
        planning_response = None
        restored_plan = StoredPlanLoadResult()

        if self.config.PLAN_ONLY_WITH_SHIFTED_DATE:
            # shift the old weekday to current week, and call OTP planner again
            logi([
                "plan_a_trip_new() Force shifting date to current week, for trip ("
                + str(desired_trip.user_id) + " " + str(desired_trip.id) +
                ") -" + desired_transport_mode
            ])
            is_desired_trip_date_shifted = True  # ***
            desired_trip_with_shifted_date = self._shift_trip_to_current_week(
                desired_trip)
            shifted_starttime = desired_trip_with_shifted_date.starttime
            res, plan, error, all_response = self._query_a_trip_plan(
                desired_trip_with_shifted_date, desired_transport_mode,
                num_of_itineraries, max_walk_distance, show_intermediate_stops)

            if res == 1:
                #store this 'shifted' trip-plan-response for later use ***
                self._store_planning_result(desired_trip_with_shifted_date,
                                            desired_transport_mode,
                                            num_of_itineraries,
                                            max_walk_distance, all_response)
                logi(["plan_a_trip_new() SUCCESS with shifted time"])
            elif res == 0 and self._has_trip_planning_error(
                    all_response
            ):  # only save errors related to trip planning, OTP and so on (NOT the network, exceptions, own custom etc. errors)
                #store this error trip-plan response for later use ***
                self._store_planning_error(desired_trip_with_shifted_date,
                                           desired_transport_mode,
                                           num_of_itineraries,
                                           max_walk_distance, all_response)

        else:
            # if such OTP plan is (requested and) stored before, just use it!
            if not self.config.RETRY_ON_ALL_STORED_PLANS:
                #TODO important, later, possible BUG: if 'itin_starttime' (planned) differs a bit from the stored 'desired_trip.starttime' (desired) ... some plans may get lost ??!
                # one solution: use the requestedParameters['date'] and ['time'] instead of values from itin ???
                restored_plan = self._restore_a_trip_plan_from_cache(
                    desired_trip, desired_transport_mode, num_of_itineraries,
                    max_walk_distance)
                res = restored_plan.res
                plan = restored_plan.plan
                error = restored_plan.error
                planning_response = restored_plan.planning_response
                is_desired_trip_date_shifted = restored_plan.date_was_shifted_forward
                shifted_starttime = restored_plan.shifted_starttime

            if restored_plan.already_restored_the_shifted_date_plan:
                print(
                    "NOTE: restored_plan.already_restored_the_shifted_date_plan"
                )

            # depending on config flags and other conditions:
            # . if flag set: requery regardless of whether we already have the plan in cache
            # . if not loaded from previous plans
            #   . ....
            # send trip-planning query to OTP server:
            if self.config.RETRY_ON_ALL_STORED_PLANS or \
                (not restored_plan.plan_made_before and \
                     ((not restored_plan.is_otp_error) or (self.config.RETRY_ON_ALL_STORED_OTP_ERRORS) or\
                       (self.config.RETRY_ON_STORED_OTP_ERROR_DATE_TOO_FAR and \
                            (not restored_plan.already_restored_the_shifted_date_plan) and\
                            (restored_plan.error['id'] == OTP_ERROR_CODE_DATE_TOO_FAR\
                             # TODO: NOTE: shifting date to current week only is useful for PT trips ***

                             or (restored_plan.error['id'] == OTP_ERROR_CODE_NO_PATH_POSSIBLE and desired_transport_mode=='PUBLIC_TRANSPORT')
                             )
                        )\
                 )\
                ):

                # TODO: important changes made to the above id condition during moprim (both 404 and 406 errors treated thesame)

                res, plan, error, all_response = self._query_a_trip_plan(
                    desired_trip, desired_transport_mode, num_of_itineraries,
                    max_walk_distance, show_intermediate_stops)
                # TODO: WARNING! dummy test only, to help regenerate the error: ValueError('No JSON object could be decoded',) is not JSON serializable
                #   error['id'] = OTP_ERROR_CODE_DATE_TOO_FAR

                if res == 0 \
                    and (error['id'] == OTP_ERROR_CODE_DATE_TOO_FAR \
                         #TODO: OTP_ERROR_CODE_NO_PATH_POSSIBLE added during MOprim data processing. Both 404 and 406 errors are now somehow synonyms fot PT
                         # TODO: NOTE: shifting date to current week only is useful for PT trips ***


                         or (error['id'] == OTP_ERROR_CODE_NO_PATH_POSSIBLE and desired_transport_mode=='PUBLIC_TRANSPORT')
                        ):
                    # second try (adjust the old weekday to current week) ---------------------
                    #store this 'intermediate' error trip-plan response for later use ***
                    self._store_planning_error(desired_trip,
                                               desired_transport_mode,
                                               num_of_itineraries,
                                               max_walk_distance, all_response)

                    # shift the old weekday to current week, and call OTP planner again
                    logi([
                        "plan_a_trip_new() FAILED for trip (" +
                        str(desired_trip.user_id) + " " +
                        str(desired_trip.id) + ") -" + desired_transport_mode +
                        ": OTP ERROR CODE=" + str(error['id']) +
                        "! => Trying second time with current week..."
                    ])
                    is_desired_trip_date_shifted = True  # ***
                    desired_trip_with_shifted_date = self._shift_trip_to_current_week(
                        desired_trip
                    )  # TODO: function algorithm has changed during Moprim ... probably suitable for other TrafficSense data sources too
                    shifted_starttime = desired_trip_with_shifted_date.starttime

                    res, plan, error, all_response = self._query_a_trip_plan(
                        desired_trip_with_shifted_date, desired_transport_mode,
                        num_of_itineraries, max_walk_distance,
                        show_intermediate_stops)
                    if res == 1:
                        #store this 'shifted' trip-plan-response for later use ***
                        self._store_planning_result(
                            desired_trip_with_shifted_date,
                            desired_transport_mode, num_of_itineraries,
                            max_walk_distance, all_response)
                        log(["plan_a_trip_new() SUCCESS with shifted time"])
                    elif res == 0 and self._has_trip_planning_error(
                            all_response
                    ):  # only save errors related to trip planning, OTP and so on (NOT the network, exceptions, own custom etc. errors)
                        #store this error trip-plan response for later use ***
                        self._store_planning_error(
                            desired_trip_with_shifted_date,
                            desired_transport_mode, num_of_itineraries,
                            max_walk_distance, all_response)
                elif res == 0 and self._has_trip_planning_error(all_response):
                    #store this error trip-plan response for later use ***
                    self._store_planning_error(desired_trip,
                                               desired_transport_mode,
                                               num_of_itineraries,
                                               max_walk_distance, all_response)
                elif res == 1:
                    #store this trip-plan-response for later use ***
                    self._store_planning_result(desired_trip,
                                                desired_transport_mode,
                                                num_of_itineraries,
                                                max_walk_distance,
                                                all_response)

        # summarize after trip planning is done: -------------------
        if res == 1 and (plan is None or 'itineraries' not in plan):
            if plan is not None:
                raise Exception("res == 1 but plan is: {}".format(
                    json.dumps(plan)))
            else:
                raise Exception('res == 1 but plan is None')

        trip_planning_res = TripPlanningResult()
        # TODO: Important change: causes that shifted date is saved in trips_alts DB table, later in code
        if is_desired_trip_date_shifted:
            trip_planning_res.is_desired_trip_date_shifted = is_desired_trip_date_shifted
            trip_planning_res.desired_trip_shifted_starttime = shifted_starttime
        if res == 0:
            if error is not None:
                trip_planning_res.error_code = error['id']
                trip_planning_res.error_msg = error['msg']
                trip_planning_res.error_message = error['message']
                return 0, None, trip_planning_res
            else:
                return 0, None, trip_planning_res
        elif res == 1:
            return 1, plan, trip_planning_res
Exemple #5
0
    def plan_a_trip(self, reference_trip, desired_transport_mode,
                    num_of_itineraries, max_walk_distance,
                    show_intermediate_stops):
        log("")
        log(["plan_a_trip::Input reference trip: ", reference_trip.starttime, \
              ":  from ", pointRow_to_geoText(reference_trip.origin), "--> to", pointRow_to_geoText(reference_trip.destination)])

        desired_trip = deepcopy(
            reference_trip
        )  # keep a copy, in order to not change the input params in the caller's scope
        desired_trip.starttime = desired_trip.starttime.replace(microsecond=0)
        desired_trip.endtime = desired_trip.endtime.replace(microsecond=0)

        # query journey planner --------------:
        is_desired_trip_date_shifted = False
        shifted_starttime = None

        plan = None
        res = 0
        error = None
        planning_response = None
        restored_plan = StoredPlanLoadResult()

        # if such OTP plan is (requested and) stored before, just use it!
        if not self.config.RETRY_ON_ALL_STORED_PLANS:
            #TODO important, later, possible BUG: if 'itin_starttime' (planned) differs a bit from the stored 'desired_trip.starttime' (desired) ... some plans may get lost ??!
            # one solution: use the requestedParameters['date'] and ['time'] instead of values from itin ???
            restored_plan = self._restore_a_trip_plan_from_cache(
                desired_trip, desired_transport_mode, num_of_itineraries,
                max_walk_distance)
            res = restored_plan.res
            plan = restored_plan.plan
            error = restored_plan.error
            planning_response = restored_plan.planning_response
            is_desired_trip_date_shifted = restored_plan.date_was_shifted_forward
            shifted_starttime = restored_plan.shifted_starttime

        # depending on config flags and other conditions:
        # . if flag set: requery regardless of whether we already have the plan in cache
        # . if not loaded from previous plans
        #   . ....
        # send trip-planning query to OTP server:
        if self.config.RETRY_ON_ALL_STORED_PLANS or \
            (not restored_plan.plan_made_before and \
             ((not restored_plan.is_otp_error) or \
              (self.config.RETRY_ON_ALL_STORED_OTP_ERRORS) or\
              (self.config.RETRY_ON_STORED_OTP_ERROR_DATE_TOO_FAR and \
               (restored_plan.error['id'] == OTP_ERROR_CODE_DATE_TOO_FAR or restored_plan.error['id'] == OTP_ERROR_CODE_NO_PATH_POSSIBLE))\
             )\
            ):
            # TODO: important changes made to the above id condition during moprim (both 404 and 406 errors treated thesame)

            res, plan, error, all_response = self._query_a_trip_plan(
                desired_trip, desired_transport_mode, num_of_itineraries,
                max_walk_distance, show_intermediate_stops)
            # TODO: WARNING! dummy test only, to help regenerate the error: ValueError('No JSON object could be decoded',) is not JSON serializable
            #   error['id'] = OTP_ERROR_CODE_DATE_TOO_FAR

            if res == 0 \
                and (error['id'] == OTP_ERROR_CODE_DATE_TOO_FAR \
                     or error['id'] == OTP_ERROR_CODE_NO_PATH_POSSIBLE): #TODO: OTP_ERROR_CODE_NO_PATH_POSSIBLE added during MOprim data processing. Both 404 and 406 errors are now somehow synonyms
                # second try (adjust the old weekday to current week)
                #store this 'intermediate' error trip-plan response for later use ***
                self._store_planning_error(desired_trip,
                                           desired_transport_mode,
                                           num_of_itineraries,
                                           max_walk_distance, all_response)

                # shift the old weekday to current week, and call OTP planner again
                logi([
                    "plan_a_trip():: FAILED for trip (" +
                    str(desired_trip.user_id) + " " + str(desired_trip.id) +
                    ") -" + desired_transport_mode + ": OTP error code=",
                    error['id'] +
                    "; Trying a second time with shifted date to current week..."
                ])
                is_desired_trip_date_shifted = True  # ***
                desired_trip_with_shifted_date = self._shift_trip_to_current_week(
                    desired_trip
                )  # TODO: function algorithm has changed during Moprim ... probably suitable for other TrafficSense data sources too
                shifted_starttime = desired_trip_with_shifted_date.starttime
                #               OLD CODE:
                #                desired_trip_with_shifted_date = deepcopy(desired_trip)
                #                desired_trip_with_shifted_date.starttime = self.find_same_journey_time_this_week(desired_trip.starttime)
                #                desired_trip_with_shifted_date.endtime = self.find_same_journey_time_this_week(desired_trip.endtime)
                res, plan, error, all_response = self._query_a_trip_plan(
                    desired_trip_with_shifted_date, desired_transport_mode,
                    num_of_itineraries, max_walk_distance,
                    show_intermediate_stops)
                if res == 1:
                    #store this 'shifted' trip-plan-response for later use ***
                    self._store_planning_result(desired_trip_with_shifted_date,
                                                desired_transport_mode,
                                                num_of_itineraries,
                                                max_walk_distance,
                                                all_response)
                    log(["plan_a_trip() SUCCESS with shifted time"])
                elif res == 0 and self._has_trip_planning_error(
                        all_response
                ):  # only save errors related to trip planning, OTP and so on (NOT the network, exceptions, own custom etc. errors)
                    #store this error trip-plan response for later use ***
                    self._store_planning_error(desired_trip_with_shifted_date,
                                               desired_transport_mode,
                                               num_of_itineraries,
                                               max_walk_distance, all_response)
            elif res == 0 and self._has_trip_planning_error(all_response):
                #store this error trip-plan response for later use ***
                self._store_planning_error(desired_trip,
                                           desired_transport_mode,
                                           num_of_itineraries,
                                           max_walk_distance, all_response)
            elif res == 1:
                #store this trip-plan-response for later use ***
                self._store_planning_result(desired_trip,
                                            desired_transport_mode,
                                            num_of_itineraries,
                                            max_walk_distance, all_response)

        # summarize after trip planning is done: -------------------
        if res == 1 and (plan is None or 'itineraries' not in plan):
            if plan is not None:
                raise Exception("res == 1 but plan is: {}".format(
                    json.dumps(plan)))
            else:
                raise Exception('res == 1 but plan is None')

        trip_planning_res = TripPlanningResult()
        if res == 0:
            if error is not None:
                trip_planning_res.error_code = error['id']
                trip_planning_res.error_msg = error['msg']
                trip_planning_res.error_message = error['message']
                return 0, None, trip_planning_res
            else:
                return 0, None, trip_planning_res
        elif res == 1:
            if is_desired_trip_date_shifted:
                trip_planning_res.is_desired_trip_date_shifted = is_desired_trip_date_shifted
                trip_planning_res.desired_trip_shifted_starttime = shifted_starttime

        # build trip objects to return to caller: --------------------------
        # go through all trip-leg-chains suggested, to build a collection of Trip objects, and return it :
        log("")
        log([
            "Working on the itins (routes) suggested by otp journey planner ...:"
        ])
        itin_index = 0
        matchcount = 0
        plannedmatches = []  # TODO: choose which returned trip?
        # e.g. when 3 public transport trips are returned * order based on what?
        trips = []

        for itin in plan['itineraries']:
            trip = Trip()
            trip.update_from_otp_trip_plan(desired_trip,
                                           is_desired_trip_date_shifted, plan,
                                           itin)

            # TODO: WARNING!! unit/integrate test.
            # Is the diff in 'trips_alts' table because of following change?! ******************
            #            trip.user_id = desired_trip.user_id
            #            trip.device_id = desired_trip.device_id
            #            trip.id = desired_trip.id
            #            itin_starttime = OTPTimeStampToNormalDateTime(itin['startTime'])
            #            itin_endtime = OTPTimeStampToNormalDateTime(itin['endTime'])
            #            # trip.shifted_starttime_for_publictransport_tripplan = itin_starttime # no need to use this field for alternative plans? (plan_id > 0)
            #            if is_desired_trip_date_shifted:
            #                trip.starttime = shift_time_to_specific_date(itin_starttime,  desired_trip.starttime) # TODO: NOTE: starttime of plan may differ from desired trip start-time (???)
            #                trip.endtime = shift_time_to_specific_date(itin_endtime,  desired_trip.endtime)
            #            else:
            #                trip.starttime = itin_starttime # TODO: NOTE: starttime.time()/endtime of planned itinerary may differ *a bit* from desired trip start-time.time/endtime (???)
            #                trip.endtime = itin_endtime
            #            trip.origin = geoLoc_to_pointRow(plan['from']['lat'], plan['from']['lon']) # TODO: are there cases where plan's origin{lat,lon} differ a bit from desired trip origin?!
            #            trip.destination = geoLoc_to_pointRow(plan['to']['lat'], plan['to']['lon']) # TODO: are there cases where plan's destination{lat,lon} differ a bit from desired trip destination?!
            #            # trip.legs = itin['legs'] #TODO remove old code?
            #            trip.append_otp_legs(itin['legs'],  is_desired_trip_date_shifted, desired_trip.starttime,  desired_trip.endtime)

            trips.append(trip)

        return 1, trips, trip_planning_res