def rollback_transaction(self): try: self.session.rollback() except Exception as e: logexc(["DatabaseSession::rollback_transaction() FAILED ..................", "EXCEPTION catched: "], e, "......................................................", True)
def __get_fastest_choices(self, alternative_trips, excluded_modes): fastest = [] try: # TODO: WARNING: //maybe implement using Loops, if deepcopy is CPU hungry # loop1: find the absolute_fastest (skip alts with mainmode = excluded_modes) # loop2: find all fastest (skip alts with mainmode = excluded_modes) # TODO: also research about performance of lambda ... alts = deepcopy(alternative_trips) # exlude modes we don't want in this comparison (e.g. ignore BICYCLE, assuming travelers don't have a bike) alts = filter(lambda x: x.mainmode not in excluded_modes, alts) # sort on alt.duration, to easily get the absolute minimum alts.sort( key=lambda x: x.duration) # now the fastest trip is at top if len(alts) > 0: absolute_fastest = alts[0] # now the fastest is the first one # iterate through all alts, add them to results, as long as trip-duration is within our margin MARGIN = datetime.timedelta( minutes=3) #TODO: make it an inpt cofig value for alt in alts: if alt.duration - absolute_fastest.duration > MARGIN: break else: fastest.append(alt) except Exception as e: logexc("(!) Exception in __get_fastest_choices()", e) except: logexc( "(!) Exception in __get_fastest_choices() UNDEFINED Exception", None) return fastest
def commit_transaction(self): try: self.session.commit() except Exception as e: logexc(["DatabaseSession::commit_transaction() FAILED ..................", "EXCEPTION catched: "], e, "......................................................", True)
def send_http_get(self, apiurl, querystr=None, verify_certificate=False): # Notes for urllib2: # GET request with urllib2: If you do not pass the data argument, urllib2 uses a GET request (you can encode the data in URL itself) # POST request with urllib2: Just as easy as GET, simply passing (encoded) request data as an extra parameter #params = urllib.urlencode(querystr) apiurl_with_query = apiurl params = querystr if params is not None and params != '': apiurl_with_query += "?" + params #log(["params:", params]) #log(["apiurl_with_query:", apiurl_with_query, "verify_certificate:", verify_certificate]) response = None res = False e = None exception_type = "" try: #response = urllib2.urlopen(apiurl_with_query) log(["send_http_get():", apiurl_with_query]) response = requests.get( apiurl_with_query, verify=verify_certificate ) # //TODO: possible security issue! verify=True works from python command line !!!! response.close() if response.status_code == 200: #TODO: does it happen that status_code is NOT CHANGED?? res = True except urllib.error.HTTPError as e: exception_type = "urllib.error.HTTPError" except requests.exceptions.ConnectionError as e: exception_type = "requests.exceptions.ConnectionError" except Exception as e: exception_type = "Exception" finally: pass # TODO, don't like the idea of finally changing program exec and exception raise path (use later, maybe) if res: response_str = response.content elif e is not None: response_str = "(!) EXCEPTION catched (class_type: {}) in WebNetworking::send_http_get(): ".format( exception_type) if response is not None: logexc(response_str, e, [ ", apiurl_with_query: ", apiurl_with_query, ", response content_type:", response.headers['content-type'] ]) else: logexc(response_str, e, [", apiurl_with_query: ", apiurl_with_query]) else: response_str = "! error in send_http_get(), res=False, response.status_code={}".format( response.status_code) loge([ "! error in send_http_get(), res=False, response.status_code=" ], response.status_code) pass #probably http error occured (eg status code != 200) return res, response_str
def _log_exception(self, method_name, qstr, exception): if method_name is None: method_name = "DatabaseCommands::???()" logexc( ">> (!) EXCEPTION catched in {}: DB Command FAILED ......................" .format(method_name), exception, [ ">> qstr:", qstr, "......................................................" ], True)
def __get_trip_comfort(self, trip): trip.comfort = 50 # (%) # traverse all alerts of each leg try: for leg in trip.legs: if 'alerts' in leg and leg['alerts'] is not None: for alert in leg['alerts']: if 'alertHeaderText' in alert and alert['alertHeaderText'] == 'Unpaved surface': #TODO is this even bad in case of 'WALK' or 'BICYCLE'? trip.comfort -= 10 except Exception as e: logexc(["trip:",trip.user_id,"|",trip.device_id,"|",trip.id,"|",trip.plan_id, " - (!) EXCEPTION catched in trip_economics.get_trip_comfort():"], e)
def HttpRequestWithGET(self, apiurl, querystr=None, verify_certificate=False): # Notes for urllib2: # GET request with urllib2: If you do not pass the data argument, urllib2 uses a GET request (you can encode the data in URL itself) # POST request with urllib2: Just as easy as GET, simply passing (encoded) request data as an extra parameter #params = urllib.urlencode(querystr) apiurl_with_query = apiurl params = querystr if params is not None and params != '': apiurl_with_query += "?" + params #log(["params:", params]) #log(["apiurl_with_query:", apiurl_with_query, "verify_certificate:", verify_certificate]) response_data_collection = None res = False e = None exception_type = "" try: #response = urllib2.urlopen(apiurl_with_query) response = requests.get( apiurl_with_query, verify=verify_certificate ) # //TODO: possible security issue! verify=True works from python command line !!!! response_data_collection = json.loads( response.content) # response.content is in JSON format (text) response.close() res = True except urllib.error.HTTPError as e: exception_type = "urllib2.HTTPError" except requests.exceptions.ConnectionError as e: exception_type = "requests.exceptions.ConnectionError" except Exception as e: exception_type = "Exception" finally: pass # TODO, don't like the idea of finally changing program exec and exception raise path (use later, maybe) if not res: response_data_collection = { "error": { "id": 0, "msg": "", "message": "" } } response_data_collection["error"]["message"] = exception_type response_data_collection["error"]["msg"] = str(e) logexc( "(!) EXCEPTION catched (class_type: {}) in HttpRequestWithGET(): " .format(exception_type), e, [", apiurl_with_query: ", apiurl_with_query]) return res, response_data_collection
def __get_lowemission_timerelevant_choices(self, alternative_trips, excluded_modes): bestest = [] try: # TODO: WARNING: //maybe implement using Loops, if deepcopy is CPU hungry # loop1: find the absolute_fastest (skip alts with mainmode = excluded_modes) # loop2: find all bestest (skip alts with mainmode = excluded_modes) # TODO: also research about performance of lambda ... alts = deepcopy(alternative_trips) # exlude modes we don't want in this comparison (e.g. ignore BICYCLE, assuming travelers don't have a bike) alts = filter(lambda x: x.mainmode not in excluded_modes, alts) # find the fastest alternative # alts.sort(key = lambda x: x.duration) # now the fastest trip is at top if len(alts) > 0: absolute_fastest = min(alts, key=lambda x: x.duration) # absolute_fastest = alts[0] # sort on alt.emission alts.sort(key=lambda x: x.emission) # sort on custom emission+activity priority # //TODO IMPORTANT, REVISE IF NEEDED # our order of low-emission and activity is now: {walk, bike, ebike, (tram, metro, train), bus, car, ferry} for alt in alts: alt.lowemission_order = deepcopy( lowEmissionOrder[alt.mainmode]) alts.sort(key=lambda x: x.lowemission_order ) # now the most suitable trip is at top if len(alts) > 0: # iterate through all alts, add them to results, as long as trip-duration is within our margin MARGIN = datetime.timedelta( minutes=3) #TODO: make it an input cofig value for alt in alts: if alt.duration - absolute_fastest.duration <= MARGIN: bestest.append(alt) except Exception as e: logexc("(!) Exception in __get_fastest_choices()", e) except: logexc( "(!) Exception in __get_fastest_choices() UNDEFINED Exception", None) return bestest
def _parse_planning_response(self, response_content_str): res = 0 try: # response content from OTP servers is supposed to be in JSON string format (json text) response_collection = json.loads(response_content_str) # TODO WARNING! dummy test only to regenerate occasional error # raise Exception('No JSON object could be decoded') except Exception as e: # build our own custom collection ---: response_collection = self._make_response_collection( None, self._make_error_collection( 0, "(!) EXCEPTION catched in _parse_planning_response()", str(e))) # response from OTP servers is supposed to be in JSON string format (json text) # ==> therefore this is an exception (unexpected): logexc("(!) EXCEPTION catched in _parse_planning_response(): ", e, response_content_str) else: # (if no exception occured) if 'plan' not in response_collection or \ response_collection['plan'] is None or \ 'itineraries' not in response_collection['plan']: # TODO: what to do? #itineraries_count = len (response_collection['plan']['itineraries']) #if itineraries_count == 0: # raise Ecception("journey planner did NOT return any itineraries!\n") # print "response_collection returned:\n", response_collection, "\n" # print "response_collection error section:\n", response_collection['error'] # build our own custome collection ---: if 'error' not in response_collection or response_collection[ 'error'] is None: response_collection["error"] = self._make_error_collection( 0, "unknown planning error", "no \'plan\' in response, BUT also no \'error\' field") response_collection['plan'] = None else: # everything was OK! res = 1 response_collection['error'] = None return res, response_collection['plan'], response_collection[ 'error'], response_collection
def plan_trip_alternatives(self, trips, min_od_distance, od_d_diff_coeff, desiredModes=MODES_FOR_OTP_PLAN_QUERY): trips_skipped = [] for trip in trips: # filter our very short trips and, # try to filter out the 'badly' detected trips, or 'round-trips', 'walking/running exercise', etc. # (do NOT waste time planning alternatives if not needed) # OLDER CODE commented out: # if trip.od_distance > min_od_distance and trip.distance < od_d_diff_coeff * trip.od_distance: print(">> Computing alternatives for trip ID:", trip.id) #TODO temp for moprim for mode in desiredModes: try: # assumptions, adjusting parameters, related cals, some kinematics, etc.: max_walk_distance = MAX_MODE_DETECTION_DELAY * 2 # e.g. 500m walk to start bus stop ... 500m walk to end bus stop # somehow max_walk_distance is equal to mode-detection-error (transitoin point error) threshold in our system # this could be also max_distance_between_busstops / 2 !! (if we have a detection between two bus stops) # 1000 m (e.g. 500 m walking at each trip end) gives good results for user id 13 ) num_of_itineraries = 3 # default is 3 maxTransfers = 2 # seems like this param didn't have any effect! show_intermediate_stops = "True" # TODO: is there a param 'max waiting time' too? # TODO: IMPORTANT: for PT plans, should this also shift back start-time same as mass_transit_match_planner? # maybe not if it's not important to time-match with the realized trip # query for a trip plan (it either makes a new trip plan (eg. from OTP) or retrieves from cache) res, planned_trips, planning_res = self.planner.plan_a_trip( trip, mode, num_of_itineraries, max_walk_distance, show_intermediate_stops) if res == 1: for planned_trip in planned_trips: planned_trip.plan_id = len( trip.alternative_trips ) + 1 # get next plan_id * trip.alternative_trips.append(planned_trip) # TODO: update the original plan field (later in code trips rows are stored in DB): if planning_res.is_desired_trip_date_shifted: trip.shifted_starttime_for_publictransport_tripplan = planning_res.desired_trip_shifted_starttime if planning_res.desired_trip_shifted_starttime is None: raise Exception( "plan_trip_alternatives(): planning_res.is_desired_trip_date_shifted True, but planning_res.desired_trip_shifted_starttime is None" ) elif res == 0: loge([ "ERROR in plan_trip_alternatives(): trip:", trip.user_id, trip.id, ": mode", mode, ": planning error:", planning_res.to_Text() ]) except Exception as e: logexc([ "(!) EXCEPTION catched in plan_trip_alternatives(): trip:", trip.user_id, trip.id, ": mode", mode, ": Exception:" ], e) # else: # print(">> Skipped computation of alternatives for trip ID:",trip.id,"!") #TODO temp for moprim # trips_skipped.append(trip) return trips_skipped
def plan_trip_alternatives_new(self, trips, desired_modes=MODES_FOR_OTP_PLAN_QUERY): trips_processed = 0 number_of_input_trips = len(trips) # compute alternatives per obsevred trip for trip in trips: trips_processed += 1 print("-------------- trip", trips_processed, "/", number_of_input_trips, ": trip (", trip.user_id, trip.id, ") --------------") for mode in desired_modes: try: # assumptions, adjusting parameters, related cals, some kinematics, etc.: max_walk_distance = MAX_MODE_DETECTION_DELAY * 2 # e.g. 500m walk to start bus stop ... 500m walk to end bus stop # somehow max_walk_distance is equal to mode-detection-error (transitoin point error) threshold in our system # this could be also max_distance_between_busstops / 2 !! (if we have a detection between two bus stops) # 1000 m (e.g. 500 m walking at each trip end) gives good results for user id 13 ) num_of_itineraries = 3 # default is 3 maxTransfers = 2 # seems like this param didn't have any effect! show_intermediate_stops = "True" # TODO: is there a param 'max waiting time' too? # TODO: IMPORTANT: for PT plans, should this also shift back start-time same as mass_transit_match_planner? # maybe not if it's not important to time-match with the realized trip # a few fixes, just in case trip.starttime = trip.starttime.replace(microsecond=0) trip.endtime = trip.endtime.replace(microsecond=0) # query for a trip plan (it either makes a new trip plan (eg. from OTP) or retrieves from cache) res, plan, planning_res = self.planner.plan_a_trip_new( trip, mode, num_of_itineraries, max_walk_distance, show_intermediate_stops) if res == 1: # attach the computed alternative to the observed trip # go through all trip-leg-chains suggested, to build a collection of Trip objects alts_added = 0 plan_id_base = MODES_PLAN_IDS[mode] for itin in plan['itineraries']: planned_trip = Trip() planned_trip.update_from_otp_trip_plan( trip, planning_res.is_desired_trip_date_shifted, plan, itin) # if mode=='PUBLIC_TRANSPORT' and len(planned_trip.legs)==1 and planned_trip.legs[0]['mode']=='WALK': # #print("len(planned_trip.legs):", len(planned_trip.legs)) # #print(planned_trip.legs[0]['mode']) # #logi("plan_trip_alternatives_new():: NOTE!!! planner returned a single WALK leg for PUBLIC_TRANSPORT. Not saving it.") # pass # else: planned_trip.plan_id = plan_id_base + alts_added trip.alternative_trips.append(planned_trip) alts_added += 1 # IMPORTANT: update the original plan field (later in code trips rows are stored in DB): # NOTE: is_desired_trip_date_shifted and the shifted date only apply to PUBLIC_TRANSPORT requested mode # is same for all itins returned by PT OTP query. Therefore, in the 'trips_alts' table, it reperesents all plan_ids of PT alternatives # print("SUCCESS; Planned itin(s) :); ") elif res == 0: loge([ "ERROR in plan_trip_alternatives(): trip (" + str(trip.user_id) + " " + str(trip.id) + ": mode " + mode + ": planning error:" + planning_res.to_Text() ]) # THIS applies only to queries for public transport if planning_res.is_desired_trip_date_shifted and mode == 'PUBLIC_TRANSPORT': print( "TEMP MESSAGE: updating the trip's shifted-date field =", planning_res.desired_trip_shifted_starttime) # update the trip's shifted-date field trip.shifted_starttime_for_publictransport_tripplan = planning_res.desired_trip_shifted_starttime if planning_res.desired_trip_shifted_starttime is None: raise Exception( "plan_trip_alternatives(): planning_res.is_desired_trip_date_shifted True, but planning_res.desired_trip_shifted_starttime is None" ) except Exception as e: logexc([ "(!) EXCEPTION catched in plan_trip_alternatives(): trip:", trip.user_id, trip.id, ": mode", mode, ": Exception:" ], e) return trips
def to_Text(self): try: #return str(self.error_code)+ ", "+ self.error_msg+ ", "+ self.error_message return "{}, {}, {}".format(self.error_code, self.error_message, self.error_msg) except Exception as e: logexc(">> (!) EXCEPTION catched in TripPlanningResult::to_Text(): ", e)