diff --git a/modules/course.py b/modules/course.py index 24ed013c..e320d69c 100644 --- a/modules/course.py +++ b/modules/course.py @@ -641,95 +641,104 @@ def modify_course_points(self): len_dist = len(self.distance) len_alt = len(self.altitude) - # calculate course point distance - if not len_pnt_dist and len_dist: - course_points.distance = np.empty(len_pnt_lat) - if not len_pnt_alt and len_alt: - course_points.altitude = np.zeros(len_pnt_lat) - - min_index = 0 - for i in range(len_pnt_lat): - b_a_x = self.points_diff[0][min_index:] - b_a_y = self.points_diff[1][min_index:] - lon_diff = course_points.longitude[i] - self.longitude[min_index:] - lat_diff = course_points.latitude[i] - self.latitude[min_index:] - p_a_x = lon_diff[:-1] - p_a_y = lat_diff[:-1] - inner_p = ( - b_a_x * p_a_x + b_a_y * p_a_y - ) / self.points_diff_sum_of_squares[min_index:] - inner_p_check = np.where( - (0.0 <= inner_p) & (inner_p <= 1.0), True, False - ) - - min_j = None - min_dist_diff_h = np.inf - min_dist_delta = 0 - min_alt_delta = 0 - for j in list(*np.where(inner_p_check == True)): - h_lon = ( - self.longitude[min_index + j] - + ( - self.longitude[min_index + j + 1] - - self.longitude[min_index + j] - ) - * inner_p[j] - ) - h_lat = ( - self.latitude[min_index + j] - + ( - self.latitude[min_index + j + 1] - - self.latitude[min_index + j] - ) - * inner_p[j] - ) - dist_diff_h = get_dist_on_earth( - h_lon, - h_lat, - course_points.longitude[i], - course_points.latitude[i], + # calculate course point distance/altitude if not both already set + # If one is already set, it's not going to be overwritten + # But if both are already set there's no need to recalculate anything + if not len_pnt_dist or not len_pnt_alt: + if not len_pnt_dist and len_dist: + course_points.distance = np.empty(len_pnt_lat) + if not len_pnt_alt and len_alt: + course_points.altitude = np.zeros(len_pnt_lat) + + min_index = 0 + + for i in range(len_pnt_lat): + b_a_x = self.points_diff[0][min_index:] + b_a_y = self.points_diff[1][min_index:] + lon_diff = course_points.longitude[i] - self.longitude[min_index:] + lat_diff = course_points.latitude[i] - self.latitude[min_index:] + p_a_x = lon_diff[:-1] + p_a_y = lat_diff[:-1] + inner_p = ( + b_a_x * p_a_x + b_a_y * p_a_y + ) / self.points_diff_sum_of_squares[min_index:] + inner_p_check = np.where( + (0.0 <= inner_p) & (inner_p <= 1.0), True, False ) - if ( - dist_diff_h < self.config.G_GPS_ON_ROUTE_CUTOFF - and dist_diff_h < min_dist_diff_h - ): - if min_j is not None and j - min_j > 2: - continue - min_j = j - min_dist_diff_h = dist_diff_h - min_dist_delta = ( - get_dist_on_earth( - self.longitude[min_index + j], - self.latitude[min_index + j], - h_lon, - h_lat, + min_j = None + min_dist_diff_h = np.inf + min_dist_delta = 0 + min_alt_delta = 0 + + for j in list(*np.where(inner_p_check == True)): + h_lon = ( + self.longitude[min_index + j] + + ( + self.longitude[min_index + j + 1] + - self.longitude[min_index + j] ) - / 1000 + * inner_p[j] ) - if len_alt: - min_alt_delta = ( - ( - self.altitude[min_index + j + 1] - - self.altitude[min_index + j] - ) - / ( - self.distance[min_index + j + 1] - - self.distance[min_index + j] + h_lat = ( + self.latitude[min_index + j] + + ( + self.latitude[min_index + j + 1] + - self.latitude[min_index + j] + ) + * inner_p[j] + ) + dist_diff_h = get_dist_on_earth( + h_lon, + h_lat, + course_points.longitude[i], + course_points.latitude[i], + ) + + if ( + dist_diff_h < self.config.G_GPS_ON_ROUTE_CUTOFF + and dist_diff_h < min_dist_diff_h + ): + if min_j is not None and j - min_j > 2: + continue + + min_j = j + min_dist_diff_h = dist_diff_h + min_dist_delta = ( + get_dist_on_earth( + self.longitude[min_index + j], + self.latitude[min_index + j], + h_lon, + h_lat, ) - * min_dist_delta + / 1000 ) + if len_alt: + min_alt_delta = ( + ( + self.altitude[min_index + j + 1] + - self.altitude[min_index + j] + ) + / ( + self.distance[min_index + j + 1] + - self.distance[min_index + j] + ) + * min_dist_delta + ) - if min_j is None: - min_j = 0 - min_index = min_index + min_j + if min_j is None: + min_j = 0 - if not len_pnt_dist and len_dist: - course_points.distance[i] = ( - self.distance[min_index] + min_dist_delta - ) - if not len_pnt_alt and len_alt: - course_points.altitude[i] = self.altitude[min_index] + min_alt_delta + min_index = min_index + min_j + + if not len_pnt_dist and len_dist: + course_points.distance[i] = ( + self.distance[min_index] + min_dist_delta + ) + if not len_pnt_alt and len_alt: + course_points.altitude[i] = ( + self.altitude[min_index] + min_alt_delta + ) # add climb tops # if len(self.climb_segment): @@ -755,6 +764,9 @@ def modify_course_points(self): # TODO do not use float and course_points.distance[0] != 0.0 ): + app_logger.info( + f"Missing start of the course point, first value is {course_points.distance[0]}, inserting" + ) course_points.name = np.insert(course_points.name, 0, "Start") course_points.latitude = np.insert( course_points.latitude, 0, self.latitude[0] @@ -770,6 +782,7 @@ def modify_course_points(self): course_points.altitude = np.insert( course_points.altitude, 0, self.altitude[0] ) + # add end course point end_distance = None if len(self.latitude) and len(course_points.longitude): @@ -786,6 +799,9 @@ def modify_course_points(self): and end_distance is not None and end_distance > 5 ): + app_logger.info( + f"Missing end of the course point last distance is {end_distance}, inserting" + ) course_points.name = np.append(course_points.name, "End") course_points.latitude = np.append( course_points.latitude, self.latitude[-1] diff --git a/modules/helper/api.py b/modules/helper/api.py index 02dfe097..9dfb2b3a 100644 --- a/modules/helper/api.py +++ b/modules/helper/api.py @@ -564,13 +564,13 @@ async def send_livetrack_data_internal(self, quick_send=False): await asyncio.sleep(5) self.bt_cmd_lock = False app_logger.error( - f"[BT] {timestamp_str} connect error, network status: {detect_network()}" + f"[BT] {timestamp_str} connect error, network status: {bool(detect_network())}" ) self.config.logger.sensor.values["integrated"]["send_time"] = ( datetime.datetime.now().strftime("%H:%M") + "CE" ) return - # print("[BT] {} connect, network status:{} {}".format(timestamp_str, detect_network(), count)) + # print(f"[BT] {timestamp_str} connect, network status:{bool(detect_network())} {count}") await asyncio.sleep(5) diff --git a/modules/helper/network.py b/modules/helper/network.py index 0cbf37bb..1de5176c 100644 --- a/modules/helper/network.py +++ b/modules/helper/network.py @@ -175,12 +175,15 @@ async def download_maptile( additional_save_paths = [] max_zoom_cond = True + if ( "max_zoomlevel" in map_config[map_name] and z + 1 >= map_config[map_name]["max_zoomlevel"] ): max_zoom_cond = False + min_zoom_cond = True + if ( "min_zoomlevel" in map_config[map_name] and z - 1 <= map_config[map_name]["min_zoomlevel"] @@ -243,6 +246,7 @@ async def download_maptile( async def download_demtile(self, z, x, y): if not detect_network(): return False + try: os.makedirs( f"maptile/{self.config.G_DEM_MAP}/{z}/{x}/", diff --git a/modules/loaders/tcx.py b/modules/loaders/tcx.py index 979721eb..0e6a26e8 100644 --- a/modules/loaders/tcx.py +++ b/modules/loaders/tcx.py @@ -16,10 +16,12 @@ "longitude": re.compile(r"(?P[^<]*)"), "altitude": re.compile(r"(?P[^<]*)"), "distance": re.compile(r"(?P[^<]*)"), + "time": re.compile(r""), "course_point": re.compile(r"(?P[\s\S]+)"), "course_name": re.compile(r"(?P[^<]*)"), "course_point_type": re.compile(r"(?P[^<]*)"), "course_notes": re.compile(r"(?P[^<]*)"), + "course_time": re.compile(r""), } @@ -39,8 +41,9 @@ def load_file(cls, file): "longitude": None, "altitude": None, "distance": None, + "time": None, } - course_points = defaultdict(list) + course_points = defaultdict(lambda: np.array([])) with open(file, "r", encoding="utf-8_sig") as f: tcx = f.read() @@ -82,6 +85,9 @@ def load_file(cls, file): for m in patterns["distance"].finditer(track) ] ) + course["time"] = np.array( + [m.group("text").strip() for m in patterns["time"].finditer(track)] + ) match_course_point = patterns["course_point"].search(tcx) @@ -117,6 +123,12 @@ def load_file(cls, file): for m in patterns["course_notes"].finditer(course_point) ] ) + course_points["time"] = np.array( + [ + m.group("text").strip() + for m in patterns["course_time"].finditer(course_point) + ] + ) valid_course = True if len(course["latitude"]) != len(course["longitude"]): @@ -145,7 +157,7 @@ def load_file(cls, file): course["altitude"] = np.array([]) course["latitude"] = np.array([]) course["longitude"] = np.array([]) - course_points = defaultdict(lambda x: np.array([])) + course_points = defaultdict(lambda: np.array([])) else: # delete 'Straight' from course points if len(course_points["type"]): @@ -156,4 +168,45 @@ def load_file(cls, file): for key in ["name", "latitude", "longitude", "notes", "type"]: course_points[key] = course_points[key][not_straight_cond] + # if time is given in the field, try to set the course point distance/altitude directly from there + # if a point can not be found, let's fail and modify_course_point will try to compute it instead + if ( + course["time"] is not None + and len(course["time"]) + and len(course_points["time"]) + ): + distance_error = False + altitude_error = False + + for point_time in course_points["time"]: + try: + index = np.where(course["time"] == point_time)[0][0] + except Exception: # noqa + # Point time not found in trackpoint reset and break + course_points.distance = np.array([]) + course_points.altitude = np.array([]) + break + if not distance_error: + try: + # course_point distance is set in [km] + course_points["distance"] = np.append( + course_points["distance"], course["distance"][index] / 1000 + ) + except IndexError: + distance_error = True + course_points.distance = np.array([]) + if not altitude_error: + try: + # course_point altitude is set in [m] + course_points["altitude"] = np.append( + course_points["altitude"], course["altitude"][index] + ) + except IndexError: + altitude_error = True + course_points.altitude = np.array([]) + + # do not keep these in memory + del course["time"] + del course_points["time"] + return course, course_points diff --git a/modules/pyqt/graph/pyqt_map.py b/modules/pyqt/graph/pyqt_map.py index 2f872b9a..02c73d59 100644 --- a/modules/pyqt/graph/pyqt_map.py +++ b/modules/pyqt/graph/pyqt_map.py @@ -946,7 +946,7 @@ def get_image_file(self, use_mbtiles, map_name, z_draw, x, y): else: sql = ( f"select tile_data from tiles where " - f"zoom_level={z_draw} and tile_column={x} and tile_row={2 ** z_draw - 1 - y}" + f"zoom_level={z_draw} and tile_column={x} and tile_row={2**z_draw - 1 - y}" ) img_file = io.BytesIO((self.cur.execute(sql).fetchone())[0]) return img_file diff --git a/tests/data/tcx/Heart_of_St._Johns_Peninsula_Ride-CP-Removed.tcx b/tests/data/tcx/Heart_of_St._Johns_Peninsula_Ride-CP-Removed.tcx new file mode 100644 index 00000000..204fc946 --- /dev/null +++ b/tests/data/tcx/Heart_of_St._Johns_Peninsula_Ride-CP-Removed.tcx @@ -0,0 +1,1848 @@ + + + + + + + Heart-of-St--Jo + + + + + + + Heart-of-St--Jo + + 184 + 12286.5 + + 45.57873 + -122.71318 + + + 45.5788 + -122.7135 + + Active + + + + + + 45.57873 + -122.71318 + + 45.8 + 0 + + + + + 45.5787199 + -122.71328 + + 45.8 + 7.871 + + + + + 45.57868 + -122.71339 + + 45.7 + 17.529 + + + + + 45.5787199 + -122.7135 + + 45.6 + 27.187 + + + + + 45.57811 + -122.7135 + + 46.0 + 95.092 + + + + + 45.57741 + -122.7135 + + 46.5 + 173.015 + + + + + 45.57671 + -122.71351 + + 47.6 + 250.942 + + + + + 45.576 + -122.71351 + + 48.2 + 329.978 + + + + + 45.5753 + -122.71351 + + 48.5 + 407.902 + + + + + 45.57529 + -122.71384 + + 48.6 + 433.639 + + + + + 45.57523 + -122.7146 + + 48.8 + 493.234 + + + + + 45.5751 + -122.71539 + + 49.0 + 556.469 + + + + + 45.57497 + -122.71618 + + 49.2 + 619.704 + + + + + 45.57502 + -122.71586 + + 49.2 + 645.253 + + + + + 45.57484 + -122.71689 + + 49.5 + 727.974 + + + + + 45.57466 + -122.71793 + + 49.8 + 811.452 + + + + + 45.57452 + -122.71857 + + 49.9 + 863.7 + + + + + 45.57436 + -122.71909 + + 50.1 + 907.961 + + + + + 45.5741299 + -122.71974 + + 50.3 + 964.714 + + + + + 45.57389 + -122.72039 + + 50.5 + 1021.977 + + + + + 45.57344 + -122.72135 + + 50.8 + 1112.006 + + + + + 45.57341 + -122.72156 + + 50.9 + 1128.707 + + + + + 45.57345 + -122.72178 + + 50.8 + 1146.419 + + + + + 45.57349 + -122.72193 + + 50.5 + 1158.927 + + + + + 45.57388 + -122.72298 + + 49.4 + 1251.55 + + + + + 45.57427 + -122.72404 + + 49.1 + 1344.861 + + + + + 45.57466 + -122.72509 + + 48.9 + 1437.484 + + + + + 45.57504 + -122.72615 + + 48.5 + 1530.282 + + + + + 45.57543 + -122.7272 + + 48.6 + 1622.903 + + + + + 45.57582 + -122.72826 + + 48.8 + 1716.212 + + + + + 45.57621 + -122.72931 + + 48.8 + 1808.833 + + + + + 45.5766 + -122.73037 + + 48.7 + 1902.141 + + + + + 45.57696 + -122.73136 + + 48.5 + 1989.069 + + + + + 45.57733 + -122.73235 + + 48.3 + 2076.514 + + + + + 45.5777 + -122.73334 + + 48.0 + 2163.96 + + + + + 45.57781 + -122.73353 + + 48.0 + 2183.172 + + + + + 45.57831 + -122.73411 + + 47.7 + 2254.867 + + + + + 45.57881 + -122.73469 + + 47.6 + 2326.562 + + + + + 45.57931 + -122.73528 + + 47.5 + 2398.751 + + + + + 45.57943 + -122.73546 + + 47.4 + 2418.119 + + + + + 45.57975 + -122.73644 + + 47.5 + 2502.376 + + + + + 45.58008 + -122.73741 + + 47.7 + 2586.407 + + + + + 45.58022 + -122.7378 + + 47.8 + 2620.556 + + + + + 45.58071 + -122.73887 + + 47.4 + 2720.182 + + + + + 45.58079 + -122.73901 + + 47.4 + 2734.264 + + + + + 45.58111 + -122.73934 + + 47.4 + 2778.195 + + + + + 45.58142 + -122.73965 + + 47.5 + 2820.317 + + + + + 45.58182 + -122.73994 + + 47.6 + 2870.249 + + + + + 45.58194 + -122.74007 + + 47.5902082 + 2887.012 + + + + + 45.582 + -122.74016 + + 47.5845519 + 2896.696 + + + + + 45.58206 + -122.74033 + + 47.5758876 + 2911.53 + + + + + 45.5823899 + -122.74147 + + 47.5197473 + 3007.645 + + + + + 45.5824 + -122.74162 + + 47.5128904 + 3019.384 + + + + + 45.58237 + -122.7419 + + 47.5 + 3041.453 + + + + + 45.58236 + -122.74211 + + 47.5 + 3057.852 + + + + + 45.58237 + -122.74228 + + 47.5 + 3071.144 + + + + + 45.58242 + -122.74255 + + 47.5 + 3092.903 + + + + + 45.58249 + -122.74277 + + 47.3 + 3111.732 + + + + + 45.5826 + -122.74299 + + 47.4 + 3132.797 + + + + + 45.58292 + -122.7436 + + 47.2 + 3192.19 + + + + + 45.58349 + -122.74417 + + 46.9 + 3269.638 + + + + + 45.58364 + -122.74434 + + 46.8 + 3290.951 + + + + + 45.58376 + -122.74455 + + 46.6 + 3312.072 + + + + + 45.58391 + -122.74496 + + 46.8 + 3348.116 + + + + + 45.58428 + -122.7461 + + 47.1 + 3446.016 + + + + + 45.58465 + -122.74724 + + 47.3 + 3543.916 + + + + + 45.58502 + -122.74838 + + 47.3 + 3641.816 + + + + + 45.5853899 + -122.74951 + + 47.1 + 3739.009 + + + + + 45.58576 + -122.75065 + + 46.4 + 3836.907 + + + + + 45.58613 + -122.75179 + + 46.0 + 3934.805 + + + + + 45.5864199 + -122.75274 + + 45.6 + 4015.549 + + + + + 45.5867099 + -122.75368 + + 44.1 + 4095.579 + + + + + 45.587 + -122.75463 + + 39.8 + 4176.322 + + + + + 45.58722 + -122.75527 + + 38.0 + 4231.87 + + + + + 45.58743 + -122.75591 + + 36.5 + 4286.937 + + + + + 45.5877399 + -122.75625 + + 34.4 + 4330.439 + + + + + 45.5878299 + -122.75631 + + 34.7 + 4341.494 + + + + + 45.58838 + -122.75684 + + 36.4 + 4415.34 + + + + + 45.5891 + -122.75755 + + 37.7 + 4512.722 + + + + + 45.58983 + -122.75825 + + 38.4 + 4610.585 + + + + + 45.59055 + -122.75895 + + 38.1 + 4707.525 + + + + + 45.59128 + -122.75965 + + 38.3 + 4805.388 + + + + + 45.592 + -122.76036 + + 38.1 + 4902.767 + + + + + 45.59273 + -122.76106 + + 37.5 + 5000.629 + + + + + 45.59345 + -122.76176 + + 37.8 + 5097.568 + + + + + 45.59418 + -122.76247 + + 37.7 + 5195.864 + + + + + 45.59473 + -122.763 + + 37.4 + 5269.708 + + + + + 45.59528 + -122.76353 + + 37.2 + 5343.551 + + + + + 45.5959999 + -122.76413 + + 36.7 + 5436.331 + + + + + 45.59672 + -122.76473 + + 36.3 + 5529.111 + + + + + 45.59699 + -122.76406 + + 35.9 + 5589.334 + + + + + 45.59739 + -122.76308 + + 34.6 + 5677.704 + + + + + 45.59779 + -122.76209 + + 33.7 + 5766.747 + + + + + 45.59809 + -122.76131 + + 34.1 + 5836.074 + + + + + 45.5985 + -122.76032 + + 33.3 + 5925.678 + + + + + 45.59892 + -122.75933 + + 32.3 + 6015.854 + + + + + 45.59937 + -122.7596 + + 31.7 + 6070.182 + + + + + 45.60002 + -122.76 + + 31.0 + 6148.961 + + + + + 45.6006799 + -122.7604 + + 30.5 + 6228.764 + + + + + 45.60133 + -122.76079 + + 29.6 + 6307.238 + + + + + 45.60198 + -122.76118 + + 28.7 + 6385.713 + + + + + 45.60221 + -122.76064 + + 28.6 + 6434.95 + + + + + 45.6025 + -122.75994 + + 28.3 + 6498.309 + + + + + 45.6028 + -122.75924 + + 27.0 + 6562.241 + + + + + 45.60204 + -122.75878 + + 28.9 + 6654.117 + + + + + 45.60127 + -122.75832 + + 29.4 + 6747.018 + + + + + 45.6004999 + -122.75785 + + 29.8 + 6840.223 + + + + + 45.59972 + -122.75738 + + 30.7 + 6934.453 + + + + + 45.59895 + -122.75692 + + 31.4 + 7027.355 + + + + + 45.59818 + -122.75645 + + 31.6 + 7120.56 + + + + + 45.59811 + -122.75662 + + 31.9 + 7135.924 + + + + + 45.59763 + -122.75616 + + 32.7 + 7200.257 + + + + + 45.59714 + -122.7557 + + 33.7 + 7265.518 + + + + + 45.59651 + -122.75508 + + 34.6 + 7350.668 + + + + + 45.59588 + -122.75447 + + 35.3 + 7435.378 + + + + + 45.59526 + -122.75386 + + 36.5 + 7519.17 + + + + + 45.59499 + -122.7536 + + 36.8 + 7555.412 + + + + + 45.59495 + -122.75347 + + 36.9 + 7566.474 + + + + + 45.59467 + -122.75243 + + 37.3 + 7653.272 + + + + + 45.5944 + -122.75139 + + 37.9 + 7739.677 + + + + + 45.5941199 + -122.75034 + + 37.8 + 7827.204 + + + + + 45.59384 + -122.7493 + + 38.5 + 7914.003 + + + + + 45.59359 + -122.74825 + + 38.8 + 8000.397 + + + + + 45.59334 + -122.7472 + + 38.6 + 8086.792 + + + + + 45.5931 + -122.74615 + + 38.6 + 8172.834 + + + + + 45.59285 + -122.74509 + + 38.6 + 8259.967 + + + + + 45.5926 + -122.74404 + + 38.8 + 8346.362 + + + + + 45.5923299 + -122.7429 + + 39.1 + 8440.113 + + + + + 45.5920599 + -122.74177 + + 38.8 + 8533.126 + + + + + 45.59179 + -122.74063 + + 38.2 + 8626.877 + + + + + 45.59153 + -122.7395 + + 38.0 + 8719.538 + + + + + 45.59126 + -122.73836 + + 37.8 + 8813.289 + + + + + 45.59138 + -122.73827 + + 37.5 + 8828.376 + + + + + 45.59144 + -122.73815 + + 37.3 + 8839.864 + + + + + 45.59173 + -122.73702 + + 35.8 + 8933.621 + + + + + 45.59202 + -122.7359 + + 34.0 + 9026.647 + + + + + 45.59231 + -122.73478 + + 32.7 + 9119.672 + + + + + 45.59257 + -122.73374 + + 31.2 + 9205.699 + + + + + 45.59284 + -122.73269 + + 30.2 + 9292.838 + + + + + 45.59264 + -122.73192 + + 30.4 + 9356.816 + + + + + 45.59244 + -122.73114 + + 30.6 + 9421.526 + + + + + 45.59222 + -122.73026 + + 30.5 + 9494.318 + + + + + 45.592 + -122.72939 + + 30.1756975 + 9566.377 + + + + + 45.59187 + -122.72888 + + 29.9854119 + 9608.658 + + + + + 45.59184 + -122.72886 + + 29.9688272 + 9612.343 + + + + + 45.59181 + -122.72875 + + 29.9274386 + 9621.54 + + + + + 45.59172 + -122.72841 + + 29.8 + 9649.856 + + + + + 45.59174 + -122.72833 + + 29.7 + 9656.474 + + + + + 45.59171 + -122.72821 + + 30.0 + 9666.4 + + + + + 45.5915 + -122.72825 + + 31.1 + 9689.984 + + + + + 45.59072 + -122.72824 + + 32.8 + 9776.816 + + + + + 45.58988 + -122.72823 + + 35.2 + 9870.327 + + + + + 45.58903 + -122.72823 + + 36.5 + 9964.948 + + + + + 45.58819 + -122.72822 + + 38.1 + 10058.459 + + + + + 45.58735 + -122.72822 + + 39.1 + 10151.967 + + + + + 45.5865 + -122.72821 + + 40.9 + 10246.591 + + + + + 45.58643 + -122.72825 + + 41.0 + 10254.984 + + + + + 45.58644 + -122.72788 + + 40.5 + 10283.83 + + + + + 45.58645 + -122.72663 + + 39.6 + 10381.217 + + + + + 45.58643 + -122.72646 + + 39.6 + 10394.647 + + + + + 45.58653 + -122.72639 + + 39.4 + 10407.042 + + + + + 45.58654 + -122.72533 + + 38.7 + 10489.629 + + + + + 45.58655 + -122.72427 + + 38.3 + 10572.215 + + + + + 45.58656 + -122.72321 + + 38.0 + 10654.801 + + + + + 45.58657 + -122.72215 + + 37.1 + 10737.387 + + + + + 45.58658 + -122.72109 + + 36.5 + 10819.973 + + + + + 45.58658 + -122.721 + + 36.5 + 10826.985 + + + + + 45.58659 + -122.71983 + + 35.8 + 10918.139 + + + + + 45.5866 + -122.71866 + + 34.4 + 11009.294 + + + + + 45.58661 + -122.7175 + + 34.0 + 11099.67 + + + + + 45.58662 + -122.71633 + + 33.4 + 11190.825 + + + + + 45.58662 + -122.71537 + + 32.9 + 11265.613 + + + + + 45.58662 + -122.7144 + + 32.2 + 11341.18 + + + + + 45.58662 + -122.71344 + + 31.1 + 11415.968 + + + + + 45.58603 + -122.71344 + + 32.5 + 11481.646 + + + + + 45.58545 + -122.71344 + + 33.9 + 11546.211 + + + + + 45.58462 + -122.71344 + + 36.5 + 11638.606 + + + + + 45.58379 + -122.71345 + + 38.2 + 11731.004 + + + + + 45.58296 + -122.71346 + + 39.8 + 11823.402 + + + + + 45.58213 + -122.71347 + + 40.7 + 11915.8 + + + + + 45.58129 + -122.71347 + + 42.6 + 12009.308 + + + + + 45.58046 + -122.71348 + + 43.7 + 12101.706 + + + + + 45.57963 + -122.71349 + + 44.6 + 12194.103 + + + + + 45.5788 + -122.7135 + + 45.5 + 12286.501 + + + + North Lomb + + + 45.57868 + -122.71339 + + Right + Turn right onto North Lombard Street + + + Sharp Nort + + + 45.5787199 + -122.7135 + + Left + Turn sharp left onto North Woolsey Avenue + + + North Will + + + 45.5753 + -122.71351 + + Right + Turn right onto North Willamette Boulevard + + + Sharp Nort + + + 45.57502 + -122.71586 + + Left + Turn sharp left onto North Willamette Boulevard + + + North Reno + + + 45.59672 + -122.76473 + + Right + Turn right onto North Reno Avenue + + + North Cent + + + 45.59892 + -122.75933 + + Left + Turn left onto North Central Street + + + North Bruc + + + 45.60198 + -122.76118 + + Right + Turn right onto North Bruce Avenue + + + North Smit + + + 45.6028 + -122.75924 + + Right + Turn right onto North Smith Street + + + North Sain + + + 45.59818 + -122.75645 + + Right + Turn right onto North Saint Johns Avenue + + + North Smit + + + 45.59811 + -122.75662 + + Left + Turn left onto North Smith Street + + + North Colu + + + 45.59126 + -122.73836 + + Left + Turn left onto North Columbia Way + + + North Wall + + + 45.59171 + -122.72821 + + Right + Turn right onto North Wall Avenue + + + Sharp Nort + + + 45.58643 + -122.72825 + + Left + Turn sharp left onto North Houghton Street + + + North McKe + + + 45.58643 + -122.72646 + + Left + Turn left onto North McKenna Avenue + + + North Houg + + + 45.58653 + -122.72639 + + Right + Turn right onto North Houghton Street + + + North Wool + + + 45.58662 + -122.71344 + + Right + Turn right onto North Woolsey Avenue + + + + diff --git a/tests/test_course.py b/tests/test_course.py new file mode 100644 index 00000000..36956bd5 --- /dev/null +++ b/tests/test_course.py @@ -0,0 +1,89 @@ +import unittest +from tempfile import NamedTemporaryFile + +from modules.course import Course + + +class Config: + G_COURSE_INDEXING = False + G_COURSE_FILE_PATH = None + + G_GPS_KEEP_ON_COURSE_CUTOFF = 60 + + # for search point on course + G_GPS_ON_ROUTE_CUTOFF = 50 # [m] #generate from course + G_GPS_SEARCH_RANGE = 6 # [km] #100km/h -> 27.7m/s + G_GPS_AZIMUTH_CUTOFF = 60 # degree(30/45/90): 0~G_GPS_AZIMUTH_CUTOFF, (360-G_GPS_AZIMUTH_CUTOFF)~G_GPS_AZIMUTH_CUTOFF + + # Graph color by slope + G_CLIMB_DISTANCE_CUTOFF = 0.3 # [km] + G_CLIMB_GRADE_CUTOFF = 2 # [%] + G_SLOPE_CUTOFF = (1, 3, 6, 9, 12, float("inf")) # by grade + G_SLOPE_COLOR = ( + (128, 128, 128), # gray(base) + (0, 255, 0), # green + (255, 255, 0), # yellow + (255, 128, 0), # orange + (255, 0, 0), # red + (128, 0, 0), # dark red + ) + G_CLIMB_CATEGORY = [ + {"volume": 8000, "name": "Cat4"}, + {"volume": 16000, "name": "Cat3"}, + {"volume": 32000, "name": "Cat2"}, + {"volume": 64000, "name": "Cat1"}, + {"volume": 80000, "name": "HC"}, + ] + + G_THINGSBOARD_API = {"STATUS": False} + + def __init__(self, indexing=False): + self.G_COURSE_INDEXING = indexing + self.G_COURSE_FILE_PATH = NamedTemporaryFile().name + + +class TestCourse(unittest.TestCase): + # TODO find/create a file where time is not set so distance is kept empty with no_indexing + # def test_load_no_indexing(self): + # config = Config() + # course = Course(config) + # course.load(file="tests/data/tcx/Heart_of_St._Johns_Peninsula_Ride.tcx") + # + # # downsampled from 184 to 31 points + # self.assertEqual(len(course.latitude), 31) + # self.assertEqual(len(course.course_points.latitude), 18) + # + # # distance was not set since there's no indexing + # self.assertEqual(len(course.course_points.distance), 0) + # + # self.assertEqual(len(course.colored_altitude), 31) + + def test_load_with_tcx_indexing(self): + config = Config(indexing=True) + course = Course(config) + course.load(file="tests/data/tcx/Heart_of_St._Johns_Peninsula_Ride.tcx") + + # downsampled from 184 to 31 points + self.assertEqual(len(course.latitude), 31) + self.assertEqual(len(course.course_points.latitude), 18) + self.assertEqual(len(course.course_points.distance), 18) + + def test_load_insert_course_point(self): + config = Config(indexing=True) + course = Course(config) + course.load( + file="tests/data/tcx/Heart_of_St._Johns_Peninsula_Ride-CP-Removed.tcx" + ) + + self.assertEqual(len(course.course_points.latitude), 18) + self.assertEqual(len(course.course_points.distance), 18) + + self.assertEqual(course.course_points.name[0], "Start") + self.assertEqual(course.course_points.latitude[0], 45.57873) + self.assertEqual(course.course_points.longitude[0], -122.71318) + self.assertEqual(course.course_points.distance[0], 0.0) + + self.assertEqual(course.course_points.name[-1], "End") + self.assertEqual(course.course_points.latitude[-1], 45.5788) + self.assertEqual(course.course_points.longitude[-1], -122.7135) + self.assertEqual(course.course_points.distance[-1], 12.286501) diff --git a/tests/test_loader.py b/tests/test_loader.py index 543ce1ea..5f48705b 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -10,3 +10,6 @@ def test_tcx(self): ) self.assertEqual(len(data_course["latitude"]), 946) self.assertEqual(len(data_course_points["latitude"]), 42) + + # validate that course_point distance was set correctly + self.assertTrue(len(data_course_points["distance"]))