From 94fa735d5448264b850c2945aa0473c2238dd342 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Sat, 20 Jul 2024 23:16:35 +0200 Subject: [PATCH 1/7] cleaned up backend to use classes and yaml files --- backend/src/landmarks_manager.py | 546 +++++++++-------- backend/src/optimizer.py | 570 ++++++++++++++++++ backend/src/optimizer_v4.py | 446 -------------- .../src/parameters/landmark_parameters.yaml | 8 +- backend/src/refiner.py | 496 +++++++++------ backend/src/structs/landmarks.py | 6 +- backend/src/structs/preferences.py | 2 +- backend/src/tester.py | 55 +- backend/src/utils.py | 106 ++++ 9 files changed, 1300 insertions(+), 935 deletions(-) create mode 100644 backend/src/optimizer.py delete mode 100644 backend/src/optimizer_v4.py create mode 100644 backend/src/utils.py diff --git a/backend/src/landmarks_manager.py b/backend/src/landmarks_manager.py index 9d4ce9b..53fa012 100644 --- a/backend/src/landmarks_manager.py +++ b/backend/src/landmarks_manager.py @@ -1,308 +1,326 @@ import math as m -import json, os +import yaml +import logging -from typing import List, Tuple, Optional +from typing import List, Tuple from OSMPythonTools.overpass import Overpass, overpassQueryBuilder +from OSMPythonTools import cachingStrategy from pywikibot import ItemPage, Site from pywikibot import config config.put_throttle = 0 config.maxlag = 0 -from structs.landmarks import Landmark, LandmarkType from structs.preferences import Preferences, Preference +from structs.landmarks import Landmark +from utils import take_most_important +import constants -SIGHTSEEING = LandmarkType(landmark_type='sightseeing') -NATURE = LandmarkType(landmark_type='nature') -SHOPPING = LandmarkType(landmark_type='shopping') +SIGHTSEEING = 'sightseeing' +NATURE = 'nature' +SHOPPING = 'shopping' -# Include the json here -# Create a list of all things to visit given some preferences and a city. Ready for the optimizer -def generate_landmarks(preferences: Preferences, coordinates: Tuple[float, float]) : - l_sights, l_nature, l_shop = get_amenities() - L = [] +class LandmarkManager: - # List for sightseeing - if preferences.sightseeing.score != 0 : - L1 = get_landmarks(l_sights, SIGHTSEEING, coordinates=coordinates) - correct_score(L1, preferences.sightseeing) - L += L1 - - # List for nature - if preferences.nature.score != 0 : - L2 = get_landmarks(l_nature, NATURE, coordinates=coordinates) - correct_score(L2, preferences.nature) - L += L2 - - # List for shopping - if preferences.shopping.score != 0 : - L3 = get_landmarks(l_shop, SHOPPING, coordinates=coordinates) - correct_score(L3, preferences.shopping) - L += L3 + logger = logging.getLogger(__name__) - L = remove_duplicates(L) + city_bbox_side: int # bbox side in meters + radius_close_to: int # radius in meters + church_coeff: float # coeff to adjsut score of churches + park_coeff: float # coeff to adjust score of parks + tag_coeff: float # coeff to adjust weight of tags + N_important: int # number of important landmarks to consider - return L, take_most_important(L) + preferences: Preferences # preferences of visit + location: Tuple[float] # coordinates around which to find a path + def __init__(self, preferences: Preferences, coordinates: Tuple[float, float]) -> None: -# Helper function to gather the amenities list -def get_amenities() -> List[List[str]] : - - # Get the list of amenities from the files - sightseeing = get_list('/amenities/sightseeing.am') - nature = get_list('/amenities/nature.am') - shopping = get_list('/amenities/shopping.am') + with constants.AMENITY_SELECTORS_PATH.open('r') as f: + self.amenity_selectors = yaml.safe_load(f) - return sightseeing, nature, shopping - - -# Helper function to read a .am file and generate the corresponding list -def get_list(path: str) -> List[str] : - - with open(os.path.dirname(os.path.abspath(__file__)) + path) as f : - content = f.readlines() - - amenities = [] - for line in content : - if not line.startswith('#') : - amenities.append(line.strip('\n')) - - return amenities - - -# Take the most important landmarks from the list -def take_most_important(L: List[Landmark], N = 0) -> List[Landmark] : - - # Read the parameters from the file - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/landmarks_manager.params', "r") as f : - parameters = json.loads(f.read()) - N_important = parameters['N important'] - - L_copy = [] - L_clean = [] - scores = [0]*len(L) - names = [] - name_id = {} - - for i, elem in enumerate(L) : - if elem.name not in names : - names.append(elem.name) - name_id[elem.name] = [i] - L_copy.append(elem) - else : - name_id[elem.name] += [i] - scores = [] - for j in name_id[elem.name] : - scores.append(L[j].attractiveness) - best_id = max(range(len(scores)), key=scores.__getitem__) - t = name_id[elem.name][best_id] - if t == i : - for old in L_copy : - if old.name == elem.name : - old.attractiveness = L[t].attractiveness - - scores = [0]*len(L_copy) - for i, elem in enumerate(L_copy) : - scores[i] = elem.attractiveness - - res = sorted(range(len(scores)), key = lambda sub: scores[sub])[-(N_important-N):] - - for i, elem in enumerate(L_copy) : - if i in res : - L_clean.append(elem) - - return L_clean - - -# Remove duplicate elements and elements with low score -def remove_duplicates(L: List[Landmark]) -> List[Landmark] : - """ - Removes duplicate landmarks based on their names from the given list. - - Parameters: - L (List[Landmark]): A list of Landmark objects. - - Returns: - List[Landmark]: A list of unique Landmark objects based on their names. - """ - - L_clean = [] - names = [] - - for landmark in L : - if landmark.name in names: - continue - - - else : - names.append(landmark.name) - L_clean.append(landmark) - - return L_clean - - -# Correct the score of a list of landmarks by taking into account preference settings -def correct_score(L: List[Landmark], preference: Preference) : - - if len(L) == 0 : - return - - if L[0].type != preference.type : - raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {L[0].name}") - - for elem in L : - elem.attractiveness = int(elem.attractiveness*preference.score/5) # arbitrary computation - - -# Function to count elements within a certain radius of a location -def count_elements_within_radius(coordinates: Tuple[float, float], radius: int) -> int: - - lat = coordinates[0] - lon = coordinates[1] - - alpha = (180*radius)/(6371000*m.pi) - bbox = {'latLower':lat-alpha,'lonLower':lon-alpha,'latHigher':lat+alpha,'lonHigher': lon+alpha} + with constants.LANDMARK_PARAMETERS_PATH.open('r') as f: + parameters = yaml.safe_load(f) + self.city_bbox_side = parameters['city_bbox_side'] + self.radius_close_to = parameters['radius_close_to'] + self.church_coeff = parameters['church_coeff'] + self.park_coeff = parameters['park_coeff'] + self.tag_coeff = parameters['tag_coeff'] + self.N_important = parameters['N_important'] - # Build the query to find elements within the radius - radius_query = overpassQueryBuilder(bbox=[bbox['latLower'],bbox['lonLower'],bbox['latHigher'],bbox['lonHigher']], - elementType=['node', 'way', 'relation']) - - try : - overpass = Overpass() - radius_result = overpass.query(radius_query) - N_elem = radius_result.countWays() + radius_result.countRelations() - #print(f"There are {N_elem} ways/relations within 50m") - if N_elem is None : - return 0 - return N_elem - - except : - return 0 + self.preferences = preferences + self.location = coordinates -# Creates a bounding box around given coordinates, side_length in meters -def create_bbox(coordinates: Tuple[float, float], side_length: int) -> Tuple[float, float, float, float]: - - lat = coordinates[0] - lon = coordinates[1] + def generate_landmarks_list(self) -> Tuple[List[Landmark], List[Landmark]] : + """ + Generate and prioritize a list of landmarks based on user preferences. - # Half the side length in km (since it's a square bbox) - half_side_length_km = side_length / 2 / 1000 + This method fetches landmarks from various categories (sightseeing, nature, shopping) based on the user's preferences + and current location. It scores and corrects these landmarks, removes duplicates, and then selects the most important + landmarks based on a predefined criterion. - # Convert distance to degrees - lat_diff = half_side_length_km / 111 # 1 degree latitude is approximately 111 km - lon_diff = half_side_length_km / (111 * m.cos(m.radians(lat))) # Adjust for longitude based on latitude + Returns: + Tuple[List[Landmark], List[Landmark]]: + - A list of all existing landmarks. + - A list of the most important landmarks based on the user's preferences. + """ - # Calculate bbox - min_lat = lat - lat_diff - max_lat = lat + lat_diff - min_lon = lon - lon_diff - max_lon = lon + lon_diff + L = [] - return min_lat, min_lon, max_lat, max_lon - - -def get_landmarks(list_amenity: list, landmarktype: LandmarkType, coordinates: Tuple[float, float]) -> List[Landmark] : - - # Read the parameters from the file - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/landmarks_manager.params', "r") as f : - parameters = json.loads(f.read()) - tag_coeff = parameters['tag coeff'] - park_coeff = parameters['park coeff'] - church_coeff = parameters['church coeff'] - radius = parameters['radius close to'] - bbox_side = parameters['city bbox side'] - - # Create bbox around start location - bbox = create_bbox(coordinates, bbox_side) - - # Initialize some variables - N = 0 - L = [] - overpass = Overpass() - - for amenity in list_amenity : - query = overpassQueryBuilder(bbox=bbox, elementType=['way', 'relation'], selector=amenity, includeCenter=True, out='body') - result = overpass.query(query) - N += result.countElements() - - for elem in result.elements(): - - name = elem.tag('name') # Add name - location = (elem.centerLat(), elem.centerLon()) # Add coordinates (lat, lon) - - # skip if unprecise location - if name is None or location[0] is None: - continue - - # skip if unused - if 'disused:leisure' in elem.tags().keys(): - continue - - # skip if part of another building - if 'building:part' in elem.tags().keys() and elem.tag('building:part') == 'yes': - continue + # List for sightseeing + if self.preferences.sightseeing.score != 0 : + L1 = self.fetch_landmarks(self.amenity_selectors['sightseeing'], SIGHTSEEING, coordinates=self.location) + self.correct_score(L1, self.preferences.sightseeing) + L += L1 + # List for nature + if self.preferences.nature.score != 0 : + L2 = self.fetch_landmarks(self.amenity_selectors['nature'], NATURE, coordinates=self.location) + self.correct_score(L2, self.preferences.nature) + L += L2 + + # List for shopping + if self.preferences.shopping.score != 0 : + L3 = self.fetch_landmarks(self.amenity_selectors['shopping'], SHOPPING, coordinates=self.location) + self.correct_score(L3, self.preferences.shopping) + L += L3 + + L = self.remove_duplicates(L) + + return L, take_most_important(L, self.N_important) + + + def remove_duplicates(self, landmarks: List[Landmark]) -> List[Landmark] : + """ + Removes duplicate landmarks based on their names from the given list. Only retains the landmark with highest score + + Parameters: + landmarks (List[Landmark]): A list of Landmark objects. + + Returns: + List[Landmark]: A list of unique Landmark objects based on their names. + """ + + L_clean = [] + names = [] + + for landmark in landmarks : + if landmark.name in names: + continue else : - osm_type = elem.type() # Add type : 'way' or 'relation' - osm_id = elem.id() # Add OSM id - elem_type = landmarktype # Add the landmark type as 'sightseeing, - n_tags = len(elem.tags().keys()) # Add number of tags + names.append(landmark.name) + L_clean.append(landmark) + + return L_clean + - # remove specific tags - skip = False - for tag in elem.tags().keys() : - if "pay" in tag : - n_tags -= 1 # discard payment options for tags + def correct_score(self, landmarks: List[Landmark], preference: Preference) : + """ + Adjust the attractiveness score of each landmark in the list based on user preferences. - if "disused" in tag : - skip = True # skip disused amenities - break + This method updates the attractiveness of each landmark by scaling it according to the user's preference score. + The score adjustment is computed using a simple linear transformation based on the preference score. - if "wikipedia" in tag : - n_tags += 3 # wikipedia entries count more + Args: + landmarks (List[Landmark]): A list of landmarks whose scores need to be corrected. + preference (Preference): The user's preference settings that influence the attractiveness score adjustment. - if tag == "wikidata" : - Q = elem.tag('wikidata') - site = Site("wikidata", "wikidata") - item = ItemPage(site, Q) - item.get() - n_languages = len(item.labels) - n_tags += n_languages/10 + Raises: + TypeError: If the type of any landmark in the list does not match the expected type in the preference. + """ - if elem_type != LandmarkType(landmark_type="nature") : - if "leisure" in tag and elem.tag('leisure') == "park": - elem_type = LandmarkType(landmark_type="nature") + if len(landmarks) == 0 : + return + + if landmarks[0].type != preference.type : + raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {landmarks[0].name}") - if amenity not in ["'shop'='department_store'", "'shop'='mall'"] : - if "shop" in tag : - skip = True - break + for elem in landmarks : + elem.attractiveness = int(elem.attractiveness*preference.score/5) # arbitrary computation - if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']: - skip = True - break - if skip: + def count_elements_close_to(self, coordinates: Tuple[float, float]) -> int: + """ + Count the number of OpenStreetMap elements (nodes, ways, relations) within a specified radius of the given location. + + This function constructs a bounding box around the specified coordinates based on the radius. It then queries + OpenStreetMap data to count the number of elements within that bounding box. + + Args: + coordinates (Tuple[float, float]): The latitude and longitude of the location to search around. + + Returns: + int: The number of elements (nodes, ways, relations) within the specified radius. Returns 0 if no elements + are found or if an error occurs during the query. + """ + + lat = coordinates[0] + lon = coordinates[1] + + radius = self.radius_close_to + + alpha = (180*radius) / (6371000*m.pi) + bbox = {'latLower':lat-alpha,'lonLower':lon-alpha,'latHigher':lat+alpha,'lonHigher': lon+alpha} + + # Build the query to find elements within the radius + radius_query = overpassQueryBuilder(bbox=[bbox['latLower'],bbox['lonLower'],bbox['latHigher'],bbox['lonHigher']], + elementType=['node', 'way', 'relation']) + + try : + overpass = Overpass() + radius_result = overpass.query(radius_query) + N_elem = radius_result.countWays() + radius_result.countRelations() + #print(f"There are {N_elem} ways/relations within 50m") + if N_elem is None : + return 0 + return N_elem + except : + return 0 + + + def create_bbox(self, coordinates: Tuple[float, float]) -> Tuple[float, float, float, float]: + """ + Create a bounding box around the given coordinates. + + Args: + coordinates (Tuple[float, float]): The latitude and longitude of the center of the bounding box. + + Returns: + Tuple[float, float, float, float]: The minimum latitude, minimum longitude, maximum latitude, and maximum longitude + defining the bounding box. + """ + + lat = coordinates[0] + lon = coordinates[1] + + # Half the side length in km (since it's a square bbox) + half_side_length_km = self.city_bbox_side / 2 / 1000 + + # Convert distance to degrees + lat_diff = half_side_length_km / 111 # 1 degree latitude is approximately 111 km + lon_diff = half_side_length_km / (111 * m.cos(m.radians(lat))) # Adjust for longitude based on latitude + + # Calculate bbox + min_lat = lat - lat_diff + max_lat = lat + lat_diff + min_lon = lon - lon_diff + max_lon = lon + lon_diff + + return min_lat, min_lon, max_lat, max_lon + + + def fetch_landmarks(self, list_amenity: list, landmarktype: str, coordinates: Tuple[float, float]) -> List[Landmark] : + """ + Fetches landmarks of a specified type from OpenStreetMap (OSM) within a bounding box centered on given coordinates. + + Args: + list_amenity (list): A list of OSM amenity queries to be used for fetching landmarks. + These queries are typically used to filter results (e.g., [''amenity'='place_of_worship']). + landmarktype (str): The type of the landmark (e.g., 'sightseeing', 'nature', 'shopping'). + coordinates (Tuple[float, float]): The central coordinates (latitude, longitude) for the bounding box. + + Returns: + List[Landmark]: A list of Landmark objects that were fetched and filtered based on the provided criteria. + + Notes: + - The bounding box is created around the given coordinates with a side length defined by `self.city_bbox_side`. + - Landmarks are fetched using Overpass API queries. + - Landmarks are filtered based on various conditions including tags and type. + - Scores are assigned to landmarks based on their attributes and surrounding elements. + """ + + # Create bbox around start location + bbox = self.create_bbox(coordinates) + + # Initialize some variables + N = 0 + L = [] + overpass = Overpass() + + for amenity in list_amenity : + query = overpassQueryBuilder(bbox=bbox, elementType=['way', 'relation'], selector=amenity, includeCenter=True, out='body') + result = overpass.query(query) + N += result.countElements() + + for elem in result.elements(): + + name = elem.tag('name') # Add name + location = (elem.centerLat(), elem.centerLon()) # Add coordinates (lat, lon) + + # skip if unprecise location + if name is None or location[0] is None: continue - # Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT - if amenity == "'amenity'='place_of_worship'" : - #score = int((count_elements_within_radius(location, radius) + (n_tags*tag_coeff) )*church_coeff) - score = int((count_elements_within_radius(location, radius) + ((n_tags**1.2)*tag_coeff) )*church_coeff) - elif amenity == "'leisure'='park'" : - score = int((count_elements_within_radius(location, radius) + ((n_tags**1.2)*tag_coeff) )*park_coeff) + # skip if unused + if 'disused:leisure' in elem.tags().keys(): + continue + + # skip if part of another building + if 'building:part' in elem.tags().keys() and elem.tag('building:part') == 'yes': + continue + else : - score = int(count_elements_within_radius(location, radius) + ((n_tags**1.2)*tag_coeff)) + osm_type = elem.type() # Add type : 'way' or 'relation' + osm_id = elem.id() # Add OSM id + elem_type = landmarktype # Add the landmark type as 'sightseeing, + n_tags = len(elem.tags().keys()) # Add number of tags - if score is not None : - # Generate the landmark and append it to the list - #print(f"There are {n_tags} tags on this Landmark. Total score : {score}\n") - landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=int(n_tags)) - L.append(landmark) + # remove specific tags + skip = False + for tag in elem.tags().keys() : + if "pay" in tag : + n_tags -= 1 # discard payment options for tags - return L + if "disused" in tag : + skip = True # skip disused amenities + break + + if "wikipedia" in tag : + n_tags += 3 # wikipedia entries count more + + if tag == "wikidata" : + Q = elem.tag('wikidata') + site = Site("wikidata", "wikidata") + item = ItemPage(site, Q) + item.get() + n_languages = len(item.labels) + n_tags += n_languages/10 + + if elem_type != "nature" : + if "leisure" in tag and elem.tag('leisure') == "park": + elem_type = "nature" + + if amenity not in ["'shop'='department_store'", "'shop'='mall'"] : + if "shop" in tag : + skip = True + break + + if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']: + skip = True + break + + if skip: + continue + + # Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT + if amenity == "'amenity'='place_of_worship'" : + #score = int((count_elements_close_to(location, radius) + (n_tags*tag_coeff) )*church_coeff) + score = int((self.count_elements_close_to(location) + ((n_tags**1.2)*self.tag_coeff) )*self.church_coeff) + elif amenity == "'leisure'='park'" : + score = int((self.count_elements_close_to(location) + ((n_tags**1.2)*self.tag_coeff) )*self.park_coeff) + else : + score = int(self.count_elements_close_to(location) + ((n_tags**1.2)*self.tag_coeff)) + + if score is not None : + + # Generate the landmark and append it to the list + #print(f"There are {n_tags} tags on this Landmark. Total score : {score}\n") + landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=int(n_tags)) + L.append(landmark) + + return L diff --git a/backend/src/optimizer.py b/backend/src/optimizer.py new file mode 100644 index 0000000..6e52de1 --- /dev/null +++ b/backend/src/optimizer.py @@ -0,0 +1,570 @@ +import yaml, logging +import numpy as np + +from typing import List, Tuple +from scipy.optimize import linprog +from collections import defaultdict, deque +from geopy.distance import geodesic + +from structs.landmarks import Landmark +import constants + + + + + +class Optimizer: + + logger = logging.getLogger(__name__) + + landmarks: List[Landmark] # list of landmarks + max_time: int = None # max visit time (in minutes) + detour: int = None # accepted max detour time (in minutes) + detour_factor: float # detour factor of straight line vs real distance in cities + average_walking_speed: float # average walking speed of adult + max_landmarks: int # max number of landmarks to visit + + + def __init__(self, max_time: int, landmarks: List[Landmark]) : + self.max_time = max_time + self.landmarks = landmarks + + # load parameters from file + with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: + parameters = yaml.safe_load(f) + self.detour_factor = parameters['detour_factor'] + self.average_walking_speed = parameters['average_walking_speed'] + self.max_landmarks = parameters['max_landmarks'] + + + def print_res(self, L: List[Landmark]): + """ + Print the suggested order of landmarks to visit and log the total time walked. + + Args: + L (List[Landmark]): List of landmarks in the suggested visit order. + """ + + self.logger.info(f'The following order is suggested : ') + dist = 0 + for elem in L : + if elem.time_to_reach_next is not None : + print('- ' + elem.name + ', time to reach next = ' + str(elem.time_to_reach_next)) + dist += elem.time_to_reach_next + else : + print('- ' + elem.name) + self.logger.info(f'Minutes walked : {dist}') + self.logger.info(f'Visited {len(L)-2} landmarks') + + + # Prevent the use of a particular solution + def prevent_config(self, resx): + """ + Prevent the use of a particular solution by adding constraints to the optimization. + + Args: + resx (List[float]): List of edge weights. + + Returns: + Tuple[List[int], List[int]]: A tuple containing a new row for constraint matrix and new value for upper bound vector. + """ + + for i, elem in enumerate(resx): + resx[i] = round(elem) + + N = len(resx) # Number of edges + L = int(np.sqrt(N)) # Number of landmarks + + nonzeroind = np.nonzero(resx)[0] # the return is a little funky so I use the [0] + nonzero_tup = np.unravel_index(nonzeroind, (L,L)) + + ind_a = nonzero_tup[0].tolist() + vertices_visited = ind_a + vertices_visited.remove(0) + + ones = [1]*L + h = [0]*N + for i in range(L) : + if i in vertices_visited : + h[i*L:i*L+L] = ones + + return h, [len(vertices_visited)-1] + + + # Prevents the creation of the same circle (both directions) + def prevent_circle(self, circle_vertices: list, L: int) : + """ + Prevent circular paths by by adding constraints to the optimization. + + Args: + circle_vertices (list): List of vertices forming a circle. + L (int): Number of landmarks. + + Returns: + Tuple[np.ndarray, List[int]]: A tuple containing a new row for constraint matrix and new value for upper bound vector. + """ + + l1 = [0]*L*L + l2 = [0]*L*L + for i, node in enumerate(circle_vertices[:-1]) : + next = circle_vertices[i+1] + + l1[node*L + next] = 1 + l2[next*L + node] = 1 + + s = circle_vertices[0] + g = circle_vertices[-1] + + l1[g*L + s] = 1 + l2[s*L + g] = 1 + + return np.vstack((l1, l2)), [0, 0] + + + def is_connected(self, resx) : + """ + Determine the order of visits and detect any circular paths in the given configuration. + + Args: + resx (list): List of edge weights. + + Returns: + Tuple[List[int], Optional[List[List[int]]]]: A tuple containing the visit order and a list of any detected circles. + """ + + # first round the results to have only 0-1 values + for i, elem in enumerate(resx): + resx[i] = round(elem) + + N = len(resx) # length of res + L = int(np.sqrt(N)) # number of landmarks. CAST INTO INT but should not be a problem because N = L**2 by def. + + nonzeroind = np.nonzero(resx)[0] # the return is a little funny so I use the [0] + nonzero_tup = np.unravel_index(nonzeroind, (L,L)) + + ind_a = nonzero_tup[0].tolist() + ind_b = nonzero_tup[1].tolist() + + # Step 1: Create a graph representation + graph = defaultdict(list) + for a, b in zip(ind_a, ind_b): + graph[a].append(b) + + # Step 2: Function to perform BFS/DFS to extract journeys + def get_journey(start): + journey_nodes = [] + visited = set() + stack = deque([start]) + + while stack: + node = stack.pop() + if node not in visited: + visited.add(node) + journey_nodes.append(node) + for neighbor in graph[node]: + if neighbor not in visited: + stack.append(neighbor) + + return journey_nodes + + # Step 3: Extract all journeys + all_journeys_nodes = [] + visited_nodes = set() + + for node in ind_a: + if node not in visited_nodes: + journey_nodes = get_journey(node) + all_journeys_nodes.append(journey_nodes) + visited_nodes.update(journey_nodes) + + for l in all_journeys_nodes : + if 0 in l : + order = l + all_journeys_nodes.remove(l) + break + + if len(all_journeys_nodes) == 0 : + return order, None + + return order, all_journeys_nodes + + + def get_time(self, p1: Tuple[float, float], p2: Tuple[float, float]) -> int : + """ + Calculate the time in minutes to travel from one location to another. + + Args: + p1 (Tuple[float, float]): Coordinates of the starting location. + p2 (Tuple[float, float]): Coordinates of the destination. + + Returns: + int: Time to travel from p1 to p2 in minutes. + """ + + # Compute the straight-line distance in km + if p1 == p2 : + return 0 + else: + dist = geodesic(p1, p2).kilometers + + # Consider the detour factor for average cityto deterline walking distance (in km) + walk_dist = dist*self.detour_factor + + # Time to walk this distance (in minutes) + walk_time = walk_dist/self.average_walking_speed*60 + + return round(walk_time) + + + def init_ub_dist(self, landmarks: List[Landmark], max_steps: int): + """ + Initialize the objective function coefficients and inequality constraints for the optimization problem. + + This function computes the distances between all landmarks and stores their attractiveness to maximize sightseeing. + The goal is to maximize the objective function subject to the constraints A*x < b and A_eq*x = b_eq. + + Args: + landmarks (List[Landmark]): List of landmarks. + max_steps (int): Maximum number of steps allowed. + + Returns: + Tuple[List[float], List[float], List[int]]: Objective function coefficients, inequality constraint coefficients, and the right-hand side of the inequality constraint. + """ + + # Objective function coefficients. a*x1 + b*x2 + c*x3 + ... + c = [] + # Coefficients of inequality constraints (left-hand side) + A_ub = [] + + for spot1 in landmarks : + dist_table = [0]*len(landmarks) + c.append(-spot1.attractiveness) + for j, spot2 in enumerate(landmarks) : + t = self.get_time(spot1.location, spot2.location) + dist_table[j] = t + closest = sorted(dist_table)[:22] + for i, dist in enumerate(dist_table) : + if dist not in closest : + dist_table[i] = 32700 + A_ub += dist_table + c = c*len(landmarks) + + return c, A_ub, [max_steps] + + + def respect_number(self, L: int): + """ + Generate constraints to ensure each landmark is visited only once and cap the total number of visited landmarks. + + Args: + L (int): Number of landmarks. + + Returns: + Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + """ + + ones = [1]*L + zeros = [0]*L + A = ones + zeros*(L-1) + b = [1] + for i in range(L-1) : + h_new = zeros*i + ones + zeros*(L-1-i) + A = np.vstack((A, h_new)) + b.append(1) + + A = np.vstack((A, ones*L)) + b.append(self.max_landmarks+1) + + return A, b + + + # Constraint to not have d14 and d41 simultaneously. Does not prevent cyclic paths with more elements + def break_sym(self, L): + """ + Generate constraints to prevent simultaneous travel between two landmarks in both directions. + + Args: + L (int): Number of landmarks. + + Returns: + Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + """ + + upper_ind = np.triu_indices(L,0,L) + + up_ind_x = upper_ind[0] + up_ind_y = upper_ind[1] + + A = [0]*L*L + b = [1] + + for i, _ in enumerate(up_ind_x[1:]) : + l = [0]*L*L + if up_ind_x[i] != up_ind_y[i] : + l[up_ind_x[i]*L + up_ind_y[i]] = 1 + l[up_ind_y[i]*L + up_ind_x[i]] = 1 + + A = np.vstack((A,l)) + b.append(1) + + return A, b + + + def init_eq_not_stay(self, L: int): + """ + Generate constraints to prevent staying in the same position (e.g., removing d11, d22, d33, etc.). + + Args: + L (int): Number of landmarks. + + Returns: + Tuple[List[np.ndarray], List[int]]: Equality constraint coefficients and the right-hand side of the equality constraints. + """ + + l = [0]*L*L + + for i in range(L) : + for j in range(L) : + if j == i : + l[j + i*L] = 1 + + l = np.array(np.array(l), dtype=np.int8) + + return [l], [0] + + + def respect_user_must_do(self, landmarks: List[Landmark]) : + """ + Generate constraints to ensure that landmarks marked as 'must_do' are included in the optimization. + + Args: + landmarks (List[Landmark]): List of landmarks, where some are marked as 'must_do'. + + Returns: + Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + """ + + L = len(landmarks) + A = [0]*L*L + b = [0] + + for i, elem in enumerate(landmarks[1:]) : + if elem.must_do is True and elem.name not in ['finish', 'start']: + l = [0]*L*L + l[i*L:i*L+L] = [1]*L # set mandatory departures from landmarks tagged as 'must_do' + + A = np.vstack((A,l)) + b.append(1) + + return A, b + + + def respect_user_must_avoid(self, landmarks: List[Landmark]) : + """ + Generate constraints to ensure that landmarks marked as 'must_avoid' are skipped in the optimization. + + Args: + landmarks (List[Landmark]): List of landmarks, where some are marked as 'must_avoid'. + + Returns: + Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + """ + + L = len(landmarks) + A = [0]*L*L + b = [0] + + for i, elem in enumerate(landmarks[1:]) : + if elem.must_avoid is True and elem.name not in ['finish', 'start']: + l = [0]*L*L + l[i*L:i*L+L] = [1]*L + + A = np.vstack((A,l)) + b.append(0) # prevent departures from landmarks tagged as 'must_do' + + return A, b + + + # Constraint to ensure start at start and finish at goal + def respect_start_finish(self, L: int): + """ + Generate constraints to ensure that the optimization starts at the designated start landmark and finishes at the goal landmark. + + Args: + L (int): Number of landmarks. + + Returns: + Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + """ + + l_start = [1]*L + [0]*L*(L-1) # sets departures only for start (horizontal ones) + l_start[L-1] = 0 # prevents the jump from start to finish + l_goal = [0]*L*L # sets arrivals only for finish (vertical ones) + l_L = [0]*L*(L-1) + [1]*L # prevents arrivals at start and departures from goal + for k in range(L-1) : # sets only vertical ones for goal (go to) + l_L[k*L] = 1 + if k != 0 : + l_goal[k*L+L-1] = 1 + + A = np.vstack((l_start, l_goal)) + b = [1, 1] + A = np.vstack((A,l_L)) + b.append(0) + + return A, b + + + def respect_order(self, L: int): + """ + Generate constraints to tie the optimization problem together and prevent stacked ones, although this does not fully prevent circles. + + Args: + L (int): Number of landmarks. + + Returns: + Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + """ + + A = [0]*L*L + b = [0] + for i in range(L-1) : # Prevent stacked ones + if i == 0 or i == L-1: # Don't touch start or finish + continue + else : + l = [0]*L + l[i] = -1 + l = l*L + for j in range(L) : + l[i*L + j] = 1 + + A = np.vstack((A,l)) + b.append(0) + + return A, b + + + def link_list(self, order: List[int], landmarks: List[Landmark])->List[Landmark] : + """ + Compute the time to reach from each landmark to the next and create a list of landmarks with updated travel times. + + Args: + order (List[int]): List of indices representing the order of landmarks to visit. + landmarks (List[Landmark]): List of all landmarks. + + Returns: + List[Landmark]]: The updated linked list of landmarks with travel times + """ + + L = [] + j = 0 + while j < len(order)-1 : + # get landmarks involved + elem = landmarks[order[j]] + next = landmarks[order[j+1]] + + # get attributes + elem.time_to_reach_next = self.get_time(elem.location, next.location) + elem.must_do = True + elem.location = (round(elem.location[0], 5), round(elem.location[1], 5)) + elem.next_uuid = next.uuid + L.append(elem) + j += 1 + + next.location = (round(next.location[0], 5), round(next.location[1], 5)) + next.must_do = True + L.append(next) + + return L + + + # Main optimization pipeline + def solve_optimization (self) : + """ + Main optimization pipeline to solve the landmark visiting problem. + + This method sets up and solves a linear programming problem with constraints to find an optimal tour of landmarks, + considering user-defined must-visit landmarks, start and finish points, and ensuring no cycles are present. + + Returns: + List[Landmark]: The optimized tour of landmarks with updated travel times, or None if no valid solution is found. + """ + + L = len(self.landmarks) + + # SET CONSTRAINTS FOR INEQUALITY + c, A_ub, b_ub = self.init_ub_dist(self.landmarks, self.max_time) # Add the distances from each landmark to the other + A, b = self.respect_number(L) # Respect max number of visits (no more possible stops than landmarks). + A_ub = np.vstack((A_ub, A), dtype=np.int16) + b_ub += b + A, b = self.break_sym(L) # break the 'zig-zag' symmetry + A_ub = np.vstack((A_ub, A), dtype=np.int16) + b_ub += b + + + # SET CONSTRAINTS FOR EQUALITY + A_eq, b_eq = self.init_eq_not_stay(L) # Force solution not to stay in same place + A, b = self.respect_user_must_do(self.landmarks) # Check if there are user_defined must_see. Also takes care of start/goal + A_eq = np.vstack((A_eq, A), dtype=np.int8) + b_eq += b + A, b = self.respect_start_finish(L) # Force start and finish positions + A_eq = np.vstack((A_eq, A), dtype=np.int8) + b_eq += b + A, b = self.respect_order(L) # Respect order of visit (only works when max_steps is limiting factor) + A_eq = np.vstack((A_eq, A), dtype=np.int8) + b_eq += b + + # SET BOUNDS FOR DECISION VARIABLE (x can only be 0 or 1) + x_bounds = [(0, 1)]*L*L + + # Solve linear programming problem + res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) + + # Raise error if no solution is found + if not res.success : + raise ArithmeticError("No solution could be found, the problem is overconstrained. Please adapt your must_dos") + + # If there is a solution, we're good to go, just check for connectiveness + else : + order, circles = self.is_connected(res.x) + #nodes, edges = is_connected(res.x) + i = 0 + timeout = 80 + while circles is not None and i < timeout: + A, b = self.prevent_config(res.x) + A_ub = np.vstack((A_ub, A)) + b_ub += b + #A_ub, b_ub = prevent_circle(order, len(landmarks), A_ub, b_ub) + for circle in circles : + A, b = self.prevent_circle(circle, L) + A_eq = np.vstack((A_eq, A)) + b_eq += b + res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) + if not res.success : + self.logger.info("Solving failed because of overconstrained problem") + return None + order, circles = self.is_connected(res.x) + #nodes, edges = is_connected(res.x) + if circles is None : + break + print(i) + i += 1 + + if i == timeout : + raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.") + + # Add the times to reach and stop optimizing + tour = self.link_list(order, self.landmarks) + + # logging + if i != 0 : + self.logger.info(f"Neded to recompute paths {i} times because of unconnected loops...") + self.print_res(tour) # how to do better ? + self.logger.info(f"Total score : {int(-res.fun)}") + + return tour + + + + + + diff --git a/backend/src/optimizer_v4.py b/backend/src/optimizer_v4.py deleted file mode 100644 index 0eecb97..0000000 --- a/backend/src/optimizer_v4.py +++ /dev/null @@ -1,446 +0,0 @@ -import numpy as np -import json, os - -from typing import List, Tuple -from scipy.optimize import linprog -from collections import defaultdict, deque -from geopy.distance import geodesic - -from structs.landmarks import Landmark - - -# Function to print the result -def print_res(L: List[Landmark]): - - print('The following order is suggested : ') - - dist = 0 - for elem in L : - if elem.time_to_reach_next is not None : - print('- ' + elem.name + ', time to reach next = ' + str(elem.time_to_reach_next)) - dist += elem.time_to_reach_next - else : - print('- ' + elem.name) - - print("\nMinutes walked : " + str(dist)) - print(f"Visited {len(L)-2} landmarks") - - -# Prevent the use of a particular solution -def prevent_config(resx): - - for i, elem in enumerate(resx): - resx[i] = round(elem) - - N = len(resx) # Number of edges - L = int(np.sqrt(N)) # Number of landmarks - - nonzeroind = np.nonzero(resx)[0] # the return is a little funky so I use the [0] - nonzero_tup = np.unravel_index(nonzeroind, (L,L)) - - ind_a = nonzero_tup[0].tolist() - vertices_visited = ind_a - vertices_visited.remove(0) - - ones = [1]*L - h = [0]*N - for i in range(L) : - if i in vertices_visited : - h[i*L:i*L+L] = ones - - return h, [len(vertices_visited)-1] - - -# Prevents the creation of the same circle (both directions) -def prevent_circle(circle_vertices: list, L: int) : - - l1 = [0]*L*L - l2 = [0]*L*L - for i, node in enumerate(circle_vertices[:-1]) : - next = circle_vertices[i+1] - - l1[node*L + next] = 1 - l2[next*L + node] = 1 - - s = circle_vertices[0] - g = circle_vertices[-1] - - l1[g*L + s] = 1 - l2[s*L + g] = 1 - - return np.vstack((l1, l2)), [0, 0] - - -# Returns the order of visit as well as any circles if there are some -def is_connected(resx) : - - # first round the results to have only 0-1 values - for i, elem in enumerate(resx): - resx[i] = round(elem) - - N = len(resx) # length of res - L = int(np.sqrt(N)) # number of landmarks. CAST INTO INT but should not be a problem because N = L**2 by def. - n_edges = resx.sum() # number of edges - - nonzeroind = np.nonzero(resx)[0] # the return is a little funny so I use the [0] - - nonzero_tup = np.unravel_index(nonzeroind, (L,L)) - - ind_a = nonzero_tup[0].tolist() - ind_b = nonzero_tup[1].tolist() - - # Step 1: Create a graph representation - graph = defaultdict(list) - for a, b in zip(ind_a, ind_b): - graph[a].append(b) - - # Step 2: Function to perform BFS/DFS to extract journeys - def get_journey(start): - journey_nodes = [] - visited = set() - stack = deque([start]) - - while stack: - node = stack.pop() - if node not in visited: - visited.add(node) - journey_nodes.append(node) - for neighbor in graph[node]: - if neighbor not in visited: - stack.append(neighbor) - - return journey_nodes - - # Step 3: Extract all journeys - all_journeys_nodes = [] - visited_nodes = set() - - for node in ind_a: - if node not in visited_nodes: - journey_nodes = get_journey(node) - all_journeys_nodes.append(journey_nodes) - visited_nodes.update(journey_nodes) - - for l in all_journeys_nodes : - if 0 in l : - order = l - all_journeys_nodes.remove(l) - break - - if len(all_journeys_nodes) == 0 : - return order, None - - return order, all_journeys_nodes - - -# Function that returns the time in minutes from one location to another -def get_time(p1: Tuple[float, float], p2: Tuple[float, float], detour: float, speed: float) : - - # Compute the straight-line distance in km - if p1 == p2 : - return 0 - else: - dist = geodesic(p1, p2).kilometers - - # Consider the detour factor for average cityto deterline walking distance (in km) - walk_dist = dist*detour - - # Time to walk this distance (in minutes) - walk_time = walk_dist/speed*60 - - return round(walk_time) - - -# Initialize A and c. Compute the distances from all landmarks to each other and store attractiveness -# We want to maximize the sightseeing : max(c) st. A*x < b and A_eq*x = b_eq -def init_ub_dist(landmarks: List[Landmark], max_steps: int): - - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : - parameters = json.loads(f.read()) - detour = parameters['detour factor'] - speed = parameters['average walking speed'] - - # Objective function coefficients. a*x1 + b*x2 + c*x3 + ... - c = [] - # Coefficients of inequality constraints (left-hand side) - A_ub = [] - - for spot1 in landmarks : - dist_table = [0]*len(landmarks) - c.append(-spot1.attractiveness) - for j, spot2 in enumerate(landmarks) : - t = get_time(spot1.location, spot2.location, detour, speed) - dist_table[j] = t - closest = sorted(dist_table)[:22] - for i, dist in enumerate(dist_table) : - if dist not in closest : - dist_table[i] = 32700 - A_ub += dist_table - c = c*len(landmarks) - - return c, A_ub, [max_steps] - - -# Constraint to respect only one travel per landmark. Also caps the total number of visited landmarks -def respect_number(L: int, max_landmarks: int): - - ones = [1]*L - zeros = [0]*L - A = ones + zeros*(L-1) - b = [1] - for i in range(L-1) : - h_new = zeros*i + ones + zeros*(L-1-i) - A = np.vstack((A, h_new)) - b.append(1) - - if max_landmarks is None : - # Read the parameters from the file - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : - parameters = json.loads(f.read()) - max_landmarks = parameters['max landmarks'] - - A = np.vstack((A, ones*L)) - b.append(max_landmarks+1) - - return A, b - - -# Constraint to not have d14 and d41 simultaneously. Does not prevent cyclic paths with more elements -def break_sym(L): - - upper_ind = np.triu_indices(L,0,L) - - up_ind_x = upper_ind[0] - up_ind_y = upper_ind[1] - - A = [0]*L*L # useless row to prevent overhead ? better solution welcomed - # A[up_ind_x[0]*L + up_ind_y[0]] = 1 - # A[up_ind_y[0]*L + up_ind_x[0]] = 1 - b = [1] - - for i, _ in enumerate(up_ind_x[1:]) : - l = [0]*L*L - if up_ind_x[i] != up_ind_y[i] : - l[up_ind_x[i]*L + up_ind_y[i]] = 1 - l[up_ind_y[i]*L + up_ind_x[i]] = 1 - - A = np.vstack((A,l)) - b.append(1) - - return A, b - - -# Constraint to not stay in position. Removes d11, d22, d33, etc. -def init_eq_not_stay(L: int): - l = [0]*L*L - - for i in range(L) : - for j in range(L) : - if j == i : - l[j + i*L] = 1 - - l = np.array(np.array(l), dtype=np.int8) - - return [l], [0] - - -# Go through the landmarks and force the optimizer to use landmarks marked as must_do -def respect_user_must_do(landmarks: List[Landmark]) : - L = len(landmarks) - - A = [0]*L*L - b = [0] - for i, elem in enumerate(landmarks[1:]) : - if elem.must_do is True and elem.name not in ['finish', 'start']: - l = [0]*L*L - l[i*L:i*L+L] = [1]*L # set mandatory departures from landmarks tagged as 'must_do' - - A = np.vstack((A,l)) - b.append(1) - - return A, b - - -# Constraint to ensure start at start and finish at goal -def respect_start_finish(L: int): - l_start = [1]*L + [0]*L*(L-1) # sets departures only for start (horizontal ones) - l_start[L-1] = 0 # prevents the jump from start to finish - l_goal = [0]*L*L # sets arrivals only for finish (vertical ones) - l_L = [0]*L*(L-1) + [1]*L # prevents arrivals at start and departures from goal - for k in range(L-1) : # sets only vertical ones for goal (go to) - l_L[k*L] = 1 - if k != 0 : - l_goal[k*L+L-1] = 1 - - - A = np.vstack((l_start, l_goal)) - b = [1, 1] - A = np.vstack((A,l_L)) - b.append(0) - - return A, b - - -# Constraint to tie the problem together. Necessary but not sufficient to avoid circles -def respect_order(L: int): - - A = [0]*L*L # useless row to reduce overhead ? better solution is welcome - b = [0] - for i in range(L-1) : # Prevent stacked ones - if i == 0 or i == L-1: # Don't touch start or finish - continue - else : - l = [0]*L - l[i] = -1 - l = l*L - for j in range(L) : - l[i*L + j] = 1 - - A = np.vstack((A,l)) - b.append(0) - - return A, b - - -# Computes the time to reach from each landmark to the next -def link_list(order: List[int], landmarks: List[Landmark])->List[Landmark] : - - # Read the parameters from the file - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : - parameters = json.loads(f.read()) - detour_factor = parameters['detour factor'] - speed = parameters['average walking speed'] - - L = [] - j = 0 - total_dist = 0 - while j < len(order)-1 : - elem = landmarks[order[j]] - next = landmarks[order[j+1]] - - d = get_time(elem.location, next.location, detour_factor, speed) - elem.time_to_reach_next = d - elem.must_do = True - elem.location = (round(elem.location[0], 5), round(elem.location[1], 5)) - L.append(elem) - j += 1 - total_dist += d - - next.location = (round(next.location[0], 5), round(next.location[1], 5)) - L.append(next) - - return L, total_dist - - -# Same as link_list but does it on a already ordered list -def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] : - - # Read the parameters from the file - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : - parameters = json.loads(f.read()) - detour_factor = parameters['detour factor'] - speed = parameters['average walking speed'] - - L = [] - j = 0 - total_dist = 0 - while j < len(ordered_visit)-1 : - elem = ordered_visit[j] - next = ordered_visit[j+1] - - elem.next_uuid = next.uuid - d = get_time(elem.location, next.location, detour_factor, speed) - elem.time_to_reach_next = d - if elem.name not in ['start', 'finish'] : - elem.must_do = True - L.append(elem) - j += 1 - total_dist += d - - L.append(next) - - return L, total_dist - - -# Main optimization pipeline -def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_details: bool, max_landmarks = None) : - - L = len(landmarks) - - # SET CONSTRAINTS FOR INEQUALITY - c, A_ub, b_ub = init_ub_dist(landmarks, max_steps) # Add the distances from each landmark to the other - A, b = respect_number(L, max_landmarks) # Respect max number of visits (no more possible stops than landmarks). - A_ub = np.vstack((A_ub, A), dtype=np.int16) - b_ub += b - A, b = break_sym(L) # break the 'zig-zag' symmetry - A_ub = np.vstack((A_ub, A), dtype=np.int16) - b_ub += b - - - # SET CONSTRAINTS FOR EQUALITY - A_eq, b_eq = init_eq_not_stay(L) # Force solution not to stay in same place - A, b = respect_user_must_do(landmarks) # Check if there are user_defined must_see. Also takes care of start/goal - A_eq = np.vstack((A_eq, A), dtype=np.int8) - b_eq += b - A, b = respect_start_finish(L) # Force start and finish positions - A_eq = np.vstack((A_eq, A), dtype=np.int8) - b_eq += b - A, b = respect_order(L) # Respect order of visit (only works when max_steps is limiting factor) - A_eq = np.vstack((A_eq, A), dtype=np.int8) - b_eq += b - - # SET BOUNDS FOR DECISION VARIABLE (x can only be 0 or 1) - x_bounds = [(0, 1)]*L*L - - # Solve linear programming problem - res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) - - # Raise error if no solution is found - if not res.success : - raise ArithmeticError("No solution could be found, the problem is overconstrained. Please adapt your must_dos") - - # If there is a solution, we're good to go, just check for connectiveness - else : - order, circles = is_connected(res.x) - #nodes, edges = is_connected(res.x) - i = 0 - timeout = 80 - while circles is not None and i < timeout: - A, b = prevent_config(res.x) - A_ub = np.vstack((A_ub, A)) - b_ub += b - #A_ub, b_ub = prevent_circle(order, len(landmarks), A_ub, b_ub) - for circle in circles : - A, b = prevent_circle(circle, len(landmarks)) - A_eq = np.vstack((A_eq, A)) - b_eq += b - res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) - if not res.success : - print("Solving failed because of overconstrained problem") - return None - order, circles = is_connected(res.x) - #nodes, edges = is_connected(res.x) - if circles is None : - break - print(i) - i += 1 - - if i == timeout : - raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.") - - # Add the times to reach and stop optimizing - L, _ = link_list(order, landmarks) - - if printing_details is True : - if i != 0 : - print(f"Neded to recompute paths {i} times because of unconnected loops...") - print_res(L) - print("\nTotal score : " + str(int(-res.fun))) - - return L - - - - - - diff --git a/backend/src/parameters/landmark_parameters.yaml b/backend/src/parameters/landmark_parameters.yaml index b85c89a..5de9c48 100644 --- a/backend/src/parameters/landmark_parameters.yaml +++ b/backend/src/parameters/landmark_parameters.yaml @@ -1,6 +1,6 @@ city_bbox_side: 5000 #m -radius_close_to: 30 -church_coeff: 0.6 -park_coeff: 1.5 -tag_coeff: 100 +radius_close_to: 50 +church_coeff: 0.8 +park_coeff: 1.2 +tag_coeff: 10 N_important: 40 diff --git a/backend/src/refiner.py b/backend/src/refiner.py index 1971170..8fbb0f5 100644 --- a/backend/src/refiner.py +++ b/backend/src/refiner.py @@ -1,244 +1,354 @@ -import os, json +import yaml, logging from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull from typing import List, Tuple from math import pi from structs.landmarks import Landmark -from landmarks_manager import take_most_important -from optimizer_v4 import solve_optimization, link_list_simple, print_res, get_time +from optimizer import Optimizer +from utils import get_time, link_list_simple, take_most_important +import constants -# Create corridor from tour -def create_corridor(landmarks: List[Landmark], width: float) : - corrected_width = (180*width)/(6371000*pi) - - path = create_linestring(landmarks) - obj = buffer(path, corrected_width, join_style="mitre", cap_style="square", mitre_limit=2) +class Refiner : - return obj + logger = logging.getLogger(__name__) + + all_landmarks: List[Landmark] # list of all landmarks + base_tour: List[Landmark] # base tour that needs to be refined + max_time: int = None # max visit time (in minutes) + detour: int = None # accepted max detour time (in minutes) + detour_factor: float # detour factor of straight line vs real distance in cities + average_walking_speed: float # average walking speed of adult + max_landmarks: int # max number of landmarks to visit -# Create linestring from tour -def create_linestring(landmarks: List[Landmark])->List[Point] : + def __init__(self, max_time: int, detour: int, all_landmarks: List[Landmark], base_tour: List[Landmark]) : + self.max_time = max_time + self.detour = detour + self.all_landmarks = all_landmarks + self.base_tour = base_tour - points = [] - - for landmark in landmarks : - points.append(Point(landmark.location)) - - return LineString(points) + # load parameters from file + with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: + parameters = yaml.safe_load(f) + self.detour_factor = parameters['detour_factor'] + self.average_walking_speed = parameters['average_walking_speed'] + self.max_landmarks = parameters['max_landmarks'] + 4 -# Check if some coordinates are in area. Used for the corridor -def is_in_area(area: Polygon, coordinates) -> bool : - point = Point(coordinates) - return point.within(area) + def create_corridor(self, landmarks: List[Landmark], width: float) : + """ + Create a corridor around the path connecting the landmarks. + + Args: + landmarks (List[Landmark]): the landmark path around which to create the corridor + width (float): Width of the corridor in meters. + + Returns: + Geometry: A buffered geometry object representing the corridor around the path. + """ + + corrected_width = (180*width)/(6371000*pi) + + path = self.create_linestring(landmarks) + obj = buffer(path, corrected_width, join_style="mitre", cap_style="square", mitre_limit=2) + + return obj -# Function to determine if two landmarks are close to each other -def is_close_to(location1: Tuple[float], location2: Tuple[float]): - """Determine if two locations are close by rounding their coordinates to 3 decimals.""" - absx = abs(location1[0] - location2[0]) - absy = abs(location1[1] - location2[1]) + def create_linestring(self, tour: List[Landmark])->LineString : + """ + Create a `LineString` object from a tour. - return absx < 0.001 and absy < 0.001 - #return (round(location1[0], 3), round(location1[1], 3)) == (round(location2[0], 3), round(location2[1], 3)) + Args: + tour (List[Landmark]): An ordered sequence of landmarks that represents the visiting order. + + Returns: + LineString: A `LineString` object representing the path through the landmarks. + """ + + points = [] + for landmark in tour : + points.append(Point(landmark.location)) + + return LineString(points) -# Rearrange some landmarks in the order of visit to group visit -def rearrange(landmarks: List[Landmark]) -> List[Landmark]: - - i = 1 - while i < len(landmarks): - j = i+1 - while j < len(landmarks): - if is_close_to(landmarks[i].location, landmarks[j].location) and landmarks[i].name not in ['start', 'finish'] and landmarks[j].name not in ['start', 'finish']: - # If they are not adjacent, move the j-th element to be adjacent to the i-th element - if j != i + 1: - landmarks.insert(i + 1, landmarks.pop(j)) - break # Move to the next i-th element after rearrangement - j += 1 - i += 1 - - return landmarks + # Check if some coordinates are in area. Used for the corridor + def is_in_area(self, area: Polygon, coordinates) -> bool : + """ + Check if a given point is within a specified area. + + Args: + area (Polygon): The polygon defining the area. + coordinates (Tuple[float, float]): The coordinates of the point to check. + + Returns: + bool: True if the point is within the area, otherwise False. + """ + point = Point(coordinates) + return point.within(area) -# Simple nearest neighbour planner to try to fix the path -def find_shortest_path_through_all_landmarks(landmarks: List[Landmark]) -> Tuple[List[Landmark], Polygon]: + # Function to determine if two landmarks are close to each other + def is_close_to(self, location1: Tuple[float], location2: Tuple[float]): + """ + Determine if two locations are close to each other by rounding their coordinates to 3 decimal places. + + Args: + location1 (Tuple[float, float]): The coordinates of the first location. + location2 (Tuple[float, float]): The coordinates of the second location. + + Returns: + bool: True if the locations are within 0.001 degrees of each other, otherwise False. + """ + + absx = abs(location1[0] - location2[0]) + absy = abs(location1[1] - location2[1]) + + return absx < 0.001 and absy < 0.001 + #return (round(location1[0], 3), round(location1[1], 3)) == (round(location2[0], 3), round(location2[1], 3)) + + + def rearrange(self, tour: List[Landmark]) -> List[Landmark]: + """ + Rearrange landmarks to group nearby visits together. + + This function reorders landmarks so that nearby landmarks are adjacent to each other in the list, + while keeping 'start' and 'finish' landmarks in their original positions. + + Args: + tour (List[Landmark]): Ordered list of landmarks to be rearranged. + + Returns: + List[Landmark]: The rearranged list of landmarks with grouped nearby visits. + """ - # Read from data - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : - parameters = json.loads(f.read()) - detour = parameters['detour factor'] - speed = parameters['average walking speed'] + i = 1 + while i < len(tour): + j = i+1 + while j < len(tour): + if self.is_close_to(tour[i].location, tour[j].location) and tour[i].name not in ['start', 'finish'] and tour[j].name not in ['start', 'finish']: + # If they are not adjacent, move the j-th element to be adjacent to the i-th element + if j != i + 1: + tour.insert(i + 1, tour.pop(j)) + break # Move to the next i-th element after rearrangement + j += 1 + i += 1 - # Step 1: Find 'start' and 'finish' landmarks - start_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'start') - finish_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'finish') - - start_landmark = landmarks[start_idx] - finish_landmark = landmarks[finish_idx] - - - # Step 2: Create a list of unvisited landmarks excluding 'start' and 'finish' - unvisited_landmarks = [lm for i, lm in enumerate(landmarks) if i not in [start_idx, finish_idx]] - - # Step 3: Initialize the path with the 'start' landmark - path = [start_landmark] - coordinates = [landmarks[start_idx].location] - - current_landmark = start_landmark - - # Step 4: Use nearest neighbor heuristic to visit all landmarks - while unvisited_landmarks: - nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time(current_landmark.location, lm.location, detour, speed)) - path.append(nearest_landmark) - coordinates.append(nearest_landmark.location) - current_landmark = nearest_landmark - unvisited_landmarks.remove(nearest_landmark) - - # Step 5: Finally add the 'finish' landmark to the path - path.append(finish_landmark) - coordinates.append(landmarks[finish_idx].location) - - path_poly = Polygon(coordinates) - - return path, path_poly + return tour -# Returns a list of minor landmarks around the planned path to enhance experience -def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] : + def find_shortest_path_through_all_landmarks(self, landmarks: List[Landmark]) -> Tuple[List[Landmark], Polygon]: + """ + Find the shortest path through all landmarks using a nearest neighbor heuristic. - second_order_landmarks = [] - visited_names = [] - area = create_corridor(visited_landmarks, width) + This function constructs a path that starts from the 'start' landmark, visits all other landmarks in the order + of their proximity, and ends at the 'finish' landmark. It returns both the ordered list of landmarks and a + polygon representing the path. - for visited in visited_landmarks : - visited_names.append(visited.name) - - for landmark in all_landmarks : - if is_in_area(area, landmark.location) and landmark.name not in visited_names: - second_order_landmarks.append(landmark) + Args: + landmarks (List[Landmark]): List of all landmarks including 'start' and 'finish'. - return take_most_important(second_order_landmarks, len(visited_landmarks)) + Returns: + Tuple[List[Landmark], Polygon]: A tuple where the first element is the list of landmarks in the order they + should be visited, and the second element is a `Polygon` representing + the path connecting all landmarks. + """ + + # Step 1: Find 'start' and 'finish' landmarks + start_idx = next(i for i, lm in enumerate(landmarks) if lm.type == 'start') + finish_idx = next(i for i, lm in enumerate(landmarks) if lm.type == 'finish') + + start_landmark = landmarks[start_idx] + finish_landmark = landmarks[finish_idx] + + + # Step 2: Create a list of unvisited landmarks excluding 'start' and 'finish' + unvisited_landmarks = [lm for i, lm in enumerate(landmarks) if i not in [start_idx, finish_idx]] + + # Step 3: Initialize the path with the 'start' landmark + path = [start_landmark] + coordinates = [landmarks[start_idx].location] + + current_landmark = start_landmark + + # Step 4: Use nearest neighbor heuristic to visit all landmarks + while unvisited_landmarks: + nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time(current_landmark.location, lm.location)) + path.append(nearest_landmark) + coordinates.append(nearest_landmark.location) + current_landmark = nearest_landmark + unvisited_landmarks.remove(nearest_landmark) + + # Step 5: Finally add the 'finish' landmark to the path + path.append(finish_landmark) + coordinates.append(landmarks[finish_idx].location) + + path_poly = Polygon(coordinates) + + return path, path_poly -# Try fix the shortest path using shapely -def fix_using_polygon(tour: List[Landmark])-> List[Landmark] : + # Returns a list of minor landmarks around the planned path to enhance experience + def get_minor_landmarks(self, all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] : + """ + Identify landmarks within a specified corridor that have not been visited yet. - coords = [] - coords_dict = {} - for landmark in tour : - coords.append(landmark.location) - if landmark.name != 'finish' : - coords_dict[landmark.location] = landmark + This function creates a corridor around the path defined by visited landmarks and then finds landmarks that fall + within this corridor. It returns a list of these landmarks, excluding those already visited, sorted by their importance. - tour_poly = Polygon(coords) - - better_tour_poly = tour_poly.buffer(0) - try : - xs, ys = better_tour_poly.exterior.xy + Args: + all_landmarks (List[Landmark]): List of all available landmarks. + visited_landmarks (List[Landmark]): List of landmarks that have already been visited. + width (float): Width of the corridor around the visited landmarks. - if len(xs) != len(tour) : - better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish - xs, ys = better_tour_poly.exterior.xy + Returns: + List[Landmark]: List of important landmarks within the corridor that have not been visited yet. + """ - except : - better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish - xs, ys = better_tour_poly.exterior.xy + second_order_landmarks = [] + visited_names = [] + area = self.create_corridor(visited_landmarks, width) + + for visited in visited_landmarks : + visited_names.append(visited.name) + + for landmark in all_landmarks : + if self.is_in_area(area, landmark.location) and landmark.name not in visited_names: + second_order_landmarks.append(landmark) + + return take_most_important(second_order_landmarks, len(visited_landmarks)) - # reverse the xs and ys - xs.reverse() - ys.reverse() + # Try fix the shortest path using shapely + def fix_using_polygon(self, tour: List[Landmark])-> List[Landmark] : + """ + Improve the tour path using geometric methods to ensure it follows a more optimal shape. - better_tour = [] # List of ordered visit - name_index = {} # Maps the name of a landmark to its index in the concave polygon + This function creates a polygon from the given tour and attempts to refine it using a concave hull. It reorders + the landmarks to fit within this refined polygon and adjusts the tour to ensure the 'start' landmark is at the + beginning. It also checks if the final polygon is simple and rearranges the tour if necessary. - # Loop through the polygon and generate the better (ordered) tour - for i,x in enumerate(xs[:-1]) : - y = ys[i] - better_tour.append(coords_dict[tuple((x,y))]) - name_index[coords_dict[tuple((x,y))].name] = i + Args: + tour (List[Landmark]): List of landmarks representing the current tour path. + + Returns: + List[Landmark]: Refined list of landmarks in the order of visit to produce a better tour path. + """ + + coords = [] + coords_dict = {} + for landmark in tour : + coords.append(landmark.location) + if landmark.name != 'finish' : + coords_dict[landmark.location] = landmark + + tour_poly = Polygon(coords) + + better_tour_poly = tour_poly.buffer(0) + try : + xs, ys = better_tour_poly.exterior.xy + + if len(xs) != len(tour) : + better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish + xs, ys = better_tour_poly.exterior.xy + + except : + better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish + xs, ys = better_tour_poly.exterior.xy - # Scroll the list to have start in front again - start_index = name_index['start'] - better_tour = better_tour[start_index:] + better_tour[:start_index] + # reverse the xs and ys + xs.reverse() + ys.reverse() - # Append the finish back and correct the time to reach - better_tour.append(tour[-1]) + better_tour = [] # List of ordered visit + name_index = {} # Maps the name of a landmark to its index in the concave polygon - # Rearrange only if polygon still not simple - if not better_tour_poly.is_simple : - better_tour = rearrange(better_tour) - - return better_tour + # Loop through the polygon and generate the better (ordered) tour + for i,x in enumerate(xs[:-1]) : + y = ys[i] + better_tour.append(coords_dict[tuple((x,y))]) + name_index[coords_dict[tuple((x,y))].name] = i -# Second stage of the optimization. Use linear programming again to refine the path -def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, detour: int, print_infos: bool) -> List[Landmark] : + # Scroll the list to have start in front again + start_index = name_index['start'] + better_tour = better_tour[start_index:] + better_tour[:start_index] - # Read from the file - with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : - parameters = json.loads(f.read()) - max_landmarks = parameters['max landmarks'] + 4 + # Append the finish back and correct the time to reach + better_tour.append(tour[-1]) - # No need to refine if no detour is taken - # if detour == 0 : - if False : - new_tour = base_tour - - else : - minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200) - - if print_infos : print("Using " + str(len(minor_landmarks)) + " minor landmarks around the predicted path") - - # full set of visitable landmarks - full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) - full_set.append(base_tour[-1]) # add finish back - - # get a new tour - new_tour = solve_optimization(full_set, max_time+detour, False, max_landmarks) - if new_tour is None : - new_tour = base_tour - - # Link the new tour - new_tour, new_dist = link_list_simple(new_tour) - - # If the tour contains only one landmark, return - if len(new_tour) < 4 : - return new_tour - - # Find shortest path using the nearest neighbor heuristic - better_tour, better_poly = find_shortest_path_through_all_landmarks(new_tour) - - # Fix the tour using Polygons if the path looks weird - if base_tour[0].location == base_tour[-1].location and not better_poly.is_valid : - better_tour = fix_using_polygon(better_tour) - - # Link the tour again - better_tour, better_dist = link_list_simple(better_tour) - - # Choose the better tour depending on walked distance - if new_dist < better_dist : - final_tour = new_tour - else : - final_tour = better_tour - - if print_infos : - print("\n\n\nRefined tour (result of second stage optimization): ") - print_res(final_tour) - total_score = 0 - for elem in final_tour : - total_score += elem.attractiveness - - print("\nTotal score : " + str(total_score)) + # Rearrange only if polygon still not simple + if not better_tour_poly.is_simple : + better_tour = self.rearrange(better_tour) + + return better_tour - - return final_tour + # Second stage of the optimization. Use linear programming again to refine the path + def refine_optimization(self) -> List[Landmark] : + """ + Refine the initial tour path by considering additional minor landmarks and optimizing the path. + + This method evaluates the need for further optimization based on the initial tour. If a detour is required, it adds + minor landmarks around the initial predicted path and solves a new optimization problem to find a potentially better + tour. It then links the new tour and adjusts it using a nearest neighbor heuristic and polygon-based methods to + ensure a valid path. The final tour is chosen based on the shortest distance. + + Returns: + List[Landmark]: The refined list of landmarks representing the optimized tour path. + """ + + # No need to refine if no detour is taken + # if detour == 0 : + if False : + new_tour = base_tour + + else : + minor_landmarks = self.get_minor_landmarks(self.all_landmarks, self.base_tour, 200) + + self.logger.info(f"Using {len(minor_landmarks)} minor landmarks around the predicted path") + + # full set of visitable landmarks + full_set = self.base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) + full_set.append(self.base_tour[-1]) # add finish back + + # get a new tour + optimizer = Optimizer(self.max_time + self.detour, full_set) + new_tour = optimizer.solve_optimization() + + if new_tour is None : + new_tour = self.base_tour + + # Link the new tour + new_tour, new_dist = link_list_simple(new_tour) + + # If the tour contains only one landmark, return + if len(new_tour) < 4 : + return new_tour + + # Find shortest path using the nearest neighbor heuristic + better_tour, better_poly = self.find_shortest_path_through_all_landmarks(new_tour) + + # Fix the tour using Polygons if the path looks weird + if self.base_tour[0].location == self.base_tour[-1].location and not better_poly.is_valid : + better_tour = self.fix_using_polygon(better_tour) + + # Link the tour again + better_tour, better_dist = link_list_simple(better_tour) + + # Choose the better tour depending on walked distance + if new_dist < better_dist : + final_tour = new_tour + else : + final_tour = better_tour + + self.logger.info("Refined tour (result of second stage optimization): ") + + return final_tour diff --git a/backend/src/structs/landmarks.py b/backend/src/structs/landmarks.py index f6db9ac..6f449a8 100644 --- a/backend/src/structs/landmarks.py +++ b/backend/src/structs/landmarks.py @@ -8,7 +8,7 @@ class Landmark(BaseModel) : # Properties of the landmark name : str - type: Literal['sightseeing', 'nature', 'shopping'] + type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] location : tuple osm_type : str osm_id : int @@ -22,8 +22,8 @@ class Landmark(BaseModel) : uuid: str = Field(default_factory=uuid4) # TODO implement this ASAP # Additional properties depending on specific tour - must_do : bool - must_avoid : bool + must_do : Optional[bool] = False + must_avoid : Optional[bool] = False is_secondary : Optional[bool] = False # TODO future time_to_reach_next : Optional[int] = 0 # TODO fix this in existing code diff --git a/backend/src/structs/preferences.py b/backend/src/structs/preferences.py index ff25007..d370fc8 100644 --- a/backend/src/structs/preferences.py +++ b/backend/src/structs/preferences.py @@ -3,7 +3,7 @@ from typing import Optional, Literal class Preference(BaseModel) : name: str - type: Literal['sightseeing', 'nature', 'shopping'] + type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] score: int # score could be from 1 to 5 # Input for optimization diff --git a/backend/src/tester.py b/backend/src/tester.py index cea6527..8f1f718 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -4,10 +4,9 @@ from typing import List from landmarks_manager import LandmarkManager from fastapi.encoders import jsonable_encoder -from optimizer_v4 import solve_optimization -from refiner import refine_optimization +from optimizer import Optimizer +from refiner import Refiner from structs.landmarks import Landmark -from structs.landmarktype import LandmarkType from structs.preferences import Preferences, Preference @@ -24,58 +23,66 @@ def write_data(L: List[Landmark], file_name: str): data.to_json(file_name, indent = 2, force_ascii=False) -def test4(coordinates: tuple[float, float]) -> List[Landmark]: +def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = None) -> List[Landmark]: - manager = LandmarkManager() + preferences = Preferences( sightseeing=Preference( name='sightseeing', - type=LandmarkType(landmark_type='sightseeing'), + type='sightseeing', score = 5), nature=Preference( name='nature', - type=LandmarkType(landmark_type='nature'), + type='nature', score = 0), shopping=Preference( name='shopping', - type=LandmarkType(landmark_type='shopping'), - score = 0)) + type='shopping', + score = 0), + max_time_minute=180, + detour_tolerance_minute=0 + ) # Create start and finish - start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=coordinates, osm_type='start', osm_id=0, attractiveness=0, must_do=False, n_tags = 0) - finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=coordinates, osm_type='finish', osm_id=0, attractiveness=0, must_do=False, n_tags = 0) + if finish_coords is None : + finish_coords = start_coords + start = Landmark(name='start', type='start', location=start_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0) + finish = Landmark(name='finish', type='start', location=finish_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8777055, 2.3640967), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.847132, 2.312359), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.843185, 2.344533), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.847132, 2.312359), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) + + manager = LandmarkManager(preferences=preferences, coordinates=start_coords) + # Generate the landmarks from the start location - landmarks, landmarks_short = generate_landmarks(preferences=preferences, coordinates=start.location) + landmarks, landmarks_short = manager.generate_landmarks_list() + + # Store data to file for debug purposes #write_data(landmarks, "landmarks_Wien.txt") # Insert start and finish to the landmarks list landmarks_short.insert(0, start) landmarks_short.append(finish) - max_walking_time = 180 # minutes - detour = 0 # minutes - # First stage optimization - base_tour = solve_optimization(landmarks_short, max_walking_time, True) + optimizer = Optimizer(max_time=preferences.max_time_minute, landmarks=landmarks_short) + base_tour = optimizer.solve_optimization() # Second stage using linear optimization - - refined_tour = refine_optimization(landmarks, base_tour, max_walking_time, detour, True) + refiner = Refiner(max_time = preferences.max_time_minute, detour = preferences.detour_tolerance_minute, all_landmarks=landmarks, base_tour=base_tour) + refined_tour = refiner.refine_optimization() return refined_tour -#test4(tuple((48.8344400, 2.3220540))) # Café Chez César -#test4(tuple((48.8375946, 2.2949904))) # Point random -#test4(tuple((47.377859, 8.540585))) # Zurich HB -#test4(tuple((45.7576485, 4.8330241))) # Lyon Bellecour -test4(tuple((48.5848435, 7.7332974))) # Strasbourg Gare -#test4(tuple((48.2067858, 16.3692340))) # Vienne +#test(tuple((48.8344400, 2.3220540))) # Café Chez César +#test(tuple((48.8375946, 2.2949904))) # Point random +#test(tuple((47.377859, 8.540585))) # Zurich HB +#test(tuple((45.7576485, 4.8330241))) # Lyon Bellecour +test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare +#test(tuple((48.2067858, 16.3692340))) # Vienne diff --git a/backend/src/utils.py b/backend/src/utils.py new file mode 100644 index 0000000..d145c6f --- /dev/null +++ b/backend/src/utils.py @@ -0,0 +1,106 @@ +import yaml +from typing import List, Tuple +from geopy.distance import geodesic + +from structs.landmarks import Landmark +import constants + +def get_time(p1: Tuple[float, float], p2: Tuple[float, float]) -> int : + """ + Calculate the time in minutes to travel from one location to another. + + Args: + p1 (Tuple[float, float]): Coordinates of the starting location. + p2 (Tuple[float, float]): Coordinates of the destination. + detour (float): Detour factor affecting the distance. + speed (float): Walking speed in kilometers per hour. + + Returns: + int: Time to travel from p1 to p2 in minutes. + """ + + with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: + parameters = yaml.safe_load(f) + detour_factor = parameters['detour_factor'] + average_walking_speed = parameters['average_walking_speed'] + + # Compute the straight-line distance in km + if p1 == p2 : + return 0 + else: + dist = geodesic(p1, p2).kilometers + + # Consider the detour factor for average cityto deterline walking distance (in km) + walk_dist = dist*detour_factor + + # Time to walk this distance (in minutes) + walk_time = walk_dist/average_walking_speed*60 + + return round(walk_time) + + + + +# Same as link_list but does it on a already ordered list +def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] : + + L = [] + j = 0 + total_dist = 0 + while j < len(ordered_visit)-1 : + elem = ordered_visit[j] + next = ordered_visit[j+1] + + elem.next_uuid = next.uuid + d = get_time(elem.location, next.location) + elem.time_to_reach_next = d + if elem.name not in ['start', 'finish'] : + elem.must_do = True + L.append(elem) + j += 1 + total_dist += d + + L.append(next) + + return L, total_dist + + + +# Take the most important landmarks from the list +def take_most_important(landmarks: List[Landmark], N_important) -> List[Landmark] : + + L = len(landmarks) + L_copy = [] + L_clean = [] + scores = [0]*len(landmarks) + names = [] + name_id = {} + + for i, elem in enumerate(landmarks) : + if elem.name not in names : + names.append(elem.name) + name_id[elem.name] = [i] + L_copy.append(elem) + else : + name_id[elem.name] += [i] + scores = [] + for j in name_id[elem.name] : + scores.append(L[j].attractiveness) + best_id = max(range(len(scores)), key=scores.__getitem__) + t = name_id[elem.name][best_id] + if t == i : + for old in L_copy : + if old.name == elem.name : + old.attractiveness = L[t].attractiveness + + scores = [0]*len(L_copy) + for i, elem in enumerate(L_copy) : + scores[i] = elem.attractiveness + + res = sorted(range(len(scores)), key = lambda sub: scores[sub])[-(N_important-L):] + + for i, elem in enumerate(L_copy) : + if i in res : + L_clean.append(elem) + + return L_clean \ No newline at end of file From 127ba8c0284a73b278e592581a96d47c555f2062 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Sun, 21 Jul 2024 10:16:13 +0200 Subject: [PATCH 2/7] fixed log --- backend/landmarks_Strasbourg.txt | 10082 +++++++++++++++++++++++++++++ backend/src/constants.py | 2 +- backend/src/optimizer.py | 22 +- backend/src/refiner.py | 23 +- backend/src/tester.py | 10 +- 5 files changed, 10111 insertions(+), 28 deletions(-) create mode 100644 backend/landmarks_Strasbourg.txt diff --git a/backend/landmarks_Strasbourg.txt b/backend/landmarks_Strasbourg.txt new file mode 100644 index 0000000..d97fb8e --- /dev/null +++ b/backend/landmarks_Strasbourg.txt @@ -0,0 +1,10082 @@ +{ + "0":{ + "name":"Musée de Sismologie et de Magnétisme Terrestre", + "type":"sightseeing", + "location":[ + 48.5839194, + 7.7656424 + ], + "osm_type":"way", + "osm_id":19794129, + "attractiveness":377, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9f0ed68d-f891-4e0a-8909-90a68e735721", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "1":{ + "name":"Jardin Botanique", + "type":"sightseeing", + "location":[ + 48.583626, + 7.7674616 + ], + "osm_type":"way", + "osm_id":19794224, + "attractiveness":569, + "n_tags":28, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bed47635-ec34-4528-bc21-235c4baf704d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "2":{ + "name":"Musée Historique", + "type":"sightseeing", + "location":[ + 48.5799461, + 7.7509819 + ], + "osm_type":"way", + "osm_id":22290183, + "attractiveness":478, + "n_tags":22, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7411ca05-62cb-42cd-9e04-ac5b7d1a8331", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "3":{ + "name":"Hôtel Mercure Strasbourg Palais des Congrès", + "type":"sightseeing", + "location":[ + 48.5960489, + 7.7580283 + ], + "osm_type":"way", + "osm_id":30923000, + "attractiveness":360, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1b573626-90fa-483d-9c78-48177c135714", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "4":{ + "name":"Hilton Strasbourg", + "type":"sightseeing", + "location":[ + 48.5970002, + 7.7547885 + ], + "osm_type":"way", + "osm_id":36526595, + "attractiveness":613, + "n_tags":30, + "image_url":null, + "description":null, + "duration":0, + "uuid":"16cec4ba-5087-4a86-bddd-4100b0616121", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "5":{ + "name":"Hôtel Suisse", + "type":"sightseeing", + "location":[ + 48.5814183, + 7.7528353 + ], + "osm_type":"way", + "osm_id":39654584, + "attractiveness":128, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a5d5ee89-d757-4728-a0c1-48814f3c0359", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "6":{ + "name":"Hôtel des Anges", + "type":"sightseeing", + "location":[ + 48.5809838, + 7.7494255 + ], + "osm_type":"way", + "osm_id":39855264, + "attractiveness":142, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5e607860-da76-4ea4-bfce-db4888919601", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "7":{ + "name":"Le Bouclier d'Or", + "type":"sightseeing", + "location":[ + 48.5806972, + 7.7436528 + ], + "osm_type":"way", + "osm_id":40019705, + "attractiveness":205, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dfd97548-6649-41a0-9d24-79b03fd7d67b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "8":{ + "name":"Cap Europe Appart'Hotel", + "type":"sightseeing", + "location":[ + 48.5913017, + 7.7535828 + ], + "osm_type":"way", + "osm_id":40030093, + "attractiveness":154, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"52bc59ca-22af-4666-8a64-20d0e255d880", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "9":{ + "name":"Best Western Hotel de l'Europe", + "type":"sightseeing", + "location":[ + 48.5821218, + 7.7428648 + ], + "osm_type":"way", + "osm_id":40108131, + "attractiveness":385, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7fee251b-a074-4831-a0a0-dec4a3c46b83", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "10":{ + "name":"BOMA", + "type":"sightseeing", + "location":[ + 48.583182, + 7.7417657 + ], + "osm_type":"way", + "osm_id":40108706, + "attractiveness":408, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bdd36f26-b30a-4c03-b746-e4ff973e8b2b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "11":{ + "name":"Barrage Vauban", + "type":"sightseeing", + "location":[ + 48.5795997, + 7.7380036 + ], + "osm_type":"way", + "osm_id":40217747, + "attractiveness":569, + "n_tags":24, + "image_url":null, + "description":null, + "duration":0, + "uuid":"615d0fb2-bd80-45e2-a3f2-6e9b56bdad3f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "12":{ + "name":"Musée d'Art Moderne et Contemporain", + "type":"sightseeing", + "location":[ + 48.5794732, + 7.7361604 + ], + "osm_type":"way", + "osm_id":40220422, + "attractiveness":494, + "n_tags":24, + "image_url":null, + "description":null, + "duration":0, + "uuid":"03715222-b85a-4cab-a19b-179f87be60f5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "13":{ + "name":"Ibis", + "type":"sightseeing", + "location":[ + 48.5784497, + 7.7354765 + ], + "osm_type":"way", + "osm_id":40222088, + "attractiveness":406, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9f1df5e2-1234-49da-a408-4ec917d31cce", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "14":{ + "name":"Hôtel du Dragon", + "type":"sightseeing", + "location":[ + 48.5779452, + 7.7464212 + ], + "osm_type":"way", + "osm_id":40379769, + "attractiveness":189, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"05b748ae-3bdb-41bb-9c4b-842017a48a02", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "15":{ + "name":"Institut de Botanique", + "type":"sightseeing", + "location":[ + 48.5840035, + 7.7667973 + ], + "osm_type":"way", + "osm_id":40818707, + "attractiveness":194, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ea3ed3d8-eb86-4b35-a8b9-72163b21403c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "16":{ + "name":"Hôtel des Vosges", + "type":"sightseeing", + "location":[ + 48.5837881, + 7.7352689 + ], + "osm_type":"way", + "osm_id":41121009, + "attractiveness":321, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5e6e4d99-eb88-4133-a462-37ab43d4390a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "17":{ + "name":"Hôtel Vendôme", + "type":"sightseeing", + "location":[ + 48.5840959, + 7.7363994 + ], + "osm_type":"way", + "osm_id":41123371, + "attractiveness":217, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"44ff2689-0ce8-4fe1-9edf-4b1e8bce1413", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "18":{ + "name":"Hôtel Victoria", + "type":"sightseeing", + "location":[ + 48.5838141, + 7.7372317 + ], + "osm_type":"way", + "osm_id":41123377, + "attractiveness":204, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7f8cf024-0833-4c33-988b-07e4483b72f5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "19":{ + "name":"Le Grand Hôtel", + "type":"sightseeing", + "location":[ + 48.5847157, + 7.7369134 + ], + "osm_type":"way", + "osm_id":41123900, + "attractiveness":206, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d8f8b313-0c62-47f6-aa2f-890fa87fbc8b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "20":{ + "name":"Hôtel Monopole Métropole", + "type":"sightseeing", + "location":[ + 48.5851187, + 7.7390396 + ], + "osm_type":"way", + "osm_id":41135600, + "attractiveness":165, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"296e4c66-7cd9-45c4-9c89-6add97eeb9e5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "21":{ + "name":"Odalys Appart'Hôtel Green Marsh", + "type":"sightseeing", + "location":[ + 48.5866791, + 7.7400733 + ], + "osm_type":"way", + "osm_id":41140005, + "attractiveness":217, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"64d72e1f-63d3-4861-9660-00abec787175", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "22":{ + "name":"Hôtel Athena", + "type":"sightseeing", + "location":[ + 48.5917916, + 7.7114199 + ], + "osm_type":"way", + "osm_id":41735108, + "attractiveness":207, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e83925cc-3415-4f86-b8bf-154cfe95b767", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "23":{ + "name":"Campanile Strasbourg Ouest", + "type":"sightseeing", + "location":[ + 48.5886845, + 7.7001986 + ], + "osm_type":"way", + "osm_id":41959958, + "attractiveness":252, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"96000a19-eac7-4494-95b0-b7a945471023", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "24":{ + "name":"Hôtel Arc-en-Ciel", + "type":"sightseeing", + "location":[ + 48.57885, + 7.7175826 + ], + "osm_type":"way", + "osm_id":42411650, + "attractiveness":130, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"11c7557a-5134-49c7-b986-6ab74d7e19df", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "25":{ + "name":"Camping de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5751089, + 7.7164414 + ], + "osm_type":"way", + "osm_id":49805933, + "attractiveness":447, + "n_tags":22, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cb06ebb6-d7fd-4065-917b-9a7999b7a3d4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "26":{ + "name":"Petit Cabinet", + "type":"sightseeing", + "location":[ + 48.5869361, + 7.746716 + ], + "osm_type":"way", + "osm_id":183655704, + "attractiveness":168, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3d5c9b13-597b-4995-adc2-43adb3c39f6c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "27":{ + "name":"Grande Île", + "type":"sightseeing", + "location":[ + 48.5829351, + 7.747696 + ], + "osm_type":"way", + "osm_id":217834967, + "attractiveness":413, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c1302da0-bbb7-4c06-8b67-fa6c4b8c3b7e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "28":{ + "name":"Musée Tomi Ungerer Centre International de l'Illustration", + "type":"sightseeing", + "location":[ + 48.585689, + 7.7550092 + ], + "osm_type":"way", + "osm_id":486650189, + "attractiveness":339, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"206cb9b5-a593-4512-9ad2-40f33fb9dfcc", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "29":{ + "name":"Musée de l'Œuvre Notre-Dame", + "type":"sightseeing", + "location":[ + 48.580867, + 7.751182 + ], + "osm_type":"way", + "osm_id":491674514, + "attractiveness":278, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8cde4028-ed83-4f45-9409-77bf4291ee06", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "30":{ + "name":"K Hôtel", + "type":"sightseeing", + "location":[ + 48.5939733, + 7.7136948 + ], + "osm_type":"way", + "osm_id":693583859, + "attractiveness":130, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6c28ce78-44a0-42bb-97a5-4803e289f85d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "31":{ + "name":"Aloft", + "type":"sightseeing", + "location":[ + 48.572935, + 7.7560101 + ], + "osm_type":"way", + "osm_id":725969144, + "attractiveness":417, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"127dbef5-3b84-475b-9dc5-c825d76a13ae", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "32":{ + "name":"Citadines Eurométropole Strasbourg", + "type":"sightseeing", + "location":[ + 48.604241, + 7.7045715 + ], + "osm_type":"way", + "osm_id":939510639, + "attractiveness":204, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"922aec12-5f43-4552-a7bc-21bd14b515f3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "33":{ + "name":"The People – Strasbourg", + "type":"sightseeing", + "location":[ + 48.581353, + 7.7575867 + ], + "osm_type":"way", + "osm_id":1053292872, + "attractiveness":407, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"223241d2-9a0a-4ef2-ace3-dfb793111952", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "34":{ + "name":"Cabinet des Estampes et des Dessins", + "type":"sightseeing", + "location":[ + 48.5810219, + 7.7507074 + ], + "osm_type":"relation", + "osm_id":222359, + "attractiveness":301, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5d08c61b-0719-4e5c-931d-4532c005be09", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "35":{ + "name":"Cathédrale Notre-Dame", + "type":"sightseeing", + "location":[ + 48.5818887, + 7.7510342 + ], + "osm_type":"relation", + "osm_id":3541088, + "attractiveness":961, + "n_tags":35, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dd630831-06b4-46a8-9cd9-8c87c017c031", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "36":{ + "name":"Circuit « Petite France »", + "type":"sightseeing", + "location":[ + 48.5807382, + 7.7450251 + ], + "osm_type":"relation", + "osm_id":5354622, + "attractiveness":423, + "n_tags":21, + "image_url":null, + "description":null, + "duration":0, + "uuid":"34b5efa9-cbb6-4986-9afa-30f48a919483", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "37":{ + "name":"De la Grande île à la Neustadt", + "type":"sightseeing", + "location":[ + 48.5849416, + 7.7539938 + ], + "osm_type":"relation", + "osm_id":16782493, + "attractiveness":432, + "n_tags":21, + "image_url":null, + "description":null, + "duration":0, + "uuid":"59ca33d2-05f3-49dc-a322-cc75245dbcf5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "38":{ + "name":"Palais Rohan", + "type":"sightseeing", + "location":[ + 48.5810157, + 7.7522537 + ], + "osm_type":"way", + "osm_id":15806990, + "attractiveness":261, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ff50c6b5-83c3-4ad5-8b92-efebeb986447", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "39":{ + "name":"Monument du Général Kléber", + "type":"sightseeing", + "location":[ + 48.5833724, + 7.7457745 + ], + "osm_type":"way", + "osm_id":39224822, + "attractiveness":262, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e9af0669-5937-49ab-a0d8-ea1147f629e6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "40":{ + "name":"Grand Séminaire Catholique", + "type":"sightseeing", + "location":[ + 48.5823972, + 7.7521116 + ], + "osm_type":"way", + "osm_id":39647774, + "attractiveness":108, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e7499242-8469-4c52-a1cb-4e4bbad7e86b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "41":{ + "name":"Tour du Bourreau", + "type":"sightseeing", + "location":[ + 48.5814532, + 7.7387351 + ], + "osm_type":"way", + "osm_id":40034170, + "attractiveness":265, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2587a519-c75b-4965-9bc5-aadf231486a1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "42":{ + "name":"Église Catholique Saint-Jean-Baptiste", + "type":"sightseeing", + "location":[ + 48.584387, + 7.7400892 + ], + "osm_type":"way", + "osm_id":40202919, + "attractiveness":396, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c1663d50-875d-4d21-a748-fd7c66c36dcf", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "43":{ + "name":"Heinrichsturm", + "type":"sightseeing", + "location":[ + 48.5802849, + 7.7390529 + ], + "osm_type":"way", + "osm_id":40217739, + "attractiveness":266, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"27845ee8-3f67-4357-9492-5af2e107255f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "44":{ + "name":"Hans von Altheimturm", + "type":"sightseeing", + "location":[ + 48.5798164, + 7.7393752 + ], + "osm_type":"way", + "osm_id":40217740, + "attractiveness":264, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5af48fb0-d564-42fa-a82b-d33af353511d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "45":{ + "name":"Tour des Français", + "type":"sightseeing", + "location":[ + 48.5793988, + 7.7396847 + ], + "osm_type":"way", + "osm_id":40217762, + "attractiveness":281, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"98b4c760-5cd0-458b-b292-a6ac5805d0b7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "46":{ + "name":"Porte de l'Hôpital", + "type":"sightseeing", + "location":[ + 48.5770255, + 7.7495671 + ], + "osm_type":"way", + "osm_id":40317901, + "attractiveness":340, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"987e083f-a93e-4c3d-8449-c6dd368731f6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "47":{ + "name":"Bains municipaux de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5833343, + 7.7595517 + ], + "osm_type":"way", + "osm_id":40469009, + "attractiveness":507, + "n_tags":25, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7c3a9e85-0b3e-44c3-8b10-10c5c0872e1c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "48":{ + "name":"Bains Médicinaux", + "type":"sightseeing", + "location":[ + 48.5834571, + 7.7603718 + ], + "osm_type":"way", + "osm_id":40469010, + "attractiveness":229, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a1c028b7-aa6d-454c-928f-ea800d0b9d51", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "49":{ + "name":"Église protestante Sainte-Aurélie", + "type":"sightseeing", + "location":[ + 48.581415, + 7.7332719 + ], + "osm_type":"way", + "osm_id":40981668, + "attractiveness":338, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5ca68982-ca85-4760-97bc-a7b817174518", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "50":{ + "name":"Ponts Couverts", + "type":"sightseeing", + "location":[ + 48.5800883, + 7.739337 + ], + "osm_type":"way", + "osm_id":416477168, + "attractiveness":284, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"51b30ff9-f05f-4664-896f-ace4944b4d78", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "51":{ + "name":"Pont Saint-Nicolas", + "type":"sightseeing", + "location":[ + 48.5787541, + 7.7485761 + ], + "osm_type":"way", + "osm_id":458914503, + "attractiveness":356, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2dd42bd5-8613-4db6-8f89-84efa594f8ae", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "52":{ + "name":"Tour du Schlössel", + "type":"sightseeing", + "location":[ + 48.5765199, + 7.7143364 + ], + "osm_type":"way", + "osm_id":944755351, + "attractiveness":242, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"506019a0-94de-4d24-9b4c-6696bd8e5e88", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "53":{ + "name":"Palais du Rhin", + "type":"sightseeing", + "location":[ + 48.5876327, + 7.7525605 + ], + "osm_type":"relation", + "osm_id":226986, + "attractiveness":693, + "n_tags":33, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9c3fb97e-de75-45cc-91e8-a4d4ee166d35", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "54":{ + "name":"Faculté de Chimie", + "type":"sightseeing", + "location":[ + 48.5808057, + 7.7675818 + ], + "osm_type":"way", + "osm_id":13864892, + "attractiveness":134, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7ff61c6a-47eb-4451-8b06-6d18f8f7cf4d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "55":{ + "name":"Faculté de Droit", + "type":"sightseeing", + "location":[ + 48.5789616, + 7.7673966 + ], + "osm_type":"way", + "osm_id":13864895, + "attractiveness":359, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eb55796d-8d08-495f-9e4e-b3a8fc33a5de", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "56":{ + "name":"Théâtre National de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5863674, + 7.7553605 + ], + "osm_type":"way", + "osm_id":15726858, + "attractiveness":377, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a4b50aa3-3866-456f-aee6-9f044f5d7357", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "57":{ + "name":"Arte", + "type":"sightseeing", + "location":[ + 48.5939554, + 7.7659797 + ], + "osm_type":"way", + "osm_id":18882357, + "attractiveness":392, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"14de4719-7d71-46a0-ab44-d4d74b06ba60", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "58":{ + "name":"Faculté de Philosophie", + "type":"sightseeing", + "location":[ + 48.5835896, + 7.7653134 + ], + "osm_type":"way", + "osm_id":19794090, + "attractiveness":111, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f0e39279-f6ab-4b40-b75d-5a8f9e561a5c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "59":{ + "name":"Institut Le Bel", + "type":"sightseeing", + "location":[ + 48.5806815, + 7.7662739 + ], + "osm_type":"way", + "osm_id":19794506, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7775dd47-73cd-47a6-bc59-e68f80a28987", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "60":{ + "name":"Restaurant Universitaire de l'Esplanade", + "type":"sightseeing", + "location":[ + 48.5816703, + 7.765895 + ], + "osm_type":"way", + "osm_id":19794529, + "attractiveness":105, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"af217de4-89cb-49c8-8a89-c6fc5c730494", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "61":{ + "name":"Institut de Physiologie et Chimie Biologique", + "type":"sightseeing", + "location":[ + 48.5797337, + 7.7657748 + ], + "osm_type":"way", + "osm_id":19794641, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"89a827de-5496-4c6a-bd19-b584858435f1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "62":{ + "name":"Institut de Biologie Moléculaire et Cellulaire", + "type":"sightseeing", + "location":[ + 48.5796264, + 7.7647679 + ], + "osm_type":"way", + "osm_id":19794665, + "attractiveness":121, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"74efed29-c7dd-47bd-984d-cbb027c35ec0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "63":{ + "name":"Institut de Science et d'Ingénierie Supramoléculaires", + "type":"sightseeing", + "location":[ + 48.5804265, + 7.7644021 + ], + "osm_type":"way", + "osm_id":19794670, + "attractiveness":199, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3c21ce48-325a-4b79-992c-9092d66b75d2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "64":{ + "name":"Centre de culture numérique", + "type":"sightseeing", + "location":[ + 48.5784977, + 7.7636069 + ], + "osm_type":"way", + "osm_id":19794752, + "attractiveness":231, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2f8d2e80-d73c-41b9-ac94-da358af78ae4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "65":{ + "name":"Escarpe", + "type":"sightseeing", + "location":[ + 48.5785033, + 7.7618452 + ], + "osm_type":"way", + "osm_id":19794775, + "attractiveness":130, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ceb0af82-7ba8-486e-a1e3-a9aeca418645", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "66":{ + "name":"L'Alinéa", + "type":"sightseeing", + "location":[ + 48.5790396, + 7.7620889 + ], + "osm_type":"way", + "osm_id":19794794, + "attractiveness":157, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"10274e35-1a17-49f5-a513-81ba0e990610", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "67":{ + "name":"Le Portique (Facultés : Arts, Lettres, STAPS et Direction du numérique)", + "type":"sightseeing", + "location":[ + 48.5783754, + 7.7626347 + ], + "osm_type":"way", + "osm_id":19794805, + "attractiveness":230, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"49570454-bdc9-4d53-afad-7dcd4209985e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "68":{ + "name":"Parking France 3", + "type":"sightseeing", + "location":[ + 48.5943751, + 7.7589818 + ], + "osm_type":"way", + "osm_id":19798679, + "attractiveness":120, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ac857c13-5696-4bf4-8002-cd1b57120ccd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "69":{ + "name":"Bourse", + "type":"sightseeing", + "location":[ + 48.5759064, + 7.7537168 + ], + "osm_type":"way", + "osm_id":20211705, + "attractiveness":151, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7195c3cd-b50d-427b-8ab7-adadb68c27ec", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "70":{ + "name":"Collège et Lycée Kléber", + "type":"sightseeing", + "location":[ + 48.5949669, + 7.7548434 + ], + "osm_type":"way", + "osm_id":20350865, + "attractiveness":90, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a9c9d65c-9d53-4f1b-9b6d-58cfe45e406a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "71":{ + "name":"Collège Sophie Germain", + "type":"sightseeing", + "location":[ + 48.601044, + 7.7190318 + ], + "osm_type":"way", + "osm_id":23291903, + "attractiveness":92, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f5c24ec4-b28a-43b1-a1ef-008e4aee8083", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "72":{ + "name":"Groupe Scolaire Gustave Doré", + "type":"sightseeing", + "location":[ + 48.5986753, + 7.7122322 + ], + "osm_type":"way", + "osm_id":23297801, + "attractiveness":95, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c4b5f4eb-32b7-4880-bb1c-5d56a30265ee", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "73":{ + "name":"Écoles Maternelles et Élémentaires Paul Langenvin 1 et 2", + "type":"sightseeing", + "location":[ + 48.6034985, + 7.716368 + ], + "osm_type":"way", + "osm_id":23312573, + "attractiveness":94, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"79e92d6b-b570-47be-b5be-ca32ca3f1ee9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "74":{ + "name":"Médiathèque de Neudorf", + "type":"sightseeing", + "location":[ + 48.5667916, + 7.7604529 + ], + "osm_type":"way", + "osm_id":23887731, + "attractiveness":313, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fe6fcdef-bddb-4caa-9c55-7bb875fedc04", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "75":{ + "name":"Place du Marché - Neudorf", + "type":"sightseeing", + "location":[ + 48.5661482, + 7.7598405 + ], + "osm_type":"way", + "osm_id":23887733, + "attractiveness":182, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dad35feb-b508-400e-9f26-bc00a51cf6a9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "76":{ + "name":"Groupement Scolaire du Neufeld", + "type":"sightseeing", + "location":[ + 48.5660134, + 7.75528 + ], + "osm_type":"way", + "osm_id":23887737, + "attractiveness":62, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"29be1355-690d-410a-92c1-def996903660", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "77":{ + "name":"École de la Musau", + "type":"sightseeing", + "location":[ + 48.5680318, + 7.7671475 + ], + "osm_type":"way", + "osm_id":24304030, + "attractiveness":88, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c0acb105-11ec-4b7d-b75a-d3e7c470aeab", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "78":{ + "name":"Place Saint-Aloïse", + "type":"sightseeing", + "location":[ + 48.5643934, + 7.7613271 + ], + "osm_type":"way", + "osm_id":24305747, + "attractiveness":135, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"09d49edc-750f-4e61-a118-1d2318b64802", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "79":{ + "name":"Schluthfeld", + "type":"sightseeing", + "location":[ + 48.5684604, + 7.7521982 + ], + "osm_type":"way", + "osm_id":24513151, + "attractiveness":177, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"daeaf610-b780-46ff-be1b-829aea90b8c4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "80":{ + "name":"Collège privé École Libre Sainte-Anne", + "type":"sightseeing", + "location":[ + 48.5636411, + 7.7607111 + ], + "osm_type":"way", + "osm_id":24805838, + "attractiveness":131, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"82022706-490c-42f7-8fc2-bf59fb4cea4e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "81":{ + "name":"École du Schluthfeld", + "type":"sightseeing", + "location":[ + 48.5678645, + 7.7491983 + ], + "osm_type":"way", + "osm_id":24909940, + "attractiveness":86, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b6ece52e-f3f9-4c78-aea3-5c45ab4f1024", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "82":{ + "name":"Station", + "type":"sightseeing", + "location":[ + 48.5656626, + 7.7515126 + ], + "osm_type":"way", + "osm_id":24909962, + "attractiveness":112, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ff00d333-26d5-4c00-ab83-de7f9356f657", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "83":{ + "name":"Rue Murillo", + "type":"sightseeing", + "location":[ + 48.5694085, + 7.7254854 + ], + "osm_type":"way", + "osm_id":25806363, + "attractiveness":133, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4e67ae72-69f0-4d53-bd2c-7e9380b311c8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "84":{ + "name":"Médiathèque André Malraux", + "type":"sightseeing", + "location":[ + 48.5743688, + 7.7603277 + ], + "osm_type":"way", + "osm_id":26199271, + "attractiveness":503, + "n_tags":25, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a06a2062-aeec-4670-8026-7613da783ac3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "85":{ + "name":"Cité de la Musique et de la Danse", + "type":"sightseeing", + "location":[ + 48.5743496, + 7.7558309 + ], + "osm_type":"way", + "osm_id":26199286, + "attractiveness":443, + "n_tags":22, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b0536c30-e21f-4d07-8d53-1b0fc6a86f06", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "86":{ + "name":"Hôtel de Ville", + "type":"sightseeing", + "location":[ + 48.5846612, + 7.7506403 + ], + "osm_type":"way", + "osm_id":26306273, + "attractiveness":518, + "n_tags":24, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3a18b2e1-4492-4b83-989f-a42d4e80473f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "87":{ + "name":"Place du Petit Broglie", + "type":"sightseeing", + "location":[ + 48.5856807, + 7.7525991 + ], + "osm_type":"way", + "osm_id":26306276, + "attractiveness":139, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c88b6d75-e648-486f-b83a-40d3aeb956d9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "88":{ + "name":"Gare Routière des Halles", + "type":"sightseeing", + "location":[ + 48.5874507, + 7.7414787 + ], + "osm_type":"way", + "osm_id":26323668, + "attractiveness":161, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"45a1f47c-5b4b-4c34-a626-456bee983735", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "89":{ + "name":"Institut de Recherches Mathématiques Avancées", + "type":"sightseeing", + "location":[ + 48.5804485, + 7.7627777 + ], + "osm_type":"way", + "osm_id":26497260, + "attractiveness":126, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2c260555-1d44-46f8-9ee6-afa4d97552ea", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "90":{ + "name":"Parking relais-tram P+R Elsau", + "type":"sightseeing", + "location":[ + 48.5683182, + 7.729944 + ], + "osm_type":"way", + "osm_id":30548950, + "attractiveness":175, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"72c7183c-46b6-4c2f-98ab-a187d6cf44dd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "91":{ + "name":"Église Saint-Étienne", + "type":"sightseeing", + "location":[ + 48.5834519, + 7.7558552 + ], + "osm_type":"way", + "osm_id":30922600, + "attractiveness":341, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f91a48e3-a996-4a26-8a05-831a2332efd0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "92":{ + "name":"Palais de la Musique et des Congrès", + "type":"sightseeing", + "location":[ + 48.5981089, + 7.7571462 + ], + "osm_type":"way", + "osm_id":30922996, + "attractiveness":144, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f79ca431-6a49-4fa1-bfee-74d28b362534", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "93":{ + "name":"Place du Faubourg de Pierre", + "type":"sightseeing", + "location":[ + 48.5904825, + 7.7453657 + ], + "osm_type":"way", + "osm_id":32261307, + "attractiveness":174, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2f1735a6-c958-44ec-8f6d-8d7bf8952274", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "94":{ + "name":"Église Saint-Florent", + "type":"sightseeing", + "location":[ + 48.5963301, + 7.7221529 + ], + "osm_type":"way", + "osm_id":33455820, + "attractiveness":196, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b9551b66-5e0f-444f-bc7e-b7e70636a813", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "95":{ + "name":"Église Évangélique Agap", + "type":"sightseeing", + "location":[ + 48.5917592, + 7.7458688 + ], + "osm_type":"way", + "osm_id":35978861, + "attractiveness":135, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8a3b8c09-6b39-4667-b2ea-7b6a2a5b54ba", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "96":{ + "name":"Salle de la Marseillaise", + "type":"sightseeing", + "location":[ + 48.5911749, + 7.7491341 + ], + "osm_type":"way", + "osm_id":36000284, + "attractiveness":108, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0a1ada42-c643-46cd-996a-f1e7060c289c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "97":{ + "name":"ESAV Strasbourg", + "type":"sightseeing", + "location":[ + 48.5906846, + 7.7397307 + ], + "osm_type":"way", + "osm_id":36269921, + "attractiveness":295, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4a3ea579-1f91-457b-a3f1-fd492df666ef", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "98":{ + "name":"Centre de bouddhisme zen", + "type":"sightseeing", + "location":[ + 48.5908924, + 7.7403924 + ], + "osm_type":"way", + "osm_id":36269935, + "attractiveness":237, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bf483162-12ad-4f4e-97ec-d8fa748d75c9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "99":{ + "name":"Halles P3 Wilson", + "type":"sightseeing", + "location":[ + 48.587919, + 7.7400469 + ], + "osm_type":"way", + "osm_id":36271630, + "attractiveness":237, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ba8054ed-02a5-440d-801a-18934d409e20", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "100":{ + "name":"Groupe École Élémentaire Saint-Jean", + "type":"sightseeing", + "location":[ + 48.5891746, + 7.7434643 + ], + "osm_type":"way", + "osm_id":36274410, + "attractiveness":78, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"470c4bf0-0c61-4b4c-ace7-40a865d3ed1d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "101":{ + "name":"Église Saint-Sauveur", + "type":"sightseeing", + "location":[ + 48.5945471, + 7.7168371 + ], + "osm_type":"way", + "osm_id":39173571, + "attractiveness":199, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2c1c488f-5e76-4118-8a7c-a1051f458056", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "102":{ + "name":"Église protestante Saint-Pierre-le-Jeune", + "type":"sightseeing", + "location":[ + 48.5855301, + 7.7465472 + ], + "osm_type":"way", + "osm_id":39540475, + "attractiveness":469, + "n_tags":22, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8093f85e-50d6-4894-9a6f-d5fb56d4eebb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "103":{ + "name":"Gymnase Jean Sturm", + "type":"sightseeing", + "location":[ + 48.5837383, + 7.7484667 + ], + "osm_type":"way", + "osm_id":39543346, + "attractiveness":419, + "n_tags":21, + "image_url":null, + "description":null, + "duration":0, + "uuid":"db33458e-8e16-4173-807c-bfab2f688a67", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "104":{ + "name":"Temple Neuf", + "type":"sightseeing", + "location":[ + 48.5832839, + 7.7484535 + ], + "osm_type":"way", + "osm_id":39543348, + "attractiveness":268, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5a9db4f3-bcb9-417e-adbc-4cf1d7922053", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "105":{ + "name":"Place du Marché-Neuf", + "type":"sightseeing", + "location":[ + 48.5826283, + 7.7483066 + ], + "osm_type":"way", + "osm_id":39546463, + "attractiveness":159, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d3119394-d88e-4aaa-b26d-cb4e31568c07", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "106":{ + "name":"Groupe Scolaire Schoepflin", + "type":"sightseeing", + "location":[ + 48.5865506, + 7.7486118 + ], + "osm_type":"way", + "osm_id":39600444, + "attractiveness":82, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cf3fdc32-803a-4f4f-9cfe-2447d1622770", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "107":{ + "name":"Banque de France", + "type":"sightseeing", + "location":[ + 48.5850576, + 7.7490192 + ], + "osm_type":"way", + "osm_id":39605775, + "attractiveness":180, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b7ccdceb-942c-4c8f-9535-3da7c4f97322", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "108":{ + "name":"Palais du Gouverneur", + "type":"sightseeing", + "location":[ + 48.5851154, + 7.751928 + ], + "osm_type":"way", + "osm_id":39610248, + "attractiveness":205, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"44a5f13b-9d7e-4ea5-ae7f-417eb9ccde37", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "109":{ + "name":"Bistrot et chocolat", + "type":"sightseeing", + "location":[ + 48.5814987, + 7.7530011 + ], + "osm_type":"way", + "osm_id":39654586, + "attractiveness":338, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5304eaca-120d-4b23-8e09-e9d28caba9e7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "110":{ + "name":"École maternelle Louis Pasteur", + "type":"sightseeing", + "location":[ + 48.5818982, + 7.7549376 + ], + "osm_type":"way", + "osm_id":39657144, + "attractiveness":206, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8966cb70-5c83-402b-a451-b18e9b36b4ec", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "111":{ + "name":"Pharmacie du Roethig", + "type":"sightseeing", + "location":[ + 48.5655159, + 7.7069482 + ], + "osm_type":"way", + "osm_id":39668928, + "attractiveness":166, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4c2273cc-6db9-4fbb-9654-c269b7b15678", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "112":{ + "name":"Église Saint-Jean", + "type":"sightseeing", + "location":[ + 48.5672768, + 7.7074115 + ], + "osm_type":"way", + "osm_id":39688961, + "attractiveness":138, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"412955bd-9b1d-4328-8952-5a29cc0abcc1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "113":{ + "name":"Au Vieux Strasbourg", + "type":"sightseeing", + "location":[ + 48.5805253, + 7.7507252 + ], + "osm_type":"way", + "osm_id":39754699, + "attractiveness":289, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b69c45da-b7c1-4140-aba6-6f3e10a2d10b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "114":{ + "name":"Au Bon Vivant", + "type":"sightseeing", + "location":[ + 48.5805996, + 7.75063 + ], + "osm_type":"way", + "osm_id":39846430, + "attractiveness":250, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"26806eb1-dd09-4c09-be55-83f49b79461d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "115":{ + "name":"Il Felice", + "type":"sightseeing", + "location":[ + 48.5806412, + 7.7489822 + ], + "osm_type":"way", + "osm_id":39846452, + "attractiveness":392, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"04dc89aa-4e60-43f0-8384-53206a9ed71f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "116":{ + "name":"Le Pilier des Anges", + "type":"sightseeing", + "location":[ + 48.5813183, + 7.7492671 + ], + "osm_type":"way", + "osm_id":39855297, + "attractiveness":149, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"636a517c-23c4-4228-b40f-39fcac5f9bbb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "117":{ + "name":"CCF", + "type":"sightseeing", + "location":[ + 48.5812475, + 7.7479124 + ], + "osm_type":"way", + "osm_id":39860111, + "attractiveness":262, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2291db6d-fc94-4999-909f-7825c409c6e4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "118":{ + "name":"McDonald's", + "type":"sightseeing", + "location":[ + 48.604711, + 7.7052976 + ], + "osm_type":"way", + "osm_id":39896378, + "attractiveness":329, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"98cae356-eba6-4ac5-a9ce-0274f1fdfbc0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "119":{ + "name":"Au Pigeon", + "type":"sightseeing", + "location":[ + 48.5803796, + 7.7487548 + ], + "osm_type":"way", + "osm_id":39971175, + "attractiveness":252, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e7741eab-1a2a-4395-9e49-4c05384d1404", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "120":{ + "name":"Église protestante Saint-Thomas", + "type":"sightseeing", + "location":[ + 48.5796572, + 7.7456235 + ], + "osm_type":"way", + "osm_id":39973703, + "attractiveness":444, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a7fd3394-6b61-4d9a-b556-4aa1cbd993ab", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "121":{ + "name":"Église Réformée", + "type":"sightseeing", + "location":[ + 48.5806662, + 7.7443997 + ], + "osm_type":"way", + "osm_id":39981658, + "attractiveness":172, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e051e440-46a4-4a67-87d3-e90eb2ac7255", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "122":{ + "name":"Centre d'incendie et de secours Strasbourg-Finkwiller", + "type":"sightseeing", + "location":[ + 48.5790899, + 7.7437902 + ], + "osm_type":"way", + "osm_id":39985236, + "attractiveness":191, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9a520e79-4efb-48c7-98a9-c40a0d63fcec", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "123":{ + "name":"École maternelle Saint-Thomas", + "type":"sightseeing", + "location":[ + 48.5799212, + 7.7439536 + ], + "osm_type":"way", + "osm_id":39985245, + "attractiveness":149, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"448c132f-ae9e-48e8-a8b4-f05820cc05e9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "124":{ + "name":"Église Méthodiste de Sion", + "type":"sightseeing", + "location":[ + 48.5814329, + 7.7425746 + ], + "osm_type":"way", + "osm_id":40020421, + "attractiveness":216, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2ce06c01-a9fe-4c28-ac78-38142dd409ed", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "125":{ + "name":"Tribunal Administratif", + "type":"sightseeing", + "location":[ + 48.5916523, + 7.7564303 + ], + "osm_type":"way", + "osm_id":40030105, + "attractiveness":166, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"02e4bb3a-2b86-448c-8795-3665c74e32a9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "126":{ + "name":"L'ami Schutz", + "type":"sightseeing", + "location":[ + 48.5804584, + 7.739231 + ], + "osm_type":"way", + "osm_id":40033008, + "attractiveness":393, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5eddab74-53a4-418b-99ab-925da5a21866", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "127":{ + "name":"Place Grimmeissen", + "type":"sightseeing", + "location":[ + 48.5818492, + 7.7403931 + ], + "osm_type":"way", + "osm_id":40098226, + "attractiveness":194, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e1d29057-fe71-4aeb-a484-10a387d5e6bb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "128":{ + "name":"Église protestante Saint-Pierre-le-Vieux", + "type":"sightseeing", + "location":[ + 48.5827492, + 7.7396207 + ], + "osm_type":"way", + "osm_id":40105161, + "attractiveness":190, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b1c60ad3-c20c-49f5-a100-0b538936af8d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "129":{ + "name":"Église catholique Saint-Pierre le-vieux", + "type":"sightseeing", + "location":[ + 48.5828014, + 7.7399978 + ], + "osm_type":"way", + "osm_id":40105163, + "attractiveness":219, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5543f0a5-b802-4161-859d-68399d7dd3ba", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "130":{ + "name":"École Aquiba (Lycée général privé)", + "type":"sightseeing", + "location":[ + 48.5898064, + 7.7530301 + ], + "osm_type":"way", + "osm_id":40106312, + "attractiveness":163, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6618c866-6fe7-49d9-97ad-cfe9aa4b3eb5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "131":{ + "name":"Synagogue de la Paix", + "type":"sightseeing", + "location":[ + 48.590289, + 7.7566482 + ], + "osm_type":"way", + "osm_id":40142894, + "attractiveness":227, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4d3b0bb2-c04b-4e69-8d00-8b540dd04809", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "132":{ + "name":"Lycée René Cassin annexe Sévigné", + "type":"sightseeing", + "location":[ + 48.5886641, + 7.7568747 + ], + "osm_type":"way", + "osm_id":40142934, + "attractiveness":105, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6bad442f-5d44-487f-98a2-4397d8fbba71", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "133":{ + "name":"Église catholique Saint-Pierre-le-Jeune", + "type":"sightseeing", + "location":[ + 48.5883647, + 7.748845 + ], + "osm_type":"way", + "osm_id":40192519, + "attractiveness":357, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9a7bee43-970a-45d5-8960-9bd3c8e12d27", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "134":{ + "name":"Collège Foch", + "type":"sightseeing", + "location":[ + 48.5886045, + 7.7512891 + ], + "osm_type":"way", + "osm_id":40196946, + "attractiveness":128, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6a167378-b59d-4909-ae28-b7d84f004b28", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "135":{ + "name":"Médiathèque Olympe de Gouges (Centre ville)", + "type":"sightseeing", + "location":[ + 48.584774, + 7.7394013 + ], + "osm_type":"way", + "osm_id":40202917, + "attractiveness":185, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8904810f-a090-4288-89e4-e3fba4b7805f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "136":{ + "name":"Ibis Kitchen Restaurant", + "type":"sightseeing", + "location":[ + 48.5783773, + 7.7356662 + ], + "osm_type":"way", + "osm_id":40222090, + "attractiveness":359, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c93b4e1c-7ef3-47ea-9c31-970811376319", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "137":{ + "name":"Faculté de Médecine", + "type":"sightseeing", + "location":[ + 48.5769454, + 7.739286 + ], + "osm_type":"way", + "osm_id":40237349, + "attractiveness":134, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5a8f4af0-9f45-4b60-9e1b-9b15a4f4fcd1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "138":{ + "name":"Lycée Louis Pasteur", + "type":"sightseeing", + "location":[ + 48.5752694, + 7.7376886 + ], + "osm_type":"way", + "osm_id":40237350, + "attractiveness":109, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"120df774-018b-498e-bfeb-9f9d7da20434", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "139":{ + "name":"Institut de Bactériologie", + "type":"sightseeing", + "location":[ + 48.5749725, + 7.738734 + ], + "osm_type":"way", + "osm_id":40237356, + "attractiveness":76, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"36a67bde-6b09-40ce-8eb9-d356dea06a15", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "140":{ + "name":"Crèche Kirschleger", + "type":"sightseeing", + "location":[ + 48.5769081, + 7.7404528 + ], + "osm_type":"way", + "osm_id":40243090, + "attractiveness":67, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1e65a474-6212-4dcb-8574-cbc07dda2b31", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "141":{ + "name":"Argos", + "type":"sightseeing", + "location":[ + 48.5746795, + 7.7448267 + ], + "osm_type":"way", + "osm_id":40243103, + "attractiveness":289, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c2e7eef1-5ddd-4e27-adee-f553667ef0c7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "142":{ + "name":"P1 Saint-Nicolas", + "type":"sightseeing", + "location":[ + 48.5755887, + 7.7495129 + ], + "osm_type":"way", + "osm_id":40245262, + "attractiveness":238, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0b77156e-a528-43fe-91b9-44dea211f5cf", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "143":{ + "name":"Amphithéâtre de la clinique médicale B", + "type":"sightseeing", + "location":[ + 48.5747867, + 7.7481906 + ], + "osm_type":"way", + "osm_id":40249470, + "attractiveness":76, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"145b1faa-f128-419a-be65-18f6e409ff64", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "144":{ + "name":"Institut de Formation en Masso-Kinésithérapie", + "type":"sightseeing", + "location":[ + 48.5781901, + 7.7415388 + ], + "osm_type":"way", + "osm_id":40253162, + "attractiveness":198, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bd41f7ed-dc73-474e-bb39-6a0aace6b66e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "145":{ + "name":"Lucie Berger", + "type":"sightseeing", + "location":[ + 48.5781225, + 7.7427041 + ], + "osm_type":"way", + "osm_id":40280907, + "attractiveness":112, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0f285a2d-5ea7-46ff-8e46-7c149d6a1b33", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "146":{ + "name":"EHPAD Emmaüs-Diaconesses Strasbourg Centre ville", + "type":"sightseeing", + "location":[ + 48.577525, + 7.7436514 + ], + "osm_type":"way", + "osm_id":40280916, + "attractiveness":315, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"481ad79d-fb8e-4e8a-ac71-44d27a575a62", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "147":{ + "name":"Résidence Les Jardins d'Alsace", + "type":"sightseeing", + "location":[ + 48.5780269, + 7.7444039 + ], + "osm_type":"way", + "osm_id":40290709, + "attractiveness":256, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"09740f80-518f-4996-bb8a-8f29826da0ce", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "148":{ + "name":"EHPAD Abrapa Finkviller", + "type":"sightseeing", + "location":[ + 48.5774871, + 7.7454283 + ], + "osm_type":"way", + "osm_id":40308509, + "attractiveness":288, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e244c5cb-b0d4-4025-9ce3-a1de5f017f82", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "149":{ + "name":"Administration faculté dentaire", + "type":"sightseeing", + "location":[ + 48.5769562, + 7.7454455 + ], + "osm_type":"way", + "osm_id":40308511, + "attractiveness":107, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"71bc70a8-0e5e-4388-a8ca-bc45cdab6740", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "150":{ + "name":"Institut d'Anatomie Normale et Pathologique", + "type":"sightseeing", + "location":[ + 48.5759435, + 7.7466173 + ], + "osm_type":"way", + "osm_id":40314911, + "attractiveness":63, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c6892618-0b06-461d-8931-a883e54dc444", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "151":{ + "name":"Institut de Physique Biologique", + "type":"sightseeing", + "location":[ + 48.5754874, + 7.7471003 + ], + "osm_type":"way", + "osm_id":40314914, + "attractiveness":81, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a423f7e5-5c37-4a99-badb-754cd442d42b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "152":{ + "name":"Institut d'Hématologie et d'Immunologie", + "type":"sightseeing", + "location":[ + 48.5760271, + 7.7477538 + ], + "osm_type":"way", + "osm_id":40314917, + "attractiveness":81, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7974cc18-bed3-4027-8cdb-f860789d2c78", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "153":{ + "name":"Chapelle Saint-Erhard", + "type":"sightseeing", + "location":[ + 48.5771492, + 7.7492781 + ], + "osm_type":"way", + "osm_id":40317899, + "attractiveness":190, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e509d687-2b41-495e-8272-1307b9963ec2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "154":{ + "name":"Église catholique Saint-Louis", + "type":"sightseeing", + "location":[ + 48.5782854, + 7.7456547 + ], + "osm_type":"way", + "osm_id":40382455, + "attractiveness":276, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b3c8c1df-33b8-41ad-b92c-8a217c43f9cd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "155":{ + "name":"Section professionnelle du lycée Cassin", + "type":"sightseeing", + "location":[ + 48.578316, + 7.7465314 + ], + "osm_type":"way", + "osm_id":40382462, + "attractiveness":197, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4961bea3-6195-4d73-9d32-d37c57bbf3b2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "156":{ + "name":"Église Saint-Nicolas", + "type":"sightseeing", + "location":[ + 48.5783593, + 7.748501 + ], + "osm_type":"way", + "osm_id":40384394, + "attractiveness":436, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"db46e597-97a4-403a-b0f3-ba7c8f8c426a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "157":{ + "name":"Église catholique Sainte-Madeleine", + "type":"sightseeing", + "location":[ + 48.5799473, + 7.7548339 + ], + "osm_type":"way", + "osm_id":40450470, + "attractiveness":375, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eff0d077-d652-4fb5-8c05-3f17670a23ba", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "158":{ + "name":"Lycée professionnel Jean Geiler de Kaysersberg", + "type":"sightseeing", + "location":[ + 48.580009, + 7.7555067 + ], + "osm_type":"way", + "osm_id":40450503, + "attractiveness":183, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b565d0e1-911a-413e-b54d-37efed6dbadd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "159":{ + "name":"École nationale du génie des eaux et de l'environnement de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5850183, + 7.7576719 + ], + "osm_type":"way", + "osm_id":40454661, + "attractiveness":343, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0e8b10c0-f988-40b1-a1e4-079bdee0fe28", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "160":{ + "name":"Direction régionale des Douanes de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5864702, + 7.7576416 + ], + "osm_type":"way", + "osm_id":40454745, + "attractiveness":402, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"baea55f5-17a0-413f-b47b-93a02c55bc14", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "161":{ + "name":"Chapelle Saint-François d'Assise", + "type":"sightseeing", + "location":[ + 48.5889097, + 7.7607568 + ], + "osm_type":"way", + "osm_id":40457237, + "attractiveness":103, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7ef6772d-7a78-4e4a-9dae-afa0d6368439", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "162":{ + "name":"Église Saint-Paul", + "type":"sightseeing", + "location":[ + 48.5863214, + 7.759848 + ], + "osm_type":"way", + "osm_id":40457313, + "attractiveness":487, + "n_tags":23, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d1187137-d3ac-4de5-bbb4-0b9354313b26", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "163":{ + "name":"Fontaine Fischart", + "type":"sightseeing", + "location":[ + 48.581319, + 7.7564887 + ], + "osm_type":"way", + "osm_id":40459907, + "attractiveness":141, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ffd5e109-8664-4a7b-84dd-518241a92ae7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "164":{ + "name":"Centre médical et dentaire de la MGEN", + "type":"sightseeing", + "location":[ + 48.5810293, + 7.7567544 + ], + "osm_type":"way", + "osm_id":40459919, + "attractiveness":316, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6577d594-1f9d-4714-be22-8aa80f1e9448", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "165":{ + "name":"Les bateliers", + "type":"sightseeing", + "location":[ + 48.5818183, + 7.7573515 + ], + "osm_type":"way", + "osm_id":40467153, + "attractiveness":102, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8b01f25c-f11c-4088-95a2-bdee1071061d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "166":{ + "name":"Église Saint-Guillaume", + "type":"sightseeing", + "location":[ + 48.5820836, + 7.7576339 + ], + "osm_type":"way", + "osm_id":40467155, + "attractiveness":413, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"345e44ef-3504-48b8-900a-a95652b60d57", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "167":{ + "name":"Résidence Abrapa Saint-Guillaume", + "type":"sightseeing", + "location":[ + 48.5822431, + 7.7580778 + ], + "osm_type":"way", + "osm_id":40467165, + "attractiveness":170, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cc7c9bdf-304a-4bcb-872d-ddf01d95115e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "168":{ + "name":"Mosquée Al Fateh", + "type":"sightseeing", + "location":[ + 48.5830212, + 7.760909 + ], + "osm_type":"way", + "osm_id":40469207, + "attractiveness":240, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3ca19fac-d4d1-4efa-a3fd-ab22553d1d4e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "169":{ + "name":"Maison de l'Étudiante", + "type":"sightseeing", + "location":[ + 48.5840162, + 7.7602468 + ], + "osm_type":"way", + "osm_id":40517838, + "attractiveness":116, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d0b758d8-c912-4279-9bdb-ea30f0ea5e54", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "170":{ + "name":"Pharmacie de la Cité", + "type":"sightseeing", + "location":[ + 48.597618, + 7.7154412 + ], + "osm_type":"way", + "osm_id":40520374, + "attractiveness":304, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8eeee135-2dc9-4d7f-b258-be9c46c81437", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "171":{ + "name":"Centre Médico-Social", + "type":"sightseeing", + "location":[ + 48.6002005, + 7.7147621 + ], + "osm_type":"way", + "osm_id":40520757, + "attractiveness":96, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"02a69ea9-6906-4c56-85a9-dd9b45eccd1d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "172":{ + "name":"Église Saint-Antoine", + "type":"sightseeing", + "location":[ + 48.5974484, + 7.7101123 + ], + "osm_type":"way", + "osm_id":40521595, + "attractiveness":154, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"67b46d20-9813-42ca-9737-13280279c308", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "173":{ + "name":"Groupe Scolaire Notre-Dame", + "type":"sightseeing", + "location":[ + 48.5878693, + 7.7437829 + ], + "osm_type":"way", + "osm_id":40522178, + "attractiveness":68, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f2357360-bc81-409f-ae55-66fac9b40029", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "174":{ + "name":"Tribunal de proximité", + "type":"sightseeing", + "location":[ + 48.5901614, + 7.7457934 + ], + "osm_type":"way", + "osm_id":40528357, + "attractiveness":89, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cc8b984c-6df2-4750-bf61-a4d7f545c01a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "175":{ + "name":"Le Jardin d'Alice", + "type":"sightseeing", + "location":[ + 48.5968424, + 7.7073052 + ], + "osm_type":"way", + "osm_id":40608831, + "attractiveness":228, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d43f415c-9ca4-4f45-aec8-560b05cfb48d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "176":{ + "name":"Église évangélique luthérienne libre", + "type":"sightseeing", + "location":[ + 48.5780754, + 7.7545344 + ], + "osm_type":"way", + "osm_id":40646869, + "attractiveness":196, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"59d1dc02-4cde-4442-b294-898fd0e9d5f9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "177":{ + "name":"Hôpital Civil", + "type":"sightseeing", + "location":[ + 48.5761071, + 7.7448917 + ], + "osm_type":"way", + "osm_id":40667164, + "attractiveness":416, + "n_tags":21, + "image_url":null, + "description":null, + "duration":0, + "uuid":"590775ca-1651-40eb-aee9-e5e08fdef7c3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "178":{ + "name":"Haute école des arts du Rhin – Batiment secondaire", + "type":"sightseeing", + "location":[ + 48.5816129, + 7.7593574 + ], + "osm_type":"way", + "osm_id":40709871, + "attractiveness":190, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"45da7ef9-56d3-44dc-84e0-114cc0f80393", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "179":{ + "name":"Lycée professionnel Jean-Frédéric Oberlin", + "type":"sightseeing", + "location":[ + 48.5814077, + 7.7601044 + ], + "osm_type":"way", + "osm_id":40709872, + "attractiveness":183, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"aaa7755d-843f-44de-ae36-643b8f39cf9a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "180":{ + "name":"La Chaufferie", + "type":"sightseeing", + "location":[ + 48.581165, + 7.7594747 + ], + "osm_type":"way", + "osm_id":40709873, + "attractiveness":168, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7115f231-5fdb-4bb5-8b7d-451a504a10a2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "181":{ + "name":"École maternelle Académie", + "type":"sightseeing", + "location":[ + 48.5813008, + 7.7607787 + ], + "osm_type":"way", + "osm_id":40709874, + "attractiveness":157, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"edba2cec-0ae2-4389-8fc4-4ad7c0ede2b2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "182":{ + "name":"Place de l'Académie", + "type":"sightseeing", + "location":[ + 48.5818254, + 7.7603049 + ], + "osm_type":"way", + "osm_id":40717063, + "attractiveness":145, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9fe48639-92db-4d98-a7cd-63e0702c052c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "183":{ + "name":"Institut National des Sciences Appliquées", + "type":"sightseeing", + "location":[ + 48.5816601, + 7.7645865 + ], + "osm_type":"way", + "osm_id":40735517, + "attractiveness":331, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f957bb8f-8ae7-4bb0-86a9-b58ff8bccb1d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "184":{ + "name":"Campus Centre", + "type":"sightseeing", + "location":[ + 48.5800231, + 7.7649906 + ], + "osm_type":"way", + "osm_id":40743589, + "attractiveness":86, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a9f89610-2f01-4a6e-9029-577e60ce6538", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "185":{ + "name":"Atelier Canopé 67 - Centre Régional de Documentation Pédagogique", + "type":"sightseeing", + "location":[ + 48.5781617, + 7.7636353 + ], + "osm_type":"way", + "osm_id":40745760, + "attractiveness":236, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"89a19a70-d512-48c5-9427-370b26271e6f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "186":{ + "name":"Institut de Biologie Moléculaire des Plantes", + "type":"sightseeing", + "location":[ + 48.5808189, + 7.7636927 + ], + "osm_type":"way", + "osm_id":40746790, + "attractiveness":88, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6496adce-70a3-40a9-9f0a-fd9d5fd9871b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "187":{ + "name":"Insectarium", + "type":"sightseeing", + "location":[ + 48.5799191, + 7.7650383 + ], + "osm_type":"way", + "osm_id":40746793, + "attractiveness":91, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"39dfaac3-2a84-4d1a-b7f4-782eb05cf216", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "188":{ + "name":"Église des Dominicains", + "type":"sightseeing", + "location":[ + 48.5822255, + 7.766828 + ], + "osm_type":"way", + "osm_id":40775124, + "attractiveness":197, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3d603f60-276a-4ba4-a876-f755d9ec70b3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "189":{ + "name":"Faculté de physique et ingénierie", + "type":"sightseeing", + "location":[ + 48.5839666, + 7.764029 + ], + "osm_type":"way", + "osm_id":40814389, + "attractiveness":285, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cf034e4e-a794-4f0f-b83d-c8c16f354d45", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "190":{ + "name":"Faculté de Psychologie", + "type":"sightseeing", + "location":[ + 48.5845432, + 7.76497 + ], + "osm_type":"way", + "osm_id":40816918, + "attractiveness":148, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"579ad28c-0e00-48f9-8891-1eb1271a74a3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "191":{ + "name":"École maternelle Oberlin", + "type":"sightseeing", + "location":[ + 48.5768752, + 7.7592111 + ], + "osm_type":"way", + "osm_id":40827656, + "attractiveness":132, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"08f79491-7180-4daa-8fee-9113a27d5c36", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "192":{ + "name":"Église du Christ Ressuscité", + "type":"sightseeing", + "location":[ + 48.5773614, + 7.7639692 + ], + "osm_type":"way", + "osm_id":40828452, + "attractiveness":178, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fdd94c0f-c50c-45e2-b797-895a049594b6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "193":{ + "name":"Synagogue de Cronenbourg", + "type":"sightseeing", + "location":[ + 48.6009376, + 7.7133344 + ], + "osm_type":"way", + "osm_id":40926492, + "attractiveness":112, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"30481c32-2d14-4b8f-ae0d-e4918c390875", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "194":{ + "name":"Département Recherches Subatomiques - Accueil - Bâtiment 27", + "type":"sightseeing", + "location":[ + 48.6061536, + 7.7105834 + ], + "osm_type":"way", + "osm_id":40926588, + "attractiveness":81, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"73757adb-bf1c-4fda-a7af-82d7f4b76259", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "195":{ + "name":"Institut Charles Sadron", + "type":"sightseeing", + "location":[ + 48.6067213, + 7.7159322 + ], + "osm_type":"way", + "osm_id":40926589, + "attractiveness":114, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"86df0596-678a-4482-8835-d907fb91bda5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "196":{ + "name":"Laboratoire d'Imagerie et de Neurosciences Cognitives", + "type":"sightseeing", + "location":[ + 48.6068086, + 7.7149081 + ], + "osm_type":"way", + "osm_id":40926597, + "attractiveness":100, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"45c8f217-0695-49fe-bd8c-7e6e630dca8d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "197":{ + "name":"Laboratoire d'Électronique et de Physique de Systèmes Instrumentaux", + "type":"sightseeing", + "location":[ + 48.6069875, + 7.7110019 + ], + "osm_type":"way", + "osm_id":40926617, + "attractiveness":78, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e3e9c244-5ffa-4c79-8bb3-59646edb9997", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "198":{ + "name":"Église Notre-Dame de Lourdes", + "type":"sightseeing", + "location":[ + 48.5762794, + 7.7307187 + ], + "osm_type":"way", + "osm_id":40927788, + "attractiveness":161, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"df4ed7e9-85d2-41db-8663-5d0a009a0382", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "199":{ + "name":"École maternelle Louise Scheppler", + "type":"sightseeing", + "location":[ + 48.5737603, + 7.7322026 + ], + "osm_type":"way", + "osm_id":40931752, + "attractiveness":117, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c46deaa4-7546-420e-97c0-d5bd86590fcd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "200":{ + "name":"Compagnons du Devoir", + "type":"sightseeing", + "location":[ + 48.5792994, + 7.7342802 + ], + "osm_type":"way", + "osm_id":40981621, + "attractiveness":143, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"70568900-5067-4944-8255-923c5d6a7ec4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "201":{ + "name":"Gendarmerie nationale", + "type":"sightseeing", + "location":[ + 48.5802099, + 7.735264 + ], + "osm_type":"way", + "osm_id":40981628, + "attractiveness":208, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5e1cd53a-2389-43ef-b520-8af519bc78f0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "202":{ + "name":"Maison de l'Enfance", + "type":"sightseeing", + "location":[ + 48.579558, + 7.7318884 + ], + "osm_type":"way", + "osm_id":40982190, + "attractiveness":133, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"284b9ab5-8d3e-4e31-9c83-aef9d8fa621f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "203":{ + "name":"Mosquée AL IMANE", + "type":"sightseeing", + "location":[ + 48.5820547, + 7.7320735 + ], + "osm_type":"way", + "osm_id":40985962, + "attractiveness":171, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6dc050e2-5b45-4d14-8b8f-7cb1ab4ce507", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "204":{ + "name":"clinique Ste Barbe", + "type":"sightseeing", + "location":[ + 48.5817039, + 7.735331 + ], + "osm_type":"way", + "osm_id":40990074, + "attractiveness":271, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d7e35198-efe4-4ad7-a45e-16894f8cf158", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "205":{ + "name":"Crédit Agricole", + "type":"sightseeing", + "location":[ + 48.583739, + 7.7345777 + ], + "osm_type":"way", + "osm_id":41121006, + "attractiveness":241, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1e5589a1-3c2e-4319-ad3e-bb1623b83072", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "206":{ + "name":"LCL", + "type":"sightseeing", + "location":[ + 48.5873763, + 7.7391771 + ], + "osm_type":"way", + "osm_id":41143117, + "attractiveness":278, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bc127860-f175-4e1e-a3d5-118535e2a527", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "207":{ + "name":"Hypromat", + "type":"sightseeing", + "location":[ + 48.591094, + 7.7405479 + ], + "osm_type":"way", + "osm_id":41143777, + "attractiveness":207, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5db5c644-c7ac-4ccc-8fa2-b0e0ae208940", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "208":{ + "name":"Sainte-Aurélie", + "type":"sightseeing", + "location":[ + 48.5827804, + 7.7326564 + ], + "osm_type":"way", + "osm_id":41159101, + "attractiveness":218, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e941ea5a-ed37-4b08-95cb-b96a10d9aeb5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "209":{ + "name":"La Semencerie", + "type":"sightseeing", + "location":[ + 48.5781475, + 7.7287408 + ], + "osm_type":"way", + "osm_id":41161762, + "attractiveness":256, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5a80464a-89f6-43cf-8d87-a2edf5d4bf48", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "210":{ + "name":"Avia", + "type":"sightseeing", + "location":[ + 48.5787496, + 7.7306511 + ], + "osm_type":"way", + "osm_id":41161921, + "attractiveness":183, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9e833fdb-957c-4460-98eb-8ae2f7ceae70", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "211":{ + "name":"Église Néo-Apostolique", + "type":"sightseeing", + "location":[ + 48.590699, + 7.763788 + ], + "osm_type":"way", + "osm_id":41270770, + "attractiveness":141, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a159aa5a-d14d-4c99-b891-bba42f27bbe8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "212":{ + "name":"Église protestante Cronenbourg Cité", + "type":"sightseeing", + "location":[ + 48.6029563, + 7.7146028 + ], + "osm_type":"way", + "osm_id":41271271, + "attractiveness":164, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5436a172-070a-44dd-8e6e-6ed24316c99f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "213":{ + "name":"Église du Bon Pasteur", + "type":"sightseeing", + "location":[ + 48.6016113, + 7.7166039 + ], + "osm_type":"way", + "osm_id":41271275, + "attractiveness":117, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"be4721ba-67e8-4e6e-8fd1-b18d72a92016", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "214":{ + "name":"Centre socio-culturel l'Aquarium", + "type":"sightseeing", + "location":[ + 48.6046063, + 7.7191672 + ], + "osm_type":"way", + "osm_id":41271280, + "attractiveness":116, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d819aaae-f8a7-433e-9527-bfb8423c32f7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "215":{ + "name":"Centre médical - \"Pierre Curie", + "type":"sightseeing", + "location":[ + 48.6040902, + 7.712959 + ], + "osm_type":"way", + "osm_id":41271283, + "attractiveness":84, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9c4a01fb-17e1-4cb8-b048-b8fd71889feb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "216":{ + "name":"Police nationale", + "type":"sightseeing", + "location":[ + 48.6031813, + 7.7176448 + ], + "osm_type":"way", + "osm_id":41271287, + "attractiveness":232, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f16e46ce-7d9a-45ba-86fc-811c7d64bb7f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "217":{ + "name":"Représentation permanente des Pays-Bas", + "type":"sightseeing", + "location":[ + 48.58907, + 7.7651598 + ], + "osm_type":"way", + "osm_id":41359549, + "attractiveness":110, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"99062710-0b4a-4e45-afda-65589ef19d4d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "218":{ + "name":"Institut des Hautes Études Européennes - Villa Knopf", + "type":"sightseeing", + "location":[ + 48.5898743, + 7.764956 + ], + "osm_type":"way", + "osm_id":41361001, + "attractiveness":148, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a589ede2-9469-4ddf-87dd-264e660f2a41", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "219":{ + "name":"Police des Autoroutes CRS37", + "type":"sightseeing", + "location":[ + 48.5885905, + 7.7274272 + ], + "osm_type":"way", + "osm_id":41418099, + "attractiveness":73, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a94c82bf-b3a5-4143-9a1d-f53be95440f4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "220":{ + "name":"Groupe Scolaire Édouard Branly", + "type":"sightseeing", + "location":[ + 48.5948377, + 7.7616068 + ], + "osm_type":"way", + "osm_id":41600709, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"712d73fe-3633-446c-aa6d-c7d894939842", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "221":{ + "name":"Centre Socio Culturel Victor Schoelcher", + "type":"sightseeing", + "location":[ + 48.6014543, + 7.7217288 + ], + "osm_type":"way", + "osm_id":41706042, + "attractiveness":74, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6784dd53-6dc3-4dc6-8317-c2dcffcee9b9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "222":{ + "name":"Médiathèque Cronenbourg", + "type":"sightseeing", + "location":[ + 48.6011733, + 7.7214887 + ], + "osm_type":"way", + "osm_id":41706044, + "attractiveness":97, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cae98965-36c2-4e57-b3d3-bcf90e267de5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "223":{ + "name":"Hôpital de Hautepierre", + "type":"sightseeing", + "location":[ + 48.5932911, + 7.7070877 + ], + "osm_type":"way", + "osm_id":41770181, + "attractiveness":323, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8c60a85b-cf82-41ae-b57b-35c4be0d7be6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "224":{ + "name":"Centre socio-culturel le Galet", + "type":"sightseeing", + "location":[ + 48.5963571, + 7.7007381 + ], + "osm_type":"way", + "osm_id":41778269, + "attractiveness":129, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e3d8c49c-dfc0-4331-bb4d-868be72c081f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "225":{ + "name":"École Maternelle Karine 1", + "type":"sightseeing", + "location":[ + 48.5972311, + 7.6990841 + ], + "osm_type":"way", + "osm_id":41780605, + "attractiveness":94, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"febe596b-070a-4351-9770-ee3c254f2756", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "226":{ + "name":"École Maternelle Éléonore B", + "type":"sightseeing", + "location":[ + 48.5900302, + 7.7036969 + ], + "osm_type":"way", + "osm_id":41958797, + "attractiveness":76, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a91d29cd-9d68-4263-9cf2-612cb82d450a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "227":{ + "name":"Place Montaigne", + "type":"sightseeing", + "location":[ + 48.5903016, + 7.7034277 + ], + "osm_type":"way", + "osm_id":41958799, + "attractiveness":92, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"98bf74e4-f8c3-4189-b2b8-ec30558d9326", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "228":{ + "name":"Police Nationale", + "type":"sightseeing", + "location":[ + 48.5800051, + 7.71575 + ], + "osm_type":"way", + "osm_id":42148186, + "attractiveness":320, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"56a094c2-8f9d-4dad-ad47-d3050ddcc5f6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "229":{ + "name":"Église Saint-Joseph", + "type":"sightseeing", + "location":[ + 48.5803892, + 7.7123663 + ], + "osm_type":"way", + "osm_id":42156579, + "attractiveness":338, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1f65be93-6d6f-4c11-9673-2442b8be4d9f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "230":{ + "name":"École Maternelle Camille Claus", + "type":"sightseeing", + "location":[ + 48.5809803, + 7.7123791 + ], + "osm_type":"way", + "osm_id":42156600, + "attractiveness":70, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9c520b85-9ee7-4cc5-be77-880dab051659", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "231":{ + "name":"AMCB Clinique Vétérinaire", + "type":"sightseeing", + "location":[ + 48.583357, + 7.7091267 + ], + "osm_type":"way", + "osm_id":42161674, + "attractiveness":193, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9046154b-272f-4578-ab76-03551b1e8d48", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "232":{ + "name":"Église Saint-Jean Bosco", + "type":"sightseeing", + "location":[ + 48.5817304, + 7.704326 + ], + "osm_type":"way", + "osm_id":42224669, + "attractiveness":126, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9a9774e6-4abe-4c04-863d-eb23fea0018f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "233":{ + "name":"Centre Socio-culturel Camille Claus", + "type":"sightseeing", + "location":[ + 48.5814468, + 7.7020699 + ], + "osm_type":"way", + "osm_id":42225734, + "attractiveness":95, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"167c0361-a976-498d-913c-1253cc8cfb45", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "234":{ + "name":"Groupe Scolaire Gustave Stoskopf", + "type":"sightseeing", + "location":[ + 48.5852962, + 7.6992587 + ], + "osm_type":"way", + "osm_id":42227436, + "attractiveness":63, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3a40527c-b85c-419c-b408-ad688a0b3a32", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "235":{ + "name":"École primaire Jean Mermoz", + "type":"sightseeing", + "location":[ + 48.6038977, + 7.7367353 + ], + "osm_type":"way", + "osm_id":42244908, + "attractiveness":159, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7e6f7140-b067-4ad8-8d4f-c6734e8f1322", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "236":{ + "name":"École élémentaire privée L'Oliveraie", + "type":"sightseeing", + "location":[ + 48.6022934, + 7.7430781 + ], + "osm_type":"way", + "osm_id":42322287, + "attractiveness":182, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"09a3d93c-bae7-4375-a4dd-b73705f75dd3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "237":{ + "name":"Collège Jacques Twinger", + "type":"sightseeing", + "location":[ + 48.5810012, + 7.705529 + ], + "osm_type":"way", + "osm_id":42352502, + "attractiveness":127, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1139fda5-f00a-4ec9-84b5-763de6c596a6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "238":{ + "name":"Groupe Scolaire du Hohberg", + "type":"sightseeing", + "location":[ + 48.579721, + 7.7058943 + ], + "osm_type":"way", + "osm_id":42366018, + "attractiveness":43, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"39c829e6-07d6-497b-82b8-b761dc397b22", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "239":{ + "name":"Église du couvent des Capucins", + "type":"sightseeing", + "location":[ + 48.5762817, + 7.6999001 + ], + "osm_type":"way", + "osm_id":42386620, + "attractiveness":140, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"277d8dc8-9103-4496-9b78-fb27b6c10623", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "240":{ + "name":"École primaire privée Joie de Vivre Ann Saint-Etienne", + "type":"sightseeing", + "location":[ + 48.5766287, + 7.6998893 + ], + "osm_type":"way", + "osm_id":42386621, + "attractiveness":119, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"35ddd958-8ba9-40df-874a-c1a1c91bde63", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "241":{ + "name":"Mairie de quartier de Koenisghoffen", + "type":"sightseeing", + "location":[ + 48.5789554, + 7.7132799 + ], + "osm_type":"way", + "osm_id":42404538, + "attractiveness":103, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eaa0d808-5ba8-462a-a529-b4a6150c83c7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "242":{ + "name":"École Élémentaire des Romains", + "type":"sightseeing", + "location":[ + 48.5787988, + 7.7153527 + ], + "osm_type":"way", + "osm_id":42411628, + "attractiveness":72, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"84013e49-98ed-497c-8bdf-5440b0674c5e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "243":{ + "name":"Au deux epices", + "type":"sightseeing", + "location":[ + 48.5785346, + 7.7173706 + ], + "osm_type":"way", + "osm_id":42411642, + "attractiveness":121, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"58abaa12-45b2-4fa3-b13d-83464a7a1729", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "244":{ + "name":"EHPAD Emmaüs-Diaconesses Koenigshoffen", + "type":"sightseeing", + "location":[ + 48.5775255, + 7.714984 + ], + "osm_type":"way", + "osm_id":42473052, + "attractiveness":350, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"accf0336-1290-46b9-869f-8d71526463d9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "245":{ + "name":"La Poste de Schiltigheim Les Brasseurs", + "type":"sightseeing", + "location":[ + 48.6066439, + 7.7488731 + ], + "osm_type":"way", + "osm_id":42506586, + "attractiveness":309, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1377698f-2bdb-410e-bc2c-4116ecf9d9f1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "246":{ + "name":"Simse imagerie médicale", + "type":"sightseeing", + "location":[ + 48.6068841, + 7.7486078 + ], + "osm_type":"way", + "osm_id":42506622, + "attractiveness":171, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2adf1c5d-538b-48cf-b5b9-ed98bf52f1ef", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "247":{ + "name":"Église de la Sainte-Famille", + "type":"sightseeing", + "location":[ + 48.6072128, + 7.7479903 + ], + "osm_type":"way", + "osm_id":42506681, + "attractiveness":212, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"86f4a837-e193-45e6-90ea-ccd1c9af5363", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "248":{ + "name":"Église Saint-Arbogast", + "type":"sightseeing", + "location":[ + 48.5722456, + 7.7188796 + ], + "osm_type":"way", + "osm_id":42937947, + "attractiveness":303, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"afc02e2c-5e07-48e5-852c-df79f9b21efa", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "249":{ + "name":"Crédit Mutuel", + "type":"sightseeing", + "location":[ + 48.5695527, + 7.7103863 + ], + "osm_type":"way", + "osm_id":42961059, + "attractiveness":141, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"74dd3c42-52ed-4202-9f5e-393978f20e13", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "250":{ + "name":"Église protestante de Schiltigheim", + "type":"sightseeing", + "location":[ + 48.6060339, + 7.7513163 + ], + "osm_type":"way", + "osm_id":42990751, + "attractiveness":498, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"510c1ac5-6125-4108-990a-9867a653cd20", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "251":{ + "name":"Maison du Jeune Citoyen", + "type":"sightseeing", + "location":[ + 48.6063013, + 7.7498734 + ], + "osm_type":"way", + "osm_id":42990788, + "attractiveness":219, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d279bdcd-8212-4c5d-9932-e9f899a2c412", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "252":{ + "name":"École des Arts", + "type":"sightseeing", + "location":[ + 48.6060788, + 7.7495907 + ], + "osm_type":"way", + "osm_id":42990791, + "attractiveness":152, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d19c81c2-72bb-4191-96e6-2df4cb59c8b9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "253":{ + "name":"Collège Hans Arp", + "type":"sightseeing", + "location":[ + 48.5692574, + 7.7183438 + ], + "osm_type":"way", + "osm_id":43092052, + "attractiveness":93, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c68ed802-7180-47ea-b9ab-5246cacbf34e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "254":{ + "name":"Protection Civile du Bas-Rhin - Base Schiltigheim - Caserne Monsché", + "type":"sightseeing", + "location":[ + 48.6047753, + 7.7519264 + ], + "osm_type":"way", + "osm_id":43105528, + "attractiveness":207, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9c4a25ae-ac86-497f-a82a-ec3ca76c91e1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "255":{ + "name":"Résidence Eugène Delacroix", + "type":"sightseeing", + "location":[ + 48.5676873, + 7.7282781 + ], + "osm_type":"way", + "osm_id":43140009, + "attractiveness":245, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"675140d2-add3-49f9-a76c-5aa9a2aca1fe", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "256":{ + "name":"Foyer Soleil", + "type":"sightseeing", + "location":[ + 48.6071693, + 7.7524723 + ], + "osm_type":"way", + "osm_id":43151859, + "attractiveness":199, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cf8c8cd7-868a-4871-a1f2-4a2d93381bf1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "257":{ + "name":"Tribunal d'Instance de Schiltigheim", + "type":"sightseeing", + "location":[ + 48.6031472, + 7.7546367 + ], + "osm_type":"way", + "osm_id":43178323, + "attractiveness":108, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3acda4aa-163b-4104-b944-4b57b1ce0ed3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "258":{ + "name":"École maternelle Martin Schongauer", + "type":"sightseeing", + "location":[ + 48.5635264, + 7.718583 + ], + "osm_type":"way", + "osm_id":43189488, + "attractiveness":108, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a6e1b16c-8801-4666-9dbc-701f23317205", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "259":{ + "name":"Service psychothérapique pour enfants et adolescents", + "type":"sightseeing", + "location":[ + 48.5648673, + 7.7170133 + ], + "osm_type":"way", + "osm_id":43248974, + "attractiveness":105, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"899ef3e9-fa82-491a-8177-f1934e0e958b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "260":{ + "name":"Groupe Scolaire Léonard de Vinci", + "type":"sightseeing", + "location":[ + 48.5658761, + 7.7271146 + ], + "osm_type":"way", + "osm_id":43306050, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eddc6d44-933e-4532-87b7-f0001d15318a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "261":{ + "name":"Kinésithérapeute Von Der Marck", + "type":"sightseeing", + "location":[ + 48.564499, + 7.7076972 + ], + "osm_type":"way", + "osm_id":43311981, + "attractiveness":133, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4815c6b8-8631-46a3-a533-405c032fc4b5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "262":{ + "name":"École Gutenberg", + "type":"sightseeing", + "location":[ + 48.5616102, + 7.7039506 + ], + "osm_type":"way", + "osm_id":43341825, + "attractiveness":56, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a49368ef-db77-4fa7-8d02-2caa5d5845b3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "263":{ + "name":"Église du Sacré-Coeur", + "type":"sightseeing", + "location":[ + 48.5631446, + 7.7082816 + ], + "osm_type":"way", + "osm_id":43345191, + "attractiveness":166, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"df41228c-4f90-422a-9e2a-a7451c10964c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "264":{ + "name":"Centre Socio-culturel du Marais", + "type":"sightseeing", + "location":[ + 48.6068071, + 7.7670547 + ], + "osm_type":"way", + "osm_id":43444536, + "attractiveness":194, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"62252fb8-b715-4d1c-a68a-901aa5b68483", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "265":{ + "name":"Institut Médico-Pédagogique \"Le Roethig\"", + "type":"sightseeing", + "location":[ + 48.5639375, + 7.7108502 + ], + "osm_type":"way", + "osm_id":43451013, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9d913755-a6b5-4690-b236-133d376d91a5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "266":{ + "name":"Église Saint-Léon", + "type":"sightseeing", + "location":[ + 48.5673784, + 7.7503971 + ], + "osm_type":"way", + "osm_id":43548694, + "attractiveness":166, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e22515c7-937b-4272-8390-536fd8af79f4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "267":{ + "name":"Centre Administratif Ville et Eurométropole de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5733899, + 7.7520803 + ], + "osm_type":"way", + "osm_id":43721734, + "attractiveness":529, + "n_tags":27, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e52e5c5a-4e72-410e-bb7f-e3ca34e733ba", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "268":{ + "name":"Maison citoyenne", + "type":"sightseeing", + "location":[ + 48.5708489, + 7.7529829 + ], + "osm_type":"way", + "osm_id":43727168, + "attractiveness":102, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eb241112-84bb-4953-b45b-5fefc84f1570", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "269":{ + "name":"Chapelle de la Sainte-Croix", + "type":"sightseeing", + "location":[ + 48.5723594, + 7.7575605 + ], + "osm_type":"way", + "osm_id":43795771, + "attractiveness":116, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"41d534f0-87d5-44b7-b1e2-a31cee7b5f3a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "270":{ + "name":"UGC Ciné Cité Strasbourg", + "type":"sightseeing", + "location":[ + 48.5731023, + 7.7641146 + ], + "osm_type":"way", + "osm_id":43799904, + "attractiveness":547, + "n_tags":26, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0310b6b3-0dce-4a40-8db3-b9a38a91995b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "271":{ + "name":"Foyer du Jeune Homme", + "type":"sightseeing", + "location":[ + 48.5694807, + 7.7619724 + ], + "osm_type":"way", + "osm_id":43926499, + "attractiveness":358, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"05e78e8e-e356-4974-8af0-df0af99ec4ab", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "272":{ + "name":"EHPAD Les Mélèzes", + "type":"sightseeing", + "location":[ + 48.5694956, + 7.7616812 + ], + "osm_type":"way", + "osm_id":43926530, + "attractiveness":465, + "n_tags":22, + "image_url":null, + "description":null, + "duration":0, + "uuid":"127bd814-70a0-44a5-bcec-9cbc4cbbae6b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "273":{ + "name":"Centre Socio-Culturel", + "type":"sightseeing", + "location":[ + 48.5662086, + 7.7562629 + ], + "osm_type":"way", + "osm_id":44064457, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bec0d273-c313-4a59-ace0-7c53007899db", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "274":{ + "name":"Église Saint-Aloyse", + "type":"sightseeing", + "location":[ + 48.56428, + 7.7616777 + ], + "osm_type":"way", + "osm_id":44149159, + "attractiveness":186, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"813a4048-9228-4235-978f-c0bd0ac393a7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "275":{ + "name":"École Élémentaire de la Ziegelau", + "type":"sightseeing", + "location":[ + 48.563777, + 7.7634095 + ], + "osm_type":"way", + "osm_id":44158007, + "attractiveness":101, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c51b14bc-7ccb-4f32-beb6-e2999cf5c5d8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "276":{ + "name":"École maternelle Ziegelau", + "type":"sightseeing", + "location":[ + 48.5643385, + 7.7631325 + ], + "osm_type":"way", + "osm_id":44158028, + "attractiveness":127, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f23520fb-985c-4244-aba6-0ea173dae64c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "277":{ + "name":"Snack du Neudorf chez Babylone", + "type":"sightseeing", + "location":[ + 48.5632939, + 7.7619842 + ], + "osm_type":"way", + "osm_id":44158199, + "attractiveness":265, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7730778e-81cf-4afb-8f2e-55f92e0164f5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "278":{ + "name":"Les Compotes", + "type":"sightseeing", + "location":[ + 48.5660264, + 7.7612988 + ], + "osm_type":"way", + "osm_id":44203857, + "attractiveness":351, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2dc17980-e5bb-4ddc-969d-5dea9c0aa797", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "279":{ + "name":"Centre Culturel le 23", + "type":"sightseeing", + "location":[ + 48.5628042, + 7.7595574 + ], + "osm_type":"way", + "osm_id":44505765, + "attractiveness":96, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4de6b991-c1dc-42d2-81f2-68c426c57e3d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "280":{ + "name":"Institut National Supérieur du Professorat et de l’Education", + "type":"sightseeing", + "location":[ + 48.5614857, + 7.7543954 + ], + "osm_type":"way", + "osm_id":44623561, + "attractiveness":110, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6179e3bb-be1d-42f6-a083-9425e5098218", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "281":{ + "name":"Centre de Formation d'Apprentis Jean Geiler de Kaysersberg", + "type":"sightseeing", + "location":[ + 48.5896621, + 7.7534819 + ], + "osm_type":"way", + "osm_id":44947849, + "attractiveness":112, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c93514fc-ab13-4345-a452-0f575f724aec", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "282":{ + "name":"EHPAD Bethesda Contades", + "type":"sightseeing", + "location":[ + 48.5920553, + 7.7603553 + ], + "osm_type":"way", + "osm_id":45872499, + "attractiveness":285, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c550c7f9-8234-4e13-b7e4-31dc62ff7a55", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "283":{ + "name":"École maternelle Cronenbourg Centre", + "type":"sightseeing", + "location":[ + 48.5928233, + 7.7204069 + ], + "osm_type":"way", + "osm_id":45962420, + "attractiveness":162, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"83d572a7-2081-415d-8343-52535972c118", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "284":{ + "name":"Véloparc CTS Rives de l'Aar", + "type":"sightseeing", + "location":[ + 48.5999311, + 7.7542461 + ], + "osm_type":"way", + "osm_id":46892641, + "attractiveness":399, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"411a9f13-dd05-4cd4-b37f-0e83b3d48e76", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "285":{ + "name":"École Maternelle du Wacken", + "type":"sightseeing", + "location":[ + 48.5970691, + 7.7655965 + ], + "osm_type":"way", + "osm_id":47042104, + "attractiveness":108, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"13f1e09c-09cc-4d1e-ba9d-c6512047ef02", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "286":{ + "name":"Lycée professionnel privé Charles de Foucauld", + "type":"sightseeing", + "location":[ + 48.6058055, + 7.7072169 + ], + "osm_type":"way", + "osm_id":49222314, + "attractiveness":89, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3d103fe3-acff-4dac-8faf-82fdb9862504", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "287":{ + "name":"Groupe Scolaire Charles Adolphe Wurtz", + "type":"sightseeing", + "location":[ + 48.6023318, + 7.7212861 + ], + "osm_type":"way", + "osm_id":49357915, + "attractiveness":77, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"019e2384-c2cc-47fd-ba0e-ce475ea03600", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "288":{ + "name":"École primaire et élémentaire Camille Hirtz", + "type":"sightseeing", + "location":[ + 48.5937226, + 7.7186074 + ], + "osm_type":"way", + "osm_id":49524024, + "attractiveness":161, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"24ae0aea-bbf4-4a8b-ae7b-21c3f10a526b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "289":{ + "name":"École Élémentaire Brigitte", + "type":"sightseeing", + "location":[ + 48.5923484, + 7.6989275 + ], + "osm_type":"way", + "osm_id":49636123, + "attractiveness":69, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c4729cf5-df04-4322-8480-1ef50f234150", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "290":{ + "name":"Collège Erasme", + "type":"sightseeing", + "location":[ + 48.5916712, + 7.7012358 + ], + "osm_type":"way", + "osm_id":49636124, + "attractiveness":69, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5753d654-de3a-4642-b744-32a8f27286cd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "291":{ + "name":"École Maternelle Brigitte", + "type":"sightseeing", + "location":[ + 48.5912406, + 7.699199 + ], + "osm_type":"way", + "osm_id":49636125, + "attractiveness":89, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6e1d3fae-32cb-46d5-aabf-62f8526991c4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "292":{ + "name":"Crêche", + "type":"sightseeing", + "location":[ + 48.5916276, + 7.6991767 + ], + "osm_type":"way", + "osm_id":49636126, + "attractiveness":56, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9e6e04de-594e-4068-863e-140f9ffb2b1a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "293":{ + "name":"École Élémentaire Éléonore 1", + "type":"sightseeing", + "location":[ + 48.5902614, + 7.704443 + ], + "osm_type":"way", + "osm_id":49641082, + "attractiveness":73, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d86fb67c-c6de-43b1-9085-b691ba53471d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "294":{ + "name":"École Maternelle Éléonore A", + "type":"sightseeing", + "location":[ + 48.5898841, + 7.7056733 + ], + "osm_type":"way", + "osm_id":49641083, + "attractiveness":74, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"20efad31-e22f-49c1-9339-36a446fc0730", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "295":{ + "name":"Direction Inter-régionale des Routes", + "type":"sightseeing", + "location":[ + 48.5877592, + 7.7266912 + ], + "osm_type":"way", + "osm_id":49704414, + "attractiveness":50, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d8cbf39a-103f-4e8f-b491-ead5607ee45c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "296":{ + "name":"Maison de Retraite Petite Sœur des Pauvres", + "type":"sightseeing", + "location":[ + 48.5759771, + 7.69803 + ], + "osm_type":"way", + "osm_id":49776695, + "attractiveness":143, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"93c5c8ab-3a9d-425c-bff2-371eb28a0d4f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "297":{ + "name":"Poste de Strasbourg Koenigshoffen", + "type":"sightseeing", + "location":[ + 48.5790736, + 7.7106223 + ], + "osm_type":"way", + "osm_id":49778428, + "attractiveness":394, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d8e0b281-a76d-4351-adc4-13ed88917ab6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "298":{ + "name":"École Michael", + "type":"sightseeing", + "location":[ + 48.5784937, + 7.7132271 + ], + "osm_type":"way", + "osm_id":49778429, + "attractiveness":99, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"44ab4712-3528-44f3-96e7-720e9dfbfc7e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "299":{ + "name":"Place Nicolas Poussin", + "type":"sightseeing", + "location":[ + 48.5655342, + 7.7257558 + ], + "osm_type":"way", + "osm_id":49939383, + "attractiveness":71, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"53e8b37d-1c74-4aca-a2a8-3f717999e352", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "300":{ + "name":"Multi-Accueil Petite Enfance", + "type":"sightseeing", + "location":[ + 48.5659127, + 7.7056958 + ], + "osm_type":"way", + "osm_id":50011925, + "attractiveness":48, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1cffd1d8-6188-48d1-b4ac-15da75265210", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "301":{ + "name":"Caisse d'Épargne", + "type":"sightseeing", + "location":[ + 48.585849, + 7.7417082 + ], + "osm_type":"way", + "osm_id":52282780, + "attractiveness":404, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0de31f5c-80bd-491d-ae4c-a3056c28f97c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "302":{ + "name":"Lycée polyvalent Jean Rostand", + "type":"sightseeing", + "location":[ + 48.5823235, + 7.7617569 + ], + "osm_type":"way", + "osm_id":52387689, + "attractiveness":95, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b9b3bb6f-7948-4879-9068-14395571fc9d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "303":{ + "name":"Lycée général Fustel de Coulanges", + "type":"sightseeing", + "location":[ + 48.581926, + 7.7524545 + ], + "osm_type":"way", + "osm_id":52404849, + "attractiveness":225, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6779ce81-aa1c-4d93-b0fa-bf4f7ab3480b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "304":{ + "name":"École primaire Notre-Dame de Sion", + "type":"sightseeing", + "location":[ + 48.5883946, + 7.7644201 + ], + "osm_type":"way", + "osm_id":62910210, + "attractiveness":145, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5f69b5f2-7829-498d-a762-504b5edb55fc", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "305":{ + "name":"Lycée professionnel Aristide Briand", + "type":"sightseeing", + "location":[ + 48.60407, + 7.7523415 + ], + "osm_type":"way", + "osm_id":81083275, + "attractiveness":153, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"37054b83-6ac0-4715-83fe-e9d303eeab2c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "306":{ + "name":"Déchèterie de Koenigshoffen", + "type":"sightseeing", + "location":[ + 48.5769907, + 7.7249363 + ], + "osm_type":"way", + "osm_id":105068401, + "attractiveness":626, + "n_tags":29, + "image_url":null, + "description":null, + "duration":0, + "uuid":"693d5c99-c1bc-4f5d-bc68-920939e88e64", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "307":{ + "name":"Parking Visiteurs", + "type":"sightseeing", + "location":[ + 48.5992428, + 7.7590191 + ], + "osm_type":"way", + "osm_id":105248582, + "attractiveness":113, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9c58d774-4357-4e6d-b2e7-f9301e5414d5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "308":{ + "name":"La Présidence", + "type":"sightseeing", + "location":[ + 48.5787378, + 7.7646311 + ], + "osm_type":"way", + "osm_id":106966312, + "attractiveness":131, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fbfe29f9-2196-4191-b75a-e21c747082cb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "309":{ + "name":"Passerelle Patio", + "type":"sightseeing", + "location":[ + 48.5785288, + 7.7648372 + ], + "osm_type":"way", + "osm_id":106966314, + "attractiveness":126, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fb68368c-6f24-4ad1-87d3-935908a78b04", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "310":{ + "name":"Platforme de Biologie", + "type":"sightseeing", + "location":[ + 48.5799438, + 7.7656975 + ], + "osm_type":"way", + "osm_id":106970374, + "attractiveness":75, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5fc6fd36-65fa-4ea9-b090-9540dadd733b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "311":{ + "name":"Parking relais-tram P+R Ducs d'Alsace", + "type":"sightseeing", + "location":[ + 48.58928, + 7.7158391 + ], + "osm_type":"way", + "osm_id":107271489, + "attractiveness":352, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"30971d91-f854-41a2-8b7d-c6da8d275963", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "312":{ + "name":"Parc de la Bergerie", + "type":"sightseeing", + "location":[ + 48.6015866, + 7.721044 + ], + "osm_type":"way", + "osm_id":115014214, + "attractiveness":146, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dcca09ab-4974-48b4-a40a-3b3744cffd7d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "313":{ + "name":"Parking Auchan Market", + "type":"sightseeing", + "location":[ + 48.5986052, + 7.7090977 + ], + "osm_type":"way", + "osm_id":118415853, + "attractiveness":103, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8580d7b9-72d0-411f-9e5e-6622fd40b71f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "314":{ + "name":"Cour Elmia", + "type":"sightseeing", + "location":[ + 48.6057282, + 7.7519829 + ], + "osm_type":"way", + "osm_id":128266115, + "attractiveness":288, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f29d29c1-6b45-4118-ae24-806fdf2afa84", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "315":{ + "name":"Parking Patinoire l'Iceberg", + "type":"sightseeing", + "location":[ + 48.5889948, + 7.7256603 + ], + "osm_type":"way", + "osm_id":131306422, + "attractiveness":89, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a0a80ad0-11c6-43ff-8b64-bd02ab6e942b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "316":{ + "name":"Collège Épiscopal Saint-Étienne", + "type":"sightseeing", + "location":[ + 48.5831924, + 7.755886 + ], + "osm_type":"way", + "osm_id":151324833, + "attractiveness":190, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c3753c44-2e17-4da5-839a-e46ae74fa563", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "317":{ + "name":"Maison de la petite enfance Cronenbourg", + "type":"sightseeing", + "location":[ + 48.6012312, + 7.7225207 + ], + "osm_type":"way", + "osm_id":151704040, + "attractiveness":82, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ee6d3ee1-1452-4d5e-99c6-ea7d08c84e74", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "318":{ + "name":"Grande Mosquée de Strasbourg", + "type":"sightseeing", + "location":[ + 48.573176, + 7.7371577 + ], + "osm_type":"way", + "osm_id":151771572, + "attractiveness":213, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"89da4376-2ab2-46e3-9500-2d3d8970cf32", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "319":{ + "name":"Société Droit Religion en Europe", + "type":"sightseeing", + "location":[ + 48.6051746, + 7.7132105 + ], + "osm_type":"way", + "osm_id":152955698, + "attractiveness":97, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"88091c88-f1a2-4404-88f2-8cd072f325b1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "320":{ + "name":"Société Droit Religion en Europe - Bâtiment 51", + "type":"sightseeing", + "location":[ + 48.6051135, + 7.7131933 + ], + "osm_type":"way", + "osm_id":152955700, + "attractiveness":99, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0029b3f8-d14c-46fb-b662-8c499e6220a4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "321":{ + "name":"École Maternelle Marguerite Perey", + "type":"sightseeing", + "location":[ + 48.6012259, + 7.7138678 + ], + "osm_type":"way", + "osm_id":152960427, + "attractiveness":92, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9459ff0e-0741-4e70-9696-fb0144c4abea", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "322":{ + "name":"K'fet des Sciences", + "type":"sightseeing", + "location":[ + 48.580333, + 7.7658151 + ], + "osm_type":"way", + "osm_id":155014772, + "attractiveness":192, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5e3c4e8f-06c3-40d5-bb2b-cf289b29a75b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "323":{ + "name":"Maison d'arrêt de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5654336, + 7.730896 + ], + "osm_type":"way", + "osm_id":160091489, + "attractiveness":120, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e1b56113-fb76-4f5e-b311-d54f624196d8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "324":{ + "name":"Emilie and the Cool Kids", + "type":"sightseeing", + "location":[ + 48.5736331, + 7.7565479 + ], + "osm_type":"way", + "osm_id":160165412, + "attractiveness":174, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1ec31729-c5f1-4fc3-821a-bd1df82d8313", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "325":{ + "name":"Pharmacie Rivétoile", + "type":"sightseeing", + "location":[ + 48.5735174, + 7.7573261 + ], + "osm_type":"way", + "osm_id":160165418, + "attractiveness":292, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"28c2d7ba-4693-4821-bf77-b3b0b2f02a8d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "326":{ + "name":"La pizza de Nico", + "type":"sightseeing", + "location":[ + 48.5737198, + 7.7585119 + ], + "osm_type":"way", + "osm_id":160278663, + "attractiveness":438, + "n_tags":21, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7d422697-9740-4800-880e-49277f10b850", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "327":{ + "name":"Yoghurt Factory", + "type":"sightseeing", + "location":[ + 48.5733819, + 7.7607013 + ], + "osm_type":"way", + "osm_id":160278666, + "attractiveness":130, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1c183054-1990-41dc-9409-d231e8d1e427", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "328":{ + "name":"Déchetterie de Strasbourg Meinau", + "type":"sightseeing", + "location":[ + 48.5643456, + 7.7414631 + ], + "osm_type":"way", + "osm_id":178449381, + "attractiveness":476, + "n_tags":24, + "image_url":null, + "description":null, + "duration":0, + "uuid":"198a6600-f7c1-499f-a6e1-8910ba13b9e1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "329":{ + "name":"EHPAD Saint-Charles", + "type":"sightseeing", + "location":[ + 48.6046396, + 7.7389266 + ], + "osm_type":"way", + "osm_id":218847489, + "attractiveness":195, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cabfee0e-af20-4064-9ce8-d43cefbf99e6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "330":{ + "name":"Archives de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5722887, + 7.7636798 + ], + "osm_type":"way", + "osm_id":237600156, + "attractiveness":140, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"361629bd-b1fa-43f6-9483-1e72c121f417", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "331":{ + "name":"Antoine Chevrier", + "type":"sightseeing", + "location":[ + 48.5649781, + 7.7258364 + ], + "osm_type":"way", + "osm_id":240820782, + "attractiveness":104, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"be5a20ab-b8f7-4598-8244-557ac1edb5e1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "332":{ + "name":"Chronopost Strasbourg", + "type":"sightseeing", + "location":[ + 48.5860227, + 7.7104656 + ], + "osm_type":"way", + "osm_id":258484499, + "attractiveness":186, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f6da222a-415c-4db2-809c-c83741756ee9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "333":{ + "name":"Centre socio-culturel du Neudorf", + "type":"sightseeing", + "location":[ + 48.572051, + 7.7646058 + ], + "osm_type":"way", + "osm_id":281553577, + "attractiveness":183, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"925e5006-87df-417e-971a-dc299f6e47e1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "334":{ + "name":"Podologue Francis Grauffel", + "type":"sightseeing", + "location":[ + 48.6046168, + 7.7461847 + ], + "osm_type":"way", + "osm_id":285038430, + "attractiveness":117, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"311caf55-ecbf-4f89-9ca2-d6354f34e06e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "335":{ + "name":"Opéra du Rhin", + "type":"sightseeing", + "location":[ + 48.5858887, + 7.752263 + ], + "osm_type":"way", + "osm_id":287247607, + "attractiveness":435, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f262dca7-ec27-4f62-bde1-eb0390a7a17f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "336":{ + "name":"INET - Institut National des Études Territoriales", + "type":"sightseeing", + "location":[ + 48.572874, + 7.7657072 + ], + "osm_type":"way", + "osm_id":287513648, + "attractiveness":240, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"41b97cf0-aac1-4955-b43c-ac2a1804e6b4", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "337":{ + "name":"Parking Panza", + "type":"sightseeing", + "location":[ + 48.5699996, + 7.7589534 + ], + "osm_type":"way", + "osm_id":299249540, + "attractiveness":89, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5cf8823c-7435-4dda-b6b5-c7b93087734b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "338":{ + "name":"Haute école des arts du Rhin", + "type":"sightseeing", + "location":[ + 48.5823167, + 7.7590964 + ], + "osm_type":"way", + "osm_id":299658097, + "attractiveness":221, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5a5e96c7-c94d-4b70-bdaa-21323e55b160", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "339":{ + "name":"Collège Lucie Berger", + "type":"sightseeing", + "location":[ + 48.5781225, + 7.7428232 + ], + "osm_type":"way", + "osm_id":299879930, + "attractiveness":63, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5a73150e-ed9f-45c0-a582-668bf311ba2a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "340":{ + "name":"Parking McDonald's", + "type":"sightseeing", + "location":[ + 48.6049331, + 7.7056469 + ], + "osm_type":"way", + "osm_id":306278684, + "attractiveness":115, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6491ccee-bae6-4d4f-9603-f14aac521262", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "341":{ + "name":"École primaire Sainte-Aurélie", + "type":"sightseeing", + "location":[ + 48.5814337, + 7.7331999 + ], + "osm_type":"way", + "osm_id":308689224, + "attractiveness":112, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b505171a-fa8f-4bc2-a3fa-1add9b9334e8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "342":{ + "name":"École maternelle Sainte-Aurèlie", + "type":"sightseeing", + "location":[ + 48.5807863, + 7.7332324 + ], + "osm_type":"way", + "osm_id":308689460, + "attractiveness":113, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eaf8556a-07f8-4e9c-9675-0a6cc7fe00e5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "343":{ + "name":"Déchèterie Wacken", + "type":"sightseeing", + "location":[ + 48.5958807, + 7.7471545 + ], + "osm_type":"way", + "osm_id":318547037, + "attractiveness":537, + "n_tags":27, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9d194e46-720a-422d-aaad-2e1918ce26a2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "344":{ + "name":"Groupe scolaire Saint-Thomas", + "type":"sightseeing", + "location":[ + 48.5799563, + 7.7439536 + ], + "osm_type":"way", + "osm_id":320756153, + "attractiveness":115, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4767b707-d25c-4410-ab36-274478527d75", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "345":{ + "name":"Café Atlantico", + "type":"sightseeing", + "location":[ + 48.5831817, + 7.7575637 + ], + "osm_type":"way", + "osm_id":343949370, + "attractiveness":374, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b762260c-d9ac-48c7-8e4f-1dab94f0bab1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "346":{ + "name":"Pharmacie de la charmille", + "type":"sightseeing", + "location":[ + 48.582341, + 7.7151628 + ], + "osm_type":"way", + "osm_id":367587980, + "attractiveness":194, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"84156f1b-4dae-439b-836a-60ec4fb32b3a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "347":{ + "name":"École Nationale Supérieure d'Architecture de Strasbourg", + "type":"sightseeing", + "location":[ + 48.5860011, + 7.7373471 + ], + "osm_type":"way", + "osm_id":398434973, + "attractiveness":327, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c0c391f4-df48-4b13-ba8d-6bf30205dff5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "348":{ + "name":"Parking du parc du château", + "type":"sightseeing", + "location":[ + 48.6024339, + 7.7497998 + ], + "osm_type":"way", + "osm_id":402195981, + "attractiveness":141, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a2c001ac-d07c-4ebf-82f3-17a0061e43ff", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "349":{ + "name":"Écoles Exen", + "type":"sightseeing", + "location":[ + 48.6054159, + 7.7499926 + ], + "osm_type":"way", + "osm_id":406268450, + "attractiveness":81, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"59630a9b-ae98-4a3f-ad15-927742e13473", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "350":{ + "name":"Parking Musique Hammer", + "type":"sightseeing", + "location":[ + 48.6039106, + 7.7508727 + ], + "osm_type":"way", + "osm_id":407875963, + "attractiveness":119, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"bfd32a12-80f4-401f-8772-b2ac7b432465", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "351":{ + "name":"Parking Steinmetz", + "type":"sightseeing", + "location":[ + 48.6035816, + 7.7513024 + ], + "osm_type":"way", + "osm_id":407875964, + "attractiveness":111, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"57158683-5a6e-4dd3-8729-6659d4d10516", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "352":{ + "name":"Parking Aldi", + "type":"sightseeing", + "location":[ + 48.5980091, + 7.7356451 + ], + "osm_type":"way", + "osm_id":433781017, + "attractiveness":72, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c4d0ca28-edd3-42e6-a033-7a912056da80", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "353":{ + "name":"Tri selectif : verre", + "type":"sightseeing", + "location":[ + 48.5990223, + 7.733174 + ], + "osm_type":"way", + "osm_id":439707000, + "attractiveness":80, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eb8ab394-c5d0-4311-81c2-0f256254903f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "354":{ + "name":"P City Residence", + "type":"sightseeing", + "location":[ + 48.5894163, + 7.7387122 + ], + "osm_type":"way", + "osm_id":445787178, + "attractiveness":115, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"719eefab-738c-405f-a908-a6f4478279f7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "355":{ + "name":"Pharmacie du Hohberg", + "type":"sightseeing", + "location":[ + 48.583705, + 7.7076849 + ], + "osm_type":"way", + "osm_id":466428293, + "attractiveness":139, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1591206c-f6cb-46cf-b9e0-9a6f80210d49", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "356":{ + "name":"Parking Vélos CHU Hautepierre", + "type":"sightseeing", + "location":[ + 48.5923944, + 7.7087279 + ], + "osm_type":"way", + "osm_id":481002897, + "attractiveness":198, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3ebc0bae-c74c-4bb8-b798-38eb7432186e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "357":{ + "name":"Mosquée de Hautepierre", + "type":"sightseeing", + "location":[ + 48.5935551, + 7.701968 + ], + "osm_type":"way", + "osm_id":488664049, + "attractiveness":129, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fb13b7cc-d93e-4604-a606-7e2ce1617a2e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "358":{ + "name":"Groupe Scolaire Catherine", + "type":"sightseeing", + "location":[ + 48.5955066, + 7.7015441 + ], + "osm_type":"way", + "osm_id":491790619, + "attractiveness":43, + "n_tags":2, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a0732543-1193-462f-9f5d-1e6741ead821", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "359":{ + "name":"Dépose Minute", + "type":"sightseeing", + "location":[ + 48.5925412, + 7.7086365 + ], + "osm_type":"way", + "osm_id":495813732, + "attractiveness":161, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9600b53f-028a-46a9-8598-f280d93699cb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "360":{ + "name":"Réservé Urgences", + "type":"sightseeing", + "location":[ + 48.5930056, + 7.7049537 + ], + "osm_type":"way", + "osm_id":495963769, + "attractiveness":172, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"186ef8bc-83a6-4b7d-8c3e-b46dcc4b6e29", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "361":{ + "name":"Cafétéria CHU Hautepierre", + "type":"sightseeing", + "location":[ + 48.5926714, + 7.7070792 + ], + "osm_type":"way", + "osm_id":500546150, + "attractiveness":122, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f2f98ebd-7a23-4c91-918f-8d5641b59e68", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "362":{ + "name":"École maternelle Jacques Prévert", + "type":"sightseeing", + "location":[ + 48.6022485, + 7.7375706 + ], + "osm_type":"way", + "osm_id":503980502, + "attractiveness":157, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0adbf9c9-7c6c-40f2-829f-2bb610e23a33", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "363":{ + "name":"Parking Rue des Vosges", + "type":"sightseeing", + "location":[ + 48.5912783, + 7.7576616 + ], + "osm_type":"way", + "osm_id":515351591, + "attractiveness":85, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"203df493-9549-4cdf-a143-c378851be21a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "364":{ + "name":"Banque Populaire", + "type":"sightseeing", + "location":[ + 48.5918863, + 7.7413117 + ], + "osm_type":"way", + "osm_id":530800397, + "attractiveness":296, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7a6c2f64-f26f-453f-ada7-233a63331c31", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "365":{ + "name":"Maison de la petite enfance de Koenigshoffen", + "type":"sightseeing", + "location":[ + 48.581552, + 7.7124979 + ], + "osm_type":"way", + "osm_id":540719645, + "attractiveness":149, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3f240d24-2df0-46a6-a919-75f19eb181f6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "366":{ + "name":"Parking Arte", + "type":"sightseeing", + "location":[ + 48.5941708, + 7.7651353 + ], + "osm_type":"way", + "osm_id":546087900, + "attractiveness":84, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3c2f4373-cb3e-4893-bb7c-37848f56028f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "367":{ + "name":"Societé de Protection des Animaux (SPA) de Strasbourg", + "type":"sightseeing", + "location":[ + 48.6005942, + 7.7288159 + ], + "osm_type":"way", + "osm_id":550714898, + "attractiveness":93, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"36d3d517-e0b2-4fea-8369-dfbf5ccf8656", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "368":{ + "name":"Parking Personnel", + "type":"sightseeing", + "location":[ + 48.5745134, + 7.743644 + ], + "osm_type":"way", + "osm_id":561121930, + "attractiveness":102, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5503fc1b-9ae4-4bb0-ab11-dc0c99f3a7e3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "369":{ + "name":"Barco Latino", + "type":"sightseeing", + "location":[ + 48.5740175, + 7.7608481 + ], + "osm_type":"way", + "osm_id":562438805, + "attractiveness":206, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4102047a-e117-4db0-879d-ec6863585fae", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "370":{ + "name":"Parking Au Plaisirs d'Asie", + "type":"sightseeing", + "location":[ + 48.5978137, + 7.7363843 + ], + "osm_type":"way", + "osm_id":572658561, + "attractiveness":92, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"007a23cd-f900-40a3-99a3-b92e7aedf052", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "371":{ + "name":"Centre de Recherche en Biomédecine", + "type":"sightseeing", + "location":[ + 48.575984, + 7.7389818 + ], + "osm_type":"way", + "osm_id":655084918, + "attractiveness":359, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e2787195-e4e1-4109-a5af-d36f49165f2d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "372":{ + "name":"Véloparc Schluthfeld", + "type":"sightseeing", + "location":[ + 48.5686777, + 7.7520356 + ], + "osm_type":"way", + "osm_id":687020295, + "attractiveness":200, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9bca7aad-b59f-433c-8447-eef314f5e4b5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "373":{ + "name":"Véloparc Krimmeri", + "type":"sightseeing", + "location":[ + 48.5625311, + 7.7524022 + ], + "osm_type":"way", + "osm_id":687020403, + "attractiveness":206, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dc02ab92-5e99-42d9-8e90-aaec9d1f5092", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "374":{ + "name":"Le kiosque d'Omnino", + "type":"sightseeing", + "location":[ + 48.583173, + 7.7401939 + ], + "osm_type":"way", + "osm_id":692196205, + "attractiveness":315, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c938588e-6c21-4d93-bfa9-d2229544a11a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "375":{ + "name":"Peniche Mécanique", + "type":"sightseeing", + "location":[ + 48.5740803, + 7.7602081 + ], + "osm_type":"way", + "osm_id":702443797, + "attractiveness":239, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0d108b49-63b9-44fa-ab20-aa63632c76bb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "376":{ + "name":"EHPAD Montagne Verte", + "type":"sightseeing", + "location":[ + 48.5721138, + 7.7220784 + ], + "osm_type":"way", + "osm_id":702551682, + "attractiveness":188, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"49c3cab2-5284-4585-b5ca-5774aa803ebe", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "377":{ + "name":"Communauté des sœurs de Marie Réparatrice", + "type":"sightseeing", + "location":[ + 48.5773525, + 7.7452864 + ], + "osm_type":"way", + "osm_id":707912156, + "attractiveness":128, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d43bea6f-a396-4130-865a-cffd72c65edb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "378":{ + "name":"Cité Universitaire Paul Appell", + "type":"sightseeing", + "location":[ + 48.5763182, + 7.7630225 + ], + "osm_type":"way", + "osm_id":713776095, + "attractiveness":117, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4763fce0-9076-45ef-8a9a-11c12f21c7f1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "379":{ + "name":"Le Studium", + "type":"sightseeing", + "location":[ + 48.5815168, + 7.7664504 + ], + "osm_type":"way", + "osm_id":725967646, + "attractiveness":300, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"12c2a8cf-6547-4dac-a7e1-ea82c73e09c6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "380":{ + "name":"EHPAD Caritas", + "type":"sightseeing", + "location":[ + 48.5825482, + 7.6982902 + ], + "osm_type":"way", + "osm_id":738897222, + "attractiveness":172, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3478c098-59e7-40b6-a6fc-12207db42e9b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "381":{ + "name":"Fontaine du Lazaret", + "type":"sightseeing", + "location":[ + 48.5626613, + 7.762019 + ], + "osm_type":"way", + "osm_id":769030230, + "attractiveness":112, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7ba0377f-fba3-4766-96ae-646d75df24f3", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "382":{ + "name":"Hôpital de Jour Abrapa", + "type":"sightseeing", + "location":[ + 48.5770354, + 7.7458673 + ], + "osm_type":"way", + "osm_id":777325748, + "attractiveness":117, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9789358e-62ee-4a4b-9f99-95034356da68", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "383":{ + "name":"Centre Médico-Chirurgical et Obstétrical", + "type":"sightseeing", + "location":[ + 48.6004476, + 7.7500196 + ], + "osm_type":"way", + "osm_id":787481692, + "attractiveness":302, + "n_tags":15, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b9c1efec-4422-4921-9518-ad664ab2701e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "384":{ + "name":"Centre Paul Strauss", + "type":"sightseeing", + "location":[ + 48.5764092, + 7.7510095 + ], + "osm_type":"way", + "osm_id":787519495, + "attractiveness":274, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"768825d9-be93-4815-8daa-305dfe18bbc7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "385":{ + "name":"Clinique de la Toussaint", + "type":"sightseeing", + "location":[ + 48.5873259, + 7.7451279 + ], + "osm_type":"way", + "osm_id":788882576, + "attractiveness":254, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4ed027f8-a845-4524-816b-bf5f7f090a86", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "386":{ + "name":"Clinique de l'Orangerie", + "type":"sightseeing", + "location":[ + 48.5881667, + 7.7647546 + ], + "osm_type":"way", + "osm_id":788885571, + "attractiveness":197, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c535660f-eec1-4347-9543-f6b15ec8bef2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "387":{ + "name":"Centre Culturel Turc", + "type":"sightseeing", + "location":[ + 48.5856451, + 7.7198093 + ], + "osm_type":"way", + "osm_id":803430879, + "attractiveness":78, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"98350b1c-7e73-4f2e-9cb4-352de3affac9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "388":{ + "name":"Centre de formation des Compagnons du Devoir", + "type":"sightseeing", + "location":[ + 48.581096, + 7.7218117 + ], + "osm_type":"way", + "osm_id":803432415, + "attractiveness":91, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"85a8b173-108e-4187-aa67-18a780339d60", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "389":{ + "name":"Blue Flamingo", + "type":"sightseeing", + "location":[ + 48.5741237, + 7.759566 + ], + "osm_type":"way", + "osm_id":849800106, + "attractiveness":211, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d2a7ba7d-587c-41dc-85a8-f2fd3134223c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "390":{ + "name":"École élementaire Louvois", + "type":"sightseeing", + "location":[ + 48.5753617, + 7.7607627 + ], + "osm_type":"way", + "osm_id":880628784, + "attractiveness":93, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2e9f9844-b93f-4bfc-8ff0-2d9305c86743", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "391":{ + "name":"Place handicapé", + "type":"sightseeing", + "location":[ + 48.5706163, + 7.7590571 + ], + "osm_type":"way", + "osm_id":898572029, + "attractiveness":172, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7beef5e7-bd51-4f49-8d48-32d6d91c34f6", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "392":{ + "name":"Maison des associations", + "type":"sightseeing", + "location":[ + 48.5710885, + 7.7560426 + ], + "osm_type":"way", + "osm_id":898629833, + "attractiveness":164, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a69f6de0-2063-480d-8e90-f0063dcdb5f9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "393":{ + "name":"Centre d'incendie et de secours Strasbourg-Ouest", + "type":"sightseeing", + "location":[ + 48.5895804, + 7.7277613 + ], + "osm_type":"way", + "osm_id":931851355, + "attractiveness":141, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2b65b4c7-5982-4391-b69a-f485164c4672", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "394":{ + "name":"Groupe Scolaire du Finkwiller", + "type":"sightseeing", + "location":[ + 48.5787085, + 7.7409624 + ], + "osm_type":"way", + "osm_id":933655725, + "attractiveness":69, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9a66ab3f-a8fe-4986-b2f6-05a6f98f89d1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "395":{ + "name":"Groupe Scolaire Saint-Jean", + "type":"sightseeing", + "location":[ + 48.5892166, + 7.7433992 + ], + "osm_type":"way", + "osm_id":936476891, + "attractiveness":34, + "n_tags":2, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f731948f-e5f8-4a3d-ae1b-d49140e0143f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "396":{ + "name":"Lycée International Pontonniers", + "type":"sightseeing", + "location":[ + 48.584644, + 7.756182 + ], + "osm_type":"way", + "osm_id":962683865, + "attractiveness":243, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5f44e1dd-ea5c-4f5d-b2d0-1dc3a00ddd53", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "397":{ + "name":"École et Observatoire des Sciences de la Terre", + "type":"sightseeing", + "location":[ + 48.5799831, + 7.7623986 + ], + "osm_type":"way", + "osm_id":968814565, + "attractiveness":57, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d51b05f8-4f94-4d59-a149-2a2ea75a1604", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "398":{ + "name":"Parc des Expositions", + "type":"sightseeing", + "location":[ + 48.5966169, + 7.7523551 + ], + "osm_type":"way", + "osm_id":973489794, + "attractiveness":70, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"442ec209-ca42-4642-acfb-d9cdacf6cb3a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "399":{ + "name":"Mosquée Turque Eyyub-Sultan", + "type":"sightseeing", + "location":[ + 48.56232, + 7.7447463 + ], + "osm_type":"way", + "osm_id":975021326, + "attractiveness":60, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c08b0e44-4af6-4012-90a3-13b313efae47", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "400":{ + "name":"Le Meiselocker", + "type":"sightseeing", + "location":[ + 48.5834011, + 7.7547026 + ], + "osm_type":"way", + "osm_id":975449056, + "attractiveness":125, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dcf3fde2-a9c5-42ab-adce-bf83737b70cc", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "401":{ + "name":"Place de Bordeaux", + "type":"sightseeing", + "location":[ + 48.5934912, + 7.7576553 + ], + "osm_type":"way", + "osm_id":981575948, + "attractiveness":176, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c0e1ceaf-b479-4e26-9d89-0198fdfaad23", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "402":{ + "name":"Hôpital Psychiatrique EPSAN à Cronenbourg", + "type":"sightseeing", + "location":[ + 48.6045624, + 7.7149985 + ], + "osm_type":"way", + "osm_id":993769600, + "attractiveness":44, + "n_tags":3, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c7a25c2b-79ff-4af3-bb15-b0c9614ec551", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "403":{ + "name":"Meet&go", + "type":"sightseeing", + "location":[ + 48.5852368, + 7.7346646 + ], + "osm_type":"way", + "osm_id":997898116, + "attractiveness":288, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a065fd49-d750-41ea-aa9f-d2bde8667786", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "404":{ + "name":"Commissariat de police", + "type":"sightseeing", + "location":[ + 48.5844008, + 7.7340232 + ], + "osm_type":"way", + "osm_id":997898127, + "attractiveness":353, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"24f3f38d-7887-4a84-a2ea-3a371df438be", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "405":{ + "name":"Subway", + "type":"sightseeing", + "location":[ + 48.5859368, + 7.7411652 + ], + "osm_type":"way", + "osm_id":1000017660, + "attractiveness":287, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d841671d-e5f4-4db0-b07a-07f418b43e24", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "406":{ + "name":"Phan Asia", + "type":"sightseeing", + "location":[ + 48.58746, + 7.7406537 + ], + "osm_type":"way", + "osm_id":1001386069, + "attractiveness":209, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"91877138-b5bc-4e91-91b4-2abd2408b0a8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "407":{ + "name":"Crêp'eat", + "type":"sightseeing", + "location":[ + 48.5868263, + 7.7409465 + ], + "osm_type":"way", + "osm_id":1001406930, + "attractiveness":249, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"423dd384-3716-4bf2-a43e-e2fb0e667e26", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "408":{ + "name":"Pharmacie des Halles", + "type":"sightseeing", + "location":[ + 48.5869146, + 7.7412203 + ], + "osm_type":"way", + "osm_id":1001406931, + "attractiveness":291, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ddf01091-17be-470b-80c3-1cc5032b73cb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "409":{ + "name":"Zumo", + "type":"sightseeing", + "location":[ + 48.5865137, + 7.7411574 + ], + "osm_type":"way", + "osm_id":1001406938, + "attractiveness":251, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4c094864-e37e-424b-973b-c87083c1c2ab", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "410":{ + "name":"Pur etc", + "type":"sightseeing", + "location":[ + 48.5869371, + 7.7407944 + ], + "osm_type":"way", + "osm_id":1001442479, + "attractiveness":202, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9200f3c9-ffb9-4f44-b757-3bf2dbd79a1c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "411":{ + "name":"La Pause", + "type":"sightseeing", + "location":[ + 48.5875266, + 7.7407115 + ], + "osm_type":"way", + "osm_id":1001442481, + "attractiveness":200, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"73775261-066d-48c3-994e-05698c2710a1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "412":{ + "name":"Dépose-minute Conservatoire", + "type":"sightseeing", + "location":[ + 48.5742487, + 7.7551635 + ], + "osm_type":"way", + "osm_id":1001891414, + "attractiveness":223, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"805d990b-c692-41d0-857c-fb68d1725fd8", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "413":{ + "name":"Le Cardo", + "type":"sightseeing", + "location":[ + 48.577191, + 7.7471325 + ], + "osm_type":"way", + "osm_id":1008875558, + "attractiveness":840, + "n_tags":17, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1b3be37a-1b99-4cad-aa7c-d55932799e03", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "414":{ + "name":"Place Dentaire", + "type":"sightseeing", + "location":[ + 48.5733154, + 7.7595294 + ], + "osm_type":"way", + "osm_id":1012884318, + "attractiveness":230, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0ed4e0b5-32a0-4673-a42b-cadc3684abff", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "415":{ + "name":"Bagelstein", + "type":"sightseeing", + "location":[ + 48.5735058, + 7.760531 + ], + "osm_type":"way", + "osm_id":1012884356, + "attractiveness":162, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"37ed5b1d-f786-4881-b4c7-5731cc7c05ee", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "416":{ + "name":"KFC", + "type":"sightseeing", + "location":[ + 48.573159, + 7.7609123 + ], + "osm_type":"way", + "osm_id":1012884357, + "attractiveness":503, + "n_tags":24, + "image_url":null, + "description":null, + "duration":0, + "uuid":"08839153-bc35-406a-b994-039a3d25c20f", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "417":{ + "name":"Direction de territoire : CRONENBOURG - HAUTEPIERRE - POTERIES - HOHBERG", + "type":"sightseeing", + "location":[ + 48.5909853, + 7.7088725 + ], + "osm_type":"way", + "osm_id":1046228331, + "attractiveness":130, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8f194d45-94de-47c7-8be1-a945c7f0ca4a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "418":{ + "name":"Restaurant Centre régional des œuvres universitaires et scolaires", + "type":"sightseeing", + "location":[ + 48.6056188, + 7.713933 + ], + "osm_type":"way", + "osm_id":1051453980, + "attractiveness":119, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7c623c55-9e70-43b2-a3df-474997219216", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "419":{ + "name":"Centre National de la Recherche Scientifique - IPHC", + "type":"sightseeing", + "location":[ + 48.6049163, + 7.7115483 + ], + "osm_type":"way", + "osm_id":1051455165, + "attractiveness":98, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f9c64bb5-d980-496c-b80c-b230477ecb37", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "420":{ + "name":"Géosciences, de l'eau, de l'environnement, et de l'ingénierie", + "type":"sightseeing", + "location":[ + 48.5808648, + 7.7584925 + ], + "osm_type":"way", + "osm_id":1053292870, + "attractiveness":78, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"28801df4-865d-45f7-b40f-6990d1a94f47", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "421":{ + "name":"Espace événementiel", + "type":"sightseeing", + "location":[ + 48.5809399, + 7.7582691 + ], + "osm_type":"way", + "osm_id":1053292874, + "attractiveness":42, + "n_tags":2, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c7606878-36c3-4b90-8bf6-031a15840720", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "422":{ + "name":"Pro Grill", + "type":"sightseeing", + "location":[ + 48.5876336, + 7.7005204 + ], + "osm_type":"way", + "osm_id":1054791888, + "attractiveness":104, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"add43b49-36a8-4327-a8ae-ee611f619441", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "423":{ + "name":"Collège Caroline Aigle", + "type":"sightseeing", + "location":[ + 48.5778284, + 7.7556221 + ], + "osm_type":"way", + "osm_id":1059530531, + "attractiveness":267, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b89d8b4e-42cb-4b53-bd90-729438b7f4fd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "424":{ + "name":"Le Lavoir", + "type":"sightseeing", + "location":[ + 48.5840505, + 7.7401703 + ], + "osm_type":"way", + "osm_id":1066869836, + "attractiveness":287, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dbf87be2-97dd-4b68-bdf4-71fa973504bd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "425":{ + "name":"BUS", + "type":"sightseeing", + "location":[ + 48.5941301, + 7.7353135 + ], + "osm_type":"way", + "osm_id":1079847903, + "attractiveness":98, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"31a6600f-d066-449a-bde6-3b33e215dfdb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "426":{ + "name":"Halle du marché de Neudorf", + "type":"sightseeing", + "location":[ + 48.5667985, + 7.7604529 + ], + "osm_type":"way", + "osm_id":1080718584, + "attractiveness":204, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"8715243c-d24e-4cc0-8fda-ed0f6ff75576", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "427":{ + "name":"Planétarium du Jardin des sciences", + "type":"sightseeing", + "location":[ + 48.5832366, + 7.7638927 + ], + "osm_type":"way", + "osm_id":1081010784, + "attractiveness":218, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"67c118cb-147b-4acd-a621-a590fd001b6c", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "428":{ + "name":"Déchèterie", + "type":"sightseeing", + "location":[ + 48.5841154, + 7.7163051 + ], + "osm_type":"way", + "osm_id":1090005393, + "attractiveness":88, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"35962c84-798c-4f09-92c8-a6798316ab29", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "429":{ + "name":"Institution La Doctrine Chrétienne", + "type":"sightseeing", + "location":[ + 48.5906187, + 7.7232206 + ], + "osm_type":"way", + "osm_id":1098843020, + "attractiveness":118, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4b9e21db-04ef-4482-ad80-f784b24ac2ff", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "430":{ + "name":"L'Orée 85", + "type":"sightseeing", + "location":[ + 48.5689771, + 7.7345561 + ], + "osm_type":"way", + "osm_id":1104400943, + "attractiveness":360, + "n_tags":18, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2c4eedcf-1eed-44c0-925c-80c91be49513", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "431":{ + "name":"CHRS Femmes de Paroles", + "type":"sightseeing", + "location":[ + 48.5752522, + 7.7261335 + ], + "osm_type":"way", + "osm_id":1119117552, + "attractiveness":202, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0f720820-1308-41c7-8b15-d521f2cfd42e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "432":{ + "name":"Cantine Louis Pasteur", + "type":"sightseeing", + "location":[ + 48.5757944, + 7.7380624 + ], + "osm_type":"way", + "osm_id":1133748232, + "attractiveness":83, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"374de9c5-1602-4ae1-a74e-f2bfa1606d46", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "433":{ + "name":"Groupe Scolaire Simone Veil", + "type":"sightseeing", + "location":[ + 48.6008454, + 7.743517 + ], + "osm_type":"way", + "osm_id":1135517313, + "attractiveness":188, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"4aa8c2c0-f03b-459e-9757-5cafc718252e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "434":{ + "name":"Accueil du Jardin des sciences", + "type":"sightseeing", + "location":[ + 48.5830548, + 7.7641569 + ], + "osm_type":"way", + "osm_id":1138976617, + "attractiveness":327, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"eab0ad0b-7cd3-4cb9-9adc-a59ffbbd11bf", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "435":{ + "name":"Baraka Jeux", + "type":"sightseeing", + "location":[ + 48.5839109, + 7.7440524 + ], + "osm_type":"way", + "osm_id":1145630033, + "attractiveness":196, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d5b0d541-f68e-4c12-9e73-21f94a2b4dd0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "436":{ + "name":"Brasserie en Alsace", + "type":"sightseeing", + "location":[ + 48.5847347, + 7.7343447 + ], + "osm_type":"way", + "osm_id":1152983997, + "attractiveness":250, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7ec68211-4939-4b74-9ef8-d432ddf230de", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "437":{ + "name":"Objets trouvés", + "type":"sightseeing", + "location":[ + 48.585184, + 7.7346631 + ], + "osm_type":"way", + "osm_id":1152990565, + "attractiveness":303, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"28d8ba23-26c2-47bb-9777-8d8144033399", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "438":{ + "name":"Salon grand voyageur", + "type":"sightseeing", + "location":[ + 48.5848874, + 7.734411 + ], + "osm_type":"way", + "osm_id":1152990567, + "attractiveness":269, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9173d29b-083c-4ffa-a3ca-f020a22804a9", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "439":{ + "name":"Bertani", + "type":"sightseeing", + "location":[ + 48.5844406, + 7.749238 + ], + "osm_type":"way", + "osm_id":1164808789, + "attractiveness":212, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7fb02857-05ac-4fc2-8f74-90264ebfc0e5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "440":{ + "name":"Parking du PEX", + "type":"sightseeing", + "location":[ + 48.5962257, + 7.7540886 + ], + "osm_type":"way", + "osm_id":1167173035, + "attractiveness":207, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"cd28ae81-0c9b-48e0-83f7-f564541b3b64", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "441":{ + "name":"Médiathèque Jeunesse Olympe de Gouges (Centre ville)", + "type":"sightseeing", + "location":[ + 48.5847306, + 7.7389687 + ], + "osm_type":"way", + "osm_id":1188398624, + "attractiveness":136, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f4ecf813-8cb9-4741-8cd6-2983de6da601", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "442":{ + "name":"École maternelle Parc du Château", + "type":"sightseeing", + "location":[ + 48.602202, + 7.750678 + ], + "osm_type":"way", + "osm_id":1216416394, + "attractiveness":143, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"56fbaecf-b35e-460c-8d6f-212f69c66be5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "443":{ + "name":"Cour des Médecins", + "type":"sightseeing", + "location":[ + 48.5864539, + 7.7365286 + ], + "osm_type":"way", + "osm_id":1243118414, + "attractiveness":99, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2be4ec5b-de9f-4dd5-8eea-bdaa5c02957b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "444":{ + "name":"Cour de l'Aigle", + "type":"sightseeing", + "location":[ + 48.5861037, + 7.7361213 + ], + "osm_type":"way", + "osm_id":1243118415, + "attractiveness":109, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"386e57b0-bd54-4ba7-a71f-474b9d16e9f2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "445":{ + "name":"Cour Intérieure", + "type":"sightseeing", + "location":[ + 48.5862623, + 7.7357454 + ], + "osm_type":"way", + "osm_id":1243118416, + "attractiveness":135, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"287b6778-4d71-4643-9631-ed4fe656b3f0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "446":{ + "name":"Saint-Florent", + "type":"sightseeing", + "location":[ + 48.5960762, + 7.7215955 + ], + "osm_type":"way", + "osm_id":1257186377, + "attractiveness":292, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"14657ed6-eda2-43ac-a5c8-587d070db846", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "447":{ + "name":"Palais des Fêtes", + "type":"sightseeing", + "location":[ + 48.5908291, + 7.7493322 + ], + "osm_type":"relation", + "osm_id":157861, + "attractiveness":273, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"ac35bc42-c751-4d2a-b2ab-5d0fde96871a", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "448":{ + "name":"BNP Paribas", + "type":"sightseeing", + "location":[ + 48.5838878, + 7.749156 + ], + "osm_type":"relation", + "osm_id":216044, + "attractiveness":263, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0ee797fc-406c-43cd-9903-9ca7bf015a53", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "449":{ + "name":"Site de la Fonderie", + "type":"sightseeing", + "location":[ + 48.5861007, + 7.749314 + ], + "osm_type":"relation", + "osm_id":216512, + "attractiveness":109, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"f6195e25-5a9a-4041-894a-c65d20f995ad", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "450":{ + "name":"Le Gruber", + "type":"sightseeing", + "location":[ + 48.5806321, + 7.7505316 + ], + "osm_type":"relation", + "osm_id":223820, + "attractiveness":463, + "n_tags":21, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1170087d-2162-48be-8387-47efcdb95b51", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "451":{ + "name":"Société Générale", + "type":"sightseeing", + "location":[ + 48.6048403, + 7.7036217 + ], + "osm_type":"relation", + "osm_id":224236, + "attractiveness":223, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"7d0a6124-c2dc-4d4a-8286-791a2f348a30", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "452":{ + "name":"Direction régionale des Finances Publiques d'Alsace et du département du Bas-Rhin", + "type":"sightseeing", + "location":[ + 48.5883877, + 7.754041 + ], + "osm_type":"relation", + "osm_id":227003, + "attractiveness":279, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fb1fb274-e37e-4037-adad-27fada9411ef", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "453":{ + "name":"Palais de Justice", + "type":"sightseeing", + "location":[ + 48.5881911, + 7.7478698 + ], + "osm_type":"relation", + "osm_id":228029, + "attractiveness":230, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"e5e22c25-ecd5-42ff-9cbc-988a0c0f77b5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "454":{ + "name":"Institut national du service public", + "type":"sightseeing", + "location":[ + 48.5808026, + 7.7373507 + ], + "osm_type":"relation", + "osm_id":228395, + "attractiveness":376, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"dd10c634-5ac1-4fe6-8744-11073f53d3ec", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "455":{ + "name":"Hôtel du Département", + "type":"sightseeing", + "location":[ + 48.5784412, + 7.7380667 + ], + "osm_type":"relation", + "osm_id":228447, + "attractiveness":120, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"96035ac3-07f2-47ba-a6e6-2d89b64f35fe", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "456":{ + "name":"Faculté de Chirurgie Dentaire", + "type":"sightseeing", + "location":[ + 48.5773439, + 7.7449516 + ], + "osm_type":"relation", + "osm_id":230046, + "attractiveness":110, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"68b58da5-61ab-47f8-bb3e-ec9eca19a00b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "457":{ + "name":"Bibliothèque Nationale Universitaire de Strasbourg", + "type":"sightseeing", + "location":[ + 48.587169, + 7.7558213 + ], + "osm_type":"relation", + "osm_id":236931, + "attractiveness":671, + "n_tags":31, + "image_url":null, + "description":null, + "duration":0, + "uuid":"31488c2a-cf7e-4bd4-8354-7f0b2c00e04e", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "458":{ + "name":"Restaurant Universitaire Gallia", + "type":"sightseeing", + "location":[ + 48.5843491, + 7.7595883 + ], + "osm_type":"relation", + "osm_id":238063, + "attractiveness":234, + "n_tags":11, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6c399982-2f67-47cc-805d-aa1ccbdda7b0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "459":{ + "name":"Faculté des Langues", + "type":"sightseeing", + "location":[ + 48.5781106, + 7.7654182 + ], + "osm_type":"relation", + "osm_id":240864, + "attractiveness":251, + "n_tags":14, + "image_url":null, + "description":null, + "duration":0, + "uuid":"1cc31db2-a5f6-416d-80a6-7f0e7a10c141", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "460":{ + "name":"Institut de Géologie", + "type":"sightseeing", + "location":[ + 48.5834376, + 7.7629399 + ], + "osm_type":"relation", + "osm_id":241594, + "attractiveness":179, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a93acdfd-af2a-4c73-aadc-968fd0e15f88", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "461":{ + "name":"Institut Universitaire de Technologie Louis Pasteur", + "type":"sightseeing", + "location":[ + 48.6074836, + 7.7079621 + ], + "osm_type":"relation", + "osm_id":252831, + "attractiveness":111, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"6ed37369-5728-46d2-a743-42543effa536", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "462":{ + "name":"Parking Gare Wodli", + "type":"sightseeing", + "location":[ + 48.5873726, + 7.7367546 + ], + "osm_type":"relation", + "osm_id":259307, + "attractiveness":282, + "n_tags":13, + "image_url":null, + "description":null, + "duration":0, + "uuid":"9a5e9bd9-052e-49c1-ad33-2258da3afaf7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "463":{ + "name":"Direction Régionale de la SNCF", + "type":"sightseeing", + "location":[ + 48.5862571, + 7.7361786 + ], + "osm_type":"relation", + "osm_id":261658, + "attractiveness":113, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"af58b049-3dfa-45dc-8fa7-63d6286f9d39", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "464":{ + "name":"Mathématique, Informatique - Physique du Globe", + "type":"sightseeing", + "location":[ + 48.5798654, + 7.7632636 + ], + "osm_type":"relation", + "osm_id":366500, + "attractiveness":90, + "n_tags":5, + "image_url":null, + "description":null, + "duration":0, + "uuid":"2109f1ba-006b-4a0e-b6ae-5a72fc1f21bb", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "465":{ + "name":"Palais Universitaire", + "type":"sightseeing", + "location":[ + 48.5848129, + 7.7624991 + ], + "osm_type":"relation", + "osm_id":368604, + "attractiveness":399, + "n_tags":19, + "image_url":null, + "description":null, + "duration":0, + "uuid":"d0845932-207f-46d4-85dc-0f2a823c5906", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "466":{ + "name":"Collège Louis Pasteur", + "type":"sightseeing", + "location":[ + 48.5733055, + 7.7387487 + ], + "osm_type":"relation", + "osm_id":4460379, + "attractiveness":117, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b8657678-a0e5-41a1-a5a4-45d6e7d00e9d", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "467":{ + "name":"École primaire Exen Pire", + "type":"sightseeing", + "location":[ + 48.6052315, + 7.7495768 + ], + "osm_type":"relation", + "osm_id":6327072, + "attractiveness":158, + "n_tags":8, + "image_url":null, + "description":null, + "duration":0, + "uuid":"36841ce3-7fef-40af-b14e-bb31068bd839", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "468":{ + "name":"École primaire Exen Schweitzer", + "type":"sightseeing", + "location":[ + 48.6057675, + 7.7499638 + ], + "osm_type":"relation", + "osm_id":6327073, + "attractiveness":130, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"3c046f26-6007-4928-9956-75fb24879d77", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "469":{ + "name":"Restaurant Universitaire Paul Appell", + "type":"sightseeing", + "location":[ + 48.5759619, + 7.762996 + ], + "osm_type":"relation", + "osm_id":8240757, + "attractiveness":190, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"c7cee4a8-b74c-428f-838f-8dc69f3703d7", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "470":{ + "name":"Parking relais-tram P+R Parc des Romains", + "type":"sightseeing", + "location":[ + 48.5817024, + 7.7241421 + ], + "osm_type":"relation", + "osm_id":11668557, + "attractiveness":418, + "n_tags":20, + "image_url":null, + "description":null, + "duration":0, + "uuid":"a2195bec-4190-474f-96cd-8c735d6a21c2", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "471":{ + "name":"Groupe scolaire Sainte-Madeleine", + "type":"sightseeing", + "location":[ + 48.579786, + 7.7542586 + ], + "osm_type":"relation", + "osm_id":14103600, + "attractiveness":247, + "n_tags":12, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0877f1d4-83e9-40bb-bdd7-996062d4ceb0", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "472":{ + "name":"La Grenze", + "type":"sightseeing", + "location":[ + 48.5889655, + 7.7348998 + ], + "osm_type":"relation", + "osm_id":14211218, + "attractiveness":317, + "n_tags":16, + "image_url":null, + "description":null, + "duration":0, + "uuid":"0cddda65-3cd3-4eac-944f-bdc8bec91fd5", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "473":{ + "name":"École maternelle-élémentaire Rosa Parks", + "type":"sightseeing", + "location":[ + 48.6074934, + 7.7664371 + ], + "osm_type":"relation", + "osm_id":14254313, + "attractiveness":250, + "n_tags":10, + "image_url":null, + "description":null, + "duration":0, + "uuid":"45ef7d92-e3b9-4340-9f20-c5033211521b", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "474":{ + "name":"Toilettes publiques", + "type":"sightseeing", + "location":[ + 48.5846113, + 7.7336135 + ], + "osm_type":"relation", + "osm_id":16354356, + "attractiveness":197, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"5b8a3a59-9468-46bc-a30e-0a480daeebe1", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "475":{ + "name":"Canal de la Marne au Rhin", + "type":"sightseeing", + "location":[ + 48.5963838, + 7.7782303 + ], + "osm_type":"way", + "osm_id":10424914, + "attractiveness":100, + "n_tags":6, + "image_url":null, + "description":null, + "duration":0, + "uuid":"144c0f13-e60a-4970-a9b6-a401075b7a54", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "476":{ + "name":"Bassin de la Porte de l’Hôpital", + "type":"sightseeing", + "location":[ + 48.573628, + 7.7456353 + ], + "osm_type":"way", + "osm_id":43520883, + "attractiveness":136, + "n_tags":7, + "image_url":null, + "description":null, + "duration":0, + "uuid":"fb1a7576-2231-4083-a23a-4aa0052c93ca", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "477":{ + "name":"Le Rhin Tortu", + "type":"sightseeing", + "location":[ + 48.5656635, + 7.7460474 + ], + "osm_type":"way", + "osm_id":43570553, + "attractiveness":140, + "n_tags":9, + "image_url":null, + "description":null, + "duration":0, + "uuid":"43da5dc5-5f34-417c-a908-893a104a8e22", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "478":{ + "name":"Bassin d'Austerlitz", + "type":"sightseeing", + "location":[ + 48.5740949, + 7.7605279 + ], + "osm_type":"way", + "osm_id":43799886, + "attractiveness":68, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"756463c9-6c39-41b6-9324-a0b812b892cd", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + }, + "479":{ + "name":"Bras de l'Ill", + "type":"sightseeing", + "location":[ + 48.6034214, + 7.7660788 + ], + "osm_type":"way", + "osm_id":931979292, + "attractiveness":60, + "n_tags":4, + "image_url":null, + "description":null, + "duration":0, + "uuid":"b062cda1-9d52-4e66-b5bb-ed98de20d999", + "must_do":false, + "must_avoid":false, + "is_secondary":false, + "time_to_reach_next":0, + "next_uuid":null + } +} \ No newline at end of file diff --git a/backend/src/constants.py b/backend/src/constants.py index d5b7b5a..2e66727 100644 --- a/backend/src/constants.py +++ b/backend/src/constants.py @@ -15,5 +15,5 @@ OSM_CACHE_DIR = Path(cache_dir_string) logger = logging.getLogger(__name__) logging.basicConfig( level = logging.INFO, - format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + format = '%(asctime)s - %(name)s\t- %(levelname)s\t- %(message)s' ) diff --git a/backend/src/optimizer.py b/backend/src/optimizer.py index 6e52de1..4c070f6 100644 --- a/backend/src/optimizer.py +++ b/backend/src/optimizer.py @@ -49,10 +49,10 @@ class Optimizer: dist = 0 for elem in L : if elem.time_to_reach_next is not None : - print('- ' + elem.name + ', time to reach next = ' + str(elem.time_to_reach_next)) + self.logger.info(f" {elem.name}, time to next = {elem.time_to_reach_next}") dist += elem.time_to_reach_next else : - print('- ' + elem.name) + self.logger.info(f" {elem.name}") self.logger.info(f'Minutes walked : {dist}') self.logger.info(f'Visited {len(L)-2} landmarks') @@ -478,7 +478,7 @@ class Optimizer: # Main optimization pipeline - def solve_optimization (self) : + def solve_optimization (self, hide_log=False) : """ Main optimization pipeline to solve the landmark visiting problem. @@ -506,6 +506,9 @@ class Optimizer: A, b = self.respect_user_must_do(self.landmarks) # Check if there are user_defined must_see. Also takes care of start/goal A_eq = np.vstack((A_eq, A), dtype=np.int8) b_eq += b + A, b = self.respect_user_must_avoid(self.landmarks) # Check if there are user_defined must_see. Also takes care of start/goal + A_eq = np.vstack((A_eq, A), dtype=np.int8) + b_eq += b A, b = self.respect_start_finish(L) # Force start and finish positions A_eq = np.vstack((A_eq, A), dtype=np.int8) b_eq += b @@ -540,13 +543,13 @@ class Optimizer: b_eq += b res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) if not res.success : - self.logger.info("Solving failed because of overconstrained problem") + raise ArithmeticError("Solving failed because of overconstrained problem") return None order, circles = self.is_connected(res.x) #nodes, edges = is_connected(res.x) if circles is None : break - print(i) + # print(i) i += 1 if i == timeout : @@ -556,10 +559,11 @@ class Optimizer: tour = self.link_list(order, self.landmarks) # logging - if i != 0 : - self.logger.info(f"Neded to recompute paths {i} times because of unconnected loops...") - self.print_res(tour) # how to do better ? - self.logger.info(f"Total score : {int(-res.fun)}") + if not hide_log : + if i != 0 : + self.logger.info(f"Neded to recompute paths {i} times") + self.print_res(tour) # how to do better ? + self.logger.info(f"Total score : {int(-res.fun)}") return tour diff --git a/backend/src/refiner.py b/backend/src/refiner.py index 8fbb0f5..85aa7c5 100644 --- a/backend/src/refiner.py +++ b/backend/src/refiner.py @@ -14,9 +14,7 @@ import constants class Refiner : logger = logging.getLogger(__name__) - - all_landmarks: List[Landmark] # list of all landmarks - base_tour: List[Landmark] # base tour that needs to be refined + max_time: int = None # max visit time (in minutes) detour: int = None # accepted max detour time (in minutes) detour_factor: float # detour factor of straight line vs real distance in cities @@ -24,11 +22,9 @@ class Refiner : max_landmarks: int # max number of landmarks to visit - def __init__(self, max_time: int, detour: int, all_landmarks: List[Landmark], base_tour: List[Landmark]) : + def __init__(self, max_time: int, detour: int) : self.max_time = max_time self.detour = detour - self.all_landmarks = all_landmarks - self.base_tour = base_tour # load parameters from file with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: @@ -290,7 +286,7 @@ class Refiner : # Second stage of the optimization. Use linear programming again to refine the path - def refine_optimization(self) -> List[Landmark] : + def refine_optimization(self, all_landmarks: List[Landmark], base_tour: List[Landmark]) -> List[Landmark] : """ Refine the initial tour path by considering additional minor landmarks and optimizing the path. @@ -309,20 +305,20 @@ class Refiner : new_tour = base_tour else : - minor_landmarks = self.get_minor_landmarks(self.all_landmarks, self.base_tour, 200) + minor_landmarks = self.get_minor_landmarks(all_landmarks, base_tour, 200) self.logger.info(f"Using {len(minor_landmarks)} minor landmarks around the predicted path") # full set of visitable landmarks - full_set = self.base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) - full_set.append(self.base_tour[-1]) # add finish back + full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) + full_set.append(base_tour[-1]) # add finish back # get a new tour optimizer = Optimizer(self.max_time + self.detour, full_set) - new_tour = optimizer.solve_optimization() + new_tour = optimizer.solve_optimization(hide_log=True) if new_tour is None : - new_tour = self.base_tour + new_tour = base_tour # Link the new tour new_tour, new_dist = link_list_simple(new_tour) @@ -335,7 +331,7 @@ class Refiner : better_tour, better_poly = self.find_shortest_path_through_all_landmarks(new_tour) # Fix the tour using Polygons if the path looks weird - if self.base_tour[0].location == self.base_tour[-1].location and not better_poly.is_valid : + if base_tour[0].location == base_tour[-1].location and not better_poly.is_valid : better_tour = self.fix_using_polygon(better_tour) # Link the tour again @@ -348,6 +344,7 @@ class Refiner : final_tour = better_tour self.logger.info("Refined tour (result of second stage optimization): ") + optimizer.print_res(final_tour) return final_tour diff --git a/backend/src/tester.py b/backend/src/tester.py index 8f1f718..156b2a5 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -41,7 +41,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = type='shopping', score = 0), - max_time_minute=180, + max_time_minute=45, detour_tolerance_minute=0 ) @@ -49,7 +49,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = if finish_coords is None : finish_coords = start_coords start = Landmark(name='start', type='start', location=start_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0) - finish = Landmark(name='finish', type='start', location=finish_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0) + finish = Landmark(name='finish', type='finish', location=finish_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8777055, 2.3640967), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.847132, 2.312359), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.843185, 2.344533), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) @@ -62,7 +62,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = landmarks, landmarks_short = manager.generate_landmarks_list() # Store data to file for debug purposes - #write_data(landmarks, "landmarks_Wien.txt") + # write_data(landmarks, "landmarks_Strasbourg.txt") # Insert start and finish to the landmarks list landmarks_short.insert(0, start) @@ -73,8 +73,8 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = base_tour = optimizer.solve_optimization() # Second stage using linear optimization - refiner = Refiner(max_time = preferences.max_time_minute, detour = preferences.detour_tolerance_minute, all_landmarks=landmarks, base_tour=base_tour) - refined_tour = refiner.refine_optimization() + refiner = Refiner(max_time = preferences.max_time_minute, detour = preferences.detour_tolerance_minute) + refined_tour = refiner.refine_optimization(all_landmarks=landmarks, base_tour=base_tour) return refined_tour From d23050b811902afcf130d15c434d3ae37c8ffd24 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Wed, 24 Jul 2024 10:34:34 +0200 Subject: [PATCH 3/7] fixed parameters folder --- backend/src/amenities/nature.am | 12 ------------ backend/src/amenities/sightseeing.am | 11 ----------- backend/src/parameters/landmarks_manager.params | 8 -------- backend/src/parameters/optimizer.params | 5 ----- backend/src/parameters/optimizer_parameters.yaml | 2 +- backend/src/tester.py | 6 +++--- 6 files changed, 4 insertions(+), 40 deletions(-) delete mode 100644 backend/src/amenities/nature.am delete mode 100644 backend/src/amenities/sightseeing.am delete mode 100644 backend/src/parameters/landmarks_manager.params delete mode 100644 backend/src/parameters/optimizer.params diff --git a/backend/src/amenities/nature.am b/backend/src/amenities/nature.am deleted file mode 100644 index 5102c02..0000000 --- a/backend/src/amenities/nature.am +++ /dev/null @@ -1,12 +0,0 @@ -'leisure'='park' -geological -'natural'='geyser' -'natural'='hot_spring' -'natural'='arch' -'natural'='volcano' -'natural'='stone' -'tourism'='alpine_hut' -'tourism'='viewpoint' -'tourism'='zoo' -'tourism'='artwork' -'waterway'='waterfall' \ No newline at end of file diff --git a/backend/src/amenities/sightseeing.am b/backend/src/amenities/sightseeing.am deleted file mode 100644 index 053f9c9..0000000 --- a/backend/src/amenities/sightseeing.am +++ /dev/null @@ -1,11 +0,0 @@ -'tourism'='museum' -'tourism'='attraction' -'tourism'='gallery' -'tourism'='artwork' -historic -'amenity'='planetarium' -'amenity'='place_of_worship' -'amenity'='fountain' -'water'='reflecting_pool' -# 'tourism'='attraction' might be a bit too broad -# historic as well \ No newline at end of file diff --git a/backend/src/parameters/landmarks_manager.params b/backend/src/parameters/landmarks_manager.params deleted file mode 100644 index e0cbe35..0000000 --- a/backend/src/parameters/landmarks_manager.params +++ /dev/null @@ -1,8 +0,0 @@ -{ - "city bbox side" : 5000, - "radius close to" : 50, - "church coeff" : 0.8, - "park coeff" : 1.2, - "tag coeff" : 10, - "N important" : 40 -} \ No newline at end of file diff --git a/backend/src/parameters/optimizer.params b/backend/src/parameters/optimizer.params deleted file mode 100644 index b971821..0000000 --- a/backend/src/parameters/optimizer.params +++ /dev/null @@ -1,5 +0,0 @@ -{ - "detour factor" : 1.4, - "average walking speed" : 4.8, - "max landmarks" : 7 -} \ No newline at end of file diff --git a/backend/src/parameters/optimizer_parameters.yaml b/backend/src/parameters/optimizer_parameters.yaml index 515d028..efd2547 100644 --- a/backend/src/parameters/optimizer_parameters.yaml +++ b/backend/src/parameters/optimizer_parameters.yaml @@ -1,3 +1,3 @@ detour_factor: 1.4 average_walking_speed: 4.8 -max_landmarks: 40 +max_landmarks: 7 diff --git a/backend/src/tester.py b/backend/src/tester.py index 156b2a5..cd75435 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -35,13 +35,13 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = nature=Preference( name='nature', type='nature', - score = 0), + score = 5), shopping=Preference( name='shopping', type='shopping', - score = 0), + score = 5), - max_time_minute=45, + max_time_minute=180, detour_tolerance_minute=0 ) From 80b3d5b0129eb718f2821719d1faac432707237e Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Thu, 25 Jul 2024 09:37:37 +0200 Subject: [PATCH 4/7] refactored landmark manager and clean up --- backend/Dockerfile | 2 +- backend/Pipfile.lock | 605 ++--------------------- backend/src/constants.py | 2 +- backend/src/example_landmarks_manager.py | 151 ------ backend/src/example_optimizer.py | 419 ---------------- backend/src/example_refiner.py | 303 ------------ backend/src/example_tester.py | 80 --- backend/src/landmarks_manager.py | 283 ++++++----- backend/src/tester.py | 8 +- deployment/deployment.yaml | 40 -- deployment/ingress.yaml | 15 - deployment/kustomization.yaml | 16 - deployment/namespace.yaml | 4 - deployment/pvc.yaml | 11 - deployment/service.yaml | 11 - 15 files changed, 218 insertions(+), 1732 deletions(-) delete mode 100644 backend/src/example_landmarks_manager.py delete mode 100644 backend/src/example_optimizer.py delete mode 100644 backend/src/example_refiner.py delete mode 100644 backend/src/example_tester.py delete mode 100644 deployment/deployment.yaml delete mode 100644 deployment/ingress.yaml delete mode 100644 deployment/kustomization.yaml delete mode 100644 deployment/namespace.yaml delete mode 100644 deployment/pvc.yaml delete mode 100644 deployment/service.yaml diff --git a/backend/Dockerfile b/backend/Dockerfile index 056c3a0..9e15e47 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3 +FROM python:3.11-slim WORKDIR /app COPY Pipfile Pipfile.lock . diff --git a/backend/Pipfile.lock b/backend/Pipfile.lock index d661287..f6188cf 100644 --- a/backend/Pipfile.lock +++ b/backend/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b089081defe09c4ffad85fd22c5de336c76b31e7f6f67e5969b731bdaa58e528" + "sha256": "6f1907b01627126d80ae688e9f2e32fc696d85f0cca3913f14fd5d26cb3ac2db" }, "pipfile-spec": 6, "requires": {}, @@ -134,102 +134,6 @@ "markers": "python_full_version >= '3.7.0'", "version": "==3.3.2" }, - "charset-normalizer": { - "hashes": [ - "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", - "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", - "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", - "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", - "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", - "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", - "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", - "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", - "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", - "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", - "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", - "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", - "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", - "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", - "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", - "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", - "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", - "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", - "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", - "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", - "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", - "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", - "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", - "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", - "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", - "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", - "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", - "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", - "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", - "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", - "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", - "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", - "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", - "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", - "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", - "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", - "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", - "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", - "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", - "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", - "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", - "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", - "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", - "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", - "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", - "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", - "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", - "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", - "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", - "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", - "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", - "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", - "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", - "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", - "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", - "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", - "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", - "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", - "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", - "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", - "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", - "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", - "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", - "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", - "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", - "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", - "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", - "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", - "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", - "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", - "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", - "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", - "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", - "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", - "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", - "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", - "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", - "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", - "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", - "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", - "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", - "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", - "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", - "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", - "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", - "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", - "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", - "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", - "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", - "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" - ], - "markers": "python_full_version >= '3.7.0'", - "version": "==3.3.2" - }, "click": { "hashes": [ "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", @@ -254,14 +158,6 @@ "markers": "python_version >= '3.8'", "version": "==2.2.0" }, - "exceptiongroup": { - "hashes": [ - "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", - "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc" - ], - "markers": "python_version < '3.11'", - "version": "==1.2.2" - }, "fastapi": { "hashes": [ "sha256:4f51cfa25d72f9fbc3280832e84b32494cf186f50158d364a8765aabf22587bf", @@ -279,54 +175,6 @@ "markers": "python_version >= '3.8'", "version": "==0.0.4" }, - "geopandas": { - "hashes": [ - "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122", - "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397", - "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f", - "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d", - "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60", - "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169", - "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8", - "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31", - "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923", - "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2", - "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb", - "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab", - "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb", - "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a", - "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670", - "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8", - "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407", - "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671", - "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88", - "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f", - "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f", - "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0", - "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb", - "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2", - "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d", - "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c", - "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3", - "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719", - "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749", - "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4", - "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f", - "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02", - "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58", - "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1", - "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41", - "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4", - "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb", - "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb", - "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3", - "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d", - "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d", - "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2" - ], - "markers": "python_version >= '3.8'", - "version": "==4.53.1" - }, "geographiclib": { "hashes": [ "sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734", @@ -335,14 +183,6 @@ "markers": "python_version >= '3.7'", "version": "==2.0" }, - "geojson": { - "hashes": [ - "sha256:58a7fa40727ea058efc28b0e9ff0099eadf6d0965e04690830208d3ef571adac", - "sha256:68a9771827237adb8c0c71f8527509c8f5bef61733aa434cefc9c9d4f0ebe8f3" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.0" - }, "geopy": { "hashes": [ "sha256:50283d8e7ad07d89be5cb027338c6365a32044df3ae2556ad3f52f4840b3d0d1", @@ -507,41 +347,6 @@ "markers": "python_version >= '3.7'", "version": "==2.1.5" }, - "matplotlib": { - "hashes": [ - "sha256:0000354e32efcfd86bda75729716b92f5c2edd5b947200be9881f0a671565c33", - "sha256:0c584210c755ae921283d21d01f03a49ef46d1afa184134dd0f95b0202ee6f03", - "sha256:0e835c6988edc3d2d08794f73c323cc62483e13df0194719ecb0723b564e0b5c", - "sha256:0fc001516ffcf1a221beb51198b194d9230199d6842c540108e4ce109ac05cc0", - "sha256:11fed08f34fa682c2b792942f8902e7aefeed400da71f9e5816bea40a7ce28fe", - "sha256:208cbce658b72bf6a8e675058fbbf59f67814057ae78165d8a2f87c45b48d0ff", - "sha256:2315837485ca6188a4b632c5199900e28d33b481eb083663f6a44cfc8987ded3", - "sha256:26040c8f5121cd1ad712abffcd4b5222a8aec3a0fe40bc8542c94331deb8780d", - "sha256:3fda72d4d472e2ccd1be0e9ccb6bf0d2eaf635e7f8f51d737ed7e465ac020cb3", - "sha256:421851f4f57350bcf0811edd754a708d2275533e84f52f6760b740766c6747a7", - "sha256:44a21d922f78ce40435cb35b43dd7d573cf2a30138d5c4b709d19f00e3907fd7", - "sha256:4db17fea0ae3aceb8e9ac69c7e3051bae0b3d083bfec932240f9bf5d0197a049", - "sha256:565d572efea2b94f264dd86ef27919515aa6d629252a169b42ce5f570db7f37b", - "sha256:591d3a88903a30a6d23b040c1e44d1afdd0d778758d07110eb7596f811f31842", - "sha256:6d397fd8ccc64af2ec0af1f0efc3bacd745ebfb9d507f3f552e8adb689ed730a", - "sha256:7ccd6270066feb9a9d8e0705aa027f1ff39f354c72a87efe8fa07632f30fc6bb", - "sha256:82cd5acf8f3ef43f7532c2f230249720f5dc5dd40ecafaf1c60ac8200d46d7eb", - "sha256:83c6a792f1465d174c86d06f3ae85a8fe36e6f5964633ae8106312ec0921fdf5", - "sha256:84b3ba8429935a444f1fdc80ed930babbe06725bcf09fbeb5c8757a2cd74af04", - "sha256:a0c977c5c382f6696caf0bd277ef4f936da7e2aa202ff66cad5f0ac1428ee15b", - "sha256:a973c53ad0668c53e0ed76b27d2eeeae8799836fd0d0caaa4ecc66bf4e6676c0", - "sha256:ab38a4f3772523179b2f772103d8030215b318fef6360cb40558f585bf3d017f", - "sha256:b3fce58971b465e01b5c538f9d44915640c20ec5ff31346e963c9e1cd66fa812", - "sha256:b918770bf3e07845408716e5bbda17eadfc3fcbd9307dc67f37d6cf834bb3d98", - "sha256:d12cb1837cffaac087ad6b44399d5e22b78c729de3cdae4629e252067b705e2b", - "sha256:dc23f48ab630474264276be156d0d7710ac6c5a09648ccdf49fef9200d8cbe80", - "sha256:dd2a59ff4b83d33bca3b5ec58203cc65985367812cb8c257f3e101632be86d92", - "sha256:de06b19b8db95dd33d0dc17c926c7c9ebed9f572074b6fac4f65068a6814d010", - "sha256:f1f2e5d29e9435c97ad4c36fb6668e89aee13d48c75893e25cef064675038ac9" - ], - "markers": "python_version >= '3.9'", - "version": "==3.9.1" - }, "mdurl": { "hashes": [ "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", @@ -594,64 +399,55 @@ }, "numpy": { "hashes": [ - "sha256:04494f6ec467ccb5369d1808570ae55f6ed9b5809d7f035059000a37b8d7e86f", - "sha256:0a43f0974d501842866cc83471bdb0116ba0dffdbaac33ec05e6afed5b615238", - "sha256:0e50842b2295ba8414c8c1d9d957083d5dfe9e16828b37de883f51fc53c4016f", - "sha256:0ec84b9ba0654f3b962802edc91424331f423dcf5d5f926676e0150789cb3d95", - "sha256:17067d097ed036636fa79f6a869ac26df7db1ba22039d962422506640314933a", - "sha256:1cde1753efe513705a0c6d28f5884e22bdc30438bf0085c5c486cdaff40cd67a", - "sha256:1e72728e7501a450288fc8e1f9ebc73d90cfd4671ebbd631f3e7857c39bd16f2", - "sha256:2635dbd200c2d6faf2ef9a0d04f0ecc6b13b3cad54f7c67c61155138835515d2", - "sha256:2ce46fd0b8a0c947ae047d222f7136fc4d55538741373107574271bc00e20e8f", - "sha256:34f003cb88b1ba38cb9a9a4a3161c1604973d7f9d5552c38bc2f04f829536609", - "sha256:354f373279768fa5a584bac997de6a6c9bc535c482592d7a813bb0c09be6c76f", - "sha256:38ecb5b0582cd125f67a629072fed6f83562d9dd04d7e03256c9829bdec027ad", - "sha256:3e8e01233d57639b2e30966c63d36fcea099d17c53bf424d77f088b0f4babd86", - "sha256:3f6bed7f840d44c08ebdb73b1825282b801799e325bcbdfa6bc5c370e5aecc65", - "sha256:4554eb96f0fd263041baf16cf0881b3f5dafae7a59b1049acb9540c4d57bc8cb", - "sha256:46e161722e0f619749d1cd892167039015b2c2817296104487cd03ed4a955995", - "sha256:49d9f7d256fbc804391a7f72d4a617302b1afac1112fac19b6c6cec63fe7fe8a", - "sha256:4d2f62e55a4cd9c58c1d9a1c9edaedcd857a73cb6fda875bf79093f9d9086f85", - "sha256:5f64641b42b2429f56ee08b4f427a4d2daf916ec59686061de751a55aafa22e4", - "sha256:63b92c512d9dbcc37f9d81b123dec99fdb318ba38c8059afc78086fe73820275", - "sha256:6d7696c615765091cc5093f76fd1fa069870304beaccfd58b5dcc69e55ef49c1", - "sha256:79e843d186c8fb1b102bef3e2bc35ef81160ffef3194646a7fdd6a73c6b97196", - "sha256:821eedb7165ead9eebdb569986968b541f9908979c2da8a4967ecac4439bae3d", - "sha256:84554fc53daa8f6abf8e8a66e076aff6ece62de68523d9f665f32d2fc50fd66e", - "sha256:8d83bb187fb647643bd56e1ae43f273c7f4dbcdf94550d7938cfc32566756514", - "sha256:903703372d46bce88b6920a0cd86c3ad82dae2dbef157b5fc01b70ea1cfc430f", - "sha256:9416a5c2e92ace094e9f0082c5fd473502c91651fb896bc17690d6fc475128d6", - "sha256:9a1712c015831da583b21c5bfe15e8684137097969c6d22e8316ba66b5baabe4", - "sha256:9c27f0946a3536403efb0e1c28def1ae6730a72cd0d5878db38824855e3afc44", - "sha256:a356364941fb0593bb899a1076b92dfa2029f6f5b8ba88a14fd0984aaf76d0df", - "sha256:a7039a136017eaa92c1848152827e1424701532ca8e8967fe480fe1569dae581", - "sha256:acd3a644e4807e73b4e1867b769fbf1ce8c5d80e7caaef0d90dcdc640dfc9787", - "sha256:ad0c86f3455fbd0de6c31a3056eb822fc939f81b1618f10ff3406971893b62a5", - "sha256:b4c76e3d4c56f145d41b7b6751255feefae92edbc9a61e1758a98204200f30fc", - "sha256:b6f6a8f45d0313db07d6d1d37bd0b112f887e1369758a5419c0370ba915b3871", - "sha256:c5a59996dc61835133b56a32ebe4ef3740ea5bc19b3983ac60cc32be5a665d54", - "sha256:c73aafd1afca80afecb22718f8700b40ac7cab927b8abab3c3e337d70e10e5a2", - "sha256:cee6cc0584f71adefe2c908856ccc98702baf95ff80092e4ca46061538a2ba98", - "sha256:cef04d068f5fb0518a77857953193b6bb94809a806bd0a14983a8f12ada060c9", - "sha256:cf5d1c9e6837f8af9f92b6bd3e86d513cdc11f60fd62185cc49ec7d1aba34864", - "sha256:e61155fae27570692ad1d327e81c6cf27d535a5d7ef97648a17d922224b216de", - "sha256:e7f387600d424f91576af20518334df3d97bc76a300a755f9a8d6e4f5cadd289", - "sha256:ed08d2703b5972ec736451b818c2eb9da80d66c3e84aed1deeb0c345fefe461b", - "sha256:fbd6acc766814ea6443628f4e6751d0da6593dae29c08c0b2606164db026970c", - "sha256:feff59f27338135776f6d4e2ec7aeeac5d5f7a08a83e80869121ef8164b74af9" + "sha256:08458fbf403bff5e2b45f08eda195d4b0c9b35682311da5a5a0a0925b11b9bd8", + "sha256:0fbb536eac80e27a2793ffd787895242b7f18ef792563d742c2d673bfcb75134", + "sha256:12f5d865d60fb9734e60a60f1d5afa6d962d8d4467c120a1c0cda6eb2964437d", + "sha256:15eb4eca47d36ec3f78cde0a3a2ee24cf05ca7396ef808dda2c0ddad7c2bde67", + "sha256:173a00b9995f73b79eb0191129f2455f1e34c203f559dd118636858cc452a1bf", + "sha256:1b902ce0e0a5bb7704556a217c4f63a7974f8f43e090aff03fcf262e0b135e02", + "sha256:1f682ea61a88479d9498bf2091fdcd722b090724b08b31d63e022adc063bad59", + "sha256:1f87fec1f9bc1efd23f4227becff04bd0e979e23ca50cc92ec88b38489db3b55", + "sha256:24a0e1befbfa14615b49ba9659d3d8818a0f4d8a1c5822af8696706fbda7310c", + "sha256:2c3a346ae20cfd80b6cfd3e60dc179963ef2ea58da5ec074fd3d9e7a1e7ba97f", + "sha256:36d3a9405fd7c511804dc56fc32974fa5533bdeb3cd1604d6b8ff1d292b819c4", + "sha256:3fdabe3e2a52bc4eff8dc7a5044342f8bd9f11ef0934fcd3289a788c0eb10018", + "sha256:4127d4303b9ac9f94ca0441138acead39928938660ca58329fe156f84b9f3015", + "sha256:4658c398d65d1b25e1760de3157011a80375da861709abd7cef3bad65d6543f9", + "sha256:485b87235796410c3519a699cfe1faab097e509e90ebb05dcd098db2ae87e7b3", + "sha256:529af13c5f4b7a932fb0e1911d3a75da204eff023ee5e0e79c1751564221a5c8", + "sha256:5a3d94942c331dd4e0e1147f7a8699a4aa47dffc11bf8a1523c12af8b2e91bbe", + "sha256:5daab361be6ddeb299a918a7c0864fa8618af66019138263247af405018b04e1", + "sha256:61728fba1e464f789b11deb78a57805c70b2ed02343560456190d0501ba37b0f", + "sha256:6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a", + "sha256:69ff563d43c69b1baba77af455dd0a839df8d25e8590e79c90fcbe1499ebde42", + "sha256:6bf4e6f4a2a2e26655717a1983ef6324f2664d7011f6ef7482e8c0b3d51e82ac", + "sha256:6e4eeb6eb2fced786e32e6d8df9e755ce5be920d17f7ce00bc38fcde8ccdbf9e", + "sha256:72dc22e9ec8f6eaa206deb1b1355eb2e253899d7347f5e2fae5f0af613741d06", + "sha256:75b4e316c5902d8163ef9d423b1c3f2f6252226d1aa5cd8a0a03a7d01ffc6268", + "sha256:7b9853803278db3bdcc6cd5beca37815b133e9e77ff3d4733c247414e78eb8d1", + "sha256:7d6fddc5fe258d3328cd8e3d7d3e02234c5d70e01ebe377a6ab92adb14039cb4", + "sha256:81b0893a39bc5b865b8bf89e9ad7807e16717f19868e9d234bdaf9b1f1393868", + "sha256:8efc84f01c1cd7e34b3fb310183e72fcdf55293ee736d679b6d35b35d80bba26", + "sha256:8fae4ebbf95a179c1156fab0b142b74e4ba4204c87bde8d3d8b6f9c34c5825ef", + "sha256:99d0d92a5e3613c33a5f01db206a33f8fdf3d71f2912b0de1739894668b7a93b", + "sha256:9adbd9bb520c866e1bfd7e10e1880a1f7749f1f6e5017686a5fbb9b72cf69f82", + "sha256:a1e01dcaab205fbece13c1410253a9eea1b1c9b61d237b6fa59bcc46e8e89343", + "sha256:a8fc2de81ad835d999113ddf87d1ea2b0f4704cbd947c948d2f5513deafe5a7b", + "sha256:b83e16a5511d1b1f8a88cbabb1a6f6a499f82c062a4251892d9ad5d609863fb7", + "sha256:bb2124fdc6e62baae159ebcfa368708867eb56806804d005860b6007388df171", + "sha256:bfc085b28d62ff4009364e7ca34b80a9a080cbd97c2c0630bb5f7f770dae9414", + "sha256:cbab9fc9c391700e3e1287666dfd82d8666d10e69a6c4a09ab97574c0b7ee0a7", + "sha256:e5eeca8067ad04bc8a2a8731183d51d7cbaac66d86085d5f4766ee6bf19c7f87", + "sha256:e9e81fa9017eaa416c056e5d9e71be93d05e2c3c2ab308d23307a8bc4443c368", + "sha256:ea2326a4dca88e4a274ba3a4405eb6c6467d3ffbd8c7d38632502eaae3820587", + "sha256:eacf3291e263d5a67d8c1a581a8ebbcfd6447204ef58828caf69a5e3e8c75990", + "sha256:ec87f5f8aca726117a1c9b7083e7656a9d0d606eec7299cc067bb83d26f16e0c", + "sha256:f1659887361a7151f89e79b276ed8dff3d75877df906328f14d8bb40bb4f5101", + "sha256:f9cf5ea551aec449206954b075db819f52adc1638d46a6738253a712d553c7b4" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==2.0.0" - }, - "osmpythontools": { - "hashes": [ - "sha256:22548d86d68d36edff3cf9ab76c45745cda86a4ea0b28442e107d6b42992a426", - "sha256:ac67bea77b521941af648ef641ae1d006101948d1112475c256ea23ef31b426a" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.9.3" + "version": "==2.0.1" }, "packaging": { "hashes": [ @@ -662,127 +458,6 @@ "markers": "python_version >= '3.8'", "version": "==24.1" }, - "pandas": { - "hashes": [ - "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863", - "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2", - "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1", - "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad", - "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db", - "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76", - "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51", - "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32", - "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08", - "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b", - "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4", - "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921", - "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288", - "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee", - "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0", - "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24", - "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99", - "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151", - "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd", - "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce", - "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57", - "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef", - "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54", - "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a", - "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238", - "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23", - "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772", - "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce", - "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad" - ], - "markers": "python_version >= '3.9'", - "version": "==2.2.2" - }, - "pillow": { - "hashes": [ - "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", - "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", - "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df", - "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", - "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", - "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d", - "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd", - "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", - "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908", - "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", - "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", - "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", - "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b", - "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", - "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a", - "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e", - "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", - "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", - "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b", - "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", - "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", - "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab", - "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d", - "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", - "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", - "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", - "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4", - "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", - "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", - "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", - "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", - "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b", - "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", - "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0", - "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", - "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", - "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856", - "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef", - "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680", - "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b", - "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", - "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e", - "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", - "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", - "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8", - "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", - "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736", - "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da", - "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126", - "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd", - "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5", - "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b", - "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026", - "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b", - "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc", - "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46", - "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2", - "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c", - "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", - "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984", - "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", - "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", - "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", - "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b", - "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", - "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3", - "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84", - "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1", - "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5", - "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", - "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f", - "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", - "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", - "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e", - "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141", - "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", - "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", - "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27", - "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e", - "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1" - ], - "markers": "python_version >= '3.8'", - "version": "==10.4.0" - }, "pydantic": { "hashes": [ "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a", @@ -895,79 +570,6 @@ "markers": "python_version >= '3.8'", "version": "==2.18.0" }, - "pyogrio": { - "hashes": [ - "sha256:019731a856a9abfe909e86f50eb13f8362f6742337caf757c54b7c8acfe75b89", - "sha256:083351b258b3e08b6c6085dac560bd321b68de5cb4a66229095da68d5f3d696b", - "sha256:13642608a1cd67797ae8b5d792b0518d8ef3eb76506c8232ab5eaa1ea1159dff", - "sha256:17420febc17651876d5140b54b24749aa751d482b5f9ef6267b8053e6e962876", - "sha256:1a495ca4fb77c69595747dd688f8f17bb7d2ea9cd86603aa71c7fc98cc8b4174", - "sha256:2829615cf58b1b24a9f96fea42abedaa1a800dd351c67374cc2f6341138608f3", - "sha256:2e98913fa183f7597c609e774820a149e9329fd2a0f8d33978252fbd00ae87e6", - "sha256:2f2ec57ab74785db9c2bf47c0a6731e5175595a13f8253f06fa84136adb310a9", - "sha256:30cbeeaedb9bced7012487e7438919aa0c7dfba18ac3d4315182b46eb3139b9d", - "sha256:3a2fcaa269031dbbc8ebd91243c6452c5d267d6df939c008ab7533413c9cf92d", - "sha256:3f964002d445521ad5b8e732a6b5ef0e2d2be7fe566768e5075c1d71398da64a", - "sha256:4a289584da6df7ca318947301fe0ba9177e7f863f63110e087c80ac5f3658de8", - "sha256:4da0b9deb380bd9a200fee13182c4f95b02b4c554c923e2e0032f32aaf1439ed", - "sha256:4e0f90a6c3771ee1f1fea857778b4b6a1b64000d851b819f435f9091b3c38c60", - "sha256:6a6fa2e8cf95b3d4a7c0fac48bce6e5037579e28d3eb33b53349d6e11f15e5a8", - "sha256:6dc94a67163218581c7df275223488ac9b31dc582ccd756da607c3338908566c", - "sha256:796e4f6a4e769b2eb6fea9a10546ea4bdee16182d1e29802b4d6349363c3c1d7", - "sha256:7fcafed24371fe6e23bcf5abebbb29269f8d79915f1dd818ac85453657ea714a", - "sha256:9440466c0211ac81f3417f274da5903f15546b486f76b2f290e74a56aaf0e737", - "sha256:959022f3ad04053f8072dc9a2ad110c46edd9e4f92352061ba835fc91df3ca96", - "sha256:d668cb10f2bf6ccd7c402f91e8b06290722dd09dbe265ae95b2c13db29ebeba0", - "sha256:e38c3c6d37cf2cc969407e4d051dcb507cfd948eb26c7b0840c4f7d7d4a71bd4", - "sha256:f47c9b6818cc0f420015b672d5dcc488530a5ee63e5ba35a184957b21ea3922a", - "sha256:f5d80eb846be4fc4e642cbedc1ed0c143e8d241653382ecc76a7620bbd2a5c3a", - "sha256:f8bf193269ea9d347ac3ddada960a59f1ab2e4a5c009be95dc70e6505346b2fc", - "sha256:fb04bd80964428491951766452f0071b0bc37c7d38c45ef02502dbd83e5d74a0" - ], - "markers": "python_version >= '3.8'", - "version": "==0.9.0" - }, - "pyproj": { - "hashes": [ - "sha256:18faa54a3ca475bfe6255156f2f2874e9a1c8917b0004eee9f664b86ccc513d3", - "sha256:1e9fbaf920f0f9b4ee62aab832be3ae3968f33f24e2e3f7fbb8c6728ef1d9746", - "sha256:2d6ff73cc6dbbce3766b6c0bce70ce070193105d8de17aa2470009463682a8eb", - "sha256:36b64c2cb6ea1cc091f329c5bd34f9c01bb5da8c8e4492c709bda6a09f96808f", - "sha256:38a3361941eb72b82bd9a18f60c78b0df8408416f9340521df442cebfc4306e2", - "sha256:447db19c7efad70ff161e5e46a54ab9cc2399acebb656b6ccf63e4bc4a04b97a", - "sha256:44aa7c704c2b7d8fb3d483bbf75af6cb2350d30a63b144279a09b75fead501bf", - "sha256:4ba1f9b03d04d8cab24d6375609070580a26ce76eaed54631f03bab00a9c737b", - "sha256:4bc0472302919e59114aa140fd7213c2370d848a7249d09704f10f5b062031fe", - "sha256:50100b2726a3ca946906cbaa789dd0749f213abf0cbb877e6de72ca7aa50e1ae", - "sha256:5279586013b8d6582e22b6f9e30c49796966770389a9d5b85e25a4223286cd3f", - "sha256:6420ea8e7d2a88cb148b124429fba8cd2e0fae700a2d96eab7083c0928a85110", - "sha256:65ad699e0c830e2b8565afe42bd58cc972b47d829b2e0e48ad9638386d994915", - "sha256:6d227a865356f225591b6732430b1d1781e946893789a609bb34f59d09b8b0f8", - "sha256:7a27151ddad8e1439ba70c9b4b2b617b290c39395fa9ddb7411ebb0eb86d6fb0", - "sha256:80fafd1f3eb421694857f254a9bdbacd1eb22fc6c24ca74b136679f376f97d35", - "sha256:83039e5ae04e5afc974f7d25ee0870a80a6bd6b7957c3aca5613ccbe0d3e72bf", - "sha256:8b8acc31fb8702c54625f4d5a2a6543557bec3c28a0ef638778b7ab1d1772132", - "sha256:9274880263256f6292ff644ca92c46d96aa7e57a75c6df3f11d636ce845a1877", - "sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4", - "sha256:c41e80ddee130450dcb8829af7118f1ab69eaf8169c4bf0ee8d52b72f098dc2f", - "sha256:db3aedd458e7f7f21d8176f0a1d924f1ae06d725228302b872885a1c34f3119e", - "sha256:e7e13c40183884ec7f94eb8e0f622f08f1d5716150b8d7a134de48c6110fee85", - "sha256:ebfbdbd0936e178091309f6cd4fcb4decd9eab12aa513cdd9add89efa3ec2882", - "sha256:fd43bd9a9b9239805f406fd82ba6b106bf4838d9ef37c167d3ed70383943ade1", - "sha256:fd93c1a0c6c4aedc77c0fe275a9f2aba4d59b8acf88cebfc19fe3c430cfabf4f", - "sha256:fffb059ba3bced6f6725961ba758649261d85ed6ce670d3e3b0a26e81cf1aa8d" - ], - "markers": "python_version >= '3.9'", - "version": "==3.6.1" - }, - "python-dateutil": { - "hashes": [ - "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", - "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.9.0.post0" - }, "python-dotenv": { "hashes": [ "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", @@ -983,13 +585,6 @@ "markers": "python_version >= '3.8'", "version": "==0.0.9" }, - "pytz": { - "hashes": [ - "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812", - "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319" - ], - "version": "==2024.1" - }, "pywikibot": { "hashes": [ "sha256:3f4fbc57f1765aa0fa1ccf84125bcfa475cae95b9cc0291867b751f3d4ac8fa2", @@ -1155,14 +750,6 @@ "markers": "python_version >= '3.7'", "version": "==1.5.4" }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" - }, "sniffio": { "hashes": [ "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", @@ -1195,98 +782,6 @@ "markers": "python_version >= '3.8'", "version": "==4.12.2" }, - "tzdata": { - "hashes": [ - "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd", - "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252" - ], - "markers": "python_version >= '2'", - "version": "==2024.1" - }, - "ujson": { - "hashes": [ - "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e", - "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b", - "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6", - "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7", - "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9", - "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd", - "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569", - "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f", - "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51", - "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", - "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1", - "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf", - "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", - "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", - "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a", - "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", - "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27", - "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", - "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126", - "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1", - "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", - "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64", - "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8", - "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", - "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", - "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3", - "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb", - "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", - "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", - "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", - "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", - "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", - "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d", - "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd", - "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0", - "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337", - "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753", - "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804", - "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f", - "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f", - "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5", - "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", - "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1", - "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00", - "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", - "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050", - "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", - "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4", - "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8", - "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996", - "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6", - "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", - "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", - "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1", - "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4", - "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b", - "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88", - "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518", - "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5", - "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770", - "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4", - "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a", - "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76", - "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe", - "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", - "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1", - "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5", - "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b", - "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7", - "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8", - "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc", - "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a", - "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720", - "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", - "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b", - "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9", - "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", - "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746" - ], - "markers": "python_version >= '3.8'", - "version": "==5.10.0" - }, "urllib3": { "hashes": [ "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", @@ -1300,11 +795,11 @@ "standard" ], "hashes": [ - "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81", - "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8" + "sha256:0d114d0831ff1adbf231d358cbf42f17333413042552a624ea6a9b4c33dcfd81", + "sha256:94a3608da0e530cea8f69683aa4126364ac18e3826b6630d1a65f4638aade503" ], "markers": "python_version >= '3.8'", - "version": "==0.30.1" + "version": "==0.30.3" }, "uvloop": { "hashes": [ diff --git a/backend/src/constants.py b/backend/src/constants.py index 2e66727..951a51d 100644 --- a/backend/src/constants.py +++ b/backend/src/constants.py @@ -14,6 +14,6 @@ OSM_CACHE_DIR = Path(cache_dir_string) logger = logging.getLogger(__name__) logging.basicConfig( - level = logging.INFO, + level = logging.DEBUG, format = '%(asctime)s - %(name)s\t- %(levelname)s\t- %(message)s' ) diff --git a/backend/src/example_landmarks_manager.py b/backend/src/example_landmarks_manager.py deleted file mode 100644 index 30df6dc..0000000 --- a/backend/src/example_landmarks_manager.py +++ /dev/null @@ -1,151 +0,0 @@ -import yaml -import logging -from OSMPythonTools import cachingStrategy, overpass -from structs.landmarks import Landmark, LandmarkType -from structs.preferences import Preferences, Preference -import constants - -SIGHTSEEING = LandmarkType(landmark_type='sightseeing') -NATURE = LandmarkType(landmark_type='nature') -SHOPPING = LandmarkType(landmark_type='shopping') - - -class LandmarkManager: - logger = logging.getLogger(__name__) - - def __init__(self) -> None: - strategy = cachingStrategy.JSON(cacheDir=constants.OSM_CACHE_DIR) - self.query_builder = overpass.Overpass() - with constants.AMENITY_SELECTORS_PATH.open('r') as f: - self.amenity_selectors = yaml.safe_load(f) - with constants.LANDMARK_PARAMETERS_PATH.open('r') as f: - self.parameters = yaml.safe_load(f) - # max_distance = parameters['city_bbox_side'] - - - def get_landmark_lists(self, preferences: Preferences, center_coordinates: tuple[float, float]) -> tuple[list[Landmark], list[Landmark]]: - ''' - Generate a list of landmarks based on the preferences of the user and the center (ie. start) coordinates. - The list is then used by the pathfinding algorithm to generate a path that goes through the most interesting landmarks. - :param preferences: the preferences specified by the user - :param center_coordinates: the coordinates of the starting point - ''' - - L = [] - - # List for sightseeing - if preferences.sightseeing.score != 0: - score_func = lambda loc, n_tags: int((10 + n_tags * self.parameters['tag_coeff']) * self.parameters['church_coeff']) - L1 = self.fetch_landmarks(self.amenity_selectors['sightseeing'], SIGHTSEEING, center_coordinates, self.parameters['city_bbox_side'], score_func) - self.correct_score(L1, preferences.sightseeing) - L += L1 - - # List for nature - if preferences.nature.score != 0: - score_func = lambda loc, n_tags: int((10 + n_tags * self.parameters['tag_coeff']) * self.parameters['park_coeff']) - L2 = self.fetch_landmarks(self.amenity_selectors['nature'], NATURE, center_coordinates, self.parameters['city_bbox_side'], score_func) - self.correct_score(L2, preferences.nature) - L += L2 - - # List for shopping - if preferences.shopping.score != 0: - score_func = lambda loc, n_tags: int((10 + n_tags * self.parameters['tag_coeff'])) - L3 = self.fetch_landmarks(self.amenity_selectors['shopping'], SHOPPING, center_coordinates, self.parameters['city_bbox_side'], score_func) - self.correct_score(L3, preferences.shopping) - L += L3 - - # remove duplicates - L = list(set(L)) - L_constrained = self.take_most_important(L, self.parameters['N_important']) - self.logger.info(f'Generated {len(L)} landmarks around {center_coordinates}, and constrained to {len(L_constrained)} most important ones.') - return L, L_constrained - - - - # Take the most important landmarks from the list - def take_most_important(self, landmarks: list[Landmark], n_max: int) -> list[Landmark]: - - landmarks_sorted = sorted(landmarks, key=lambda x: x.attractiveness, reverse=True) - return landmarks_sorted[:n_max] - - - - # Correct the score of a list of landmarks by taking into account preference settings - def correct_score(self, L: list[Landmark], preference: Preference): - - if len(L) == 0 : - return - - if L[0].type != preference.type : - raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {L[0].name}") - - for elem in L : - elem.attractiveness = int(elem.attractiveness*preference.score/500) # arbitrary computation - - - # Function to count elements within a certain radius of a location - def count_elements_within_radius(self, point: Point, radius: int) -> int: - - center_coordinates = (point.x, point.y) - try: - landmarks = ox.features_from_point( - center_point = center_coordinates, - dist = radius, - tags = {'building': True} # this is a common tag to give an estimation of the number of elements in the area - ) - return len(landmarks) - except ox._errors.InsufficientResponseError: - return 0 - - - - - def fetch_landmarks( - self, - amenity_selectors: list[dict], - landmarktype: LandmarkType, - center_coordinates: tuple[float, float], - distance: int, - score_function: callable - ) -> list[Landmark]: - - landmarks = ox.features_from_point( - center_point = center_coordinates, - dist = distance, - tags = amenity_selectors - ) - self.logger.info(f'Fetched {len(landmarks)} landmarks around {center_coordinates}.') - - # cleanup the list - # remove rows where name is None - landmarks = landmarks[landmarks['name'].notna()] - # TODO: remove rows that are part of another building - - ret_landmarks = [] - for element, description in landmarks.iterrows(): - osm_type = element[0] - osm_id = element[1] - location = description['geometry'] - n_tags = len(description['nodes']) if type(description['nodes']) == list else 1 - - if type(location) == Point: - location = location - elif type(location) == Polygon or type(location) == MultiPolygon: - location = location.centroid - elif type(location) == LineString: - location = location.interpolate(location.length/2) - - score = score_function(location, n_tags) - landmark = Landmark( - name = description['name'], - type = landmarktype, - location = (location.x, location.y), - osm_type = osm_type, - osm_id = osm_id, - attractiveness = score, - must_do = False, - n_tags = n_tags - ) - ret_landmarks.append(landmark) - - return ret_landmarks diff --git a/backend/src/example_optimizer.py b/backend/src/example_optimizer.py deleted file mode 100644 index 922af99..0000000 --- a/backend/src/example_optimizer.py +++ /dev/null @@ -1,419 +0,0 @@ -import numpy as np -import yaml - -from typing import List, Tuple -from scipy.optimize import linprog -from math import radians, sin, cos, acos - -from structs.landmarks import Landmark -import constants - -# Function to print the result -def print_res(L: List[Landmark], L_tot): - - if len(L) == L_tot: - print('\nAll landmarks can be visited within max_steps, the following order is suggested : ') - else : - print('Could not visit all the landmarks, the following order is suggested : ') - - dist = 0 - for elem in L : - if elem.time_to_reach_next is not None : - print('- ' + elem.name + ', time to reach next = ' + str(elem.time_to_reach_next)) - dist += elem.time_to_reach_next - else : - print('- ' + elem.name) - - print("\nMinutes walked : " + str(dist)) - print(f"Visited {len(L)-2} out of {L_tot-2} landmarks") - - -# Prevent the use of a particular solution -def prevent_config(resx, A_ub, b_ub) -> bool: - - for i, elem in enumerate(resx): - resx[i] = round(elem) - - N = len(resx) # Number of edges - L = int(np.sqrt(N)) # Number of landmarks - - nonzeroind = np.nonzero(resx)[0] # the return is a little funky so I use the [0] - nonzero_tup = np.unravel_index(nonzeroind, (L,L)) - - ind_a = nonzero_tup[0].tolist() - vertices_visited = ind_a - vertices_visited.remove(0) - - ones = [1]*L - h = [0]*N - for i in range(L) : - if i in vertices_visited : - h[i*L:i*L+L] = ones - - A_ub = np.vstack((A_ub, h)) - b_ub.append(len(vertices_visited)-1) - - return A_ub, b_ub - - -# Prevent the possibility of a given solution bit -def break_cricle(circle_vertices: list, L: int, A_ub: list, b_ub: list) -> bool: - - if L-1 in circle_vertices : - circle_vertices.remove(L-1) - - h = [0]*L*L - for i in range(L) : - if i in circle_vertices : - h[i*L:i*L+L] = [1]*L - - A_ub = np.vstack((A_ub, h)) - b_ub.append(len(circle_vertices)-1) - - return A_ub, b_ub - - -# Checks if the path is connected, returns a circle if it finds one and the RESULT -def is_connected(resx) -> bool: - - # first round the results to have only 0-1 values - for i, elem in enumerate(resx): - resx[i] = round(elem) - - N = len(resx) # length of res - L = int(np.sqrt(N)) # number of landmarks. CAST INTO INT but should not be a problem because N = L**2 by def. - n_edges = resx.sum() # number of edges - - nonzeroind = np.nonzero(resx)[0] # the return is a little funny so I use the [0] - - nonzero_tup = np.unravel_index(nonzeroind, (L,L)) - - ind_a = nonzero_tup[0].tolist() - ind_b = nonzero_tup[1].tolist() - - edges = [] - edges_visited = [] - vertices_visited = [] - - edge1 = (ind_a[0], ind_b[0]) - edges_visited.append(edge1) - vertices_visited.append(edge1[0]) - - for i, a in enumerate(ind_a) : - edges.append((a, ind_b[i])) # Create the list of edges - - remaining = edges - remaining.remove(edge1) - - break_flag = False - while len(remaining) > 0 and not break_flag: - for edge2 in remaining : - if edge2[0] == edge1[1] : - if edge1[1] in vertices_visited : - edges_visited.append(edge2) - break_flag = True - break - else : - vertices_visited.append(edge1[1]) - edges_visited.append(edge2) - remaining.remove(edge2) - edge1 = edge2 - - elif edge1[1] == L-1 or edge1[1] in vertices_visited: - break_flag = True - break - - vertices_visited.append(edge1[1]) - - - if len(vertices_visited) == n_edges +1 : - return vertices_visited, [] - else: - return vertices_visited, edges_visited - - -# Function that returns the distance in meters from one location to another -def get_distance(p1: Tuple[float, float], p2: Tuple[float, float], detour: float, speed: float) : - - # Compute the straight-line distance in km - if p1 == p2 : - return 0, 0 - else: - dist = 6371.01 * acos(sin(radians(p1[0]))*sin(radians(p2[0])) + cos(radians(p1[0]))*cos(radians(p2[0]))*cos(radians(p1[1]) - radians(p2[1]))) - - # Consider the detour factor for average cityto deterline walking distance (in km) - walk_dist = dist*detour - - # Time to walk this distance (in minutes) - walk_time = walk_dist/speed*60 - - if walk_time > 15 : - walk_time = 5*round(walk_time/5) - else : - walk_time = round(walk_time) - - - return round(walk_dist, 1), walk_time - - -# Initialize A and c. Compute the distances from all landmarks to each other and store attractiveness -# We want to maximize the sightseeing : max(c) st. A*x < b and A_eq*x = b_eq -def init_ub_dist(landmarks: List[Landmark], max_steps: int): - - # Read the parameters from the file - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - detour = parameters['detour_factor'] - speed = parameters['average_walking_speed'] - - # Objective function coefficients. a*x1 + b*x2 + c*x3 + ... - c = [] - # Coefficients of inequality constraints (left-hand side) - A_ub = [] - - for spot1 in landmarks : - dist_table = [0]*len(landmarks) - c.append(-spot1.attractiveness) - for j, spot2 in enumerate(landmarks) : - t = get_distance(spot1.location, spot2.location, detour, speed)[1] - dist_table[j] = t - A_ub += dist_table - c = c*len(landmarks) - - return c, A_ub, [max_steps] - - -# Constraint to respect only one travel per landmark. Also caps the total number of visited landmarks -def respect_number(L:int, A_ub, b_ub): - - ones = [1]*L - zeros = [0]*L - for i in range(L) : - h = zeros*i + ones + zeros*(L-1-i) - A_ub = np.vstack((A_ub, h)) - b_ub.append(1) - - # Read the parameters from the file - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - max_landmarks = parameters['max_landmarks'] - - A_ub = np.vstack((A_ub, ones*L)) - b_ub.append(max_landmarks+1) - - return A_ub, b_ub - - -# Constraint to not have d14 and d41 simultaneously. Does not prevent circular symmetry with more elements -def break_sym(L, A_ub, b_ub): - upper_ind = np.triu_indices(L,0,L) - - up_ind_x = upper_ind[0] - up_ind_y = upper_ind[1] - - for i, _ in enumerate(up_ind_x) : - l = [0]*L*L - if up_ind_x[i] != up_ind_y[i] : - l[up_ind_x[i]*L + up_ind_y[i]] = 1 - l[up_ind_y[i]*L + up_ind_x[i]] = 1 - - A_ub = np.vstack((A_ub,l)) - b_ub.append(1) - - return A_ub, b_ub - - -# Constraint to not stay in position. Removes d11, d22, d33, etc. -def init_eq_not_stay(L: int): - l = [0]*L*L - - for i in range(L) : - for j in range(L) : - if j == i : - l[j + i*L] = 1 - - l = np.array(np.array(l)) - - return [l], [0] - - -# Go through the landmarks and force the optimizer to use landmarks where attractiveness is set to -1 -def respect_user_mustsee(landmarks: List[Landmark], A_eq: list, b_eq: list) : - L = len(landmarks) - - for i, elem in enumerate(landmarks) : - if elem.must_do is True and elem.name not in ['finish', 'start']: - l = [0]*L*L - for j in range(L) : # sets the horizontal ones (go from) - l[j +i*L] = 1 # sets the vertical ones (go to) double check if good - - for k in range(L-1) : - l[k*L+L-1] = 1 - - A_eq = np.vstack((A_eq,l)) - b_eq.append(2) - - return A_eq, b_eq - - -# Constraint to ensure start at start and finish at goal -def respect_start_finish(L: int, A_eq: list, b_eq: list): - ls = [1]*L + [0]*L*(L-1) # sets only horizontal ones for start (go from) - ljump = [0]*L*L - ljump[L-1] = 1 # Prevent start finish jump - lg = [0]*L*L - ll = [0]*L*(L-1) + [1]*L - for k in range(L-1) : # sets only vertical ones for goal (go to) - ll[k*L] = 1 - if k != 0 : # Prevent the shortcut start -> finish - lg[k*L+L-1] = 1 - - - A_eq = np.vstack((A_eq,ls)) - A_eq = np.vstack((A_eq,ljump)) - A_eq = np.vstack((A_eq,lg)) - A_eq = np.vstack((A_eq,ll)) - b_eq.append(1) - b_eq.append(0) - b_eq.append(1) - b_eq.append(0) - - return A_eq, b_eq - - -# Constraint to tie the problem together. Necessary but not sufficient to avoid circles -def respect_order(N: int, A_eq, b_eq): - for i in range(N-1) : # Prevent stacked ones - if i == 0 or i == N-1: # Don't touch start or finish - continue - else : - l = [0]*N - l[i] = -1 - l = l*N - for j in range(N) : - l[i*N + j] = 1 - - A_eq = np.vstack((A_eq,l)) - b_eq.append(0) - - return A_eq, b_eq - - -# Computes the time to reach from each landmark to the next -def link_list(order: List[int], landmarks: List[Landmark]) -> List[Landmark]: - - # Read the parameters from the file - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - - detour_factor = parameters['detour_factor'] - speed = parameters['average_walking_speed'] - - L = [] - j = 0 - total_dist = 0 - while j < len(order)-1 : - elem = landmarks[order[j]] - next = landmarks[order[j+1]] - - d = get_distance(elem.location, next.location, detour_factor, speed)[1] - elem.time_to_reach_next = d - L.append(elem) - j += 1 - total_dist += d - - L.append(next) - - return L, total_dist - - -def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] : - - # Read the parameters from the file - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - - detour_factor = parameters['detour_factor'] - speed = parameters['average_walking_speed'] - - L = [] - j = 0 - total_dist = 0 - while j < len(ordered_visit)-1 : - elem = ordered_visit[j] - next = ordered_visit[j+1] - - elem.next_uuid = next.uuid - d = get_distance(elem.location, next.location, detour_factor, speed)[1] - elem.time_to_reach_next = d - if elem.name not in ['start', 'finish'] : - elem.must_do = True - L.append(elem) - j += 1 - total_dist += d - - L.append(next) - - return L, total_dist - - -# Main optimization pipeline -def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_details: bool) : - - L = len(landmarks) - - # SET CONSTRAINTS FOR INEQUALITY - c, A_ub, b_ub = init_ub_dist(landmarks, max_steps) # Add the distances from each landmark to the other - A_ub, b_ub = respect_number(L, A_ub, b_ub) # Respect max number of visits (no more possible stops than landmarks). - A_ub, b_ub = break_sym(L, A_ub, b_ub) # break the 'zig-zag' symmetry - - # SET CONSTRAINTS FOR EQUALITY - A_eq, b_eq = init_eq_not_stay(L) # Force solution not to stay in same place - A_eq, b_eq = respect_user_mustsee(landmarks, A_eq, b_eq) # Check if there are user_defined must_see. Also takes care of start/goal - A_eq, b_eq = respect_start_finish(L, A_eq, b_eq) # Force start and finish positions - A_eq, b_eq = respect_order(L, A_eq, b_eq) # Respect order of visit (only works when max_steps is limiting factor) - - # SET BOUNDS FOR DECISION VARIABLE (x can only be 0 or 1) - x_bounds = [(0, 1)]*L*L - - # Solve linear programming problem - res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) - - # Raise error if no solution is found - if not res.success : - raise ArithmeticError("No solution could be found, the problem is overconstrained. Please adapt your must_dos") - - # If there is a solution, we're good to go, just check for connectiveness - else : - order, circle = is_connected(res.x) - i = 0 - timeout = 80 - while len(circle) != 0 and i < timeout: - A_ub, b_ub = prevent_config(res.x, A_ub, b_ub) - A_ub, b_ub = break_cricle(order, len(landmarks), A_ub, b_ub) - res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) - order, circle = is_connected(res.x) - if len(circle) == 0 : - break - print(i) - i += 1 - - if i == timeout : - raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.") - - # Add the times to reach and stop optimizing - L, total_dist = link_list(order, landmarks) - - if printing_details is True : - if i != 0 : - print(f"Neded to recompute paths {i} times because of unconnected loops...") - print_res(L, len(landmarks)) - print("\nTotal score : " + str(int(-res.fun))) - - return L - - - - - - diff --git a/backend/src/example_refiner.py b/backend/src/example_refiner.py deleted file mode 100644 index 4b1c306..0000000 --- a/backend/src/example_refiner.py +++ /dev/null @@ -1,303 +0,0 @@ -from collections import defaultdict -from heapq import heappop, heappush -from itertools import permutations -import os -import yaml - -from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull -from typing import List, Tuple -from math import pi - -from structs.landmarks import Landmark -from landmarks_manager import take_most_important -from backend.src.example_optimizer import solve_optimization, link_list_simple, print_res, get_distance -import constants - - -# Create corridor from tour -def create_corridor(landmarks: List[Landmark], width: float) : - - corrected_width = (180*width)/(6371000*pi) - - path = create_linestring(landmarks) - obj = buffer(path, corrected_width, join_style="mitre", cap_style="square", mitre_limit=2) - - return obj - - -# Create linestring from tour -def create_linestring(landmarks: List[Landmark])->List[Point] : - - points = [] - - for landmark in landmarks : - points.append(Point(landmark.location)) - - return LineString(points) - - -# Check if some coordinates are in area. Used for the corridor -def is_in_area(area: Polygon, coordinates) -> bool : - point = Point(coordinates) - return point.within(area) - - -# Function to determine if two landmarks are close to each other -def is_close_to(location1: Tuple[float], location2: Tuple[float]): - """Determine if two locations are close by rounding their coordinates to 3 decimals.""" - absx = abs(location1[0] - location2[0]) - absy = abs(location1[1] - location2[1]) - - return absx < 0.001 and absy < 0.001 - #return (round(location1[0], 3), round(location1[1], 3)) == (round(location2[0], 3), round(location2[1], 3)) - - -# Rearrange some landmarks in the order of visit to group visit -def rearrange(landmarks: List[Landmark]) -> List[Landmark]: - - i = 1 - while i < len(landmarks): - j = i+1 - while j < len(landmarks): - if is_close_to(landmarks[i].location, landmarks[j].location) and landmarks[i].name not in ['start', 'finish'] and landmarks[j].name not in ['start', 'finish']: - # If they are not adjacent, move the j-th element to be adjacent to the i-th element - if j != i + 1: - landmarks.insert(i + 1, landmarks.pop(j)) - break # Move to the next i-th element after rearrangement - j += 1 - i += 1 - - return landmarks - - - # Step 1: Build the graph - graph = defaultdict(list) - for i in range(len(landmarks)): - for j in range(len(landmarks)): - if i != j: - distance = get_distance(landmarks[i].location, landmarks[j].location, detour, speed)[1] - graph[i].append((distance, j)) - - # Step 2: Dijkstra's algorithm to find the shortest path from start to finish - start_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'start') - finish_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'finish') - - distances = {i: float('inf') for i in range(len(landmarks))} - previous_nodes = {i: None for i in range(len(landmarks))} - distances[start_idx] = 0 - priority_queue = [(0, start_idx)] - - while priority_queue: - current_distance, current_index = heappop(priority_queue) - - if current_distance > distances[current_index]: - continue - - for neighbor_distance, neighbor_index in graph[current_index]: - distance = current_distance + neighbor_distance - - if distance < distances[neighbor_index]: - distances[neighbor_index] = distance - previous_nodes[neighbor_index] = current_index - heappush(priority_queue, (distance, neighbor_index)) - - # Step 3: Backtrack from finish to start to find the path - path = [] - current_index = finish_idx - while current_index is not None: - path.append(landmarks[current_index]) - current_index = previous_nodes[current_index] - path.reverse() - - return path -""" -def total_path_distance(path: List[Landmark], detour, speed) -> float: - total_distance = 0 - for i in range(len(path) - 1): - total_distance += get_distance(path[i].location, path[i + 1].location, detour, speed)[1] - return total_distance -""" - - -def find_shortest_path_through_all_landmarks(landmarks: List[Landmark]) -> List[Landmark]: - # Read the parameters from the file - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - - detour = parameters['detour_factor'] - speed = parameters['average_walking_speed'] - - # Step 1: Find 'start' and 'finish' landmarks - start_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'start') - finish_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'finish') - - start_landmark = landmarks[start_idx] - finish_landmark = landmarks[finish_idx] - - - # Step 2: Create a list of unvisited landmarks excluding 'start' and 'finish' - unvisited_landmarks = [lm for i, lm in enumerate(landmarks) if i not in [start_idx, finish_idx]] - - # Step 3: Initialize the path with the 'start' landmark - path = [start_landmark] - coordinates = [landmarks[start_idx].location] - - current_landmark = start_landmark - - # Step 4: Use nearest neighbor heuristic to visit all landmarks - while unvisited_landmarks: - nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time(current_landmark.location, lm.location, detour, speed)) - path.append(nearest_landmark) - coordinates.append(nearest_landmark.location) - current_landmark = nearest_landmark - unvisited_landmarks.remove(nearest_landmark) - - # Step 5: Finally add the 'finish' landmark to the path - path.append(finish_landmark) - coordinates.append(landmarks[finish_idx].location) - - path_poly = Polygon(coordinates) - - return path, path_poly - - -# Returns a list of minor landmarks around the planned path to enhance experience -def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] : - - second_order_landmarks = [] - visited_names = [] - area = create_corridor(visited_landmarks, width) - - for visited in visited_landmarks : - visited_names.append(visited.name) - - for landmark in all_landmarks : - if is_in_area(area, landmark.location) and landmark.name not in visited_names: - second_order_landmarks.append(landmark) - - with constants.LANDMARK_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - return take_most_important(second_order_landmarks, parameters, len(visited_landmarks)) - - -# Try fix the shortest path using shapely -def fix_using_polygon(tour: List[Landmark])-> List[Landmark] : - - coords = [] - coords_dict = {} - for landmark in tour : - coords.append(landmark.location) - if landmark.name != 'finish' : - coords_dict[landmark.location] = landmark - - tour_poly = Polygon(coords) - - better_tour_poly = tour_poly.buffer(0) - try : - xs, ys = better_tour_poly.exterior.xy - - if len(xs) != len(tour) : - better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish - xs, ys = better_tour_poly.exterior.xy - - except : - better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish - xs, ys = better_tour_poly.exterior.xy - - - # reverse the xs and ys - xs.reverse() - ys.reverse() - - better_tour = [] # List of ordered visit - name_index = {} # Maps the name of a landmark to its index in the concave polygon - - # Loop through the polygon and generate the better (ordered) tour - for i,x in enumerate(xs[:-1]) : - y = ys[i] - better_tour.append(coords_dict[tuple((x,y))]) - name_index[coords_dict[tuple((x,y))].name] = i - - - # Scroll the list to have start in front again - start_index = name_index['start'] - better_tour = better_tour[start_index:] + better_tour[:start_index] - - # Append the finish back and correct the time to reach - better_tour.append(tour[-1]) - - # Rearrange only if polygon still not simple - if not better_tour_poly.is_simple : - better_tour = rearrange(better_tour) - - return better_tour - - -# Second stage of the optimization. Use linear programming again to refine the path -def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, detour: int, print_infos: bool) -> List[Landmark] : - - # Read the parameters from the file - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - max_landmarks = parameters['max_landmarks'] - - if len(base_tour)-2 >= max_landmarks : - return base_tour - - - # No need to refine if no detour is taken - # if detour == 0 : - if False : - new_tour = base_tour - - else : - minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200) - - if print_infos : print("Using " + str(len(minor_landmarks)) + " minor landmarks around the predicted path") - - # full set of visitable landmarks - full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) - full_set.append(base_tour[-1]) # add finish back - - # get a new tour - new_tour = solve_optimization(full_set, max_time+detour, False, max_landmarks) - if new_tour is None : - new_tour = base_tour - - # Link the new tour - new_tour, new_dist = link_list_simple(new_tour) - - # If the tour contains only one landmark, return - if len(new_tour) < 4 : - return new_tour - - # Find shortest path using the nearest neighbor heuristic - better_tour, better_poly = find_shortest_path_through_all_landmarks(new_tour) - - # Fix the tour using Polygons if the path looks weird - if base_tour[0].location == base_tour[-1].location and not better_poly.is_valid : - better_tour = fix_using_polygon(better_tour) - - # Link the tour again - better_tour, better_dist = link_list_simple(better_tour) - - # Choose the better tour depending on walked distance - if new_dist < better_dist : - final_tour = new_tour - else : - final_tour = better_tour - - if print_infos : - print("\n\n\nRefined tour (result of second stage optimization): ") - print_res(final_tour) - total_score = 0 - for elem in final_tour : - total_score += elem.attractiveness - - print("\nTotal score : " + str(total_score)) - - - - return final_tour - - diff --git a/backend/src/example_tester.py b/backend/src/example_tester.py deleted file mode 100644 index 71d82e7..0000000 --- a/backend/src/example_tester.py +++ /dev/null @@ -1,80 +0,0 @@ -import pandas as pd - -from typing import List -from landmarks_manager import LandmarkManager -from fastapi.encoders import jsonable_encoder - -from backend.src.example_optimizer import solve_optimization -# from refiner import refine_optimization -from structs.landmarks import Landmark -from structs.landmarktype import LandmarkType -from structs.preferences import Preferences, Preference - - -# Helper function to create a .txt file with results -def write_data(L: List[Landmark], file_name: str): - - data = pd.DataFrame() - i = 0 - - for landmark in L : - data[i] = jsonable_encoder(landmark) - i += 1 - - data.to_json(file_name, indent = 2, force_ascii=False) - -def main(coordinates: tuple[float, float]) -> List[Landmark]: - - manager = LandmarkManager() - - preferences = Preferences( - sightseeing=Preference( - name='sightseeing', - type=LandmarkType(landmark_type='sightseeing'), - score = 5 - ), - nature=Preference( - name='nature', - type=LandmarkType(landmark_type='nature'), - score = 5 - ), - shopping=Preference( - name='shopping', - type=LandmarkType(landmark_type='shopping'), - score = 5 - ) - ) - - - # Create start and finish - start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=coordinates, osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=coordinates, osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - - # Generate the landmarks from the start location - landmarks, landmarks_short = manager.get_landmark_lists(preferences=preferences, center_coordinates=start.location) - print([l.name for l in landmarks_short]) - - #write_data(landmarks, "landmarks.txt") - - # Insert start and finish to the landmarks list - landmarks_short.insert(0, start) - landmarks_short.append(finish) - - # TODO use these parameters in another way - max_walking_time = 3 # hours - detour = 30 # minutes - - # First stage optimization - base_tour = solve_optimization(landmarks_short, max_walking_time*60, True) - - # Second stage optimization - # refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True) - - return base_tour - - - -if __name__ == '__main__': - start = (48.847132, 2.312359) # Café Chez César - # start = (47.377859, 8.540585) # Zurich HB - main(start) diff --git a/backend/src/landmarks_manager.py b/backend/src/landmarks_manager.py index 53fa012..403648f 100644 --- a/backend/src/landmarks_manager.py +++ b/backend/src/landmarks_manager.py @@ -2,9 +2,8 @@ import math as m import yaml import logging -from typing import List, Tuple from OSMPythonTools.overpass import Overpass, overpassQueryBuilder -from OSMPythonTools import cachingStrategy +from OSMPythonTools.cachingStrategy import CachingStrategy, JSON from pywikibot import ItemPage, Site from pywikibot import config config.put_throttle = 0 @@ -33,10 +32,8 @@ class LandmarkManager: tag_coeff: float # coeff to adjust weight of tags N_important: int # number of important landmarks to consider - preferences: Preferences # preferences of visit - location: Tuple[float] # coordinates around which to find a path - def __init__(self, preferences: Preferences, coordinates: Tuple[float, float]) -> None: + def __init__(self) -> None: with constants.AMENITY_SELECTORS_PATH.open('r') as f: self.amenity_selectors = yaml.safe_load(f) @@ -49,12 +46,12 @@ class LandmarkManager: self.park_coeff = parameters['park_coeff'] self.tag_coeff = parameters['tag_coeff'] self.N_important = parameters['N_important'] - - self.preferences = preferences - self.location = coordinates + + self.overpass = Overpass() + CachingStrategy.use(JSON, cacheDir=constants.OSM_CACHE_DIR) - def generate_landmarks_list(self) -> Tuple[List[Landmark], List[Landmark]] : + def generate_landmarks_list(self, center_coordinates: tuple[float, float], preferences: Preferences) -> tuple[list[Landmark], list[Landmark]]: """ Generate and prioritize a list of landmarks based on user preferences. @@ -62,62 +59,71 @@ class LandmarkManager: and current location. It scores and corrects these landmarks, removes duplicates, and then selects the most important landmarks based on a predefined criterion. + Parameters: + center_coordinates (tuple[float, float]): The latitude and longitude of the center location around which to search. + preferences (Preferences): The user's preference settings that influence the landmark selection. + Returns: - Tuple[List[Landmark], List[Landmark]]: + tuple[list[Landmark], list[Landmark]]: - A list of all existing landmarks. - A list of the most important landmarks based on the user's preferences. """ L = [] - - # List for sightseeing - if self.preferences.sightseeing.score != 0 : - L1 = self.fetch_landmarks(self.amenity_selectors['sightseeing'], SIGHTSEEING, coordinates=self.location) - self.correct_score(L1, self.preferences.sightseeing) + bbox = self.create_bbox(center_coordinates) + # list for sightseeing + if preferences.sightseeing.score != 0: + score_function = lambda loc, n_tags: int((self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff) )*self.church_coeff) + L1 = self.fetch_landmarks(bbox, self.amenity_selectors['sightseeing'], SIGHTSEEING, score_function) + self.correct_score(L1, preferences.sightseeing) L += L1 - - # List for nature - if self.preferences.nature.score != 0 : - L2 = self.fetch_landmarks(self.amenity_selectors['nature'], NATURE, coordinates=self.location) - self.correct_score(L2, self.preferences.nature) + + # list for nature + if preferences.nature.score != 0: + score_function = lambda loc, n_tags: int((self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff) )*self.park_coeff) + L2 = self.fetch_landmarks(bbox, self.amenity_selectors['nature'], NATURE, score_function) + self.correct_score(L2, preferences.nature) L += L2 - - # List for shopping - if self.preferences.shopping.score != 0 : - L3 = self.fetch_landmarks(self.amenity_selectors['shopping'], SHOPPING, coordinates=self.location) - self.correct_score(L3, self.preferences.shopping) + + # list for shopping + if preferences.shopping.score != 0: + score_function = lambda loc, n_tags: int(self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff)) + L3 = self.fetch_landmarks(bbox, self.amenity_selectors['shopping'], SHOPPING, score_function) + self.correct_score(L3, preferences.shopping) L += L3 L = self.remove_duplicates(L) + L_constrained = take_most_important(L, self.N_important) + self.logger.info(f'Generated {len(L)} landmarks around {center_coordinates}, and constrained to {len(L_constrained)} most important ones.') - return L, take_most_important(L, self.N_important) + return L, L_constrained - def remove_duplicates(self, landmarks: List[Landmark]) -> List[Landmark] : + def remove_duplicates(self, landmarks: list[Landmark]) -> list[Landmark]: """ Removes duplicate landmarks based on their names from the given list. Only retains the landmark with highest score Parameters: - landmarks (List[Landmark]): A list of Landmark objects. + landmarks (list[Landmark]): A list of Landmark objects. Returns: - List[Landmark]: A list of unique Landmark objects based on their names. + list[Landmark]: A list of unique Landmark objects based on their names. """ L_clean = [] names = [] - for landmark in landmarks : + for landmark in landmarks: if landmark.name in names: continue - else : + else: names.append(landmark.name) L_clean.append(landmark) return L_clean - def correct_score(self, landmarks: List[Landmark], preference: Preference) : + def correct_score(self, landmarks: list[Landmark], preference: Preference): """ Adjust the attractiveness score of each landmark in the list based on user preferences. @@ -125,24 +131,24 @@ class LandmarkManager: The score adjustment is computed using a simple linear transformation based on the preference score. Args: - landmarks (List[Landmark]): A list of landmarks whose scores need to be corrected. + landmarks (list[Landmark]): A list of landmarks whose scores need to be corrected. preference (Preference): The user's preference settings that influence the attractiveness score adjustment. Raises: TypeError: If the type of any landmark in the list does not match the expected type in the preference. """ - if len(landmarks) == 0 : + if len(landmarks) == 0: return - if landmarks[0].type != preference.type : + if landmarks[0].type != preference.type: raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {landmarks[0].name}") - for elem in landmarks : + for elem in landmarks: elem.attractiveness = int(elem.attractiveness*preference.score/5) # arbitrary computation - def count_elements_close_to(self, coordinates: Tuple[float, float]) -> int: + def count_elements_close_to(self, coordinates: tuple[float, float]) -> int: """ Count the number of OpenStreetMap elements (nodes, ways, relations) within a specified radius of the given location. @@ -150,7 +156,7 @@ class LandmarkManager: OpenStreetMap data to count the number of elements within that bounding box. Args: - coordinates (Tuple[float, float]): The latitude and longitude of the location to search around. + coordinates (tuple[float, float]): The latitude and longitude of the location to search around. Returns: int: The number of elements (nodes, ways, relations) within the specified radius. Returns 0 if no elements @@ -164,32 +170,36 @@ class LandmarkManager: alpha = (180*radius) / (6371000*m.pi) bbox = {'latLower':lat-alpha,'lonLower':lon-alpha,'latHigher':lat+alpha,'lonHigher': lon+alpha} - - # Build the query to find elements within the radius - radius_query = overpassQueryBuilder(bbox=[bbox['latLower'],bbox['lonLower'],bbox['latHigher'],bbox['lonHigher']], - elementType=['node', 'way', 'relation']) - try : - overpass = Overpass() - radius_result = overpass.query(radius_query) + # Build the query to find elements within the radius + radius_query = overpassQueryBuilder( + bbox=[bbox['latLower'], + bbox['lonLower'], + bbox['latHigher'], + bbox['lonHigher']], + elementType=['node', 'way', 'relation'] + ) + + try: + radius_result = self.overpass.query(radius_query) N_elem = radius_result.countWays() + radius_result.countRelations() - #print(f"There are {N_elem} ways/relations within 50m") - if N_elem is None : + self.logger.debug(f"There are {N_elem} ways/relations within 50m") + if N_elem is None: return 0 return N_elem - except : + except: return 0 - def create_bbox(self, coordinates: Tuple[float, float]) -> Tuple[float, float, float, float]: + def create_bbox(self, coordinates: tuple[float, float]) -> tuple[float, float, float, float]: """ Create a bounding box around the given coordinates. Args: - coordinates (Tuple[float, float]): The latitude and longitude of the center of the bounding box. + coordinates (tuple[float, float]): The latitude and longitude of the center of the bounding box. Returns: - Tuple[float, float, float, float]: The minimum latitude, minimum longitude, maximum latitude, and maximum longitude + tuple[float, float, float, float]: The minimum latitude, minimum longitude, maximum latitude, and maximum longitude defining the bounding box. """ @@ -212,44 +222,52 @@ class LandmarkManager: return min_lat, min_lon, max_lat, max_lon - def fetch_landmarks(self, list_amenity: list, landmarktype: str, coordinates: Tuple[float, float]) -> List[Landmark] : + def fetch_landmarks(self, bbox: tuple, amenity_selector: dict, landmarktype: str, score_function: callable) -> list[Landmark]: """ Fetches landmarks of a specified type from OpenStreetMap (OSM) within a bounding box centered on given coordinates. Args: - list_amenity (list): A list of OSM amenity queries to be used for fetching landmarks. - These queries are typically used to filter results (e.g., [''amenity'='place_of_worship']). + bbox (tuple[float, float, float, float]): The bounding box coordinates (min_lat, min_lon, max_lat, max_lon). + amenity_selector (dict): The Overpass API query selector for the desired landmark type. landmarktype (str): The type of the landmark (e.g., 'sightseeing', 'nature', 'shopping'). - coordinates (Tuple[float, float]): The central coordinates (latitude, longitude) for the bounding box. + score_function (callable): The function to compute the score of the landmark based on its attributes. Returns: - List[Landmark]: A list of Landmark objects that were fetched and filtered based on the provided criteria. + list[Landmark]: A list of Landmark objects that were fetched and filtered based on the provided criteria. Notes: - - The bounding box is created around the given coordinates with a side length defined by `self.city_bbox_side`. - Landmarks are fetched using Overpass API queries. + - Selectors are translated from the dictionary to the Overpass query format. (e.g., 'amenity'='place_of_worship') - Landmarks are filtered based on various conditions including tags and type. - Scores are assigned to landmarks based on their attributes and surrounding elements. """ - - # Create bbox around start location - bbox = self.create_bbox(coordinates) + return_list = [] - # Initialize some variables - N = 0 - L = [] - overpass = Overpass() - - for amenity in list_amenity : - query = overpassQueryBuilder(bbox=bbox, elementType=['way', 'relation'], selector=amenity, includeCenter=True, out='body') - result = overpass.query(query) - N += result.countElements() + # caution, when applying a list of selectors, overpass will search for elements that match ALL selectors simultaneously + # we need to split the selectors into separate queries and merge the results + for sel in dict_to_selector_list(amenity_selector): + self.logger.debug(f"Current selector: {sel}") + query = overpassQueryBuilder( + bbox = bbox, + elementType = ['way', 'relation'], + selector = sel, + # conditions = [], + includeCenter = True, + out = 'body' + ) + try: + result = self.overpass.query(query) + except Exception as e: + self.logger.error(f"Error fetching landmarks: {e}") + return + for elem in result.elements(): name = elem.tag('name') # Add name location = (elem.centerLat(), elem.centerLon()) # Add coordinates (lat, lon) + # TODO: exclude these from the get go # skip if unprecise location if name is None or location[0] is None: continue @@ -262,65 +280,86 @@ class LandmarkManager: if 'building:part' in elem.tags().keys() and elem.tag('building:part') == 'yes': continue - else : - osm_type = elem.type() # Add type : 'way' or 'relation' - osm_id = elem.id() # Add OSM id - elem_type = landmarktype # Add the landmark type as 'sightseeing, - n_tags = len(elem.tags().keys()) # Add number of tags + osm_type = elem.type() # Add type: 'way' or 'relation' + osm_id = elem.id() # Add OSM id + elem_type = landmarktype # Add the landmark type as 'sightseeing, + n_tags = len(elem.tags().keys()) # Add number of tags - # remove specific tags - skip = False - for tag in elem.tags().keys() : - if "pay" in tag : - n_tags -= 1 # discard payment options for tags + # remove specific tags + skip = False + for tag in elem.tags().keys(): + if "pay" in tag: + n_tags -= 1 # discard payment options for tags - if "disused" in tag : - skip = True # skip disused amenities + if "disused" in tag: + skip = True # skip disused amenities + break + + if "wikipedia" in tag: + n_tags += 3 # wikipedia entries count more + + if tag == "wikidata": + Q = elem.tag('wikidata') + site = Site("wikidata", "wikidata") + item = ItemPage(site, Q) + item.get() + n_languages = len(item.labels) + n_tags += n_languages/10 + + if elem_type != "nature": + if "leisure" in tag and elem.tag('leisure') == "park": + elem_type = "nature" + + if landmarktype != SHOPPING: + if "shop" in tag: + skip = True break - if "wikipedia" in tag : - n_tags += 3 # wikipedia entries count more + if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']: + skip = True + break - if tag == "wikidata" : - Q = elem.tag('wikidata') - site = Site("wikidata", "wikidata") - item = ItemPage(site, Q) - item.get() - n_languages = len(item.labels) - n_tags += n_languages/10 + if skip: + continue - if elem_type != "nature" : - if "leisure" in tag and elem.tag('leisure') == "park": - elem_type = "nature" + score = score_function(location, n_tags) + if score != 0: + # Generate the landmark and append it to the list + landmark = Landmark( + name=name, + type=elem_type, + location=location, + osm_type=osm_type, + osm_id=osm_id, + attractiveness=score, + must_do=False, + n_tags=int(n_tags) + ) + return_list.append(landmark) + + self.logger.debug(f"Fetched {len(return_list)} landmarks of type {landmarktype} in {bbox}") - if amenity not in ["'shop'='department_store'", "'shop'='mall'"] : - if "shop" in tag : - skip = True - break - - if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']: - skip = True - break - - if skip: - continue - - # Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT - if amenity == "'amenity'='place_of_worship'" : - #score = int((count_elements_close_to(location, radius) + (n_tags*tag_coeff) )*church_coeff) - score = int((self.count_elements_close_to(location) + ((n_tags**1.2)*self.tag_coeff) )*self.church_coeff) - elif amenity == "'leisure'='park'" : - score = int((self.count_elements_close_to(location) + ((n_tags**1.2)*self.tag_coeff) )*self.park_coeff) - else : - score = int(self.count_elements_close_to(location) + ((n_tags**1.2)*self.tag_coeff)) - - if score is not None : - - # Generate the landmark and append it to the list - #print(f"There are {n_tags} tags on this Landmark. Total score : {score}\n") - landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=int(n_tags)) - L.append(landmark) - - return L + return return_list + +def dict_to_selector_list(d: dict) -> list: + """ + Convert a dictionary of key-value pairs to a list of Overpass query strings. + + Args: + d (dict): A dictionary of key-value pairs representing the selector. + + Returns: + list: A list of strings representing the Overpass query selectors. + """ + return_list = [] + for key, value in d.items(): + if type(value) == list: + val = '|'.join(value) + return_list.append(f'{key}~"{val}"') + elif type(value) == str and len(value) == 0: + return_list.append(f'{key}') + else: + return_list.append(f'{key}={value}') + return return_list diff --git a/backend/src/tester.py b/backend/src/tester.py index cd75435..3c1cd94 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -24,9 +24,9 @@ def write_data(L: List[Landmark], file_name: str): def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = None) -> List[Landmark]: + manager = LandmarkManager() - preferences = Preferences( sightseeing=Preference( name='sightseeing', @@ -56,10 +56,12 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.847132, 2.312359), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - manager = LandmarkManager(preferences=preferences, coordinates=start_coords) # Generate the landmarks from the start location - landmarks, landmarks_short = manager.generate_landmarks_list() + landmarks, landmarks_short = manager.generate_landmarks_list( + center_coordinates = start_coords, + preferences = preferences + ) # Store data to file for debug purposes # write_data(landmarks, "landmarks_Strasbourg.txt") diff --git a/deployment/deployment.yaml b/deployment/deployment.yaml deleted file mode 100644 index aabc6fa..0000000 --- a/deployment/deployment.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nav-backend -spec: - replicas: 1 - selector: - matchLabels: - app: nav-backend - template: - metadata: - labels: - app: nav-backend - spec: - containers: - - name: worker - image: backend-image - ports: - - containerPort: 8000 - env: - - name: NUM_WORKERS - value: "3" - - name: OSM_CACHE_DIR - value: "/osm-cache" - volumeMounts: - - name: osm-cache - mountPath: /osm-cache - resources: - requests: - cpu: 100m - memory: 100Mi - limits: - cpu: 4 - memory: 10Gi - volumes: - - name: osm-cache - persistentVolumeClaim: - claimName: osm-cache - - \ No newline at end of file diff --git a/deployment/ingress.yaml b/deployment/ingress.yaml deleted file mode 100644 index 8fa3b41..0000000 --- a/deployment/ingress.yaml +++ /dev/null @@ -1,15 +0,0 @@ -kind: IngressRoute -apiVersion: traefik.io/v1alpha1 -metadata: - name: nav-ingress -spec: - entryPoints: - - websecure - routes: - - match: Host(`nav.kluster.moll.re`) - kind: Rule - services: - - name: nav-service - port: 8000 - tls: - certResolver: default-tls diff --git a/deployment/kustomization.yaml b/deployment/kustomization.yaml deleted file mode 100644 index bbb5d0c..0000000 --- a/deployment/kustomization.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - - -namespace: nav -resources: - - namespace.yaml - - pvc.yaml - - deployment.yaml - - service.yaml - - ingress.yaml - -images: - - name: backend-image - newName: git.kluster.moll.re/remoll/fast_network_navigation/backend - newTag: latest \ No newline at end of file diff --git a/deployment/namespace.yaml b/deployment/namespace.yaml deleted file mode 100644 index 0a074bd..0000000 --- a/deployment/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: placeholder diff --git a/deployment/pvc.yaml b/deployment/pvc.yaml deleted file mode 100644 index a7e747f..0000000 --- a/deployment/pvc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: osm-cache -spec: - storageClassName: "nfs-client" - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "5Gi" diff --git a/deployment/service.yaml b/deployment/service.yaml deleted file mode 100644 index c4e5de3..0000000 --- a/deployment/service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: nav-service -spec: - selector: - app: nav-backend - ports: - - protocol: TCP - port: 8000 - targetPort: 8000 From 2863c99d7c5858faf5459cef020d532c943e0776 Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Thu, 25 Jul 2024 17:15:18 +0200 Subject: [PATCH 5/7] style corrections, documentation, duplicate removal, flow improvement --- backend/src/constants.py | 2 +- backend/src/main.py | 47 +++-- .../src/parameters/optimizer_parameters.yaml | 1 + .../src/structs/{landmarks.py => landmark.py} | 3 +- backend/src/structs/linked_landmarks.py | 48 +++++ backend/src/tester.py | 32 +-- backend/src/utils.py | 106 ---------- backend/src/utils/get_time_separation.py | 39 ++++ backend/src/{ => utils}/landmarks_manager.py | 4 +- backend/src/{ => utils}/optimizer.py | 195 +++++++----------- backend/src/{ => utils}/refiner.py | 147 ++++++------- backend/src/utils/take_most_important.py | 38 ++++ 12 files changed, 314 insertions(+), 348 deletions(-) rename backend/src/structs/{landmarks.py => landmark.py} (84%) create mode 100644 backend/src/structs/linked_landmarks.py delete mode 100644 backend/src/utils.py create mode 100644 backend/src/utils/get_time_separation.py rename backend/src/{ => utils}/landmarks_manager.py (97%) rename backend/src/{ => utils}/optimizer.py (71%) rename backend/src/{ => utils}/refiner.py (71%) create mode 100644 backend/src/utils/take_most_important.py diff --git a/backend/src/constants.py b/backend/src/constants.py index 951a51d..2e66727 100644 --- a/backend/src/constants.py +++ b/backend/src/constants.py @@ -14,6 +14,6 @@ OSM_CACHE_DIR = Path(cache_dir_string) logger = logging.getLogger(__name__) logging.basicConfig( - level = logging.DEBUG, + level = logging.INFO, format = '%(asctime)s - %(name)s\t- %(levelname)s\t- %(message)s' ) diff --git a/backend/src/main.py b/backend/src/main.py index 8a76288..6a63300 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -1,16 +1,20 @@ -from backend.src.example_optimizer import solve_optimization -# from refiner import refine_optimization -from landmarks_manager import LandmarkManager -from structs.landmarks import Landmark -from structs.landmarktype import LandmarkType -from structs.preferences import Preferences +import logging from fastapi import FastAPI, Query, Body +from structs.landmark import Landmark +from structs.preferences import Preferences +from structs.linked_landmarks import LinkedLandmarks +from utils.landmarks_manager import LandmarkManager +from utils.optimizer import Optimizer +from utils.refiner import Refiner + + +logger = logging.getLogger(__name__) + app = FastAPI() manager = LandmarkManager() - -# TODO: needs a global variable to store the landmarks accross function calls -# linked_tour = [] +optimizer = Optimizer() +refiner = Refiner(optimizer=optimizer) @app.post("/route/new") @@ -22,19 +26,23 @@ def main1(preferences: Preferences, start: tuple[float, float], end: tuple[float :param end: the coordinates of the finishing point as a tuple of floats (as url query parameters) :return: the uuid of the first landmark in the optimized route ''' - if preferences is None : + if preferences is None: raise ValueError("Please provide preferences in the form of a 'Preference' BaseModel class.") if start is None: raise ValueError("Please provide the starting coordinates as a tuple of floats.") if end is None: end = start + logger.info("No end coordinates provided. Using start=end.") + + start_landmark = Landmark(name='start', type='start', location=(start[0], start[1]), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) + end_landmark = Landmark(name='end', type='end', location=(end[0], end[1]), osm_type='end', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - start_landmark = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(start[0], start[1]), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - end_landmark = Landmark(name='end', type=LandmarkType(landmark_type='end'), location=(end[0], end[1]), osm_type='end', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - # Generate the landmarks from the start location - landmarks, landmarks_short = LandmarkManager.get_landmark_lists(preferences=preferences, coordinates=start.location) - print([l.name for l in landmarks_short]) + landmarks, landmarks_short = manager.generate_landmarks_list( + center_coordinates = start, + preferences = preferences + ) + # insert start and finish to the landmarks list landmarks_short.insert(0, start_landmark) landmarks_short.append(end_landmark) @@ -44,14 +52,13 @@ def main1(preferences: Preferences, start: tuple[float, float], end: tuple[float detour = 30 # minutes # First stage optimization - base_tour = solve_optimization(landmarks_short, max_walking_time*60, True) + base_tour = optimizer.solve_optimization(max_walking_time*60, landmarks_short) # Second stage optimization - # refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True) + refined_tour = refiner.refine_optimization(landmarks, base_tour, max_walking_time*60, detour) - # linked_tour = ... - # return linked_tour[0].uuid - return base_tour[0].uuid + linked_tour = LinkedLandmarks(refined_tour) + return linked_tour[0].uuid diff --git a/backend/src/parameters/optimizer_parameters.yaml b/backend/src/parameters/optimizer_parameters.yaml index efd2547..2bf4f32 100644 --- a/backend/src/parameters/optimizer_parameters.yaml +++ b/backend/src/parameters/optimizer_parameters.yaml @@ -1,3 +1,4 @@ detour_factor: 1.4 +detour_corridor_width: 200 average_walking_speed: 4.8 max_landmarks: 7 diff --git a/backend/src/structs/landmarks.py b/backend/src/structs/landmark.py similarity index 84% rename from backend/src/structs/landmarks.py rename to backend/src/structs/landmark.py index 6f449a8..2f22d42 100644 --- a/backend/src/structs/landmarks.py +++ b/backend/src/structs/landmark.py @@ -33,5 +33,6 @@ class Landmark(BaseModel) : return self.uuid.int def __str__(self) -> str: - return f'Landmark: [{self.name}, {self.location}, {self.attractiveness}]' + time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" + return f'Landmark({self.type}): [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}]' diff --git a/backend/src/structs/linked_landmarks.py b/backend/src/structs/linked_landmarks.py new file mode 100644 index 0000000..72a260a --- /dev/null +++ b/backend/src/structs/linked_landmarks.py @@ -0,0 +1,48 @@ +import uuid + +from .landmark import Landmark +from utils.get_time_separation import get_time + +class LinkedLandmarks: + """ + A list of landmarks that are linked together, e.g. in a route. + Each landmark serves as a node in the linked list, but since we expect these to be consumed through the rest API, a pythonic reference to the next landmark is not well suited. Instead we use the uuid of the next landmark to reference the next landmark in the list. This is not very efficient, but appropriate for the expected use case ("short" trips with onyl few landmarks). + """ + + _landmarks = list[Landmark] + total_time = int + uuid = str + + def __init__(self, data: list[Landmark] = None) -> None: + """ + Initialize a new LinkedLandmarks object. This expects an ORDERED list of landmarks, where the first landmark is the starting point and the last landmark is the end point. + + Args: + data (list[Landmark], optional): The list of landmarks that are linked together. Defaults to None. + """ + self.uuid = uuid.uuid4() + self._landmarks = data if data else [] + self._link_landmarks() + + + def _link_landmarks(self) -> None: + """ + Create the links between the landmarks in the list by setting their .next_uuid and the .time_to_next attributes. + """ + self.total_time = 0 + for i, landmark in enumerate(self._landmarks[:-1]): + landmark.next_uuid = self._landmarks[i + 1].uuid + time_to_next = get_time(landmark.location, self._landmarks[i + 1].location) + landmark.time_to_reach_next = time_to_next + self.total_time += time_to_next + + self._landmarks[-1].next_uuid = None + self._landmarks[-1].time_to_reach_next = 0 + + + def __getitem__(self, index: int) -> Landmark: + return self._landmarks[index] + + + def __str__(self) -> str: + return f"LinkedLandmarks, total time: {self.total_time} minutes, {len(self._landmarks)} stops: [\n\t{'\n\t'.join([str(landmark) for landmark in self._landmarks])}\n]" \ No newline at end of file diff --git a/backend/src/tester.py b/backend/src/tester.py index 3c1cd94..a3195a3 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -1,17 +1,19 @@ import pandas as pd - -from typing import List -from landmarks_manager import LandmarkManager +import logging from fastapi.encoders import jsonable_encoder -from optimizer import Optimizer -from refiner import Refiner -from structs.landmarks import Landmark +from utils.landmarks_manager import LandmarkManager +from utils.optimizer import Optimizer +from utils.refiner import Refiner +from structs.landmark import Landmark +from structs.linked_landmarks import LinkedLandmarks from structs.preferences import Preferences, Preference +logger = logging.getLogger(__name__) + # Helper function to create a .txt file with results -def write_data(L: List[Landmark], file_name: str): +def write_data(L: list[Landmark], file_name: str): data = pd.DataFrame() i = 0 @@ -23,8 +25,10 @@ def write_data(L: List[Landmark], file_name: str): data.to_json(file_name, indent = 2, force_ascii=False) -def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = None) -> List[Landmark]: +def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = None) -> list[Landmark]: manager = LandmarkManager() + optimizer = Optimizer() + refiner = Refiner(optimizer=optimizer) preferences = Preferences( @@ -42,7 +46,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = score = 5), max_time_minute=180, - detour_tolerance_minute=0 + detour_tolerance_minute=30 ) # Create start and finish @@ -71,15 +75,15 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = landmarks_short.append(finish) # First stage optimization - optimizer = Optimizer(max_time=preferences.max_time_minute, landmarks=landmarks_short) - base_tour = optimizer.solve_optimization() + base_tour = optimizer.solve_optimization(max_time=preferences.max_time_minute, landmarks=landmarks_short) # Second stage using linear optimization - refiner = Refiner(max_time = preferences.max_time_minute, detour = preferences.detour_tolerance_minute) - refined_tour = refiner.refine_optimization(all_landmarks=landmarks, base_tour=base_tour) + refined_tour = refiner.refine_optimization(all_landmarks=landmarks, base_tour=base_tour, max_time = preferences.max_time_minute, detour = preferences.detour_tolerance_minute) + linked_tour = LinkedLandmarks(refined_tour) + logger.info(f"Optimized route: {linked_tour}") - return refined_tour + return linked_tour #test(tuple((48.8344400, 2.3220540))) # Café Chez César diff --git a/backend/src/utils.py b/backend/src/utils.py deleted file mode 100644 index d145c6f..0000000 --- a/backend/src/utils.py +++ /dev/null @@ -1,106 +0,0 @@ -import yaml -from typing import List, Tuple -from geopy.distance import geodesic - -from structs.landmarks import Landmark -import constants - -def get_time(p1: Tuple[float, float], p2: Tuple[float, float]) -> int : - """ - Calculate the time in minutes to travel from one location to another. - - Args: - p1 (Tuple[float, float]): Coordinates of the starting location. - p2 (Tuple[float, float]): Coordinates of the destination. - detour (float): Detour factor affecting the distance. - speed (float): Walking speed in kilometers per hour. - - Returns: - int: Time to travel from p1 to p2 in minutes. - """ - - with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: - parameters = yaml.safe_load(f) - detour_factor = parameters['detour_factor'] - average_walking_speed = parameters['average_walking_speed'] - - # Compute the straight-line distance in km - if p1 == p2 : - return 0 - else: - dist = geodesic(p1, p2).kilometers - - # Consider the detour factor for average cityto deterline walking distance (in km) - walk_dist = dist*detour_factor - - # Time to walk this distance (in minutes) - walk_time = walk_dist/average_walking_speed*60 - - return round(walk_time) - - - - -# Same as link_list but does it on a already ordered list -def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] : - - L = [] - j = 0 - total_dist = 0 - while j < len(ordered_visit)-1 : - elem = ordered_visit[j] - next = ordered_visit[j+1] - - elem.next_uuid = next.uuid - d = get_time(elem.location, next.location) - elem.time_to_reach_next = d - if elem.name not in ['start', 'finish'] : - elem.must_do = True - L.append(elem) - j += 1 - total_dist += d - - L.append(next) - - return L, total_dist - - - -# Take the most important landmarks from the list -def take_most_important(landmarks: List[Landmark], N_important) -> List[Landmark] : - - L = len(landmarks) - L_copy = [] - L_clean = [] - scores = [0]*len(landmarks) - names = [] - name_id = {} - - for i, elem in enumerate(landmarks) : - if elem.name not in names : - names.append(elem.name) - name_id[elem.name] = [i] - L_copy.append(elem) - else : - name_id[elem.name] += [i] - scores = [] - for j in name_id[elem.name] : - scores.append(L[j].attractiveness) - best_id = max(range(len(scores)), key=scores.__getitem__) - t = name_id[elem.name][best_id] - if t == i : - for old in L_copy : - if old.name == elem.name : - old.attractiveness = L[t].attractiveness - - scores = [0]*len(L_copy) - for i, elem in enumerate(L_copy) : - scores[i] = elem.attractiveness - - res = sorted(range(len(scores)), key = lambda sub: scores[sub])[-(N_important-L):] - - for i, elem in enumerate(L_copy) : - if i in res : - L_clean.append(elem) - - return L_clean \ No newline at end of file diff --git a/backend/src/utils/get_time_separation.py b/backend/src/utils/get_time_separation.py new file mode 100644 index 0000000..5d7f5cb --- /dev/null +++ b/backend/src/utils/get_time_separation.py @@ -0,0 +1,39 @@ +import yaml +from geopy.distance import geodesic + +import constants + +with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: + parameters = yaml.safe_load(f) + DETOUR_FACTOR = parameters['detour_factor'] + AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] + + +def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: + """ + Calculate the time in minutes to travel from one location to another. + + Args: + p1 (Tuple[float, float]): Coordinates of the starting location. + p2 (Tuple[float, float]): Coordinates of the destination. + detour (float): Detour factor affecting the distance. + speed (float): Walking speed in kilometers per hour. + + Returns: + int: Time to travel from p1 to p2 in minutes. + """ + + + # Compute the straight-line distance in km + if p1 == p2 : + return 0 + else: + dist = geodesic(p1, p2).kilometers + + # Consider the detour factor for average cityto deterline walking distance (in km) + walk_dist = dist*DETOUR_FACTOR + + # Time to walk this distance (in minutes) + walk_time = walk_dist/AVERAGE_WALKING_SPEED*60 + + return round(walk_time) diff --git a/backend/src/landmarks_manager.py b/backend/src/utils/landmarks_manager.py similarity index 97% rename from backend/src/landmarks_manager.py rename to backend/src/utils/landmarks_manager.py index 403648f..2ba9100 100644 --- a/backend/src/landmarks_manager.py +++ b/backend/src/utils/landmarks_manager.py @@ -10,8 +10,8 @@ config.put_throttle = 0 config.maxlag = 0 from structs.preferences import Preferences, Preference -from structs.landmarks import Landmark -from utils import take_most_important +from structs.landmark import Landmark +from .take_most_important import take_most_important import constants diff --git a/backend/src/optimizer.py b/backend/src/utils/optimizer.py similarity index 71% rename from backend/src/optimizer.py rename to backend/src/utils/optimizer.py index 4c070f6..931a3d2 100644 --- a/backend/src/optimizer.py +++ b/backend/src/utils/optimizer.py @@ -1,12 +1,12 @@ import yaml, logging import numpy as np -from typing import List, Tuple from scipy.optimize import linprog from collections import defaultdict, deque from geopy.distance import geodesic -from structs.landmarks import Landmark +from structs.landmark import Landmark +from .get_time_separation import get_time import constants @@ -17,17 +17,13 @@ class Optimizer: logger = logging.getLogger(__name__) - landmarks: List[Landmark] # list of landmarks - max_time: int = None # max visit time (in minutes) detour: int = None # accepted max detour time (in minutes) detour_factor: float # detour factor of straight line vs real distance in cities average_walking_speed: float # average walking speed of adult max_landmarks: int # max number of landmarks to visit - def __init__(self, max_time: int, landmarks: List[Landmark]) : - self.max_time = max_time - self.landmarks = landmarks + def __init__(self) : # load parameters from file with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: @@ -37,25 +33,6 @@ class Optimizer: self.max_landmarks = parameters['max_landmarks'] - def print_res(self, L: List[Landmark]): - """ - Print the suggested order of landmarks to visit and log the total time walked. - - Args: - L (List[Landmark]): List of landmarks in the suggested visit order. - """ - - self.logger.info(f'The following order is suggested : ') - dist = 0 - for elem in L : - if elem.time_to_reach_next is not None : - self.logger.info(f" {elem.name}, time to next = {elem.time_to_reach_next}") - dist += elem.time_to_reach_next - else : - self.logger.info(f" {elem.name}") - self.logger.info(f'Minutes walked : {dist}') - self.logger.info(f'Visited {len(L)-2} landmarks') - # Prevent the use of a particular solution def prevent_config(self, resx): @@ -63,10 +40,10 @@ class Optimizer: Prevent the use of a particular solution by adding constraints to the optimization. Args: - resx (List[float]): List of edge weights. + resx (list[float]): List of edge weights. Returns: - Tuple[List[int], List[int]]: A tuple containing a new row for constraint matrix and new value for upper bound vector. + Tuple[list[int], list[int]]: A tuple containing a new row for constraint matrix and new value for upper bound vector. """ for i, elem in enumerate(resx): @@ -101,7 +78,7 @@ class Optimizer: L (int): Number of landmarks. Returns: - Tuple[np.ndarray, List[int]]: A tuple containing a new row for constraint matrix and new value for upper bound vector. + Tuple[np.ndarray, list[int]]: A tuple containing a new row for constraint matrix and new value for upper bound vector. """ l1 = [0]*L*L @@ -129,7 +106,7 @@ class Optimizer: resx (list): List of edge weights. Returns: - Tuple[List[int], Optional[List[List[int]]]]: A tuple containing the visit order and a list of any detected circles. + Tuple[list[int], Optional[list[list[int]]]]: A tuple containing the visit order and a list of any detected circles. """ # first round the results to have only 0-1 values @@ -189,34 +166,8 @@ class Optimizer: return order, all_journeys_nodes - def get_time(self, p1: Tuple[float, float], p2: Tuple[float, float]) -> int : - """ - Calculate the time in minutes to travel from one location to another. - Args: - p1 (Tuple[float, float]): Coordinates of the starting location. - p2 (Tuple[float, float]): Coordinates of the destination. - - Returns: - int: Time to travel from p1 to p2 in minutes. - """ - - # Compute the straight-line distance in km - if p1 == p2 : - return 0 - else: - dist = geodesic(p1, p2).kilometers - - # Consider the detour factor for average cityto deterline walking distance (in km) - walk_dist = dist*self.detour_factor - - # Time to walk this distance (in minutes) - walk_time = walk_dist/self.average_walking_speed*60 - - return round(walk_time) - - - def init_ub_dist(self, landmarks: List[Landmark], max_steps: int): + def init_ub_dist(self, landmarks: list[Landmark], max_steps: int): """ Initialize the objective function coefficients and inequality constraints for the optimization problem. @@ -224,11 +175,11 @@ class Optimizer: The goal is to maximize the objective function subject to the constraints A*x < b and A_eq*x = b_eq. Args: - landmarks (List[Landmark]): List of landmarks. + landmarks (list[Landmark]): List of landmarks. max_steps (int): Maximum number of steps allowed. Returns: - Tuple[List[float], List[float], List[int]]: Objective function coefficients, inequality constraint coefficients, and the right-hand side of the inequality constraint. + Tuple[list[float], list[float], list[int]]: Objective function coefficients, inequality constraint coefficients, and the right-hand side of the inequality constraint. """ # Objective function coefficients. a*x1 + b*x2 + c*x3 + ... @@ -240,7 +191,7 @@ class Optimizer: dist_table = [0]*len(landmarks) c.append(-spot1.attractiveness) for j, spot2 in enumerate(landmarks) : - t = self.get_time(spot1.location, spot2.location) + t = get_time(spot1.location, spot2.location) dist_table[j] = t closest = sorted(dist_table)[:22] for i, dist in enumerate(dist_table) : @@ -260,7 +211,7 @@ class Optimizer: L (int): Number of landmarks. Returns: - Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + Tuple[np.ndarray, list[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. """ ones = [1]*L @@ -287,7 +238,7 @@ class Optimizer: L (int): Number of landmarks. Returns: - Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + Tuple[np.ndarray, list[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. """ upper_ind = np.triu_indices(L,0,L) @@ -318,7 +269,7 @@ class Optimizer: L (int): Number of landmarks. Returns: - Tuple[List[np.ndarray], List[int]]: Equality constraint coefficients and the right-hand side of the equality constraints. + Tuple[list[np.ndarray], list[int]]: Equality constraint coefficients and the right-hand side of the equality constraints. """ l = [0]*L*L @@ -333,15 +284,15 @@ class Optimizer: return [l], [0] - def respect_user_must_do(self, landmarks: List[Landmark]) : + def respect_user_must_do(self, landmarks: list[Landmark]) : """ Generate constraints to ensure that landmarks marked as 'must_do' are included in the optimization. Args: - landmarks (List[Landmark]): List of landmarks, where some are marked as 'must_do'. + landmarks (list[Landmark]): List of landmarks, where some are marked as 'must_do'. Returns: - Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + Tuple[np.ndarray, list[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. """ L = len(landmarks) @@ -359,15 +310,15 @@ class Optimizer: return A, b - def respect_user_must_avoid(self, landmarks: List[Landmark]) : + def respect_user_must_avoid(self, landmarks: list[Landmark]) : """ Generate constraints to ensure that landmarks marked as 'must_avoid' are skipped in the optimization. Args: - landmarks (List[Landmark]): List of landmarks, where some are marked as 'must_avoid'. + landmarks (list[Landmark]): List of landmarks, where some are marked as 'must_avoid'. Returns: - Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + Tuple[np.ndarray, list[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. """ L = len(landmarks) @@ -394,7 +345,7 @@ class Optimizer: L (int): Number of landmarks. Returns: - Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + Tuple[np.ndarray, list[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. """ l_start = [1]*L + [0]*L*(L-1) # sets departures only for start (horizontal ones) @@ -422,7 +373,7 @@ class Optimizer: L (int): Number of landmarks. Returns: - Tuple[np.ndarray, List[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. + Tuple[np.ndarray, list[int]]: Inequality constraint coefficients and the right-hand side of the inequality constraints. """ A = [0]*L*L @@ -443,16 +394,16 @@ class Optimizer: return A, b - def link_list(self, order: List[int], landmarks: List[Landmark])->List[Landmark] : + def link_list(self, order: list[int], landmarks: list[Landmark])->list[Landmark] : """ Compute the time to reach from each landmark to the next and create a list of landmarks with updated travel times. Args: - order (List[int]): List of indices representing the order of landmarks to visit. - landmarks (List[Landmark]): List of all landmarks. + order (list[int]): List of indices representing the order of landmarks to visit. + landmarks (list[Landmark]): List of all landmarks. Returns: - List[Landmark]]: The updated linked list of landmarks with travel times + list[Landmark]]: The updated linked list of landmarks with travel times """ L = [] @@ -463,7 +414,7 @@ class Optimizer: next = landmarks[order[j+1]] # get attributes - elem.time_to_reach_next = self.get_time(elem.location, next.location) + elem.time_to_reach_next = get_time(elem.location, next.location) elem.must_do = True elem.location = (round(elem.location[0], 5), round(elem.location[1], 5)) elem.next_uuid = next.uuid @@ -478,21 +429,28 @@ class Optimizer: # Main optimization pipeline - def solve_optimization (self, hide_log=False) : + def solve_optimization( + self, + max_time: int, + landmarks: list[Landmark], + ) -> list[Landmark]: """ Main optimization pipeline to solve the landmark visiting problem. This method sets up and solves a linear programming problem with constraints to find an optimal tour of landmarks, considering user-defined must-visit landmarks, start and finish points, and ensuring no cycles are present. + Args: + max_time (int): Maximum time allowed for the tour in minutes. + landmarks (list[Landmark]): List of landmarks to visit. Returns: - List[Landmark]: The optimized tour of landmarks with updated travel times, or None if no valid solution is found. + list[Landmark]: The optimized tour of landmarks with updated travel times, or None if no valid solution is found. """ - L = len(self.landmarks) + L = len(landmarks) # SET CONSTRAINTS FOR INEQUALITY - c, A_ub, b_ub = self.init_ub_dist(self.landmarks, self.max_time) # Add the distances from each landmark to the other + c, A_ub, b_ub = self.init_ub_dist(landmarks, max_time) # Add the distances from each landmark to the other A, b = self.respect_number(L) # Respect max number of visits (no more possible stops than landmarks). A_ub = np.vstack((A_ub, A), dtype=np.int16) b_ub += b @@ -503,10 +461,10 @@ class Optimizer: # SET CONSTRAINTS FOR EQUALITY A_eq, b_eq = self.init_eq_not_stay(L) # Force solution not to stay in same place - A, b = self.respect_user_must_do(self.landmarks) # Check if there are user_defined must_see. Also takes care of start/goal + A, b = self.respect_user_must_do(landmarks) # Check if there are user_defined must_see. Also takes care of start/goal A_eq = np.vstack((A_eq, A), dtype=np.int8) b_eq += b - A, b = self.respect_user_must_avoid(self.landmarks) # Check if there are user_defined must_see. Also takes care of start/goal + A, b = self.respect_user_must_avoid(landmarks) # Check if there are user_defined must_see. Also takes care of start/goal A_eq = np.vstack((A_eq, A), dtype=np.int8) b_eq += b A, b = self.respect_start_finish(L) # Force start and finish positions @@ -524,51 +482,38 @@ class Optimizer: # Raise error if no solution is found if not res.success : - raise ArithmeticError("No solution could be found, the problem is overconstrained. Please adapt your must_dos") + raise ArithmeticError("No solution could be found, the problem is overconstrained. Please adapt your must_dos") # If there is a solution, we're good to go, just check for connectiveness - else : + order, circles = self.is_connected(res.x) + #nodes, edges = is_connected(res.x) + i = 0 + timeout = 80 + while circles is not None and i < timeout: + A, b = self.prevent_config(res.x) + A_ub = np.vstack((A_ub, A)) + b_ub += b + #A_ub, b_ub = prevent_circle(order, len(landmarks), A_ub, b_ub) + for circle in circles : + A, b = self.prevent_circle(circle, L) + A_eq = np.vstack((A_eq, A)) + b_eq += b + res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) + if not res.success : + raise ArithmeticError("Solving failed because of overconstrained problem") + return None order, circles = self.is_connected(res.x) #nodes, edges = is_connected(res.x) - i = 0 - timeout = 80 - while circles is not None and i < timeout: - A, b = self.prevent_config(res.x) - A_ub = np.vstack((A_ub, A)) - b_ub += b - #A_ub, b_ub = prevent_circle(order, len(landmarks), A_ub, b_ub) - for circle in circles : - A, b = self.prevent_circle(circle, L) - A_eq = np.vstack((A_eq, A)) - b_eq += b - res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3) - if not res.success : - raise ArithmeticError("Solving failed because of overconstrained problem") - return None - order, circles = self.is_connected(res.x) - #nodes, edges = is_connected(res.x) - if circles is None : - break - # print(i) - i += 1 - - if i == timeout : - raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.") - - # Add the times to reach and stop optimizing - tour = self.link_list(order, self.landmarks) - - # logging - if not hide_log : - if i != 0 : - self.logger.info(f"Neded to recompute paths {i} times") - self.print_res(tour) # how to do better ? - self.logger.info(f"Total score : {int(-res.fun)}") - - return tour - - - - - + if circles is None : + break + # print(i) + i += 1 + + if i == timeout : + raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.") + #sort the landmarks in the order of the solution + tour = [landmarks[i] for i in order] + + self.logger.debug(f"Re-optimized {i} times, score: {int(-res.fun)}") + return tour diff --git a/backend/src/refiner.py b/backend/src/utils/refiner.py similarity index 71% rename from backend/src/refiner.py rename to backend/src/utils/refiner.py index 85aa7c5..c8f0aa5 100644 --- a/backend/src/refiner.py +++ b/backend/src/utils/refiner.py @@ -1,12 +1,11 @@ import yaml, logging from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull -from typing import List, Tuple from math import pi -from structs.landmarks import Landmark -from optimizer import Optimizer -from utils import get_time, link_list_simple, take_most_important +from structs.landmark import Landmark +from . import take_most_important, get_time_separation +from .optimizer import Optimizer import constants @@ -15,31 +14,30 @@ class Refiner : logger = logging.getLogger(__name__) - max_time: int = None # max visit time (in minutes) - detour: int = None # accepted max detour time (in minutes) detour_factor: float # detour factor of straight line vs real distance in cities + detour_corridor_width: float # width of the corridor around the path average_walking_speed: float # average walking speed of adult max_landmarks: int # max number of landmarks to visit + optimizer: Optimizer # optimizer object - - def __init__(self, max_time: int, detour: int) : - self.max_time = max_time - self.detour = detour + def __init__(self, optimizer: Optimizer) : + self.optimizer = optimizer # load parameters from file with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: parameters = yaml.safe_load(f) self.detour_factor = parameters['detour_factor'] + self.detour_corridor_width = parameters['detour_corridor_width'] self.average_walking_speed = parameters['average_walking_speed'] self.max_landmarks = parameters['max_landmarks'] + 4 - def create_corridor(self, landmarks: List[Landmark], width: float) : + def create_corridor(self, landmarks: list[Landmark], width: float) : """ Create a corridor around the path connecting the landmarks. Args: - landmarks (List[Landmark]): the landmark path around which to create the corridor + landmarks (list[Landmark]): the landmark path around which to create the corridor width (float): Width of the corridor in meters. Returns: @@ -54,12 +52,12 @@ class Refiner : return obj - def create_linestring(self, tour: List[Landmark])->LineString : + def create_linestring(self, tour: list[Landmark]) -> LineString : """ Create a `LineString` object from a tour. Args: - tour (List[Landmark]): An ordered sequence of landmarks that represents the visiting order. + tour (list[Landmark]): An ordered sequence of landmarks that represents the visiting order. Returns: LineString: A `LineString` object representing the path through the landmarks. @@ -79,7 +77,7 @@ class Refiner : Args: area (Polygon): The polygon defining the area. - coordinates (Tuple[float, float]): The coordinates of the point to check. + coordinates (tuple[float, float]): The coordinates of the point to check. Returns: bool: True if the point is within the area, otherwise False. @@ -89,13 +87,13 @@ class Refiner : # Function to determine if two landmarks are close to each other - def is_close_to(self, location1: Tuple[float], location2: Tuple[float]): + def is_close_to(self, location1: tuple[float], location2: tuple[float]): """ Determine if two locations are close to each other by rounding their coordinates to 3 decimal places. Args: - location1 (Tuple[float, float]): The coordinates of the first location. - location2 (Tuple[float, float]): The coordinates of the second location. + location1 (tuple[float, float]): The coordinates of the first location. + location2 (tuple[float, float]): The coordinates of the second location. Returns: bool: True if the locations are within 0.001 degrees of each other, otherwise False. @@ -108,7 +106,7 @@ class Refiner : #return (round(location1[0], 3), round(location1[1], 3)) == (round(location2[0], 3), round(location2[1], 3)) - def rearrange(self, tour: List[Landmark]) -> List[Landmark]: + def rearrange(self, tour: list[Landmark]) -> list[Landmark]: """ Rearrange landmarks to group nearby visits together. @@ -116,10 +114,10 @@ class Refiner : while keeping 'start' and 'finish' landmarks in their original positions. Args: - tour (List[Landmark]): Ordered list of landmarks to be rearranged. + tour (list[Landmark]): Ordered list of landmarks to be rearranged. Returns: - List[Landmark]: The rearranged list of landmarks with grouped nearby visits. + list[Landmark]: The rearranged list of landmarks with grouped nearby visits. """ i = 1 @@ -137,7 +135,7 @@ class Refiner : return tour - def find_shortest_path_through_all_landmarks(self, landmarks: List[Landmark]) -> Tuple[List[Landmark], Polygon]: + def find_shortest_path_through_all_landmarks(self, landmarks: list[Landmark]) -> tuple[list[Landmark], Polygon]: """ Find the shortest path through all landmarks using a nearest neighbor heuristic. @@ -146,10 +144,10 @@ class Refiner : polygon representing the path. Args: - landmarks (List[Landmark]): List of all landmarks including 'start' and 'finish'. + landmarks (list[Landmark]): list of all landmarks including 'start' and 'finish'. Returns: - Tuple[List[Landmark], Polygon]: A tuple where the first element is the list of landmarks in the order they + tuple[list[Landmark], Polygon]: A tuple where the first element is the list of landmarks in the order they should be visited, and the second element is a `Polygon` representing the path connecting all landmarks. """ @@ -173,7 +171,7 @@ class Refiner : # Step 4: Use nearest neighbor heuristic to visit all landmarks while unvisited_landmarks: - nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time(current_landmark.location, lm.location)) + nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time_separation.get_time(current_landmark.location, lm.location)) path.append(nearest_landmark) coordinates.append(nearest_landmark.location) current_landmark = nearest_landmark @@ -189,7 +187,7 @@ class Refiner : # Returns a list of minor landmarks around the planned path to enhance experience - def get_minor_landmarks(self, all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] : + def get_minor_landmarks(self, all_landmarks: list[Landmark], visited_landmarks: list[Landmark], width: float) -> list[Landmark] : """ Identify landmarks within a specified corridor that have not been visited yet. @@ -197,12 +195,12 @@ class Refiner : within this corridor. It returns a list of these landmarks, excluding those already visited, sorted by their importance. Args: - all_landmarks (List[Landmark]): List of all available landmarks. - visited_landmarks (List[Landmark]): List of landmarks that have already been visited. + all_landmarks (list[Landmark]): list of all available landmarks. + visited_landmarks (list[Landmark]): list of landmarks that have already been visited. width (float): Width of the corridor around the visited landmarks. Returns: - List[Landmark]: List of important landmarks within the corridor that have not been visited yet. + list[Landmark]: list of important landmarks within the corridor that have not been visited yet. """ second_order_landmarks = [] @@ -216,11 +214,11 @@ class Refiner : if self.is_in_area(area, landmark.location) and landmark.name not in visited_names: second_order_landmarks.append(landmark) - return take_most_important(second_order_landmarks, len(visited_landmarks)) + return take_most_important.take_most_important(second_order_landmarks, len(visited_landmarks)) # Try fix the shortest path using shapely - def fix_using_polygon(self, tour: List[Landmark])-> List[Landmark] : + def fix_using_polygon(self, tour: list[Landmark])-> list[Landmark] : """ Improve the tour path using geometric methods to ensure it follows a more optimal shape. @@ -229,10 +227,10 @@ class Refiner : beginning. It also checks if the final polygon is simple and rearranges the tour if necessary. Args: - tour (List[Landmark]): List of landmarks representing the current tour path. + tour (list[Landmark]): list of landmarks representing the current tour path. Returns: - List[Landmark]: Refined list of landmarks in the order of visit to produce a better tour path. + list[Landmark]: Refined list of landmarks in the order of visit to produce a better tour path. """ coords = [] @@ -261,7 +259,7 @@ class Refiner : xs.reverse() ys.reverse() - better_tour = [] # List of ordered visit + better_tour = [] # list of ordered visit name_index = {} # Maps the name of a landmark to its index in the concave polygon # Loop through the polygon and generate the better (ordered) tour @@ -285,67 +283,58 @@ class Refiner : return better_tour - # Second stage of the optimization. Use linear programming again to refine the path - def refine_optimization(self, all_landmarks: List[Landmark], base_tour: List[Landmark]) -> List[Landmark] : + def refine_optimization( + self, + all_landmarks: list[Landmark], + base_tour: list[Landmark], + max_time: int, + detour: int + ) -> list[Landmark]: """ - Refine the initial tour path by considering additional minor landmarks and optimizing the path. + This is the second stage of the optimization. It refines the initial tour path by considering additional minor landmarks and optimizes the path. - This method evaluates the need for further optimization based on the initial tour. If a detour is required, it adds - minor landmarks around the initial predicted path and solves a new optimization problem to find a potentially better + This method evaluates the need for further optimization based on the initial tour. If a detour is required + it adds minor landmarks around the initial predicted path and solves a new optimization problem to find a potentially better tour. It then links the new tour and adjusts it using a nearest neighbor heuristic and polygon-based methods to ensure a valid path. The final tour is chosen based on the shortest distance. + Args: + all_landmarks (list[Landmark]): The full list of landmarks available for the optimization. + base_tour (list[Landmark]): The initial tour path to be refined. + max_time (int): The maximum time available for the tour in minutes. + detour (int): The maximum detour time allowed for the tour in minutes. Returns: - List[Landmark]: The refined list of landmarks representing the optimized tour path. + list[Landmark]: The refined list of landmarks representing the optimized tour path. """ # No need to refine if no detour is taken - # if detour == 0 : - if False : + if detour == 0: + return base_tour + + minor_landmarks = self.get_minor_landmarks(all_landmarks, base_tour, self.detour_corridor_width) + + self.logger.info(f"Using {len(minor_landmarks)} minor landmarks around the predicted path") + + # full set of visitable landmarks + full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) + full_set.append(base_tour[-1]) # add finish back + + # get a new tour + new_tour = self.optimizer.solve_optimization( + max_time = max_time + detour, + landmarks = full_set + ) + + if new_tour is None: + self.logger.warning("No solution found for the refined tour. Returning the initial tour.") new_tour = base_tour - - else : - minor_landmarks = self.get_minor_landmarks(all_landmarks, base_tour, 200) - self.logger.info(f"Using {len(minor_landmarks)} minor landmarks around the predicted path") - # full set of visitable landmarks - full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) - full_set.append(base_tour[-1]) # add finish back - - # get a new tour - optimizer = Optimizer(self.max_time + self.detour, full_set) - new_tour = optimizer.solve_optimization(hide_log=True) - - if new_tour is None : - new_tour = base_tour - - # Link the new tour - new_tour, new_dist = link_list_simple(new_tour) - - # If the tour contains only one landmark, return - if len(new_tour) < 4 : - return new_tour - # Find shortest path using the nearest neighbor heuristic better_tour, better_poly = self.find_shortest_path_through_all_landmarks(new_tour) # Fix the tour using Polygons if the path looks weird if base_tour[0].location == base_tour[-1].location and not better_poly.is_valid : better_tour = self.fix_using_polygon(better_tour) - - # Link the tour again - better_tour, better_dist = link_list_simple(better_tour) - - # Choose the better tour depending on walked distance - if new_dist < better_dist : - final_tour = new_tour - else : - final_tour = better_tour - - self.logger.info("Refined tour (result of second stage optimization): ") - optimizer.print_res(final_tour) - - return final_tour - + return better_tour diff --git a/backend/src/utils/take_most_important.py b/backend/src/utils/take_most_important.py new file mode 100644 index 0000000..b363add --- /dev/null +++ b/backend/src/utils/take_most_important.py @@ -0,0 +1,38 @@ +from structs.landmark import Landmark + +def take_most_important(landmarks: list[Landmark], N_important) -> list[Landmark] : + L = len(landmarks) + L_copy = [] + L_clean = [] + scores = [0]*len(landmarks) + names = [] + name_id = {} + + for i, elem in enumerate(landmarks) : + if elem.name not in names : + names.append(elem.name) + name_id[elem.name] = [i] + L_copy.append(elem) + else : + name_id[elem.name] += [i] + scores = [] + for j in name_id[elem.name] : + scores.append(L[j].attractiveness) + best_id = max(range(len(scores)), key=scores.__getitem__) + t = name_id[elem.name][best_id] + if t == i : + for old in L_copy : + if old.name == elem.name : + old.attractiveness = L[t].attractiveness + + scores = [0]*len(L_copy) + for i, elem in enumerate(L_copy) : + scores[i] = elem.attractiveness + + res = sorted(range(len(scores)), key = lambda sub: scores[sub])[-(N_important-L):] + + for i, elem in enumerate(L_copy) : + if i in res : + L_clean.append(elem) + + return L_clean From 2736a89f70433f9ee77c000e5c76192bc8dafb0b Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Fri, 26 Jul 2024 13:13:36 +0200 Subject: [PATCH 6/7] cleanup in view of docker builds --- .vscode/launch.json | 52 + backend/Dockerfile | 2 +- backend/Pipfile | 13 +- backend/Pipfile.lock | 696 +- backend/landmarks_Strasbourg.txt | 10082 ---------------------- backend/log_config.yaml | 34 + backend/src/constants.py | 19 +- backend/src/main.py | 4 +- backend/src/structs/linked_landmarks.py | 17 +- backend/src/tester.py | 17 +- backend/throttle.ctrl | 0 11 files changed, 809 insertions(+), 10127 deletions(-) create mode 100644 .vscode/launch.json delete mode 100644 backend/landmarks_Strasbourg.txt create mode 100644 backend/log_config.yaml delete mode 100644 backend/throttle.ctrl diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c0cf17a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,52 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + // backend - python using fastapi + { + "name": "Backend - debug", + "type": "debugpy", + "request": "launch", + "module": "uvicorn", + "env": { + "DEBUG": "true" + }, + "args": [ + "--app-dir", + "src", + "main:app", + "--reload", + ], + "jinja": true, + "cwd": "${workspaceFolder}/backend" + }, + { + "name": "Backend - tester", + "type": "debugpy", + "request": "launch", + "program": "src/tester.py", + "env": { + "DEBUG": "true" + }, + "cwd": "${workspaceFolder}/backend" + }, + // frontend - flutter app + { + "name": "Frontend - debug", + "type": "dart", + "request": "launch", + "program": "lib/main.dart", + "cwd": "${workspaceFolder}/frontend" + }, + { + "name": "Frontend - profile", + "type": "dart", + "request": "launch", + "program": "lib/main.dart", + "flutterMode": "profile", + "cwd": "${workspaceFolder}/frontend" + } + ] +} \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile index 9e15e47..b21b3c3 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -14,4 +14,4 @@ EXPOSE 8000 ENV NUM_WORKERS=1 ENV OSM_CACHE_DIR=/cache -CMD ["pipenv", "run", "fastapi", "run", "src/main.py", '--port 8000', '--workers $NUM_WORKERS'] +CMD ["fastapi", "run", "src/main.py", "--port 8000", "--workers $NUM_WORKERS"] diff --git a/backend/Pipfile b/backend/Pipfile index 4197132..c590ded 100644 --- a/backend/Pipfile +++ b/backend/Pipfile @@ -3,17 +3,14 @@ url = "https://pypi.org/simple" verify_ssl = true name = "pypi" +[dev-packages] + [packages] numpy = "*" -scipy = "*" fastapi = "*" pydantic = "*" -shapely = "*" -networkx = "*" geopy = "*" -requests = ">=2.20.1" -mwparserfromhell = ">=0.5.2" -packaging = "*" +shapely = "*" +scipy = "*" +osmpythontools = "*" pywikibot = "*" - -[dev-packages] diff --git a/backend/Pipfile.lock b/backend/Pipfile.lock index f6188cf..387fcbd 100644 --- a/backend/Pipfile.lock +++ b/backend/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6f1907b01627126d80ae688e9f2e32fc696d85f0cca3913f14fd5d26cb3ac2db" + "sha256": "f0de801038593d42d8b780d14c2c72bb4f5f5e66df02f72244917ede5d5ebce6" }, "pipfile-spec": 6, "requires": {}, @@ -30,6 +30,14 @@ "markers": "python_version >= '3.8'", "version": "==4.4.0" }, + "beautifulsoup4": { + "hashes": [ + "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", + "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed" + ], + "markers": "python_full_version >= '3.6.0'", + "version": "==4.12.3" + }, "certifi": { "hashes": [ "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b", @@ -142,6 +150,64 @@ "markers": "python_version >= '3.7'", "version": "==8.1.7" }, + "contourpy": { + "hashes": [ + "sha256:00e5388f71c1a0610e6fe56b5c44ab7ba14165cdd6d695429c5cd94021e390b2", + "sha256:10a37ae557aabf2509c79715cd20b62e4c7c28b8cd62dd7d99e5ed3ce28c3fd9", + "sha256:11959f0ce4a6f7b76ec578576a0b61a28bdc0696194b6347ba3f1c53827178b9", + "sha256:187fa1d4c6acc06adb0fae5544c59898ad781409e61a926ac7e84b8f276dcef4", + "sha256:1a07fc092a4088ee952ddae19a2b2a85757b923217b7eed584fdf25f53a6e7ce", + "sha256:1cac0a8f71a041aa587410424ad46dfa6a11f6149ceb219ce7dd48f6b02b87a7", + "sha256:1d59e739ab0e3520e62a26c60707cc3ab0365d2f8fecea74bfe4de72dc56388f", + "sha256:2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922", + "sha256:2e785e0f2ef0d567099b9ff92cbfb958d71c2d5b9259981cd9bee81bd194c9a4", + "sha256:309be79c0a354afff9ff7da4aaed7c3257e77edf6c1b448a779329431ee79d7e", + "sha256:39f3ecaf76cd98e802f094e0d4fbc6dc9c45a8d0c4d185f0f6c2234e14e5f75b", + "sha256:457499c79fa84593f22454bbd27670227874cd2ff5d6c84e60575c8b50a69619", + "sha256:49e70d111fee47284d9dd867c9bb9a7058a3c617274900780c43e38d90fe1205", + "sha256:4c75507d0a55378240f781599c30e7776674dbaf883a46d1c90f37e563453480", + "sha256:4c863140fafc615c14a4bf4efd0f4425c02230eb8ef02784c9a156461e62c965", + "sha256:4d8908b3bee1c889e547867ca4cdc54e5ab6be6d3e078556814a22457f49423c", + "sha256:5b9eb0ca724a241683c9685a484da9d35c872fd42756574a7cfbf58af26677fd", + "sha256:6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5", + "sha256:6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f", + "sha256:62828cada4a2b850dbef89c81f5a33741898b305db244904de418cc957ff05dc", + "sha256:7b4182299f251060996af5249c286bae9361fa8c6a9cda5efc29fe8bfd6062ec", + "sha256:94b34f32646ca0414237168d68a9157cb3889f06b096612afdd296003fdd32fd", + "sha256:9ce6889abac9a42afd07a562c2d6d4b2b7134f83f18571d859b25624a331c90b", + "sha256:9cffe0f850e89d7c0012a1fb8730f75edd4320a0a731ed0c183904fe6ecfc3a9", + "sha256:a12a813949e5066148712a0626895c26b2578874e4cc63160bb007e6df3436fe", + "sha256:a1eea9aecf761c661d096d39ed9026574de8adb2ae1c5bd7b33558af884fb2ce", + "sha256:a31f94983fecbac95e58388210427d68cd30fe8a36927980fab9c20062645609", + "sha256:ac58bdee53cbeba2ecad824fa8159493f0bf3b8ea4e93feb06c9a465d6c87da8", + "sha256:af3f4485884750dddd9c25cb7e3915d83c2db92488b38ccb77dd594eac84c4a0", + "sha256:b33d2bc4f69caedcd0a275329eb2198f560b325605810895627be5d4b876bf7f", + "sha256:b59c0ffceff8d4d3996a45f2bb6f4c207f94684a96bf3d9728dbb77428dd8cb8", + "sha256:bb6834cbd983b19f06908b45bfc2dad6ac9479ae04abe923a275b5f48f1a186b", + "sha256:bd3db01f59fdcbce5b22afad19e390260d6d0222f35a1023d9adc5690a889364", + "sha256:bd7c23df857d488f418439686d3b10ae2fbf9bc256cd045b37a8c16575ea1040", + "sha256:c2528d60e398c7c4c799d56f907664673a807635b857df18f7ae64d3e6ce2d9f", + "sha256:d31a63bc6e6d87f77d71e1abbd7387ab817a66733734883d1fc0021ed9bfa083", + "sha256:d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df", + "sha256:ddcb8581510311e13421b1f544403c16e901c4e8f09083c881fab2be80ee31ba", + "sha256:e1d59258c3c67c865435d8fbeb35f8c59b8bef3d6f46c1f29f6123556af28445", + "sha256:eb3315a8a236ee19b6df481fc5f997436e8ade24a9f03dfdc6bd490fea20c6da", + "sha256:ef2b055471c0eb466033760a521efb9d8a32b99ab907fc8358481a1dd29e3bd3", + "sha256:ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72", + "sha256:f32c38afb74bd98ce26de7cc74a67b40afb7b05aae7b42924ea990d51e4dac02", + "sha256:fe0ccca550bb8e5abc22f530ec0466136379c01321fd94f30a22231e8a48d985" + ], + "markers": "python_version >= '3.9'", + "version": "==1.2.1" + }, + "cycler": { + "hashes": [ + "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", + "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.1" + }, "dnspython": { "hashes": [ "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50", @@ -175,6 +241,54 @@ "markers": "python_version >= '3.8'", "version": "==0.0.4" }, + "fonttools": { + "hashes": [ + "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122", + "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397", + "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f", + "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d", + "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60", + "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169", + "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8", + "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31", + "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923", + "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2", + "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb", + "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab", + "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb", + "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a", + "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670", + "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8", + "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407", + "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671", + "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88", + "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f", + "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f", + "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0", + "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb", + "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2", + "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d", + "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c", + "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3", + "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719", + "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749", + "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4", + "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f", + "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02", + "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58", + "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1", + "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41", + "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4", + "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb", + "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb", + "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3", + "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d", + "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d", + "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2" + ], + "markers": "python_version >= '3.8'", + "version": "==4.53.1" + }, "geographiclib": { "hashes": [ "sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734", @@ -183,6 +297,14 @@ "markers": "python_version >= '3.7'", "version": "==2.0" }, + "geojson": { + "hashes": [ + "sha256:58a7fa40727ea058efc28b0e9ff0099eadf6d0965e04690830208d3ef571adac", + "sha256:68a9771827237adb8c0c71f8527509c8f5bef61733aa434cefc9c9d4f0ebe8f3" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.0" + }, "geopy": { "hashes": [ "sha256:50283d8e7ad07d89be5cb027338c6365a32044df3ae2556ad3f52f4840b3d0d1", @@ -273,6 +395,264 @@ "markers": "python_version >= '3.7'", "version": "==3.1.4" }, + "kiwisolver": { + "hashes": [ + "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf", + "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e", + "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af", + "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f", + "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046", + "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3", + "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5", + "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71", + "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee", + "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3", + "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9", + "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b", + "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985", + "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea", + "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16", + "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89", + "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c", + "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9", + "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712", + "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342", + "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a", + "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958", + "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d", + "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a", + "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130", + "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff", + "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898", + "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b", + "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f", + "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265", + "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93", + "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929", + "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635", + "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709", + "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b", + "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb", + "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a", + "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920", + "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e", + "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544", + "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45", + "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390", + "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77", + "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355", + "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff", + "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4", + "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7", + "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20", + "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c", + "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162", + "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228", + "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437", + "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc", + "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a", + "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901", + "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4", + "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770", + "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525", + "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad", + "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a", + "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29", + "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90", + "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250", + "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d", + "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3", + "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54", + "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f", + "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1", + "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da", + "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238", + "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa", + "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523", + "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0", + "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205", + "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3", + "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4", + "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac", + "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9", + "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb", + "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced", + "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd", + "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0", + "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da", + "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18", + "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9", + "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276", + "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333", + "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b", + "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db", + "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126", + "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9", + "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09", + "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0", + "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec", + "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7", + "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff", + "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9", + "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192", + "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8", + "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d", + "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6", + "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797", + "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892", + "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.4.5" + }, + "lxml": { + "hashes": [ + "sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3", + "sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a", + "sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0", + "sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b", + "sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f", + "sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6", + "sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73", + "sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d", + "sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad", + "sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b", + "sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a", + "sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5", + "sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab", + "sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316", + "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6", + "sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df", + "sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca", + "sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264", + "sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8", + "sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f", + "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b", + "sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3", + "sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5", + "sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed", + "sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab", + "sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5", + "sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726", + "sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d", + "sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632", + "sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706", + "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8", + "sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472", + "sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835", + "sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf", + "sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db", + "sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d", + "sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545", + "sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9", + "sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be", + "sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe", + "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905", + "sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438", + "sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db", + "sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776", + "sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c", + "sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed", + "sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd", + "sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484", + "sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d", + "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6", + "sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30", + "sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182", + "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61", + "sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425", + "sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb", + "sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1", + "sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511", + "sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e", + "sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207", + "sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b", + "sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585", + "sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56", + "sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391", + "sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85", + "sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147", + "sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18", + "sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1", + "sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa", + "sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48", + "sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3", + "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184", + "sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67", + "sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7", + "sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34", + "sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706", + "sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8", + "sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c", + "sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115", + "sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009", + "sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466", + "sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526", + "sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d", + "sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525", + "sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14", + "sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3", + "sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0", + "sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b", + "sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1", + "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f", + "sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf", + "sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf", + "sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0", + "sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b", + "sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff", + "sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88", + "sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2", + "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40", + "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716", + "sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2", + "sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2", + "sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a", + "sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734", + "sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87", + "sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48", + "sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36", + "sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b", + "sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07", + "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c", + "sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573", + "sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001", + "sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9", + "sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3", + "sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce", + "sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3", + "sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04", + "sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927", + "sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083", + "sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d", + "sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32", + "sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9", + "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f", + "sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2", + "sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c", + "sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d", + "sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393", + "sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8", + "sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6", + "sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66", + "sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5", + "sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97", + "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196", + "sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836", + "sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae", + "sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297", + "sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421", + "sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6", + "sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981", + "sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30", + "sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30", + "sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f", + "sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324", + "sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b" + ], + "markers": "python_version >= '3.6'", + "version": "==5.2.2" + }, "markdown-it-py": { "hashes": [ "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", @@ -347,6 +727,41 @@ "markers": "python_version >= '3.7'", "version": "==2.1.5" }, + "matplotlib": { + "hashes": [ + "sha256:0000354e32efcfd86bda75729716b92f5c2edd5b947200be9881f0a671565c33", + "sha256:0c584210c755ae921283d21d01f03a49ef46d1afa184134dd0f95b0202ee6f03", + "sha256:0e835c6988edc3d2d08794f73c323cc62483e13df0194719ecb0723b564e0b5c", + "sha256:0fc001516ffcf1a221beb51198b194d9230199d6842c540108e4ce109ac05cc0", + "sha256:11fed08f34fa682c2b792942f8902e7aefeed400da71f9e5816bea40a7ce28fe", + "sha256:208cbce658b72bf6a8e675058fbbf59f67814057ae78165d8a2f87c45b48d0ff", + "sha256:2315837485ca6188a4b632c5199900e28d33b481eb083663f6a44cfc8987ded3", + "sha256:26040c8f5121cd1ad712abffcd4b5222a8aec3a0fe40bc8542c94331deb8780d", + "sha256:3fda72d4d472e2ccd1be0e9ccb6bf0d2eaf635e7f8f51d737ed7e465ac020cb3", + "sha256:421851f4f57350bcf0811edd754a708d2275533e84f52f6760b740766c6747a7", + "sha256:44a21d922f78ce40435cb35b43dd7d573cf2a30138d5c4b709d19f00e3907fd7", + "sha256:4db17fea0ae3aceb8e9ac69c7e3051bae0b3d083bfec932240f9bf5d0197a049", + "sha256:565d572efea2b94f264dd86ef27919515aa6d629252a169b42ce5f570db7f37b", + "sha256:591d3a88903a30a6d23b040c1e44d1afdd0d778758d07110eb7596f811f31842", + "sha256:6d397fd8ccc64af2ec0af1f0efc3bacd745ebfb9d507f3f552e8adb689ed730a", + "sha256:7ccd6270066feb9a9d8e0705aa027f1ff39f354c72a87efe8fa07632f30fc6bb", + "sha256:82cd5acf8f3ef43f7532c2f230249720f5dc5dd40ecafaf1c60ac8200d46d7eb", + "sha256:83c6a792f1465d174c86d06f3ae85a8fe36e6f5964633ae8106312ec0921fdf5", + "sha256:84b3ba8429935a444f1fdc80ed930babbe06725bcf09fbeb5c8757a2cd74af04", + "sha256:a0c977c5c382f6696caf0bd277ef4f936da7e2aa202ff66cad5f0ac1428ee15b", + "sha256:a973c53ad0668c53e0ed76b27d2eeeae8799836fd0d0caaa4ecc66bf4e6676c0", + "sha256:ab38a4f3772523179b2f772103d8030215b318fef6360cb40558f585bf3d017f", + "sha256:b3fce58971b465e01b5c538f9d44915640c20ec5ff31346e963c9e1cd66fa812", + "sha256:b918770bf3e07845408716e5bbda17eadfc3fcbd9307dc67f37d6cf834bb3d98", + "sha256:d12cb1837cffaac087ad6b44399d5e22b78c729de3cdae4629e252067b705e2b", + "sha256:dc23f48ab630474264276be156d0d7710ac6c5a09648ccdf49fef9200d8cbe80", + "sha256:dd2a59ff4b83d33bca3b5ec58203cc65985367812cb8c257f3e101632be86d92", + "sha256:de06b19b8db95dd33d0dc17c926c7c9ebed9f572074b6fac4f65068a6814d010", + "sha256:f1f2e5d29e9435c97ad4c36fb6668e89aee13d48c75893e25cef064675038ac9" + ], + "markers": "python_version >= '3.9'", + "version": "==3.9.1" + }, "mdurl": { "hashes": [ "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", @@ -384,19 +799,9 @@ "sha256:fd05481adc0806f4b8f8f8cb309ec56924b17ce386cb1c2f73919d8a012e6b16", "sha256:fff66e97f7c02aa0fd57ff8f702977a9c5a1d72ef55b64ee9b146291e4c41057" ], - "index": "pypi", "markers": "python_version >= '3.8'", "version": "==0.6.6" }, - "networkx": { - "hashes": [ - "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9", - "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==3.3" - }, "numpy": { "hashes": [ "sha256:08458fbf403bff5e2b45f08eda195d4b0c9b35682311da5a5a0a0925b11b9bd8", @@ -449,15 +854,142 @@ "markers": "python_version >= '3.9'", "version": "==2.0.1" }, + "osmpythontools": { + "hashes": [ + "sha256:13ff721f760fdad5dd78b4d1461d286b78bba96ee151a7301ee8c11a0c258be9" + ], + "index": "pypi", + "version": "==0.3.5" + }, "packaging": { "hashes": [ "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "index": "pypi", "markers": "python_version >= '3.8'", "version": "==24.1" }, + "pandas": { + "hashes": [ + "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863", + "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2", + "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1", + "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad", + "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db", + "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76", + "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51", + "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32", + "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08", + "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b", + "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4", + "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921", + "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288", + "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee", + "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0", + "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24", + "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99", + "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151", + "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd", + "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce", + "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57", + "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef", + "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54", + "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a", + "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238", + "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23", + "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772", + "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce", + "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad" + ], + "markers": "python_version >= '3.9'", + "version": "==2.2.2" + }, + "pillow": { + "hashes": [ + "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", + "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", + "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df", + "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", + "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", + "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d", + "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd", + "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", + "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908", + "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", + "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", + "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", + "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b", + "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", + "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a", + "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e", + "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", + "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", + "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b", + "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", + "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", + "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab", + "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d", + "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", + "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", + "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", + "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4", + "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", + "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", + "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", + "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", + "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b", + "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", + "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0", + "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", + "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", + "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856", + "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef", + "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680", + "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b", + "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", + "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e", + "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", + "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", + "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8", + "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", + "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736", + "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da", + "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126", + "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd", + "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5", + "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b", + "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026", + "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b", + "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc", + "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46", + "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2", + "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c", + "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", + "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984", + "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", + "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", + "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", + "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b", + "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", + "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3", + "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84", + "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1", + "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5", + "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", + "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f", + "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", + "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", + "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e", + "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141", + "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", + "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", + "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27", + "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e", + "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1" + ], + "markers": "python_version >= '3.8'", + "version": "==10.4.0" + }, "pydantic": { "hashes": [ "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a", @@ -570,6 +1102,22 @@ "markers": "python_version >= '3.8'", "version": "==2.18.0" }, + "pyparsing": { + "hashes": [ + "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad", + "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742" + ], + "markers": "python_full_version >= '3.6.8'", + "version": "==3.1.2" + }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.0.post0" + }, "python-dotenv": { "hashes": [ "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", @@ -585,6 +1133,13 @@ "markers": "python_version >= '3.8'", "version": "==0.0.9" }, + "pytz": { + "hashes": [ + "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812", + "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319" + ], + "version": "==2024.1" + }, "pywikibot": { "hashes": [ "sha256:3f4fbc57f1765aa0fa1ccf84125bcfa475cae95b9cc0291867b751f3d4ac8fa2", @@ -655,7 +1210,6 @@ "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" ], - "index": "pypi", "markers": "python_version >= '3.8'", "version": "==2.32.3" }, @@ -750,6 +1304,14 @@ "markers": "python_version >= '3.7'", "version": "==1.5.4" }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, "sniffio": { "hashes": [ "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", @@ -758,6 +1320,14 @@ "markers": "python_version >= '3.7'", "version": "==1.3.1" }, + "soupsieve": { + "hashes": [ + "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", + "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5" + }, "starlette": { "hashes": [ "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee", @@ -782,6 +1352,98 @@ "markers": "python_version >= '3.8'", "version": "==4.12.2" }, + "tzdata": { + "hashes": [ + "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd", + "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252" + ], + "markers": "python_version >= '2'", + "version": "==2024.1" + }, + "ujson": { + "hashes": [ + "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e", + "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b", + "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6", + "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7", + "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9", + "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd", + "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569", + "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f", + "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51", + "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", + "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1", + "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf", + "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", + "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", + "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a", + "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", + "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27", + "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", + "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126", + "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1", + "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", + "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64", + "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8", + "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", + "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", + "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3", + "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb", + "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", + "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", + "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", + "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", + "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", + "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d", + "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd", + "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0", + "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337", + "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753", + "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804", + "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f", + "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f", + "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5", + "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", + "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1", + "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00", + "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", + "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050", + "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", + "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4", + "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8", + "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996", + "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6", + "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", + "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", + "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1", + "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4", + "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b", + "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88", + "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518", + "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5", + "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770", + "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4", + "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a", + "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76", + "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe", + "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", + "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1", + "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5", + "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b", + "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7", + "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8", + "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc", + "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a", + "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720", + "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", + "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b", + "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9", + "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", + "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746" + ], + "markers": "python_version >= '3.8'", + "version": "==5.10.0" + }, "urllib3": { "hashes": [ "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", @@ -993,6 +1655,14 @@ "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7" ], "version": "==12.0" + }, + "xarray": { + "hashes": [ + "sha256:0b91e0bc4dc0296947947640fe31ec6e867ce258d2f7cbc10bedf4a6d68340c7", + "sha256:721a7394e8ec3d592b2d8ebe21eed074ac077dc1bb1bd777ce00e41700b4866c" + ], + "markers": "python_version >= '3.9'", + "version": "==2024.6.0" } }, "develop": {} diff --git a/backend/landmarks_Strasbourg.txt b/backend/landmarks_Strasbourg.txt deleted file mode 100644 index d97fb8e..0000000 --- a/backend/landmarks_Strasbourg.txt +++ /dev/null @@ -1,10082 +0,0 @@ -{ - "0":{ - "name":"Musée de Sismologie et de Magnétisme Terrestre", - "type":"sightseeing", - "location":[ - 48.5839194, - 7.7656424 - ], - "osm_type":"way", - "osm_id":19794129, - "attractiveness":377, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9f0ed68d-f891-4e0a-8909-90a68e735721", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "1":{ - "name":"Jardin Botanique", - "type":"sightseeing", - "location":[ - 48.583626, - 7.7674616 - ], - "osm_type":"way", - "osm_id":19794224, - "attractiveness":569, - "n_tags":28, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bed47635-ec34-4528-bc21-235c4baf704d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "2":{ - "name":"Musée Historique", - "type":"sightseeing", - "location":[ - 48.5799461, - 7.7509819 - ], - "osm_type":"way", - "osm_id":22290183, - "attractiveness":478, - "n_tags":22, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7411ca05-62cb-42cd-9e04-ac5b7d1a8331", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "3":{ - "name":"Hôtel Mercure Strasbourg Palais des Congrès", - "type":"sightseeing", - "location":[ - 48.5960489, - 7.7580283 - ], - "osm_type":"way", - "osm_id":30923000, - "attractiveness":360, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1b573626-90fa-483d-9c78-48177c135714", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "4":{ - "name":"Hilton Strasbourg", - "type":"sightseeing", - "location":[ - 48.5970002, - 7.7547885 - ], - "osm_type":"way", - "osm_id":36526595, - "attractiveness":613, - "n_tags":30, - "image_url":null, - "description":null, - "duration":0, - "uuid":"16cec4ba-5087-4a86-bddd-4100b0616121", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "5":{ - "name":"Hôtel Suisse", - "type":"sightseeing", - "location":[ - 48.5814183, - 7.7528353 - ], - "osm_type":"way", - "osm_id":39654584, - "attractiveness":128, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a5d5ee89-d757-4728-a0c1-48814f3c0359", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "6":{ - "name":"Hôtel des Anges", - "type":"sightseeing", - "location":[ - 48.5809838, - 7.7494255 - ], - "osm_type":"way", - "osm_id":39855264, - "attractiveness":142, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5e607860-da76-4ea4-bfce-db4888919601", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "7":{ - "name":"Le Bouclier d'Or", - "type":"sightseeing", - "location":[ - 48.5806972, - 7.7436528 - ], - "osm_type":"way", - "osm_id":40019705, - "attractiveness":205, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dfd97548-6649-41a0-9d24-79b03fd7d67b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "8":{ - "name":"Cap Europe Appart'Hotel", - "type":"sightseeing", - "location":[ - 48.5913017, - 7.7535828 - ], - "osm_type":"way", - "osm_id":40030093, - "attractiveness":154, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"52bc59ca-22af-4666-8a64-20d0e255d880", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "9":{ - "name":"Best Western Hotel de l'Europe", - "type":"sightseeing", - "location":[ - 48.5821218, - 7.7428648 - ], - "osm_type":"way", - "osm_id":40108131, - "attractiveness":385, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7fee251b-a074-4831-a0a0-dec4a3c46b83", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "10":{ - "name":"BOMA", - "type":"sightseeing", - "location":[ - 48.583182, - 7.7417657 - ], - "osm_type":"way", - "osm_id":40108706, - "attractiveness":408, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bdd36f26-b30a-4c03-b746-e4ff973e8b2b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "11":{ - "name":"Barrage Vauban", - "type":"sightseeing", - "location":[ - 48.5795997, - 7.7380036 - ], - "osm_type":"way", - "osm_id":40217747, - "attractiveness":569, - "n_tags":24, - "image_url":null, - "description":null, - "duration":0, - "uuid":"615d0fb2-bd80-45e2-a3f2-6e9b56bdad3f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "12":{ - "name":"Musée d'Art Moderne et Contemporain", - "type":"sightseeing", - "location":[ - 48.5794732, - 7.7361604 - ], - "osm_type":"way", - "osm_id":40220422, - "attractiveness":494, - "n_tags":24, - "image_url":null, - "description":null, - "duration":0, - "uuid":"03715222-b85a-4cab-a19b-179f87be60f5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "13":{ - "name":"Ibis", - "type":"sightseeing", - "location":[ - 48.5784497, - 7.7354765 - ], - "osm_type":"way", - "osm_id":40222088, - "attractiveness":406, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9f1df5e2-1234-49da-a408-4ec917d31cce", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "14":{ - "name":"Hôtel du Dragon", - "type":"sightseeing", - "location":[ - 48.5779452, - 7.7464212 - ], - "osm_type":"way", - "osm_id":40379769, - "attractiveness":189, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"05b748ae-3bdb-41bb-9c4b-842017a48a02", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "15":{ - "name":"Institut de Botanique", - "type":"sightseeing", - "location":[ - 48.5840035, - 7.7667973 - ], - "osm_type":"way", - "osm_id":40818707, - "attractiveness":194, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ea3ed3d8-eb86-4b35-a8b9-72163b21403c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "16":{ - "name":"Hôtel des Vosges", - "type":"sightseeing", - "location":[ - 48.5837881, - 7.7352689 - ], - "osm_type":"way", - "osm_id":41121009, - "attractiveness":321, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5e6e4d99-eb88-4133-a462-37ab43d4390a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "17":{ - "name":"Hôtel Vendôme", - "type":"sightseeing", - "location":[ - 48.5840959, - 7.7363994 - ], - "osm_type":"way", - "osm_id":41123371, - "attractiveness":217, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"44ff2689-0ce8-4fe1-9edf-4b1e8bce1413", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "18":{ - "name":"Hôtel Victoria", - "type":"sightseeing", - "location":[ - 48.5838141, - 7.7372317 - ], - "osm_type":"way", - "osm_id":41123377, - "attractiveness":204, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7f8cf024-0833-4c33-988b-07e4483b72f5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "19":{ - "name":"Le Grand Hôtel", - "type":"sightseeing", - "location":[ - 48.5847157, - 7.7369134 - ], - "osm_type":"way", - "osm_id":41123900, - "attractiveness":206, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d8f8b313-0c62-47f6-aa2f-890fa87fbc8b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "20":{ - "name":"Hôtel Monopole Métropole", - "type":"sightseeing", - "location":[ - 48.5851187, - 7.7390396 - ], - "osm_type":"way", - "osm_id":41135600, - "attractiveness":165, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"296e4c66-7cd9-45c4-9c89-6add97eeb9e5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "21":{ - "name":"Odalys Appart'Hôtel Green Marsh", - "type":"sightseeing", - "location":[ - 48.5866791, - 7.7400733 - ], - "osm_type":"way", - "osm_id":41140005, - "attractiveness":217, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"64d72e1f-63d3-4861-9660-00abec787175", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "22":{ - "name":"Hôtel Athena", - "type":"sightseeing", - "location":[ - 48.5917916, - 7.7114199 - ], - "osm_type":"way", - "osm_id":41735108, - "attractiveness":207, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e83925cc-3415-4f86-b8bf-154cfe95b767", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "23":{ - "name":"Campanile Strasbourg Ouest", - "type":"sightseeing", - "location":[ - 48.5886845, - 7.7001986 - ], - "osm_type":"way", - "osm_id":41959958, - "attractiveness":252, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"96000a19-eac7-4494-95b0-b7a945471023", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "24":{ - "name":"Hôtel Arc-en-Ciel", - "type":"sightseeing", - "location":[ - 48.57885, - 7.7175826 - ], - "osm_type":"way", - "osm_id":42411650, - "attractiveness":130, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"11c7557a-5134-49c7-b986-6ab74d7e19df", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "25":{ - "name":"Camping de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5751089, - 7.7164414 - ], - "osm_type":"way", - "osm_id":49805933, - "attractiveness":447, - "n_tags":22, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cb06ebb6-d7fd-4065-917b-9a7999b7a3d4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "26":{ - "name":"Petit Cabinet", - "type":"sightseeing", - "location":[ - 48.5869361, - 7.746716 - ], - "osm_type":"way", - "osm_id":183655704, - "attractiveness":168, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3d5c9b13-597b-4995-adc2-43adb3c39f6c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "27":{ - "name":"Grande Île", - "type":"sightseeing", - "location":[ - 48.5829351, - 7.747696 - ], - "osm_type":"way", - "osm_id":217834967, - "attractiveness":413, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c1302da0-bbb7-4c06-8b67-fa6c4b8c3b7e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "28":{ - "name":"Musée Tomi Ungerer Centre International de l'Illustration", - "type":"sightseeing", - "location":[ - 48.585689, - 7.7550092 - ], - "osm_type":"way", - "osm_id":486650189, - "attractiveness":339, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"206cb9b5-a593-4512-9ad2-40f33fb9dfcc", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "29":{ - "name":"Musée de l'Œuvre Notre-Dame", - "type":"sightseeing", - "location":[ - 48.580867, - 7.751182 - ], - "osm_type":"way", - "osm_id":491674514, - "attractiveness":278, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8cde4028-ed83-4f45-9409-77bf4291ee06", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "30":{ - "name":"K Hôtel", - "type":"sightseeing", - "location":[ - 48.5939733, - 7.7136948 - ], - "osm_type":"way", - "osm_id":693583859, - "attractiveness":130, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6c28ce78-44a0-42bb-97a5-4803e289f85d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "31":{ - "name":"Aloft", - "type":"sightseeing", - "location":[ - 48.572935, - 7.7560101 - ], - "osm_type":"way", - "osm_id":725969144, - "attractiveness":417, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"127dbef5-3b84-475b-9dc5-c825d76a13ae", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "32":{ - "name":"Citadines Eurométropole Strasbourg", - "type":"sightseeing", - "location":[ - 48.604241, - 7.7045715 - ], - "osm_type":"way", - "osm_id":939510639, - "attractiveness":204, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"922aec12-5f43-4552-a7bc-21bd14b515f3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "33":{ - "name":"The People – Strasbourg", - "type":"sightseeing", - "location":[ - 48.581353, - 7.7575867 - ], - "osm_type":"way", - "osm_id":1053292872, - "attractiveness":407, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"223241d2-9a0a-4ef2-ace3-dfb793111952", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "34":{ - "name":"Cabinet des Estampes et des Dessins", - "type":"sightseeing", - "location":[ - 48.5810219, - 7.7507074 - ], - "osm_type":"relation", - "osm_id":222359, - "attractiveness":301, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5d08c61b-0719-4e5c-931d-4532c005be09", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "35":{ - "name":"Cathédrale Notre-Dame", - "type":"sightseeing", - "location":[ - 48.5818887, - 7.7510342 - ], - "osm_type":"relation", - "osm_id":3541088, - "attractiveness":961, - "n_tags":35, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dd630831-06b4-46a8-9cd9-8c87c017c031", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "36":{ - "name":"Circuit « Petite France »", - "type":"sightseeing", - "location":[ - 48.5807382, - 7.7450251 - ], - "osm_type":"relation", - "osm_id":5354622, - "attractiveness":423, - "n_tags":21, - "image_url":null, - "description":null, - "duration":0, - "uuid":"34b5efa9-cbb6-4986-9afa-30f48a919483", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "37":{ - "name":"De la Grande île à la Neustadt", - "type":"sightseeing", - "location":[ - 48.5849416, - 7.7539938 - ], - "osm_type":"relation", - "osm_id":16782493, - "attractiveness":432, - "n_tags":21, - "image_url":null, - "description":null, - "duration":0, - "uuid":"59ca33d2-05f3-49dc-a322-cc75245dbcf5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "38":{ - "name":"Palais Rohan", - "type":"sightseeing", - "location":[ - 48.5810157, - 7.7522537 - ], - "osm_type":"way", - "osm_id":15806990, - "attractiveness":261, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ff50c6b5-83c3-4ad5-8b92-efebeb986447", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "39":{ - "name":"Monument du Général Kléber", - "type":"sightseeing", - "location":[ - 48.5833724, - 7.7457745 - ], - "osm_type":"way", - "osm_id":39224822, - "attractiveness":262, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e9af0669-5937-49ab-a0d8-ea1147f629e6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "40":{ - "name":"Grand Séminaire Catholique", - "type":"sightseeing", - "location":[ - 48.5823972, - 7.7521116 - ], - "osm_type":"way", - "osm_id":39647774, - "attractiveness":108, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e7499242-8469-4c52-a1cb-4e4bbad7e86b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "41":{ - "name":"Tour du Bourreau", - "type":"sightseeing", - "location":[ - 48.5814532, - 7.7387351 - ], - "osm_type":"way", - "osm_id":40034170, - "attractiveness":265, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2587a519-c75b-4965-9bc5-aadf231486a1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "42":{ - "name":"Église Catholique Saint-Jean-Baptiste", - "type":"sightseeing", - "location":[ - 48.584387, - 7.7400892 - ], - "osm_type":"way", - "osm_id":40202919, - "attractiveness":396, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c1663d50-875d-4d21-a748-fd7c66c36dcf", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "43":{ - "name":"Heinrichsturm", - "type":"sightseeing", - "location":[ - 48.5802849, - 7.7390529 - ], - "osm_type":"way", - "osm_id":40217739, - "attractiveness":266, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"27845ee8-3f67-4357-9492-5af2e107255f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "44":{ - "name":"Hans von Altheimturm", - "type":"sightseeing", - "location":[ - 48.5798164, - 7.7393752 - ], - "osm_type":"way", - "osm_id":40217740, - "attractiveness":264, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5af48fb0-d564-42fa-a82b-d33af353511d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "45":{ - "name":"Tour des Français", - "type":"sightseeing", - "location":[ - 48.5793988, - 7.7396847 - ], - "osm_type":"way", - "osm_id":40217762, - "attractiveness":281, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"98b4c760-5cd0-458b-b292-a6ac5805d0b7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "46":{ - "name":"Porte de l'Hôpital", - "type":"sightseeing", - "location":[ - 48.5770255, - 7.7495671 - ], - "osm_type":"way", - "osm_id":40317901, - "attractiveness":340, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"987e083f-a93e-4c3d-8449-c6dd368731f6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "47":{ - "name":"Bains municipaux de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5833343, - 7.7595517 - ], - "osm_type":"way", - "osm_id":40469009, - "attractiveness":507, - "n_tags":25, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7c3a9e85-0b3e-44c3-8b10-10c5c0872e1c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "48":{ - "name":"Bains Médicinaux", - "type":"sightseeing", - "location":[ - 48.5834571, - 7.7603718 - ], - "osm_type":"way", - "osm_id":40469010, - "attractiveness":229, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a1c028b7-aa6d-454c-928f-ea800d0b9d51", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "49":{ - "name":"Église protestante Sainte-Aurélie", - "type":"sightseeing", - "location":[ - 48.581415, - 7.7332719 - ], - "osm_type":"way", - "osm_id":40981668, - "attractiveness":338, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5ca68982-ca85-4760-97bc-a7b817174518", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "50":{ - "name":"Ponts Couverts", - "type":"sightseeing", - "location":[ - 48.5800883, - 7.739337 - ], - "osm_type":"way", - "osm_id":416477168, - "attractiveness":284, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"51b30ff9-f05f-4664-896f-ace4944b4d78", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "51":{ - "name":"Pont Saint-Nicolas", - "type":"sightseeing", - "location":[ - 48.5787541, - 7.7485761 - ], - "osm_type":"way", - "osm_id":458914503, - "attractiveness":356, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2dd42bd5-8613-4db6-8f89-84efa594f8ae", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "52":{ - "name":"Tour du Schlössel", - "type":"sightseeing", - "location":[ - 48.5765199, - 7.7143364 - ], - "osm_type":"way", - "osm_id":944755351, - "attractiveness":242, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"506019a0-94de-4d24-9b4c-6696bd8e5e88", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "53":{ - "name":"Palais du Rhin", - "type":"sightseeing", - "location":[ - 48.5876327, - 7.7525605 - ], - "osm_type":"relation", - "osm_id":226986, - "attractiveness":693, - "n_tags":33, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9c3fb97e-de75-45cc-91e8-a4d4ee166d35", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "54":{ - "name":"Faculté de Chimie", - "type":"sightseeing", - "location":[ - 48.5808057, - 7.7675818 - ], - "osm_type":"way", - "osm_id":13864892, - "attractiveness":134, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7ff61c6a-47eb-4451-8b06-6d18f8f7cf4d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "55":{ - "name":"Faculté de Droit", - "type":"sightseeing", - "location":[ - 48.5789616, - 7.7673966 - ], - "osm_type":"way", - "osm_id":13864895, - "attractiveness":359, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eb55796d-8d08-495f-9e4e-b3a8fc33a5de", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "56":{ - "name":"Théâtre National de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5863674, - 7.7553605 - ], - "osm_type":"way", - "osm_id":15726858, - "attractiveness":377, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a4b50aa3-3866-456f-aee6-9f044f5d7357", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "57":{ - "name":"Arte", - "type":"sightseeing", - "location":[ - 48.5939554, - 7.7659797 - ], - "osm_type":"way", - "osm_id":18882357, - "attractiveness":392, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"14de4719-7d71-46a0-ab44-d4d74b06ba60", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "58":{ - "name":"Faculté de Philosophie", - "type":"sightseeing", - "location":[ - 48.5835896, - 7.7653134 - ], - "osm_type":"way", - "osm_id":19794090, - "attractiveness":111, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f0e39279-f6ab-4b40-b75d-5a8f9e561a5c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "59":{ - "name":"Institut Le Bel", - "type":"sightseeing", - "location":[ - 48.5806815, - 7.7662739 - ], - "osm_type":"way", - "osm_id":19794506, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7775dd47-73cd-47a6-bc59-e68f80a28987", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "60":{ - "name":"Restaurant Universitaire de l'Esplanade", - "type":"sightseeing", - "location":[ - 48.5816703, - 7.765895 - ], - "osm_type":"way", - "osm_id":19794529, - "attractiveness":105, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"af217de4-89cb-49c8-8a89-c6fc5c730494", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "61":{ - "name":"Institut de Physiologie et Chimie Biologique", - "type":"sightseeing", - "location":[ - 48.5797337, - 7.7657748 - ], - "osm_type":"way", - "osm_id":19794641, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"89a827de-5496-4c6a-bd19-b584858435f1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "62":{ - "name":"Institut de Biologie Moléculaire et Cellulaire", - "type":"sightseeing", - "location":[ - 48.5796264, - 7.7647679 - ], - "osm_type":"way", - "osm_id":19794665, - "attractiveness":121, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"74efed29-c7dd-47bd-984d-cbb027c35ec0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "63":{ - "name":"Institut de Science et d'Ingénierie Supramoléculaires", - "type":"sightseeing", - "location":[ - 48.5804265, - 7.7644021 - ], - "osm_type":"way", - "osm_id":19794670, - "attractiveness":199, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3c21ce48-325a-4b79-992c-9092d66b75d2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "64":{ - "name":"Centre de culture numérique", - "type":"sightseeing", - "location":[ - 48.5784977, - 7.7636069 - ], - "osm_type":"way", - "osm_id":19794752, - "attractiveness":231, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2f8d2e80-d73c-41b9-ac94-da358af78ae4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "65":{ - "name":"Escarpe", - "type":"sightseeing", - "location":[ - 48.5785033, - 7.7618452 - ], - "osm_type":"way", - "osm_id":19794775, - "attractiveness":130, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ceb0af82-7ba8-486e-a1e3-a9aeca418645", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "66":{ - "name":"L'Alinéa", - "type":"sightseeing", - "location":[ - 48.5790396, - 7.7620889 - ], - "osm_type":"way", - "osm_id":19794794, - "attractiveness":157, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"10274e35-1a17-49f5-a513-81ba0e990610", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "67":{ - "name":"Le Portique (Facultés : Arts, Lettres, STAPS et Direction du numérique)", - "type":"sightseeing", - "location":[ - 48.5783754, - 7.7626347 - ], - "osm_type":"way", - "osm_id":19794805, - "attractiveness":230, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"49570454-bdc9-4d53-afad-7dcd4209985e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "68":{ - "name":"Parking France 3", - "type":"sightseeing", - "location":[ - 48.5943751, - 7.7589818 - ], - "osm_type":"way", - "osm_id":19798679, - "attractiveness":120, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ac857c13-5696-4bf4-8002-cd1b57120ccd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "69":{ - "name":"Bourse", - "type":"sightseeing", - "location":[ - 48.5759064, - 7.7537168 - ], - "osm_type":"way", - "osm_id":20211705, - "attractiveness":151, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7195c3cd-b50d-427b-8ab7-adadb68c27ec", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "70":{ - "name":"Collège et Lycée Kléber", - "type":"sightseeing", - "location":[ - 48.5949669, - 7.7548434 - ], - "osm_type":"way", - "osm_id":20350865, - "attractiveness":90, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a9c9d65c-9d53-4f1b-9b6d-58cfe45e406a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "71":{ - "name":"Collège Sophie Germain", - "type":"sightseeing", - "location":[ - 48.601044, - 7.7190318 - ], - "osm_type":"way", - "osm_id":23291903, - "attractiveness":92, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f5c24ec4-b28a-43b1-a1ef-008e4aee8083", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "72":{ - "name":"Groupe Scolaire Gustave Doré", - "type":"sightseeing", - "location":[ - 48.5986753, - 7.7122322 - ], - "osm_type":"way", - "osm_id":23297801, - "attractiveness":95, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c4b5f4eb-32b7-4880-bb1c-5d56a30265ee", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "73":{ - "name":"Écoles Maternelles et Élémentaires Paul Langenvin 1 et 2", - "type":"sightseeing", - "location":[ - 48.6034985, - 7.716368 - ], - "osm_type":"way", - "osm_id":23312573, - "attractiveness":94, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"79e92d6b-b570-47be-b5be-ca32ca3f1ee9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "74":{ - "name":"Médiathèque de Neudorf", - "type":"sightseeing", - "location":[ - 48.5667916, - 7.7604529 - ], - "osm_type":"way", - "osm_id":23887731, - "attractiveness":313, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fe6fcdef-bddb-4caa-9c55-7bb875fedc04", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "75":{ - "name":"Place du Marché - Neudorf", - "type":"sightseeing", - "location":[ - 48.5661482, - 7.7598405 - ], - "osm_type":"way", - "osm_id":23887733, - "attractiveness":182, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dad35feb-b508-400e-9f26-bc00a51cf6a9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "76":{ - "name":"Groupement Scolaire du Neufeld", - "type":"sightseeing", - "location":[ - 48.5660134, - 7.75528 - ], - "osm_type":"way", - "osm_id":23887737, - "attractiveness":62, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"29be1355-690d-410a-92c1-def996903660", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "77":{ - "name":"École de la Musau", - "type":"sightseeing", - "location":[ - 48.5680318, - 7.7671475 - ], - "osm_type":"way", - "osm_id":24304030, - "attractiveness":88, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c0acb105-11ec-4b7d-b75a-d3e7c470aeab", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "78":{ - "name":"Place Saint-Aloïse", - "type":"sightseeing", - "location":[ - 48.5643934, - 7.7613271 - ], - "osm_type":"way", - "osm_id":24305747, - "attractiveness":135, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"09d49edc-750f-4e61-a118-1d2318b64802", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "79":{ - "name":"Schluthfeld", - "type":"sightseeing", - "location":[ - 48.5684604, - 7.7521982 - ], - "osm_type":"way", - "osm_id":24513151, - "attractiveness":177, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"daeaf610-b780-46ff-be1b-829aea90b8c4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "80":{ - "name":"Collège privé École Libre Sainte-Anne", - "type":"sightseeing", - "location":[ - 48.5636411, - 7.7607111 - ], - "osm_type":"way", - "osm_id":24805838, - "attractiveness":131, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"82022706-490c-42f7-8fc2-bf59fb4cea4e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "81":{ - "name":"École du Schluthfeld", - "type":"sightseeing", - "location":[ - 48.5678645, - 7.7491983 - ], - "osm_type":"way", - "osm_id":24909940, - "attractiveness":86, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b6ece52e-f3f9-4c78-aea3-5c45ab4f1024", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "82":{ - "name":"Station", - "type":"sightseeing", - "location":[ - 48.5656626, - 7.7515126 - ], - "osm_type":"way", - "osm_id":24909962, - "attractiveness":112, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ff00d333-26d5-4c00-ab83-de7f9356f657", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "83":{ - "name":"Rue Murillo", - "type":"sightseeing", - "location":[ - 48.5694085, - 7.7254854 - ], - "osm_type":"way", - "osm_id":25806363, - "attractiveness":133, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4e67ae72-69f0-4d53-bd2c-7e9380b311c8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "84":{ - "name":"Médiathèque André Malraux", - "type":"sightseeing", - "location":[ - 48.5743688, - 7.7603277 - ], - "osm_type":"way", - "osm_id":26199271, - "attractiveness":503, - "n_tags":25, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a06a2062-aeec-4670-8026-7613da783ac3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "85":{ - "name":"Cité de la Musique et de la Danse", - "type":"sightseeing", - "location":[ - 48.5743496, - 7.7558309 - ], - "osm_type":"way", - "osm_id":26199286, - "attractiveness":443, - "n_tags":22, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b0536c30-e21f-4d07-8d53-1b0fc6a86f06", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "86":{ - "name":"Hôtel de Ville", - "type":"sightseeing", - "location":[ - 48.5846612, - 7.7506403 - ], - "osm_type":"way", - "osm_id":26306273, - "attractiveness":518, - "n_tags":24, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3a18b2e1-4492-4b83-989f-a42d4e80473f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "87":{ - "name":"Place du Petit Broglie", - "type":"sightseeing", - "location":[ - 48.5856807, - 7.7525991 - ], - "osm_type":"way", - "osm_id":26306276, - "attractiveness":139, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c88b6d75-e648-486f-b83a-40d3aeb956d9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "88":{ - "name":"Gare Routière des Halles", - "type":"sightseeing", - "location":[ - 48.5874507, - 7.7414787 - ], - "osm_type":"way", - "osm_id":26323668, - "attractiveness":161, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"45a1f47c-5b4b-4c34-a626-456bee983735", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "89":{ - "name":"Institut de Recherches Mathématiques Avancées", - "type":"sightseeing", - "location":[ - 48.5804485, - 7.7627777 - ], - "osm_type":"way", - "osm_id":26497260, - "attractiveness":126, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2c260555-1d44-46f8-9ee6-afa4d97552ea", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "90":{ - "name":"Parking relais-tram P+R Elsau", - "type":"sightseeing", - "location":[ - 48.5683182, - 7.729944 - ], - "osm_type":"way", - "osm_id":30548950, - "attractiveness":175, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"72c7183c-46b6-4c2f-98ab-a187d6cf44dd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "91":{ - "name":"Église Saint-Étienne", - "type":"sightseeing", - "location":[ - 48.5834519, - 7.7558552 - ], - "osm_type":"way", - "osm_id":30922600, - "attractiveness":341, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f91a48e3-a996-4a26-8a05-831a2332efd0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "92":{ - "name":"Palais de la Musique et des Congrès", - "type":"sightseeing", - "location":[ - 48.5981089, - 7.7571462 - ], - "osm_type":"way", - "osm_id":30922996, - "attractiveness":144, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f79ca431-6a49-4fa1-bfee-74d28b362534", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "93":{ - "name":"Place du Faubourg de Pierre", - "type":"sightseeing", - "location":[ - 48.5904825, - 7.7453657 - ], - "osm_type":"way", - "osm_id":32261307, - "attractiveness":174, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2f1735a6-c958-44ec-8f6d-8d7bf8952274", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "94":{ - "name":"Église Saint-Florent", - "type":"sightseeing", - "location":[ - 48.5963301, - 7.7221529 - ], - "osm_type":"way", - "osm_id":33455820, - "attractiveness":196, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b9551b66-5e0f-444f-bc7e-b7e70636a813", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "95":{ - "name":"Église Évangélique Agap", - "type":"sightseeing", - "location":[ - 48.5917592, - 7.7458688 - ], - "osm_type":"way", - "osm_id":35978861, - "attractiveness":135, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8a3b8c09-6b39-4667-b2ea-7b6a2a5b54ba", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "96":{ - "name":"Salle de la Marseillaise", - "type":"sightseeing", - "location":[ - 48.5911749, - 7.7491341 - ], - "osm_type":"way", - "osm_id":36000284, - "attractiveness":108, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0a1ada42-c643-46cd-996a-f1e7060c289c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "97":{ - "name":"ESAV Strasbourg", - "type":"sightseeing", - "location":[ - 48.5906846, - 7.7397307 - ], - "osm_type":"way", - "osm_id":36269921, - "attractiveness":295, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4a3ea579-1f91-457b-a3f1-fd492df666ef", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "98":{ - "name":"Centre de bouddhisme zen", - "type":"sightseeing", - "location":[ - 48.5908924, - 7.7403924 - ], - "osm_type":"way", - "osm_id":36269935, - "attractiveness":237, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bf483162-12ad-4f4e-97ec-d8fa748d75c9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "99":{ - "name":"Halles P3 Wilson", - "type":"sightseeing", - "location":[ - 48.587919, - 7.7400469 - ], - "osm_type":"way", - "osm_id":36271630, - "attractiveness":237, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ba8054ed-02a5-440d-801a-18934d409e20", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "100":{ - "name":"Groupe École Élémentaire Saint-Jean", - "type":"sightseeing", - "location":[ - 48.5891746, - 7.7434643 - ], - "osm_type":"way", - "osm_id":36274410, - "attractiveness":78, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"470c4bf0-0c61-4b4c-ace7-40a865d3ed1d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "101":{ - "name":"Église Saint-Sauveur", - "type":"sightseeing", - "location":[ - 48.5945471, - 7.7168371 - ], - "osm_type":"way", - "osm_id":39173571, - "attractiveness":199, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2c1c488f-5e76-4118-8a7c-a1051f458056", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "102":{ - "name":"Église protestante Saint-Pierre-le-Jeune", - "type":"sightseeing", - "location":[ - 48.5855301, - 7.7465472 - ], - "osm_type":"way", - "osm_id":39540475, - "attractiveness":469, - "n_tags":22, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8093f85e-50d6-4894-9a6f-d5fb56d4eebb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "103":{ - "name":"Gymnase Jean Sturm", - "type":"sightseeing", - "location":[ - 48.5837383, - 7.7484667 - ], - "osm_type":"way", - "osm_id":39543346, - "attractiveness":419, - "n_tags":21, - "image_url":null, - "description":null, - "duration":0, - "uuid":"db33458e-8e16-4173-807c-bfab2f688a67", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "104":{ - "name":"Temple Neuf", - "type":"sightseeing", - "location":[ - 48.5832839, - 7.7484535 - ], - "osm_type":"way", - "osm_id":39543348, - "attractiveness":268, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5a9db4f3-bcb9-417e-adbc-4cf1d7922053", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "105":{ - "name":"Place du Marché-Neuf", - "type":"sightseeing", - "location":[ - 48.5826283, - 7.7483066 - ], - "osm_type":"way", - "osm_id":39546463, - "attractiveness":159, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d3119394-d88e-4aaa-b26d-cb4e31568c07", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "106":{ - "name":"Groupe Scolaire Schoepflin", - "type":"sightseeing", - "location":[ - 48.5865506, - 7.7486118 - ], - "osm_type":"way", - "osm_id":39600444, - "attractiveness":82, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cf3fdc32-803a-4f4f-9cfe-2447d1622770", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "107":{ - "name":"Banque de France", - "type":"sightseeing", - "location":[ - 48.5850576, - 7.7490192 - ], - "osm_type":"way", - "osm_id":39605775, - "attractiveness":180, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b7ccdceb-942c-4c8f-9535-3da7c4f97322", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "108":{ - "name":"Palais du Gouverneur", - "type":"sightseeing", - "location":[ - 48.5851154, - 7.751928 - ], - "osm_type":"way", - "osm_id":39610248, - "attractiveness":205, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"44a5f13b-9d7e-4ea5-ae7f-417eb9ccde37", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "109":{ - "name":"Bistrot et chocolat", - "type":"sightseeing", - "location":[ - 48.5814987, - 7.7530011 - ], - "osm_type":"way", - "osm_id":39654586, - "attractiveness":338, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5304eaca-120d-4b23-8e09-e9d28caba9e7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "110":{ - "name":"École maternelle Louis Pasteur", - "type":"sightseeing", - "location":[ - 48.5818982, - 7.7549376 - ], - "osm_type":"way", - "osm_id":39657144, - "attractiveness":206, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8966cb70-5c83-402b-a451-b18e9b36b4ec", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "111":{ - "name":"Pharmacie du Roethig", - "type":"sightseeing", - "location":[ - 48.5655159, - 7.7069482 - ], - "osm_type":"way", - "osm_id":39668928, - "attractiveness":166, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4c2273cc-6db9-4fbb-9654-c269b7b15678", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "112":{ - "name":"Église Saint-Jean", - "type":"sightseeing", - "location":[ - 48.5672768, - 7.7074115 - ], - "osm_type":"way", - "osm_id":39688961, - "attractiveness":138, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"412955bd-9b1d-4328-8952-5a29cc0abcc1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "113":{ - "name":"Au Vieux Strasbourg", - "type":"sightseeing", - "location":[ - 48.5805253, - 7.7507252 - ], - "osm_type":"way", - "osm_id":39754699, - "attractiveness":289, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b69c45da-b7c1-4140-aba6-6f3e10a2d10b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "114":{ - "name":"Au Bon Vivant", - "type":"sightseeing", - "location":[ - 48.5805996, - 7.75063 - ], - "osm_type":"way", - "osm_id":39846430, - "attractiveness":250, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"26806eb1-dd09-4c09-be55-83f49b79461d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "115":{ - "name":"Il Felice", - "type":"sightseeing", - "location":[ - 48.5806412, - 7.7489822 - ], - "osm_type":"way", - "osm_id":39846452, - "attractiveness":392, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"04dc89aa-4e60-43f0-8384-53206a9ed71f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "116":{ - "name":"Le Pilier des Anges", - "type":"sightseeing", - "location":[ - 48.5813183, - 7.7492671 - ], - "osm_type":"way", - "osm_id":39855297, - "attractiveness":149, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"636a517c-23c4-4228-b40f-39fcac5f9bbb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "117":{ - "name":"CCF", - "type":"sightseeing", - "location":[ - 48.5812475, - 7.7479124 - ], - "osm_type":"way", - "osm_id":39860111, - "attractiveness":262, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2291db6d-fc94-4999-909f-7825c409c6e4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "118":{ - "name":"McDonald's", - "type":"sightseeing", - "location":[ - 48.604711, - 7.7052976 - ], - "osm_type":"way", - "osm_id":39896378, - "attractiveness":329, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"98cae356-eba6-4ac5-a9ce-0274f1fdfbc0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "119":{ - "name":"Au Pigeon", - "type":"sightseeing", - "location":[ - 48.5803796, - 7.7487548 - ], - "osm_type":"way", - "osm_id":39971175, - "attractiveness":252, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e7741eab-1a2a-4395-9e49-4c05384d1404", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "120":{ - "name":"Église protestante Saint-Thomas", - "type":"sightseeing", - "location":[ - 48.5796572, - 7.7456235 - ], - "osm_type":"way", - "osm_id":39973703, - "attractiveness":444, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a7fd3394-6b61-4d9a-b556-4aa1cbd993ab", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "121":{ - "name":"Église Réformée", - "type":"sightseeing", - "location":[ - 48.5806662, - 7.7443997 - ], - "osm_type":"way", - "osm_id":39981658, - "attractiveness":172, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e051e440-46a4-4a67-87d3-e90eb2ac7255", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "122":{ - "name":"Centre d'incendie et de secours Strasbourg-Finkwiller", - "type":"sightseeing", - "location":[ - 48.5790899, - 7.7437902 - ], - "osm_type":"way", - "osm_id":39985236, - "attractiveness":191, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9a520e79-4efb-48c7-98a9-c40a0d63fcec", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "123":{ - "name":"École maternelle Saint-Thomas", - "type":"sightseeing", - "location":[ - 48.5799212, - 7.7439536 - ], - "osm_type":"way", - "osm_id":39985245, - "attractiveness":149, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"448c132f-ae9e-48e8-a8b4-f05820cc05e9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "124":{ - "name":"Église Méthodiste de Sion", - "type":"sightseeing", - "location":[ - 48.5814329, - 7.7425746 - ], - "osm_type":"way", - "osm_id":40020421, - "attractiveness":216, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2ce06c01-a9fe-4c28-ac78-38142dd409ed", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "125":{ - "name":"Tribunal Administratif", - "type":"sightseeing", - "location":[ - 48.5916523, - 7.7564303 - ], - "osm_type":"way", - "osm_id":40030105, - "attractiveness":166, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"02e4bb3a-2b86-448c-8795-3665c74e32a9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "126":{ - "name":"L'ami Schutz", - "type":"sightseeing", - "location":[ - 48.5804584, - 7.739231 - ], - "osm_type":"way", - "osm_id":40033008, - "attractiveness":393, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5eddab74-53a4-418b-99ab-925da5a21866", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "127":{ - "name":"Place Grimmeissen", - "type":"sightseeing", - "location":[ - 48.5818492, - 7.7403931 - ], - "osm_type":"way", - "osm_id":40098226, - "attractiveness":194, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e1d29057-fe71-4aeb-a484-10a387d5e6bb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "128":{ - "name":"Église protestante Saint-Pierre-le-Vieux", - "type":"sightseeing", - "location":[ - 48.5827492, - 7.7396207 - ], - "osm_type":"way", - "osm_id":40105161, - "attractiveness":190, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b1c60ad3-c20c-49f5-a100-0b538936af8d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "129":{ - "name":"Église catholique Saint-Pierre le-vieux", - "type":"sightseeing", - "location":[ - 48.5828014, - 7.7399978 - ], - "osm_type":"way", - "osm_id":40105163, - "attractiveness":219, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5543f0a5-b802-4161-859d-68399d7dd3ba", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "130":{ - "name":"École Aquiba (Lycée général privé)", - "type":"sightseeing", - "location":[ - 48.5898064, - 7.7530301 - ], - "osm_type":"way", - "osm_id":40106312, - "attractiveness":163, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6618c866-6fe7-49d9-97ad-cfe9aa4b3eb5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "131":{ - "name":"Synagogue de la Paix", - "type":"sightseeing", - "location":[ - 48.590289, - 7.7566482 - ], - "osm_type":"way", - "osm_id":40142894, - "attractiveness":227, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4d3b0bb2-c04b-4e69-8d00-8b540dd04809", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "132":{ - "name":"Lycée René Cassin annexe Sévigné", - "type":"sightseeing", - "location":[ - 48.5886641, - 7.7568747 - ], - "osm_type":"way", - "osm_id":40142934, - "attractiveness":105, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6bad442f-5d44-487f-98a2-4397d8fbba71", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "133":{ - "name":"Église catholique Saint-Pierre-le-Jeune", - "type":"sightseeing", - "location":[ - 48.5883647, - 7.748845 - ], - "osm_type":"way", - "osm_id":40192519, - "attractiveness":357, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9a7bee43-970a-45d5-8960-9bd3c8e12d27", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "134":{ - "name":"Collège Foch", - "type":"sightseeing", - "location":[ - 48.5886045, - 7.7512891 - ], - "osm_type":"way", - "osm_id":40196946, - "attractiveness":128, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6a167378-b59d-4909-ae28-b7d84f004b28", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "135":{ - "name":"Médiathèque Olympe de Gouges (Centre ville)", - "type":"sightseeing", - "location":[ - 48.584774, - 7.7394013 - ], - "osm_type":"way", - "osm_id":40202917, - "attractiveness":185, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8904810f-a090-4288-89e4-e3fba4b7805f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "136":{ - "name":"Ibis Kitchen Restaurant", - "type":"sightseeing", - "location":[ - 48.5783773, - 7.7356662 - ], - "osm_type":"way", - "osm_id":40222090, - "attractiveness":359, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c93b4e1c-7ef3-47ea-9c31-970811376319", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "137":{ - "name":"Faculté de Médecine", - "type":"sightseeing", - "location":[ - 48.5769454, - 7.739286 - ], - "osm_type":"way", - "osm_id":40237349, - "attractiveness":134, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5a8f4af0-9f45-4b60-9e1b-9b15a4f4fcd1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "138":{ - "name":"Lycée Louis Pasteur", - "type":"sightseeing", - "location":[ - 48.5752694, - 7.7376886 - ], - "osm_type":"way", - "osm_id":40237350, - "attractiveness":109, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"120df774-018b-498e-bfeb-9f9d7da20434", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "139":{ - "name":"Institut de Bactériologie", - "type":"sightseeing", - "location":[ - 48.5749725, - 7.738734 - ], - "osm_type":"way", - "osm_id":40237356, - "attractiveness":76, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"36a67bde-6b09-40ce-8eb9-d356dea06a15", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "140":{ - "name":"Crèche Kirschleger", - "type":"sightseeing", - "location":[ - 48.5769081, - 7.7404528 - ], - "osm_type":"way", - "osm_id":40243090, - "attractiveness":67, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1e65a474-6212-4dcb-8574-cbc07dda2b31", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "141":{ - "name":"Argos", - "type":"sightseeing", - "location":[ - 48.5746795, - 7.7448267 - ], - "osm_type":"way", - "osm_id":40243103, - "attractiveness":289, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c2e7eef1-5ddd-4e27-adee-f553667ef0c7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "142":{ - "name":"P1 Saint-Nicolas", - "type":"sightseeing", - "location":[ - 48.5755887, - 7.7495129 - ], - "osm_type":"way", - "osm_id":40245262, - "attractiveness":238, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0b77156e-a528-43fe-91b9-44dea211f5cf", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "143":{ - "name":"Amphithéâtre de la clinique médicale B", - "type":"sightseeing", - "location":[ - 48.5747867, - 7.7481906 - ], - "osm_type":"way", - "osm_id":40249470, - "attractiveness":76, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"145b1faa-f128-419a-be65-18f6e409ff64", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "144":{ - "name":"Institut de Formation en Masso-Kinésithérapie", - "type":"sightseeing", - "location":[ - 48.5781901, - 7.7415388 - ], - "osm_type":"way", - "osm_id":40253162, - "attractiveness":198, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bd41f7ed-dc73-474e-bb39-6a0aace6b66e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "145":{ - "name":"Lucie Berger", - "type":"sightseeing", - "location":[ - 48.5781225, - 7.7427041 - ], - "osm_type":"way", - "osm_id":40280907, - "attractiveness":112, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0f285a2d-5ea7-46ff-8e46-7c149d6a1b33", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "146":{ - "name":"EHPAD Emmaüs-Diaconesses Strasbourg Centre ville", - "type":"sightseeing", - "location":[ - 48.577525, - 7.7436514 - ], - "osm_type":"way", - "osm_id":40280916, - "attractiveness":315, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"481ad79d-fb8e-4e8a-ac71-44d27a575a62", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "147":{ - "name":"Résidence Les Jardins d'Alsace", - "type":"sightseeing", - "location":[ - 48.5780269, - 7.7444039 - ], - "osm_type":"way", - "osm_id":40290709, - "attractiveness":256, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"09740f80-518f-4996-bb8a-8f29826da0ce", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "148":{ - "name":"EHPAD Abrapa Finkviller", - "type":"sightseeing", - "location":[ - 48.5774871, - 7.7454283 - ], - "osm_type":"way", - "osm_id":40308509, - "attractiveness":288, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e244c5cb-b0d4-4025-9ce3-a1de5f017f82", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "149":{ - "name":"Administration faculté dentaire", - "type":"sightseeing", - "location":[ - 48.5769562, - 7.7454455 - ], - "osm_type":"way", - "osm_id":40308511, - "attractiveness":107, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"71bc70a8-0e5e-4388-a8ca-bc45cdab6740", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "150":{ - "name":"Institut d'Anatomie Normale et Pathologique", - "type":"sightseeing", - "location":[ - 48.5759435, - 7.7466173 - ], - "osm_type":"way", - "osm_id":40314911, - "attractiveness":63, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c6892618-0b06-461d-8931-a883e54dc444", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "151":{ - "name":"Institut de Physique Biologique", - "type":"sightseeing", - "location":[ - 48.5754874, - 7.7471003 - ], - "osm_type":"way", - "osm_id":40314914, - "attractiveness":81, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a423f7e5-5c37-4a99-badb-754cd442d42b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "152":{ - "name":"Institut d'Hématologie et d'Immunologie", - "type":"sightseeing", - "location":[ - 48.5760271, - 7.7477538 - ], - "osm_type":"way", - "osm_id":40314917, - "attractiveness":81, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7974cc18-bed3-4027-8cdb-f860789d2c78", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "153":{ - "name":"Chapelle Saint-Erhard", - "type":"sightseeing", - "location":[ - 48.5771492, - 7.7492781 - ], - "osm_type":"way", - "osm_id":40317899, - "attractiveness":190, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e509d687-2b41-495e-8272-1307b9963ec2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "154":{ - "name":"Église catholique Saint-Louis", - "type":"sightseeing", - "location":[ - 48.5782854, - 7.7456547 - ], - "osm_type":"way", - "osm_id":40382455, - "attractiveness":276, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b3c8c1df-33b8-41ad-b92c-8a217c43f9cd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "155":{ - "name":"Section professionnelle du lycée Cassin", - "type":"sightseeing", - "location":[ - 48.578316, - 7.7465314 - ], - "osm_type":"way", - "osm_id":40382462, - "attractiveness":197, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4961bea3-6195-4d73-9d32-d37c57bbf3b2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "156":{ - "name":"Église Saint-Nicolas", - "type":"sightseeing", - "location":[ - 48.5783593, - 7.748501 - ], - "osm_type":"way", - "osm_id":40384394, - "attractiveness":436, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"db46e597-97a4-403a-b0f3-ba7c8f8c426a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "157":{ - "name":"Église catholique Sainte-Madeleine", - "type":"sightseeing", - "location":[ - 48.5799473, - 7.7548339 - ], - "osm_type":"way", - "osm_id":40450470, - "attractiveness":375, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eff0d077-d652-4fb5-8c05-3f17670a23ba", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "158":{ - "name":"Lycée professionnel Jean Geiler de Kaysersberg", - "type":"sightseeing", - "location":[ - 48.580009, - 7.7555067 - ], - "osm_type":"way", - "osm_id":40450503, - "attractiveness":183, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b565d0e1-911a-413e-b54d-37efed6dbadd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "159":{ - "name":"École nationale du génie des eaux et de l'environnement de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5850183, - 7.7576719 - ], - "osm_type":"way", - "osm_id":40454661, - "attractiveness":343, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0e8b10c0-f988-40b1-a1e4-079bdee0fe28", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "160":{ - "name":"Direction régionale des Douanes de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5864702, - 7.7576416 - ], - "osm_type":"way", - "osm_id":40454745, - "attractiveness":402, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"baea55f5-17a0-413f-b47b-93a02c55bc14", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "161":{ - "name":"Chapelle Saint-François d'Assise", - "type":"sightseeing", - "location":[ - 48.5889097, - 7.7607568 - ], - "osm_type":"way", - "osm_id":40457237, - "attractiveness":103, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7ef6772d-7a78-4e4a-9dae-afa0d6368439", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "162":{ - "name":"Église Saint-Paul", - "type":"sightseeing", - "location":[ - 48.5863214, - 7.759848 - ], - "osm_type":"way", - "osm_id":40457313, - "attractiveness":487, - "n_tags":23, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d1187137-d3ac-4de5-bbb4-0b9354313b26", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "163":{ - "name":"Fontaine Fischart", - "type":"sightseeing", - "location":[ - 48.581319, - 7.7564887 - ], - "osm_type":"way", - "osm_id":40459907, - "attractiveness":141, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ffd5e109-8664-4a7b-84dd-518241a92ae7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "164":{ - "name":"Centre médical et dentaire de la MGEN", - "type":"sightseeing", - "location":[ - 48.5810293, - 7.7567544 - ], - "osm_type":"way", - "osm_id":40459919, - "attractiveness":316, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6577d594-1f9d-4714-be22-8aa80f1e9448", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "165":{ - "name":"Les bateliers", - "type":"sightseeing", - "location":[ - 48.5818183, - 7.7573515 - ], - "osm_type":"way", - "osm_id":40467153, - "attractiveness":102, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8b01f25c-f11c-4088-95a2-bdee1071061d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "166":{ - "name":"Église Saint-Guillaume", - "type":"sightseeing", - "location":[ - 48.5820836, - 7.7576339 - ], - "osm_type":"way", - "osm_id":40467155, - "attractiveness":413, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"345e44ef-3504-48b8-900a-a95652b60d57", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "167":{ - "name":"Résidence Abrapa Saint-Guillaume", - "type":"sightseeing", - "location":[ - 48.5822431, - 7.7580778 - ], - "osm_type":"way", - "osm_id":40467165, - "attractiveness":170, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cc7c9bdf-304a-4bcb-872d-ddf01d95115e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "168":{ - "name":"Mosquée Al Fateh", - "type":"sightseeing", - "location":[ - 48.5830212, - 7.760909 - ], - "osm_type":"way", - "osm_id":40469207, - "attractiveness":240, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3ca19fac-d4d1-4efa-a3fd-ab22553d1d4e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "169":{ - "name":"Maison de l'Étudiante", - "type":"sightseeing", - "location":[ - 48.5840162, - 7.7602468 - ], - "osm_type":"way", - "osm_id":40517838, - "attractiveness":116, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d0b758d8-c912-4279-9bdb-ea30f0ea5e54", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "170":{ - "name":"Pharmacie de la Cité", - "type":"sightseeing", - "location":[ - 48.597618, - 7.7154412 - ], - "osm_type":"way", - "osm_id":40520374, - "attractiveness":304, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8eeee135-2dc9-4d7f-b258-be9c46c81437", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "171":{ - "name":"Centre Médico-Social", - "type":"sightseeing", - "location":[ - 48.6002005, - 7.7147621 - ], - "osm_type":"way", - "osm_id":40520757, - "attractiveness":96, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"02a69ea9-6906-4c56-85a9-dd9b45eccd1d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "172":{ - "name":"Église Saint-Antoine", - "type":"sightseeing", - "location":[ - 48.5974484, - 7.7101123 - ], - "osm_type":"way", - "osm_id":40521595, - "attractiveness":154, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"67b46d20-9813-42ca-9737-13280279c308", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "173":{ - "name":"Groupe Scolaire Notre-Dame", - "type":"sightseeing", - "location":[ - 48.5878693, - 7.7437829 - ], - "osm_type":"way", - "osm_id":40522178, - "attractiveness":68, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f2357360-bc81-409f-ae55-66fac9b40029", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "174":{ - "name":"Tribunal de proximité", - "type":"sightseeing", - "location":[ - 48.5901614, - 7.7457934 - ], - "osm_type":"way", - "osm_id":40528357, - "attractiveness":89, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cc8b984c-6df2-4750-bf61-a4d7f545c01a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "175":{ - "name":"Le Jardin d'Alice", - "type":"sightseeing", - "location":[ - 48.5968424, - 7.7073052 - ], - "osm_type":"way", - "osm_id":40608831, - "attractiveness":228, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d43f415c-9ca4-4f45-aec8-560b05cfb48d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "176":{ - "name":"Église évangélique luthérienne libre", - "type":"sightseeing", - "location":[ - 48.5780754, - 7.7545344 - ], - "osm_type":"way", - "osm_id":40646869, - "attractiveness":196, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"59d1dc02-4cde-4442-b294-898fd0e9d5f9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "177":{ - "name":"Hôpital Civil", - "type":"sightseeing", - "location":[ - 48.5761071, - 7.7448917 - ], - "osm_type":"way", - "osm_id":40667164, - "attractiveness":416, - "n_tags":21, - "image_url":null, - "description":null, - "duration":0, - "uuid":"590775ca-1651-40eb-aee9-e5e08fdef7c3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "178":{ - "name":"Haute école des arts du Rhin – Batiment secondaire", - "type":"sightseeing", - "location":[ - 48.5816129, - 7.7593574 - ], - "osm_type":"way", - "osm_id":40709871, - "attractiveness":190, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"45da7ef9-56d3-44dc-84e0-114cc0f80393", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "179":{ - "name":"Lycée professionnel Jean-Frédéric Oberlin", - "type":"sightseeing", - "location":[ - 48.5814077, - 7.7601044 - ], - "osm_type":"way", - "osm_id":40709872, - "attractiveness":183, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"aaa7755d-843f-44de-ae36-643b8f39cf9a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "180":{ - "name":"La Chaufferie", - "type":"sightseeing", - "location":[ - 48.581165, - 7.7594747 - ], - "osm_type":"way", - "osm_id":40709873, - "attractiveness":168, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7115f231-5fdb-4bb5-8b7d-451a504a10a2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "181":{ - "name":"École maternelle Académie", - "type":"sightseeing", - "location":[ - 48.5813008, - 7.7607787 - ], - "osm_type":"way", - "osm_id":40709874, - "attractiveness":157, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"edba2cec-0ae2-4389-8fc4-4ad7c0ede2b2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "182":{ - "name":"Place de l'Académie", - "type":"sightseeing", - "location":[ - 48.5818254, - 7.7603049 - ], - "osm_type":"way", - "osm_id":40717063, - "attractiveness":145, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9fe48639-92db-4d98-a7cd-63e0702c052c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "183":{ - "name":"Institut National des Sciences Appliquées", - "type":"sightseeing", - "location":[ - 48.5816601, - 7.7645865 - ], - "osm_type":"way", - "osm_id":40735517, - "attractiveness":331, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f957bb8f-8ae7-4bb0-86a9-b58ff8bccb1d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "184":{ - "name":"Campus Centre", - "type":"sightseeing", - "location":[ - 48.5800231, - 7.7649906 - ], - "osm_type":"way", - "osm_id":40743589, - "attractiveness":86, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a9f89610-2f01-4a6e-9029-577e60ce6538", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "185":{ - "name":"Atelier Canopé 67 - Centre Régional de Documentation Pédagogique", - "type":"sightseeing", - "location":[ - 48.5781617, - 7.7636353 - ], - "osm_type":"way", - "osm_id":40745760, - "attractiveness":236, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"89a19a70-d512-48c5-9427-370b26271e6f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "186":{ - "name":"Institut de Biologie Moléculaire des Plantes", - "type":"sightseeing", - "location":[ - 48.5808189, - 7.7636927 - ], - "osm_type":"way", - "osm_id":40746790, - "attractiveness":88, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6496adce-70a3-40a9-9f0a-fd9d5fd9871b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "187":{ - "name":"Insectarium", - "type":"sightseeing", - "location":[ - 48.5799191, - 7.7650383 - ], - "osm_type":"way", - "osm_id":40746793, - "attractiveness":91, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"39dfaac3-2a84-4d1a-b7f4-782eb05cf216", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "188":{ - "name":"Église des Dominicains", - "type":"sightseeing", - "location":[ - 48.5822255, - 7.766828 - ], - "osm_type":"way", - "osm_id":40775124, - "attractiveness":197, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3d603f60-276a-4ba4-a876-f755d9ec70b3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "189":{ - "name":"Faculté de physique et ingénierie", - "type":"sightseeing", - "location":[ - 48.5839666, - 7.764029 - ], - "osm_type":"way", - "osm_id":40814389, - "attractiveness":285, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cf034e4e-a794-4f0f-b83d-c8c16f354d45", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "190":{ - "name":"Faculté de Psychologie", - "type":"sightseeing", - "location":[ - 48.5845432, - 7.76497 - ], - "osm_type":"way", - "osm_id":40816918, - "attractiveness":148, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"579ad28c-0e00-48f9-8891-1eb1271a74a3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "191":{ - "name":"École maternelle Oberlin", - "type":"sightseeing", - "location":[ - 48.5768752, - 7.7592111 - ], - "osm_type":"way", - "osm_id":40827656, - "attractiveness":132, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"08f79491-7180-4daa-8fee-9113a27d5c36", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "192":{ - "name":"Église du Christ Ressuscité", - "type":"sightseeing", - "location":[ - 48.5773614, - 7.7639692 - ], - "osm_type":"way", - "osm_id":40828452, - "attractiveness":178, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fdd94c0f-c50c-45e2-b797-895a049594b6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "193":{ - "name":"Synagogue de Cronenbourg", - "type":"sightseeing", - "location":[ - 48.6009376, - 7.7133344 - ], - "osm_type":"way", - "osm_id":40926492, - "attractiveness":112, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"30481c32-2d14-4b8f-ae0d-e4918c390875", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "194":{ - "name":"Département Recherches Subatomiques - Accueil - Bâtiment 27", - "type":"sightseeing", - "location":[ - 48.6061536, - 7.7105834 - ], - "osm_type":"way", - "osm_id":40926588, - "attractiveness":81, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"73757adb-bf1c-4fda-a7af-82d7f4b76259", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "195":{ - "name":"Institut Charles Sadron", - "type":"sightseeing", - "location":[ - 48.6067213, - 7.7159322 - ], - "osm_type":"way", - "osm_id":40926589, - "attractiveness":114, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"86df0596-678a-4482-8835-d907fb91bda5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "196":{ - "name":"Laboratoire d'Imagerie et de Neurosciences Cognitives", - "type":"sightseeing", - "location":[ - 48.6068086, - 7.7149081 - ], - "osm_type":"way", - "osm_id":40926597, - "attractiveness":100, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"45c8f217-0695-49fe-bd8c-7e6e630dca8d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "197":{ - "name":"Laboratoire d'Électronique et de Physique de Systèmes Instrumentaux", - "type":"sightseeing", - "location":[ - 48.6069875, - 7.7110019 - ], - "osm_type":"way", - "osm_id":40926617, - "attractiveness":78, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e3e9c244-5ffa-4c79-8bb3-59646edb9997", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "198":{ - "name":"Église Notre-Dame de Lourdes", - "type":"sightseeing", - "location":[ - 48.5762794, - 7.7307187 - ], - "osm_type":"way", - "osm_id":40927788, - "attractiveness":161, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"df4ed7e9-85d2-41db-8663-5d0a009a0382", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "199":{ - "name":"École maternelle Louise Scheppler", - "type":"sightseeing", - "location":[ - 48.5737603, - 7.7322026 - ], - "osm_type":"way", - "osm_id":40931752, - "attractiveness":117, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c46deaa4-7546-420e-97c0-d5bd86590fcd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "200":{ - "name":"Compagnons du Devoir", - "type":"sightseeing", - "location":[ - 48.5792994, - 7.7342802 - ], - "osm_type":"way", - "osm_id":40981621, - "attractiveness":143, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"70568900-5067-4944-8255-923c5d6a7ec4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "201":{ - "name":"Gendarmerie nationale", - "type":"sightseeing", - "location":[ - 48.5802099, - 7.735264 - ], - "osm_type":"way", - "osm_id":40981628, - "attractiveness":208, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5e1cd53a-2389-43ef-b520-8af519bc78f0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "202":{ - "name":"Maison de l'Enfance", - "type":"sightseeing", - "location":[ - 48.579558, - 7.7318884 - ], - "osm_type":"way", - "osm_id":40982190, - "attractiveness":133, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"284b9ab5-8d3e-4e31-9c83-aef9d8fa621f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "203":{ - "name":"Mosquée AL IMANE", - "type":"sightseeing", - "location":[ - 48.5820547, - 7.7320735 - ], - "osm_type":"way", - "osm_id":40985962, - "attractiveness":171, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6dc050e2-5b45-4d14-8b8f-7cb1ab4ce507", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "204":{ - "name":"clinique Ste Barbe", - "type":"sightseeing", - "location":[ - 48.5817039, - 7.735331 - ], - "osm_type":"way", - "osm_id":40990074, - "attractiveness":271, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d7e35198-efe4-4ad7-a45e-16894f8cf158", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "205":{ - "name":"Crédit Agricole", - "type":"sightseeing", - "location":[ - 48.583739, - 7.7345777 - ], - "osm_type":"way", - "osm_id":41121006, - "attractiveness":241, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1e5589a1-3c2e-4319-ad3e-bb1623b83072", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "206":{ - "name":"LCL", - "type":"sightseeing", - "location":[ - 48.5873763, - 7.7391771 - ], - "osm_type":"way", - "osm_id":41143117, - "attractiveness":278, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bc127860-f175-4e1e-a3d5-118535e2a527", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "207":{ - "name":"Hypromat", - "type":"sightseeing", - "location":[ - 48.591094, - 7.7405479 - ], - "osm_type":"way", - "osm_id":41143777, - "attractiveness":207, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5db5c644-c7ac-4ccc-8fa2-b0e0ae208940", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "208":{ - "name":"Sainte-Aurélie", - "type":"sightseeing", - "location":[ - 48.5827804, - 7.7326564 - ], - "osm_type":"way", - "osm_id":41159101, - "attractiveness":218, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e941ea5a-ed37-4b08-95cb-b96a10d9aeb5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "209":{ - "name":"La Semencerie", - "type":"sightseeing", - "location":[ - 48.5781475, - 7.7287408 - ], - "osm_type":"way", - "osm_id":41161762, - "attractiveness":256, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5a80464a-89f6-43cf-8d87-a2edf5d4bf48", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "210":{ - "name":"Avia", - "type":"sightseeing", - "location":[ - 48.5787496, - 7.7306511 - ], - "osm_type":"way", - "osm_id":41161921, - "attractiveness":183, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9e833fdb-957c-4460-98eb-8ae2f7ceae70", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "211":{ - "name":"Église Néo-Apostolique", - "type":"sightseeing", - "location":[ - 48.590699, - 7.763788 - ], - "osm_type":"way", - "osm_id":41270770, - "attractiveness":141, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a159aa5a-d14d-4c99-b891-bba42f27bbe8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "212":{ - "name":"Église protestante Cronenbourg Cité", - "type":"sightseeing", - "location":[ - 48.6029563, - 7.7146028 - ], - "osm_type":"way", - "osm_id":41271271, - "attractiveness":164, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5436a172-070a-44dd-8e6e-6ed24316c99f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "213":{ - "name":"Église du Bon Pasteur", - "type":"sightseeing", - "location":[ - 48.6016113, - 7.7166039 - ], - "osm_type":"way", - "osm_id":41271275, - "attractiveness":117, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"be4721ba-67e8-4e6e-8fd1-b18d72a92016", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "214":{ - "name":"Centre socio-culturel l'Aquarium", - "type":"sightseeing", - "location":[ - 48.6046063, - 7.7191672 - ], - "osm_type":"way", - "osm_id":41271280, - "attractiveness":116, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d819aaae-f8a7-433e-9527-bfb8423c32f7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "215":{ - "name":"Centre médical - \"Pierre Curie", - "type":"sightseeing", - "location":[ - 48.6040902, - 7.712959 - ], - "osm_type":"way", - "osm_id":41271283, - "attractiveness":84, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9c4a01fb-17e1-4cb8-b048-b8fd71889feb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "216":{ - "name":"Police nationale", - "type":"sightseeing", - "location":[ - 48.6031813, - 7.7176448 - ], - "osm_type":"way", - "osm_id":41271287, - "attractiveness":232, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f16e46ce-7d9a-45ba-86fc-811c7d64bb7f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "217":{ - "name":"Représentation permanente des Pays-Bas", - "type":"sightseeing", - "location":[ - 48.58907, - 7.7651598 - ], - "osm_type":"way", - "osm_id":41359549, - "attractiveness":110, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"99062710-0b4a-4e45-afda-65589ef19d4d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "218":{ - "name":"Institut des Hautes Études Européennes - Villa Knopf", - "type":"sightseeing", - "location":[ - 48.5898743, - 7.764956 - ], - "osm_type":"way", - "osm_id":41361001, - "attractiveness":148, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a589ede2-9469-4ddf-87dd-264e660f2a41", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "219":{ - "name":"Police des Autoroutes CRS37", - "type":"sightseeing", - "location":[ - 48.5885905, - 7.7274272 - ], - "osm_type":"way", - "osm_id":41418099, - "attractiveness":73, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a94c82bf-b3a5-4143-9a1d-f53be95440f4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "220":{ - "name":"Groupe Scolaire Édouard Branly", - "type":"sightseeing", - "location":[ - 48.5948377, - 7.7616068 - ], - "osm_type":"way", - "osm_id":41600709, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"712d73fe-3633-446c-aa6d-c7d894939842", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "221":{ - "name":"Centre Socio Culturel Victor Schoelcher", - "type":"sightseeing", - "location":[ - 48.6014543, - 7.7217288 - ], - "osm_type":"way", - "osm_id":41706042, - "attractiveness":74, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6784dd53-6dc3-4dc6-8317-c2dcffcee9b9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "222":{ - "name":"Médiathèque Cronenbourg", - "type":"sightseeing", - "location":[ - 48.6011733, - 7.7214887 - ], - "osm_type":"way", - "osm_id":41706044, - "attractiveness":97, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cae98965-36c2-4e57-b3d3-bcf90e267de5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "223":{ - "name":"Hôpital de Hautepierre", - "type":"sightseeing", - "location":[ - 48.5932911, - 7.7070877 - ], - "osm_type":"way", - "osm_id":41770181, - "attractiveness":323, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8c60a85b-cf82-41ae-b57b-35c4be0d7be6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "224":{ - "name":"Centre socio-culturel le Galet", - "type":"sightseeing", - "location":[ - 48.5963571, - 7.7007381 - ], - "osm_type":"way", - "osm_id":41778269, - "attractiveness":129, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e3d8c49c-dfc0-4331-bb4d-868be72c081f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "225":{ - "name":"École Maternelle Karine 1", - "type":"sightseeing", - "location":[ - 48.5972311, - 7.6990841 - ], - "osm_type":"way", - "osm_id":41780605, - "attractiveness":94, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"febe596b-070a-4351-9770-ee3c254f2756", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "226":{ - "name":"École Maternelle Éléonore B", - "type":"sightseeing", - "location":[ - 48.5900302, - 7.7036969 - ], - "osm_type":"way", - "osm_id":41958797, - "attractiveness":76, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a91d29cd-9d68-4263-9cf2-612cb82d450a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "227":{ - "name":"Place Montaigne", - "type":"sightseeing", - "location":[ - 48.5903016, - 7.7034277 - ], - "osm_type":"way", - "osm_id":41958799, - "attractiveness":92, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"98bf74e4-f8c3-4189-b2b8-ec30558d9326", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "228":{ - "name":"Police Nationale", - "type":"sightseeing", - "location":[ - 48.5800051, - 7.71575 - ], - "osm_type":"way", - "osm_id":42148186, - "attractiveness":320, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"56a094c2-8f9d-4dad-ad47-d3050ddcc5f6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "229":{ - "name":"Église Saint-Joseph", - "type":"sightseeing", - "location":[ - 48.5803892, - 7.7123663 - ], - "osm_type":"way", - "osm_id":42156579, - "attractiveness":338, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1f65be93-6d6f-4c11-9673-2442b8be4d9f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "230":{ - "name":"École Maternelle Camille Claus", - "type":"sightseeing", - "location":[ - 48.5809803, - 7.7123791 - ], - "osm_type":"way", - "osm_id":42156600, - "attractiveness":70, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9c520b85-9ee7-4cc5-be77-880dab051659", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "231":{ - "name":"AMCB Clinique Vétérinaire", - "type":"sightseeing", - "location":[ - 48.583357, - 7.7091267 - ], - "osm_type":"way", - "osm_id":42161674, - "attractiveness":193, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9046154b-272f-4578-ab76-03551b1e8d48", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "232":{ - "name":"Église Saint-Jean Bosco", - "type":"sightseeing", - "location":[ - 48.5817304, - 7.704326 - ], - "osm_type":"way", - "osm_id":42224669, - "attractiveness":126, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9a9774e6-4abe-4c04-863d-eb23fea0018f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "233":{ - "name":"Centre Socio-culturel Camille Claus", - "type":"sightseeing", - "location":[ - 48.5814468, - 7.7020699 - ], - "osm_type":"way", - "osm_id":42225734, - "attractiveness":95, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"167c0361-a976-498d-913c-1253cc8cfb45", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "234":{ - "name":"Groupe Scolaire Gustave Stoskopf", - "type":"sightseeing", - "location":[ - 48.5852962, - 7.6992587 - ], - "osm_type":"way", - "osm_id":42227436, - "attractiveness":63, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3a40527c-b85c-419c-b408-ad688a0b3a32", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "235":{ - "name":"École primaire Jean Mermoz", - "type":"sightseeing", - "location":[ - 48.6038977, - 7.7367353 - ], - "osm_type":"way", - "osm_id":42244908, - "attractiveness":159, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7e6f7140-b067-4ad8-8d4f-c6734e8f1322", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "236":{ - "name":"École élémentaire privée L'Oliveraie", - "type":"sightseeing", - "location":[ - 48.6022934, - 7.7430781 - ], - "osm_type":"way", - "osm_id":42322287, - "attractiveness":182, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"09a3d93c-bae7-4375-a4dd-b73705f75dd3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "237":{ - "name":"Collège Jacques Twinger", - "type":"sightseeing", - "location":[ - 48.5810012, - 7.705529 - ], - "osm_type":"way", - "osm_id":42352502, - "attractiveness":127, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1139fda5-f00a-4ec9-84b5-763de6c596a6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "238":{ - "name":"Groupe Scolaire du Hohberg", - "type":"sightseeing", - "location":[ - 48.579721, - 7.7058943 - ], - "osm_type":"way", - "osm_id":42366018, - "attractiveness":43, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"39c829e6-07d6-497b-82b8-b761dc397b22", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "239":{ - "name":"Église du couvent des Capucins", - "type":"sightseeing", - "location":[ - 48.5762817, - 7.6999001 - ], - "osm_type":"way", - "osm_id":42386620, - "attractiveness":140, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"277d8dc8-9103-4496-9b78-fb27b6c10623", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "240":{ - "name":"École primaire privée Joie de Vivre Ann Saint-Etienne", - "type":"sightseeing", - "location":[ - 48.5766287, - 7.6998893 - ], - "osm_type":"way", - "osm_id":42386621, - "attractiveness":119, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"35ddd958-8ba9-40df-874a-c1a1c91bde63", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "241":{ - "name":"Mairie de quartier de Koenisghoffen", - "type":"sightseeing", - "location":[ - 48.5789554, - 7.7132799 - ], - "osm_type":"way", - "osm_id":42404538, - "attractiveness":103, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eaa0d808-5ba8-462a-a529-b4a6150c83c7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "242":{ - "name":"École Élémentaire des Romains", - "type":"sightseeing", - "location":[ - 48.5787988, - 7.7153527 - ], - "osm_type":"way", - "osm_id":42411628, - "attractiveness":72, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"84013e49-98ed-497c-8bdf-5440b0674c5e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "243":{ - "name":"Au deux epices", - "type":"sightseeing", - "location":[ - 48.5785346, - 7.7173706 - ], - "osm_type":"way", - "osm_id":42411642, - "attractiveness":121, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"58abaa12-45b2-4fa3-b13d-83464a7a1729", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "244":{ - "name":"EHPAD Emmaüs-Diaconesses Koenigshoffen", - "type":"sightseeing", - "location":[ - 48.5775255, - 7.714984 - ], - "osm_type":"way", - "osm_id":42473052, - "attractiveness":350, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"accf0336-1290-46b9-869f-8d71526463d9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "245":{ - "name":"La Poste de Schiltigheim Les Brasseurs", - "type":"sightseeing", - "location":[ - 48.6066439, - 7.7488731 - ], - "osm_type":"way", - "osm_id":42506586, - "attractiveness":309, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1377698f-2bdb-410e-bc2c-4116ecf9d9f1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "246":{ - "name":"Simse imagerie médicale", - "type":"sightseeing", - "location":[ - 48.6068841, - 7.7486078 - ], - "osm_type":"way", - "osm_id":42506622, - "attractiveness":171, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2adf1c5d-538b-48cf-b5b9-ed98bf52f1ef", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "247":{ - "name":"Église de la Sainte-Famille", - "type":"sightseeing", - "location":[ - 48.6072128, - 7.7479903 - ], - "osm_type":"way", - "osm_id":42506681, - "attractiveness":212, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"86f4a837-e193-45e6-90ea-ccd1c9af5363", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "248":{ - "name":"Église Saint-Arbogast", - "type":"sightseeing", - "location":[ - 48.5722456, - 7.7188796 - ], - "osm_type":"way", - "osm_id":42937947, - "attractiveness":303, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"afc02e2c-5e07-48e5-852c-df79f9b21efa", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "249":{ - "name":"Crédit Mutuel", - "type":"sightseeing", - "location":[ - 48.5695527, - 7.7103863 - ], - "osm_type":"way", - "osm_id":42961059, - "attractiveness":141, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"74dd3c42-52ed-4202-9f5e-393978f20e13", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "250":{ - "name":"Église protestante de Schiltigheim", - "type":"sightseeing", - "location":[ - 48.6060339, - 7.7513163 - ], - "osm_type":"way", - "osm_id":42990751, - "attractiveness":498, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"510c1ac5-6125-4108-990a-9867a653cd20", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "251":{ - "name":"Maison du Jeune Citoyen", - "type":"sightseeing", - "location":[ - 48.6063013, - 7.7498734 - ], - "osm_type":"way", - "osm_id":42990788, - "attractiveness":219, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d279bdcd-8212-4c5d-9932-e9f899a2c412", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "252":{ - "name":"École des Arts", - "type":"sightseeing", - "location":[ - 48.6060788, - 7.7495907 - ], - "osm_type":"way", - "osm_id":42990791, - "attractiveness":152, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d19c81c2-72bb-4191-96e6-2df4cb59c8b9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "253":{ - "name":"Collège Hans Arp", - "type":"sightseeing", - "location":[ - 48.5692574, - 7.7183438 - ], - "osm_type":"way", - "osm_id":43092052, - "attractiveness":93, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c68ed802-7180-47ea-b9ab-5246cacbf34e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "254":{ - "name":"Protection Civile du Bas-Rhin - Base Schiltigheim - Caserne Monsché", - "type":"sightseeing", - "location":[ - 48.6047753, - 7.7519264 - ], - "osm_type":"way", - "osm_id":43105528, - "attractiveness":207, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9c4a25ae-ac86-497f-a82a-ec3ca76c91e1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "255":{ - "name":"Résidence Eugène Delacroix", - "type":"sightseeing", - "location":[ - 48.5676873, - 7.7282781 - ], - "osm_type":"way", - "osm_id":43140009, - "attractiveness":245, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"675140d2-add3-49f9-a76c-5aa9a2aca1fe", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "256":{ - "name":"Foyer Soleil", - "type":"sightseeing", - "location":[ - 48.6071693, - 7.7524723 - ], - "osm_type":"way", - "osm_id":43151859, - "attractiveness":199, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cf8c8cd7-868a-4871-a1f2-4a2d93381bf1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "257":{ - "name":"Tribunal d'Instance de Schiltigheim", - "type":"sightseeing", - "location":[ - 48.6031472, - 7.7546367 - ], - "osm_type":"way", - "osm_id":43178323, - "attractiveness":108, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3acda4aa-163b-4104-b944-4b57b1ce0ed3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "258":{ - "name":"École maternelle Martin Schongauer", - "type":"sightseeing", - "location":[ - 48.5635264, - 7.718583 - ], - "osm_type":"way", - "osm_id":43189488, - "attractiveness":108, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a6e1b16c-8801-4666-9dbc-701f23317205", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "259":{ - "name":"Service psychothérapique pour enfants et adolescents", - "type":"sightseeing", - "location":[ - 48.5648673, - 7.7170133 - ], - "osm_type":"way", - "osm_id":43248974, - "attractiveness":105, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"899ef3e9-fa82-491a-8177-f1934e0e958b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "260":{ - "name":"Groupe Scolaire Léonard de Vinci", - "type":"sightseeing", - "location":[ - 48.5658761, - 7.7271146 - ], - "osm_type":"way", - "osm_id":43306050, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eddc6d44-933e-4532-87b7-f0001d15318a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "261":{ - "name":"Kinésithérapeute Von Der Marck", - "type":"sightseeing", - "location":[ - 48.564499, - 7.7076972 - ], - "osm_type":"way", - "osm_id":43311981, - "attractiveness":133, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4815c6b8-8631-46a3-a533-405c032fc4b5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "262":{ - "name":"École Gutenberg", - "type":"sightseeing", - "location":[ - 48.5616102, - 7.7039506 - ], - "osm_type":"way", - "osm_id":43341825, - "attractiveness":56, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a49368ef-db77-4fa7-8d02-2caa5d5845b3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "263":{ - "name":"Église du Sacré-Coeur", - "type":"sightseeing", - "location":[ - 48.5631446, - 7.7082816 - ], - "osm_type":"way", - "osm_id":43345191, - "attractiveness":166, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"df41228c-4f90-422a-9e2a-a7451c10964c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "264":{ - "name":"Centre Socio-culturel du Marais", - "type":"sightseeing", - "location":[ - 48.6068071, - 7.7670547 - ], - "osm_type":"way", - "osm_id":43444536, - "attractiveness":194, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"62252fb8-b715-4d1c-a68a-901aa5b68483", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "265":{ - "name":"Institut Médico-Pédagogique \"Le Roethig\"", - "type":"sightseeing", - "location":[ - 48.5639375, - 7.7108502 - ], - "osm_type":"way", - "osm_id":43451013, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9d913755-a6b5-4690-b236-133d376d91a5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "266":{ - "name":"Église Saint-Léon", - "type":"sightseeing", - "location":[ - 48.5673784, - 7.7503971 - ], - "osm_type":"way", - "osm_id":43548694, - "attractiveness":166, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e22515c7-937b-4272-8390-536fd8af79f4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "267":{ - "name":"Centre Administratif Ville et Eurométropole de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5733899, - 7.7520803 - ], - "osm_type":"way", - "osm_id":43721734, - "attractiveness":529, - "n_tags":27, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e52e5c5a-4e72-410e-bb7f-e3ca34e733ba", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "268":{ - "name":"Maison citoyenne", - "type":"sightseeing", - "location":[ - 48.5708489, - 7.7529829 - ], - "osm_type":"way", - "osm_id":43727168, - "attractiveness":102, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eb241112-84bb-4953-b45b-5fefc84f1570", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "269":{ - "name":"Chapelle de la Sainte-Croix", - "type":"sightseeing", - "location":[ - 48.5723594, - 7.7575605 - ], - "osm_type":"way", - "osm_id":43795771, - "attractiveness":116, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"41d534f0-87d5-44b7-b1e2-a31cee7b5f3a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "270":{ - "name":"UGC Ciné Cité Strasbourg", - "type":"sightseeing", - "location":[ - 48.5731023, - 7.7641146 - ], - "osm_type":"way", - "osm_id":43799904, - "attractiveness":547, - "n_tags":26, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0310b6b3-0dce-4a40-8db3-b9a38a91995b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "271":{ - "name":"Foyer du Jeune Homme", - "type":"sightseeing", - "location":[ - 48.5694807, - 7.7619724 - ], - "osm_type":"way", - "osm_id":43926499, - "attractiveness":358, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"05e78e8e-e356-4974-8af0-df0af99ec4ab", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "272":{ - "name":"EHPAD Les Mélèzes", - "type":"sightseeing", - "location":[ - 48.5694956, - 7.7616812 - ], - "osm_type":"way", - "osm_id":43926530, - "attractiveness":465, - "n_tags":22, - "image_url":null, - "description":null, - "duration":0, - "uuid":"127bd814-70a0-44a5-bcec-9cbc4cbbae6b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "273":{ - "name":"Centre Socio-Culturel", - "type":"sightseeing", - "location":[ - 48.5662086, - 7.7562629 - ], - "osm_type":"way", - "osm_id":44064457, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bec0d273-c313-4a59-ace0-7c53007899db", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "274":{ - "name":"Église Saint-Aloyse", - "type":"sightseeing", - "location":[ - 48.56428, - 7.7616777 - ], - "osm_type":"way", - "osm_id":44149159, - "attractiveness":186, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"813a4048-9228-4235-978f-c0bd0ac393a7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "275":{ - "name":"École Élémentaire de la Ziegelau", - "type":"sightseeing", - "location":[ - 48.563777, - 7.7634095 - ], - "osm_type":"way", - "osm_id":44158007, - "attractiveness":101, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c51b14bc-7ccb-4f32-beb6-e2999cf5c5d8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "276":{ - "name":"École maternelle Ziegelau", - "type":"sightseeing", - "location":[ - 48.5643385, - 7.7631325 - ], - "osm_type":"way", - "osm_id":44158028, - "attractiveness":127, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f23520fb-985c-4244-aba6-0ea173dae64c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "277":{ - "name":"Snack du Neudorf chez Babylone", - "type":"sightseeing", - "location":[ - 48.5632939, - 7.7619842 - ], - "osm_type":"way", - "osm_id":44158199, - "attractiveness":265, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7730778e-81cf-4afb-8f2e-55f92e0164f5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "278":{ - "name":"Les Compotes", - "type":"sightseeing", - "location":[ - 48.5660264, - 7.7612988 - ], - "osm_type":"way", - "osm_id":44203857, - "attractiveness":351, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2dc17980-e5bb-4ddc-969d-5dea9c0aa797", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "279":{ - "name":"Centre Culturel le 23", - "type":"sightseeing", - "location":[ - 48.5628042, - 7.7595574 - ], - "osm_type":"way", - "osm_id":44505765, - "attractiveness":96, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4de6b991-c1dc-42d2-81f2-68c426c57e3d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "280":{ - "name":"Institut National Supérieur du Professorat et de l’Education", - "type":"sightseeing", - "location":[ - 48.5614857, - 7.7543954 - ], - "osm_type":"way", - "osm_id":44623561, - "attractiveness":110, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6179e3bb-be1d-42f6-a083-9425e5098218", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "281":{ - "name":"Centre de Formation d'Apprentis Jean Geiler de Kaysersberg", - "type":"sightseeing", - "location":[ - 48.5896621, - 7.7534819 - ], - "osm_type":"way", - "osm_id":44947849, - "attractiveness":112, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c93514fc-ab13-4345-a452-0f575f724aec", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "282":{ - "name":"EHPAD Bethesda Contades", - "type":"sightseeing", - "location":[ - 48.5920553, - 7.7603553 - ], - "osm_type":"way", - "osm_id":45872499, - "attractiveness":285, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c550c7f9-8234-4e13-b7e4-31dc62ff7a55", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "283":{ - "name":"École maternelle Cronenbourg Centre", - "type":"sightseeing", - "location":[ - 48.5928233, - 7.7204069 - ], - "osm_type":"way", - "osm_id":45962420, - "attractiveness":162, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"83d572a7-2081-415d-8343-52535972c118", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "284":{ - "name":"Véloparc CTS Rives de l'Aar", - "type":"sightseeing", - "location":[ - 48.5999311, - 7.7542461 - ], - "osm_type":"way", - "osm_id":46892641, - "attractiveness":399, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"411a9f13-dd05-4cd4-b37f-0e83b3d48e76", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "285":{ - "name":"École Maternelle du Wacken", - "type":"sightseeing", - "location":[ - 48.5970691, - 7.7655965 - ], - "osm_type":"way", - "osm_id":47042104, - "attractiveness":108, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"13f1e09c-09cc-4d1e-ba9d-c6512047ef02", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "286":{ - "name":"Lycée professionnel privé Charles de Foucauld", - "type":"sightseeing", - "location":[ - 48.6058055, - 7.7072169 - ], - "osm_type":"way", - "osm_id":49222314, - "attractiveness":89, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3d103fe3-acff-4dac-8faf-82fdb9862504", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "287":{ - "name":"Groupe Scolaire Charles Adolphe Wurtz", - "type":"sightseeing", - "location":[ - 48.6023318, - 7.7212861 - ], - "osm_type":"way", - "osm_id":49357915, - "attractiveness":77, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"019e2384-c2cc-47fd-ba0e-ce475ea03600", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "288":{ - "name":"École primaire et élémentaire Camille Hirtz", - "type":"sightseeing", - "location":[ - 48.5937226, - 7.7186074 - ], - "osm_type":"way", - "osm_id":49524024, - "attractiveness":161, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"24ae0aea-bbf4-4a8b-ae7b-21c3f10a526b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "289":{ - "name":"École Élémentaire Brigitte", - "type":"sightseeing", - "location":[ - 48.5923484, - 7.6989275 - ], - "osm_type":"way", - "osm_id":49636123, - "attractiveness":69, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c4729cf5-df04-4322-8480-1ef50f234150", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "290":{ - "name":"Collège Erasme", - "type":"sightseeing", - "location":[ - 48.5916712, - 7.7012358 - ], - "osm_type":"way", - "osm_id":49636124, - "attractiveness":69, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5753d654-de3a-4642-b744-32a8f27286cd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "291":{ - "name":"École Maternelle Brigitte", - "type":"sightseeing", - "location":[ - 48.5912406, - 7.699199 - ], - "osm_type":"way", - "osm_id":49636125, - "attractiveness":89, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6e1d3fae-32cb-46d5-aabf-62f8526991c4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "292":{ - "name":"Crêche", - "type":"sightseeing", - "location":[ - 48.5916276, - 7.6991767 - ], - "osm_type":"way", - "osm_id":49636126, - "attractiveness":56, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9e6e04de-594e-4068-863e-140f9ffb2b1a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "293":{ - "name":"École Élémentaire Éléonore 1", - "type":"sightseeing", - "location":[ - 48.5902614, - 7.704443 - ], - "osm_type":"way", - "osm_id":49641082, - "attractiveness":73, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d86fb67c-c6de-43b1-9085-b691ba53471d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "294":{ - "name":"École Maternelle Éléonore A", - "type":"sightseeing", - "location":[ - 48.5898841, - 7.7056733 - ], - "osm_type":"way", - "osm_id":49641083, - "attractiveness":74, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"20efad31-e22f-49c1-9339-36a446fc0730", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "295":{ - "name":"Direction Inter-régionale des Routes", - "type":"sightseeing", - "location":[ - 48.5877592, - 7.7266912 - ], - "osm_type":"way", - "osm_id":49704414, - "attractiveness":50, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d8cbf39a-103f-4e8f-b491-ead5607ee45c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "296":{ - "name":"Maison de Retraite Petite Sœur des Pauvres", - "type":"sightseeing", - "location":[ - 48.5759771, - 7.69803 - ], - "osm_type":"way", - "osm_id":49776695, - "attractiveness":143, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"93c5c8ab-3a9d-425c-bff2-371eb28a0d4f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "297":{ - "name":"Poste de Strasbourg Koenigshoffen", - "type":"sightseeing", - "location":[ - 48.5790736, - 7.7106223 - ], - "osm_type":"way", - "osm_id":49778428, - "attractiveness":394, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d8e0b281-a76d-4351-adc4-13ed88917ab6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "298":{ - "name":"École Michael", - "type":"sightseeing", - "location":[ - 48.5784937, - 7.7132271 - ], - "osm_type":"way", - "osm_id":49778429, - "attractiveness":99, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"44ab4712-3528-44f3-96e7-720e9dfbfc7e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "299":{ - "name":"Place Nicolas Poussin", - "type":"sightseeing", - "location":[ - 48.5655342, - 7.7257558 - ], - "osm_type":"way", - "osm_id":49939383, - "attractiveness":71, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"53e8b37d-1c74-4aca-a2a8-3f717999e352", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "300":{ - "name":"Multi-Accueil Petite Enfance", - "type":"sightseeing", - "location":[ - 48.5659127, - 7.7056958 - ], - "osm_type":"way", - "osm_id":50011925, - "attractiveness":48, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1cffd1d8-6188-48d1-b4ac-15da75265210", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "301":{ - "name":"Caisse d'Épargne", - "type":"sightseeing", - "location":[ - 48.585849, - 7.7417082 - ], - "osm_type":"way", - "osm_id":52282780, - "attractiveness":404, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0de31f5c-80bd-491d-ae4c-a3056c28f97c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "302":{ - "name":"Lycée polyvalent Jean Rostand", - "type":"sightseeing", - "location":[ - 48.5823235, - 7.7617569 - ], - "osm_type":"way", - "osm_id":52387689, - "attractiveness":95, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b9b3bb6f-7948-4879-9068-14395571fc9d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "303":{ - "name":"Lycée général Fustel de Coulanges", - "type":"sightseeing", - "location":[ - 48.581926, - 7.7524545 - ], - "osm_type":"way", - "osm_id":52404849, - "attractiveness":225, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6779ce81-aa1c-4d93-b0fa-bf4f7ab3480b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "304":{ - "name":"École primaire Notre-Dame de Sion", - "type":"sightseeing", - "location":[ - 48.5883946, - 7.7644201 - ], - "osm_type":"way", - "osm_id":62910210, - "attractiveness":145, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5f69b5f2-7829-498d-a762-504b5edb55fc", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "305":{ - "name":"Lycée professionnel Aristide Briand", - "type":"sightseeing", - "location":[ - 48.60407, - 7.7523415 - ], - "osm_type":"way", - "osm_id":81083275, - "attractiveness":153, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"37054b83-6ac0-4715-83fe-e9d303eeab2c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "306":{ - "name":"Déchèterie de Koenigshoffen", - "type":"sightseeing", - "location":[ - 48.5769907, - 7.7249363 - ], - "osm_type":"way", - "osm_id":105068401, - "attractiveness":626, - "n_tags":29, - "image_url":null, - "description":null, - "duration":0, - "uuid":"693d5c99-c1bc-4f5d-bc68-920939e88e64", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "307":{ - "name":"Parking Visiteurs", - "type":"sightseeing", - "location":[ - 48.5992428, - 7.7590191 - ], - "osm_type":"way", - "osm_id":105248582, - "attractiveness":113, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9c58d774-4357-4e6d-b2e7-f9301e5414d5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "308":{ - "name":"La Présidence", - "type":"sightseeing", - "location":[ - 48.5787378, - 7.7646311 - ], - "osm_type":"way", - "osm_id":106966312, - "attractiveness":131, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fbfe29f9-2196-4191-b75a-e21c747082cb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "309":{ - "name":"Passerelle Patio", - "type":"sightseeing", - "location":[ - 48.5785288, - 7.7648372 - ], - "osm_type":"way", - "osm_id":106966314, - "attractiveness":126, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fb68368c-6f24-4ad1-87d3-935908a78b04", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "310":{ - "name":"Platforme de Biologie", - "type":"sightseeing", - "location":[ - 48.5799438, - 7.7656975 - ], - "osm_type":"way", - "osm_id":106970374, - "attractiveness":75, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5fc6fd36-65fa-4ea9-b090-9540dadd733b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "311":{ - "name":"Parking relais-tram P+R Ducs d'Alsace", - "type":"sightseeing", - "location":[ - 48.58928, - 7.7158391 - ], - "osm_type":"way", - "osm_id":107271489, - "attractiveness":352, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"30971d91-f854-41a2-8b7d-c6da8d275963", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "312":{ - "name":"Parc de la Bergerie", - "type":"sightseeing", - "location":[ - 48.6015866, - 7.721044 - ], - "osm_type":"way", - "osm_id":115014214, - "attractiveness":146, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dcca09ab-4974-48b4-a40a-3b3744cffd7d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "313":{ - "name":"Parking Auchan Market", - "type":"sightseeing", - "location":[ - 48.5986052, - 7.7090977 - ], - "osm_type":"way", - "osm_id":118415853, - "attractiveness":103, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8580d7b9-72d0-411f-9e5e-6622fd40b71f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "314":{ - "name":"Cour Elmia", - "type":"sightseeing", - "location":[ - 48.6057282, - 7.7519829 - ], - "osm_type":"way", - "osm_id":128266115, - "attractiveness":288, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f29d29c1-6b45-4118-ae24-806fdf2afa84", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "315":{ - "name":"Parking Patinoire l'Iceberg", - "type":"sightseeing", - "location":[ - 48.5889948, - 7.7256603 - ], - "osm_type":"way", - "osm_id":131306422, - "attractiveness":89, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a0a80ad0-11c6-43ff-8b64-bd02ab6e942b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "316":{ - "name":"Collège Épiscopal Saint-Étienne", - "type":"sightseeing", - "location":[ - 48.5831924, - 7.755886 - ], - "osm_type":"way", - "osm_id":151324833, - "attractiveness":190, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c3753c44-2e17-4da5-839a-e46ae74fa563", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "317":{ - "name":"Maison de la petite enfance Cronenbourg", - "type":"sightseeing", - "location":[ - 48.6012312, - 7.7225207 - ], - "osm_type":"way", - "osm_id":151704040, - "attractiveness":82, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ee6d3ee1-1452-4d5e-99c6-ea7d08c84e74", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "318":{ - "name":"Grande Mosquée de Strasbourg", - "type":"sightseeing", - "location":[ - 48.573176, - 7.7371577 - ], - "osm_type":"way", - "osm_id":151771572, - "attractiveness":213, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"89da4376-2ab2-46e3-9500-2d3d8970cf32", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "319":{ - "name":"Société Droit Religion en Europe", - "type":"sightseeing", - "location":[ - 48.6051746, - 7.7132105 - ], - "osm_type":"way", - "osm_id":152955698, - "attractiveness":97, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"88091c88-f1a2-4404-88f2-8cd072f325b1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "320":{ - "name":"Société Droit Religion en Europe - Bâtiment 51", - "type":"sightseeing", - "location":[ - 48.6051135, - 7.7131933 - ], - "osm_type":"way", - "osm_id":152955700, - "attractiveness":99, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0029b3f8-d14c-46fb-b662-8c499e6220a4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "321":{ - "name":"École Maternelle Marguerite Perey", - "type":"sightseeing", - "location":[ - 48.6012259, - 7.7138678 - ], - "osm_type":"way", - "osm_id":152960427, - "attractiveness":92, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9459ff0e-0741-4e70-9696-fb0144c4abea", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "322":{ - "name":"K'fet des Sciences", - "type":"sightseeing", - "location":[ - 48.580333, - 7.7658151 - ], - "osm_type":"way", - "osm_id":155014772, - "attractiveness":192, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5e3c4e8f-06c3-40d5-bb2b-cf289b29a75b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "323":{ - "name":"Maison d'arrêt de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5654336, - 7.730896 - ], - "osm_type":"way", - "osm_id":160091489, - "attractiveness":120, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e1b56113-fb76-4f5e-b311-d54f624196d8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "324":{ - "name":"Emilie and the Cool Kids", - "type":"sightseeing", - "location":[ - 48.5736331, - 7.7565479 - ], - "osm_type":"way", - "osm_id":160165412, - "attractiveness":174, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1ec31729-c5f1-4fc3-821a-bd1df82d8313", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "325":{ - "name":"Pharmacie Rivétoile", - "type":"sightseeing", - "location":[ - 48.5735174, - 7.7573261 - ], - "osm_type":"way", - "osm_id":160165418, - "attractiveness":292, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"28c2d7ba-4693-4821-bf77-b3b0b2f02a8d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "326":{ - "name":"La pizza de Nico", - "type":"sightseeing", - "location":[ - 48.5737198, - 7.7585119 - ], - "osm_type":"way", - "osm_id":160278663, - "attractiveness":438, - "n_tags":21, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7d422697-9740-4800-880e-49277f10b850", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "327":{ - "name":"Yoghurt Factory", - "type":"sightseeing", - "location":[ - 48.5733819, - 7.7607013 - ], - "osm_type":"way", - "osm_id":160278666, - "attractiveness":130, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1c183054-1990-41dc-9409-d231e8d1e427", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "328":{ - "name":"Déchetterie de Strasbourg Meinau", - "type":"sightseeing", - "location":[ - 48.5643456, - 7.7414631 - ], - "osm_type":"way", - "osm_id":178449381, - "attractiveness":476, - "n_tags":24, - "image_url":null, - "description":null, - "duration":0, - "uuid":"198a6600-f7c1-499f-a6e1-8910ba13b9e1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "329":{ - "name":"EHPAD Saint-Charles", - "type":"sightseeing", - "location":[ - 48.6046396, - 7.7389266 - ], - "osm_type":"way", - "osm_id":218847489, - "attractiveness":195, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cabfee0e-af20-4064-9ce8-d43cefbf99e6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "330":{ - "name":"Archives de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5722887, - 7.7636798 - ], - "osm_type":"way", - "osm_id":237600156, - "attractiveness":140, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"361629bd-b1fa-43f6-9483-1e72c121f417", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "331":{ - "name":"Antoine Chevrier", - "type":"sightseeing", - "location":[ - 48.5649781, - 7.7258364 - ], - "osm_type":"way", - "osm_id":240820782, - "attractiveness":104, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"be5a20ab-b8f7-4598-8244-557ac1edb5e1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "332":{ - "name":"Chronopost Strasbourg", - "type":"sightseeing", - "location":[ - 48.5860227, - 7.7104656 - ], - "osm_type":"way", - "osm_id":258484499, - "attractiveness":186, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f6da222a-415c-4db2-809c-c83741756ee9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "333":{ - "name":"Centre socio-culturel du Neudorf", - "type":"sightseeing", - "location":[ - 48.572051, - 7.7646058 - ], - "osm_type":"way", - "osm_id":281553577, - "attractiveness":183, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"925e5006-87df-417e-971a-dc299f6e47e1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "334":{ - "name":"Podologue Francis Grauffel", - "type":"sightseeing", - "location":[ - 48.6046168, - 7.7461847 - ], - "osm_type":"way", - "osm_id":285038430, - "attractiveness":117, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"311caf55-ecbf-4f89-9ca2-d6354f34e06e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "335":{ - "name":"Opéra du Rhin", - "type":"sightseeing", - "location":[ - 48.5858887, - 7.752263 - ], - "osm_type":"way", - "osm_id":287247607, - "attractiveness":435, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f262dca7-ec27-4f62-bde1-eb0390a7a17f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "336":{ - "name":"INET - Institut National des Études Territoriales", - "type":"sightseeing", - "location":[ - 48.572874, - 7.7657072 - ], - "osm_type":"way", - "osm_id":287513648, - "attractiveness":240, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"41b97cf0-aac1-4955-b43c-ac2a1804e6b4", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "337":{ - "name":"Parking Panza", - "type":"sightseeing", - "location":[ - 48.5699996, - 7.7589534 - ], - "osm_type":"way", - "osm_id":299249540, - "attractiveness":89, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5cf8823c-7435-4dda-b6b5-c7b93087734b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "338":{ - "name":"Haute école des arts du Rhin", - "type":"sightseeing", - "location":[ - 48.5823167, - 7.7590964 - ], - "osm_type":"way", - "osm_id":299658097, - "attractiveness":221, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5a5e96c7-c94d-4b70-bdaa-21323e55b160", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "339":{ - "name":"Collège Lucie Berger", - "type":"sightseeing", - "location":[ - 48.5781225, - 7.7428232 - ], - "osm_type":"way", - "osm_id":299879930, - "attractiveness":63, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5a73150e-ed9f-45c0-a582-668bf311ba2a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "340":{ - "name":"Parking McDonald's", - "type":"sightseeing", - "location":[ - 48.6049331, - 7.7056469 - ], - "osm_type":"way", - "osm_id":306278684, - "attractiveness":115, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6491ccee-bae6-4d4f-9603-f14aac521262", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "341":{ - "name":"École primaire Sainte-Aurélie", - "type":"sightseeing", - "location":[ - 48.5814337, - 7.7331999 - ], - "osm_type":"way", - "osm_id":308689224, - "attractiveness":112, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b505171a-fa8f-4bc2-a3fa-1add9b9334e8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "342":{ - "name":"École maternelle Sainte-Aurèlie", - "type":"sightseeing", - "location":[ - 48.5807863, - 7.7332324 - ], - "osm_type":"way", - "osm_id":308689460, - "attractiveness":113, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eaf8556a-07f8-4e9c-9675-0a6cc7fe00e5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "343":{ - "name":"Déchèterie Wacken", - "type":"sightseeing", - "location":[ - 48.5958807, - 7.7471545 - ], - "osm_type":"way", - "osm_id":318547037, - "attractiveness":537, - "n_tags":27, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9d194e46-720a-422d-aaad-2e1918ce26a2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "344":{ - "name":"Groupe scolaire Saint-Thomas", - "type":"sightseeing", - "location":[ - 48.5799563, - 7.7439536 - ], - "osm_type":"way", - "osm_id":320756153, - "attractiveness":115, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4767b707-d25c-4410-ab36-274478527d75", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "345":{ - "name":"Café Atlantico", - "type":"sightseeing", - "location":[ - 48.5831817, - 7.7575637 - ], - "osm_type":"way", - "osm_id":343949370, - "attractiveness":374, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b762260c-d9ac-48c7-8e4f-1dab94f0bab1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "346":{ - "name":"Pharmacie de la charmille", - "type":"sightseeing", - "location":[ - 48.582341, - 7.7151628 - ], - "osm_type":"way", - "osm_id":367587980, - "attractiveness":194, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"84156f1b-4dae-439b-836a-60ec4fb32b3a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "347":{ - "name":"École Nationale Supérieure d'Architecture de Strasbourg", - "type":"sightseeing", - "location":[ - 48.5860011, - 7.7373471 - ], - "osm_type":"way", - "osm_id":398434973, - "attractiveness":327, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c0c391f4-df48-4b13-ba8d-6bf30205dff5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "348":{ - "name":"Parking du parc du château", - "type":"sightseeing", - "location":[ - 48.6024339, - 7.7497998 - ], - "osm_type":"way", - "osm_id":402195981, - "attractiveness":141, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a2c001ac-d07c-4ebf-82f3-17a0061e43ff", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "349":{ - "name":"Écoles Exen", - "type":"sightseeing", - "location":[ - 48.6054159, - 7.7499926 - ], - "osm_type":"way", - "osm_id":406268450, - "attractiveness":81, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"59630a9b-ae98-4a3f-ad15-927742e13473", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "350":{ - "name":"Parking Musique Hammer", - "type":"sightseeing", - "location":[ - 48.6039106, - 7.7508727 - ], - "osm_type":"way", - "osm_id":407875963, - "attractiveness":119, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"bfd32a12-80f4-401f-8772-b2ac7b432465", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "351":{ - "name":"Parking Steinmetz", - "type":"sightseeing", - "location":[ - 48.6035816, - 7.7513024 - ], - "osm_type":"way", - "osm_id":407875964, - "attractiveness":111, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"57158683-5a6e-4dd3-8729-6659d4d10516", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "352":{ - "name":"Parking Aldi", - "type":"sightseeing", - "location":[ - 48.5980091, - 7.7356451 - ], - "osm_type":"way", - "osm_id":433781017, - "attractiveness":72, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c4d0ca28-edd3-42e6-a033-7a912056da80", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "353":{ - "name":"Tri selectif : verre", - "type":"sightseeing", - "location":[ - 48.5990223, - 7.733174 - ], - "osm_type":"way", - "osm_id":439707000, - "attractiveness":80, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eb8ab394-c5d0-4311-81c2-0f256254903f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "354":{ - "name":"P City Residence", - "type":"sightseeing", - "location":[ - 48.5894163, - 7.7387122 - ], - "osm_type":"way", - "osm_id":445787178, - "attractiveness":115, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"719eefab-738c-405f-a908-a6f4478279f7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "355":{ - "name":"Pharmacie du Hohberg", - "type":"sightseeing", - "location":[ - 48.583705, - 7.7076849 - ], - "osm_type":"way", - "osm_id":466428293, - "attractiveness":139, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1591206c-f6cb-46cf-b9e0-9a6f80210d49", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "356":{ - "name":"Parking Vélos CHU Hautepierre", - "type":"sightseeing", - "location":[ - 48.5923944, - 7.7087279 - ], - "osm_type":"way", - "osm_id":481002897, - "attractiveness":198, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3ebc0bae-c74c-4bb8-b798-38eb7432186e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "357":{ - "name":"Mosquée de Hautepierre", - "type":"sightseeing", - "location":[ - 48.5935551, - 7.701968 - ], - "osm_type":"way", - "osm_id":488664049, - "attractiveness":129, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fb13b7cc-d93e-4604-a606-7e2ce1617a2e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "358":{ - "name":"Groupe Scolaire Catherine", - "type":"sightseeing", - "location":[ - 48.5955066, - 7.7015441 - ], - "osm_type":"way", - "osm_id":491790619, - "attractiveness":43, - "n_tags":2, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a0732543-1193-462f-9f5d-1e6741ead821", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "359":{ - "name":"Dépose Minute", - "type":"sightseeing", - "location":[ - 48.5925412, - 7.7086365 - ], - "osm_type":"way", - "osm_id":495813732, - "attractiveness":161, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9600b53f-028a-46a9-8598-f280d93699cb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "360":{ - "name":"Réservé Urgences", - "type":"sightseeing", - "location":[ - 48.5930056, - 7.7049537 - ], - "osm_type":"way", - "osm_id":495963769, - "attractiveness":172, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"186ef8bc-83a6-4b7d-8c3e-b46dcc4b6e29", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "361":{ - "name":"Cafétéria CHU Hautepierre", - "type":"sightseeing", - "location":[ - 48.5926714, - 7.7070792 - ], - "osm_type":"way", - "osm_id":500546150, - "attractiveness":122, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f2f98ebd-7a23-4c91-918f-8d5641b59e68", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "362":{ - "name":"École maternelle Jacques Prévert", - "type":"sightseeing", - "location":[ - 48.6022485, - 7.7375706 - ], - "osm_type":"way", - "osm_id":503980502, - "attractiveness":157, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0adbf9c9-7c6c-40f2-829f-2bb610e23a33", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "363":{ - "name":"Parking Rue des Vosges", - "type":"sightseeing", - "location":[ - 48.5912783, - 7.7576616 - ], - "osm_type":"way", - "osm_id":515351591, - "attractiveness":85, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"203df493-9549-4cdf-a143-c378851be21a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "364":{ - "name":"Banque Populaire", - "type":"sightseeing", - "location":[ - 48.5918863, - 7.7413117 - ], - "osm_type":"way", - "osm_id":530800397, - "attractiveness":296, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7a6c2f64-f26f-453f-ada7-233a63331c31", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "365":{ - "name":"Maison de la petite enfance de Koenigshoffen", - "type":"sightseeing", - "location":[ - 48.581552, - 7.7124979 - ], - "osm_type":"way", - "osm_id":540719645, - "attractiveness":149, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3f240d24-2df0-46a6-a919-75f19eb181f6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "366":{ - "name":"Parking Arte", - "type":"sightseeing", - "location":[ - 48.5941708, - 7.7651353 - ], - "osm_type":"way", - "osm_id":546087900, - "attractiveness":84, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3c2f4373-cb3e-4893-bb7c-37848f56028f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "367":{ - "name":"Societé de Protection des Animaux (SPA) de Strasbourg", - "type":"sightseeing", - "location":[ - 48.6005942, - 7.7288159 - ], - "osm_type":"way", - "osm_id":550714898, - "attractiveness":93, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"36d3d517-e0b2-4fea-8369-dfbf5ccf8656", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "368":{ - "name":"Parking Personnel", - "type":"sightseeing", - "location":[ - 48.5745134, - 7.743644 - ], - "osm_type":"way", - "osm_id":561121930, - "attractiveness":102, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5503fc1b-9ae4-4bb0-ab11-dc0c99f3a7e3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "369":{ - "name":"Barco Latino", - "type":"sightseeing", - "location":[ - 48.5740175, - 7.7608481 - ], - "osm_type":"way", - "osm_id":562438805, - "attractiveness":206, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4102047a-e117-4db0-879d-ec6863585fae", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "370":{ - "name":"Parking Au Plaisirs d'Asie", - "type":"sightseeing", - "location":[ - 48.5978137, - 7.7363843 - ], - "osm_type":"way", - "osm_id":572658561, - "attractiveness":92, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"007a23cd-f900-40a3-99a3-b92e7aedf052", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "371":{ - "name":"Centre de Recherche en Biomédecine", - "type":"sightseeing", - "location":[ - 48.575984, - 7.7389818 - ], - "osm_type":"way", - "osm_id":655084918, - "attractiveness":359, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e2787195-e4e1-4109-a5af-d36f49165f2d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "372":{ - "name":"Véloparc Schluthfeld", - "type":"sightseeing", - "location":[ - 48.5686777, - 7.7520356 - ], - "osm_type":"way", - "osm_id":687020295, - "attractiveness":200, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9bca7aad-b59f-433c-8447-eef314f5e4b5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "373":{ - "name":"Véloparc Krimmeri", - "type":"sightseeing", - "location":[ - 48.5625311, - 7.7524022 - ], - "osm_type":"way", - "osm_id":687020403, - "attractiveness":206, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dc02ab92-5e99-42d9-8e90-aaec9d1f5092", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "374":{ - "name":"Le kiosque d'Omnino", - "type":"sightseeing", - "location":[ - 48.583173, - 7.7401939 - ], - "osm_type":"way", - "osm_id":692196205, - "attractiveness":315, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c938588e-6c21-4d93-bfa9-d2229544a11a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "375":{ - "name":"Peniche Mécanique", - "type":"sightseeing", - "location":[ - 48.5740803, - 7.7602081 - ], - "osm_type":"way", - "osm_id":702443797, - "attractiveness":239, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0d108b49-63b9-44fa-ab20-aa63632c76bb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "376":{ - "name":"EHPAD Montagne Verte", - "type":"sightseeing", - "location":[ - 48.5721138, - 7.7220784 - ], - "osm_type":"way", - "osm_id":702551682, - "attractiveness":188, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"49c3cab2-5284-4585-b5ca-5774aa803ebe", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "377":{ - "name":"Communauté des sœurs de Marie Réparatrice", - "type":"sightseeing", - "location":[ - 48.5773525, - 7.7452864 - ], - "osm_type":"way", - "osm_id":707912156, - "attractiveness":128, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d43bea6f-a396-4130-865a-cffd72c65edb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "378":{ - "name":"Cité Universitaire Paul Appell", - "type":"sightseeing", - "location":[ - 48.5763182, - 7.7630225 - ], - "osm_type":"way", - "osm_id":713776095, - "attractiveness":117, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4763fce0-9076-45ef-8a9a-11c12f21c7f1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "379":{ - "name":"Le Studium", - "type":"sightseeing", - "location":[ - 48.5815168, - 7.7664504 - ], - "osm_type":"way", - "osm_id":725967646, - "attractiveness":300, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"12c2a8cf-6547-4dac-a7e1-ea82c73e09c6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "380":{ - "name":"EHPAD Caritas", - "type":"sightseeing", - "location":[ - 48.5825482, - 7.6982902 - ], - "osm_type":"way", - "osm_id":738897222, - "attractiveness":172, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3478c098-59e7-40b6-a6fc-12207db42e9b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "381":{ - "name":"Fontaine du Lazaret", - "type":"sightseeing", - "location":[ - 48.5626613, - 7.762019 - ], - "osm_type":"way", - "osm_id":769030230, - "attractiveness":112, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7ba0377f-fba3-4766-96ae-646d75df24f3", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "382":{ - "name":"Hôpital de Jour Abrapa", - "type":"sightseeing", - "location":[ - 48.5770354, - 7.7458673 - ], - "osm_type":"way", - "osm_id":777325748, - "attractiveness":117, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9789358e-62ee-4a4b-9f99-95034356da68", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "383":{ - "name":"Centre Médico-Chirurgical et Obstétrical", - "type":"sightseeing", - "location":[ - 48.6004476, - 7.7500196 - ], - "osm_type":"way", - "osm_id":787481692, - "attractiveness":302, - "n_tags":15, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b9c1efec-4422-4921-9518-ad664ab2701e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "384":{ - "name":"Centre Paul Strauss", - "type":"sightseeing", - "location":[ - 48.5764092, - 7.7510095 - ], - "osm_type":"way", - "osm_id":787519495, - "attractiveness":274, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"768825d9-be93-4815-8daa-305dfe18bbc7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "385":{ - "name":"Clinique de la Toussaint", - "type":"sightseeing", - "location":[ - 48.5873259, - 7.7451279 - ], - "osm_type":"way", - "osm_id":788882576, - "attractiveness":254, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4ed027f8-a845-4524-816b-bf5f7f090a86", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "386":{ - "name":"Clinique de l'Orangerie", - "type":"sightseeing", - "location":[ - 48.5881667, - 7.7647546 - ], - "osm_type":"way", - "osm_id":788885571, - "attractiveness":197, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c535660f-eec1-4347-9543-f6b15ec8bef2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "387":{ - "name":"Centre Culturel Turc", - "type":"sightseeing", - "location":[ - 48.5856451, - 7.7198093 - ], - "osm_type":"way", - "osm_id":803430879, - "attractiveness":78, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"98350b1c-7e73-4f2e-9cb4-352de3affac9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "388":{ - "name":"Centre de formation des Compagnons du Devoir", - "type":"sightseeing", - "location":[ - 48.581096, - 7.7218117 - ], - "osm_type":"way", - "osm_id":803432415, - "attractiveness":91, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"85a8b173-108e-4187-aa67-18a780339d60", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "389":{ - "name":"Blue Flamingo", - "type":"sightseeing", - "location":[ - 48.5741237, - 7.759566 - ], - "osm_type":"way", - "osm_id":849800106, - "attractiveness":211, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d2a7ba7d-587c-41dc-85a8-f2fd3134223c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "390":{ - "name":"École élementaire Louvois", - "type":"sightseeing", - "location":[ - 48.5753617, - 7.7607627 - ], - "osm_type":"way", - "osm_id":880628784, - "attractiveness":93, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2e9f9844-b93f-4bfc-8ff0-2d9305c86743", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "391":{ - "name":"Place handicapé", - "type":"sightseeing", - "location":[ - 48.5706163, - 7.7590571 - ], - "osm_type":"way", - "osm_id":898572029, - "attractiveness":172, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7beef5e7-bd51-4f49-8d48-32d6d91c34f6", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "392":{ - "name":"Maison des associations", - "type":"sightseeing", - "location":[ - 48.5710885, - 7.7560426 - ], - "osm_type":"way", - "osm_id":898629833, - "attractiveness":164, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a69f6de0-2063-480d-8e90-f0063dcdb5f9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "393":{ - "name":"Centre d'incendie et de secours Strasbourg-Ouest", - "type":"sightseeing", - "location":[ - 48.5895804, - 7.7277613 - ], - "osm_type":"way", - "osm_id":931851355, - "attractiveness":141, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2b65b4c7-5982-4391-b69a-f485164c4672", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "394":{ - "name":"Groupe Scolaire du Finkwiller", - "type":"sightseeing", - "location":[ - 48.5787085, - 7.7409624 - ], - "osm_type":"way", - "osm_id":933655725, - "attractiveness":69, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9a66ab3f-a8fe-4986-b2f6-05a6f98f89d1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "395":{ - "name":"Groupe Scolaire Saint-Jean", - "type":"sightseeing", - "location":[ - 48.5892166, - 7.7433992 - ], - "osm_type":"way", - "osm_id":936476891, - "attractiveness":34, - "n_tags":2, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f731948f-e5f8-4a3d-ae1b-d49140e0143f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "396":{ - "name":"Lycée International Pontonniers", - "type":"sightseeing", - "location":[ - 48.584644, - 7.756182 - ], - "osm_type":"way", - "osm_id":962683865, - "attractiveness":243, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5f44e1dd-ea5c-4f5d-b2d0-1dc3a00ddd53", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "397":{ - "name":"École et Observatoire des Sciences de la Terre", - "type":"sightseeing", - "location":[ - 48.5799831, - 7.7623986 - ], - "osm_type":"way", - "osm_id":968814565, - "attractiveness":57, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d51b05f8-4f94-4d59-a149-2a2ea75a1604", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "398":{ - "name":"Parc des Expositions", - "type":"sightseeing", - "location":[ - 48.5966169, - 7.7523551 - ], - "osm_type":"way", - "osm_id":973489794, - "attractiveness":70, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"442ec209-ca42-4642-acfb-d9cdacf6cb3a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "399":{ - "name":"Mosquée Turque Eyyub-Sultan", - "type":"sightseeing", - "location":[ - 48.56232, - 7.7447463 - ], - "osm_type":"way", - "osm_id":975021326, - "attractiveness":60, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c08b0e44-4af6-4012-90a3-13b313efae47", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "400":{ - "name":"Le Meiselocker", - "type":"sightseeing", - "location":[ - 48.5834011, - 7.7547026 - ], - "osm_type":"way", - "osm_id":975449056, - "attractiveness":125, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dcf3fde2-a9c5-42ab-adce-bf83737b70cc", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "401":{ - "name":"Place de Bordeaux", - "type":"sightseeing", - "location":[ - 48.5934912, - 7.7576553 - ], - "osm_type":"way", - "osm_id":981575948, - "attractiveness":176, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c0e1ceaf-b479-4e26-9d89-0198fdfaad23", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "402":{ - "name":"Hôpital Psychiatrique EPSAN à Cronenbourg", - "type":"sightseeing", - "location":[ - 48.6045624, - 7.7149985 - ], - "osm_type":"way", - "osm_id":993769600, - "attractiveness":44, - "n_tags":3, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c7a25c2b-79ff-4af3-bb15-b0c9614ec551", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "403":{ - "name":"Meet&go", - "type":"sightseeing", - "location":[ - 48.5852368, - 7.7346646 - ], - "osm_type":"way", - "osm_id":997898116, - "attractiveness":288, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a065fd49-d750-41ea-aa9f-d2bde8667786", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "404":{ - "name":"Commissariat de police", - "type":"sightseeing", - "location":[ - 48.5844008, - 7.7340232 - ], - "osm_type":"way", - "osm_id":997898127, - "attractiveness":353, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"24f3f38d-7887-4a84-a2ea-3a371df438be", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "405":{ - "name":"Subway", - "type":"sightseeing", - "location":[ - 48.5859368, - 7.7411652 - ], - "osm_type":"way", - "osm_id":1000017660, - "attractiveness":287, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d841671d-e5f4-4db0-b07a-07f418b43e24", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "406":{ - "name":"Phan Asia", - "type":"sightseeing", - "location":[ - 48.58746, - 7.7406537 - ], - "osm_type":"way", - "osm_id":1001386069, - "attractiveness":209, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"91877138-b5bc-4e91-91b4-2abd2408b0a8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "407":{ - "name":"Crêp'eat", - "type":"sightseeing", - "location":[ - 48.5868263, - 7.7409465 - ], - "osm_type":"way", - "osm_id":1001406930, - "attractiveness":249, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"423dd384-3716-4bf2-a43e-e2fb0e667e26", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "408":{ - "name":"Pharmacie des Halles", - "type":"sightseeing", - "location":[ - 48.5869146, - 7.7412203 - ], - "osm_type":"way", - "osm_id":1001406931, - "attractiveness":291, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ddf01091-17be-470b-80c3-1cc5032b73cb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "409":{ - "name":"Zumo", - "type":"sightseeing", - "location":[ - 48.5865137, - 7.7411574 - ], - "osm_type":"way", - "osm_id":1001406938, - "attractiveness":251, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4c094864-e37e-424b-973b-c87083c1c2ab", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "410":{ - "name":"Pur etc", - "type":"sightseeing", - "location":[ - 48.5869371, - 7.7407944 - ], - "osm_type":"way", - "osm_id":1001442479, - "attractiveness":202, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9200f3c9-ffb9-4f44-b757-3bf2dbd79a1c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "411":{ - "name":"La Pause", - "type":"sightseeing", - "location":[ - 48.5875266, - 7.7407115 - ], - "osm_type":"way", - "osm_id":1001442481, - "attractiveness":200, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"73775261-066d-48c3-994e-05698c2710a1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "412":{ - "name":"Dépose-minute Conservatoire", - "type":"sightseeing", - "location":[ - 48.5742487, - 7.7551635 - ], - "osm_type":"way", - "osm_id":1001891414, - "attractiveness":223, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"805d990b-c692-41d0-857c-fb68d1725fd8", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "413":{ - "name":"Le Cardo", - "type":"sightseeing", - "location":[ - 48.577191, - 7.7471325 - ], - "osm_type":"way", - "osm_id":1008875558, - "attractiveness":840, - "n_tags":17, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1b3be37a-1b99-4cad-aa7c-d55932799e03", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "414":{ - "name":"Place Dentaire", - "type":"sightseeing", - "location":[ - 48.5733154, - 7.7595294 - ], - "osm_type":"way", - "osm_id":1012884318, - "attractiveness":230, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0ed4e0b5-32a0-4673-a42b-cadc3684abff", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "415":{ - "name":"Bagelstein", - "type":"sightseeing", - "location":[ - 48.5735058, - 7.760531 - ], - "osm_type":"way", - "osm_id":1012884356, - "attractiveness":162, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"37ed5b1d-f786-4881-b4c7-5731cc7c05ee", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "416":{ - "name":"KFC", - "type":"sightseeing", - "location":[ - 48.573159, - 7.7609123 - ], - "osm_type":"way", - "osm_id":1012884357, - "attractiveness":503, - "n_tags":24, - "image_url":null, - "description":null, - "duration":0, - "uuid":"08839153-bc35-406a-b994-039a3d25c20f", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "417":{ - "name":"Direction de territoire : CRONENBOURG - HAUTEPIERRE - POTERIES - HOHBERG", - "type":"sightseeing", - "location":[ - 48.5909853, - 7.7088725 - ], - "osm_type":"way", - "osm_id":1046228331, - "attractiveness":130, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8f194d45-94de-47c7-8be1-a945c7f0ca4a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "418":{ - "name":"Restaurant Centre régional des œuvres universitaires et scolaires", - "type":"sightseeing", - "location":[ - 48.6056188, - 7.713933 - ], - "osm_type":"way", - "osm_id":1051453980, - "attractiveness":119, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7c623c55-9e70-43b2-a3df-474997219216", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "419":{ - "name":"Centre National de la Recherche Scientifique - IPHC", - "type":"sightseeing", - "location":[ - 48.6049163, - 7.7115483 - ], - "osm_type":"way", - "osm_id":1051455165, - "attractiveness":98, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f9c64bb5-d980-496c-b80c-b230477ecb37", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "420":{ - "name":"Géosciences, de l'eau, de l'environnement, et de l'ingénierie", - "type":"sightseeing", - "location":[ - 48.5808648, - 7.7584925 - ], - "osm_type":"way", - "osm_id":1053292870, - "attractiveness":78, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"28801df4-865d-45f7-b40f-6990d1a94f47", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "421":{ - "name":"Espace événementiel", - "type":"sightseeing", - "location":[ - 48.5809399, - 7.7582691 - ], - "osm_type":"way", - "osm_id":1053292874, - "attractiveness":42, - "n_tags":2, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c7606878-36c3-4b90-8bf6-031a15840720", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "422":{ - "name":"Pro Grill", - "type":"sightseeing", - "location":[ - 48.5876336, - 7.7005204 - ], - "osm_type":"way", - "osm_id":1054791888, - "attractiveness":104, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"add43b49-36a8-4327-a8ae-ee611f619441", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "423":{ - "name":"Collège Caroline Aigle", - "type":"sightseeing", - "location":[ - 48.5778284, - 7.7556221 - ], - "osm_type":"way", - "osm_id":1059530531, - "attractiveness":267, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b89d8b4e-42cb-4b53-bd90-729438b7f4fd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "424":{ - "name":"Le Lavoir", - "type":"sightseeing", - "location":[ - 48.5840505, - 7.7401703 - ], - "osm_type":"way", - "osm_id":1066869836, - "attractiveness":287, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dbf87be2-97dd-4b68-bdf4-71fa973504bd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "425":{ - "name":"BUS", - "type":"sightseeing", - "location":[ - 48.5941301, - 7.7353135 - ], - "osm_type":"way", - "osm_id":1079847903, - "attractiveness":98, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"31a6600f-d066-449a-bde6-3b33e215dfdb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "426":{ - "name":"Halle du marché de Neudorf", - "type":"sightseeing", - "location":[ - 48.5667985, - 7.7604529 - ], - "osm_type":"way", - "osm_id":1080718584, - "attractiveness":204, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"8715243c-d24e-4cc0-8fda-ed0f6ff75576", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "427":{ - "name":"Planétarium du Jardin des sciences", - "type":"sightseeing", - "location":[ - 48.5832366, - 7.7638927 - ], - "osm_type":"way", - "osm_id":1081010784, - "attractiveness":218, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"67c118cb-147b-4acd-a621-a590fd001b6c", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "428":{ - "name":"Déchèterie", - "type":"sightseeing", - "location":[ - 48.5841154, - 7.7163051 - ], - "osm_type":"way", - "osm_id":1090005393, - "attractiveness":88, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"35962c84-798c-4f09-92c8-a6798316ab29", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "429":{ - "name":"Institution La Doctrine Chrétienne", - "type":"sightseeing", - "location":[ - 48.5906187, - 7.7232206 - ], - "osm_type":"way", - "osm_id":1098843020, - "attractiveness":118, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4b9e21db-04ef-4482-ad80-f784b24ac2ff", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "430":{ - "name":"L'Orée 85", - "type":"sightseeing", - "location":[ - 48.5689771, - 7.7345561 - ], - "osm_type":"way", - "osm_id":1104400943, - "attractiveness":360, - "n_tags":18, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2c4eedcf-1eed-44c0-925c-80c91be49513", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "431":{ - "name":"CHRS Femmes de Paroles", - "type":"sightseeing", - "location":[ - 48.5752522, - 7.7261335 - ], - "osm_type":"way", - "osm_id":1119117552, - "attractiveness":202, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0f720820-1308-41c7-8b15-d521f2cfd42e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "432":{ - "name":"Cantine Louis Pasteur", - "type":"sightseeing", - "location":[ - 48.5757944, - 7.7380624 - ], - "osm_type":"way", - "osm_id":1133748232, - "attractiveness":83, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"374de9c5-1602-4ae1-a74e-f2bfa1606d46", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "433":{ - "name":"Groupe Scolaire Simone Veil", - "type":"sightseeing", - "location":[ - 48.6008454, - 7.743517 - ], - "osm_type":"way", - "osm_id":1135517313, - "attractiveness":188, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"4aa8c2c0-f03b-459e-9757-5cafc718252e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "434":{ - "name":"Accueil du Jardin des sciences", - "type":"sightseeing", - "location":[ - 48.5830548, - 7.7641569 - ], - "osm_type":"way", - "osm_id":1138976617, - "attractiveness":327, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"eab0ad0b-7cd3-4cb9-9adc-a59ffbbd11bf", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "435":{ - "name":"Baraka Jeux", - "type":"sightseeing", - "location":[ - 48.5839109, - 7.7440524 - ], - "osm_type":"way", - "osm_id":1145630033, - "attractiveness":196, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d5b0d541-f68e-4c12-9e73-21f94a2b4dd0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "436":{ - "name":"Brasserie en Alsace", - "type":"sightseeing", - "location":[ - 48.5847347, - 7.7343447 - ], - "osm_type":"way", - "osm_id":1152983997, - "attractiveness":250, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7ec68211-4939-4b74-9ef8-d432ddf230de", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "437":{ - "name":"Objets trouvés", - "type":"sightseeing", - "location":[ - 48.585184, - 7.7346631 - ], - "osm_type":"way", - "osm_id":1152990565, - "attractiveness":303, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"28d8ba23-26c2-47bb-9777-8d8144033399", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "438":{ - "name":"Salon grand voyageur", - "type":"sightseeing", - "location":[ - 48.5848874, - 7.734411 - ], - "osm_type":"way", - "osm_id":1152990567, - "attractiveness":269, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9173d29b-083c-4ffa-a3ca-f020a22804a9", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "439":{ - "name":"Bertani", - "type":"sightseeing", - "location":[ - 48.5844406, - 7.749238 - ], - "osm_type":"way", - "osm_id":1164808789, - "attractiveness":212, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7fb02857-05ac-4fc2-8f74-90264ebfc0e5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "440":{ - "name":"Parking du PEX", - "type":"sightseeing", - "location":[ - 48.5962257, - 7.7540886 - ], - "osm_type":"way", - "osm_id":1167173035, - "attractiveness":207, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"cd28ae81-0c9b-48e0-83f7-f564541b3b64", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "441":{ - "name":"Médiathèque Jeunesse Olympe de Gouges (Centre ville)", - "type":"sightseeing", - "location":[ - 48.5847306, - 7.7389687 - ], - "osm_type":"way", - "osm_id":1188398624, - "attractiveness":136, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f4ecf813-8cb9-4741-8cd6-2983de6da601", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "442":{ - "name":"École maternelle Parc du Château", - "type":"sightseeing", - "location":[ - 48.602202, - 7.750678 - ], - "osm_type":"way", - "osm_id":1216416394, - "attractiveness":143, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"56fbaecf-b35e-460c-8d6f-212f69c66be5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "443":{ - "name":"Cour des Médecins", - "type":"sightseeing", - "location":[ - 48.5864539, - 7.7365286 - ], - "osm_type":"way", - "osm_id":1243118414, - "attractiveness":99, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2be4ec5b-de9f-4dd5-8eea-bdaa5c02957b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "444":{ - "name":"Cour de l'Aigle", - "type":"sightseeing", - "location":[ - 48.5861037, - 7.7361213 - ], - "osm_type":"way", - "osm_id":1243118415, - "attractiveness":109, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"386e57b0-bd54-4ba7-a71f-474b9d16e9f2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "445":{ - "name":"Cour Intérieure", - "type":"sightseeing", - "location":[ - 48.5862623, - 7.7357454 - ], - "osm_type":"way", - "osm_id":1243118416, - "attractiveness":135, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"287b6778-4d71-4643-9631-ed4fe656b3f0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "446":{ - "name":"Saint-Florent", - "type":"sightseeing", - "location":[ - 48.5960762, - 7.7215955 - ], - "osm_type":"way", - "osm_id":1257186377, - "attractiveness":292, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"14657ed6-eda2-43ac-a5c8-587d070db846", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "447":{ - "name":"Palais des Fêtes", - "type":"sightseeing", - "location":[ - 48.5908291, - 7.7493322 - ], - "osm_type":"relation", - "osm_id":157861, - "attractiveness":273, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"ac35bc42-c751-4d2a-b2ab-5d0fde96871a", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "448":{ - "name":"BNP Paribas", - "type":"sightseeing", - "location":[ - 48.5838878, - 7.749156 - ], - "osm_type":"relation", - "osm_id":216044, - "attractiveness":263, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0ee797fc-406c-43cd-9903-9ca7bf015a53", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "449":{ - "name":"Site de la Fonderie", - "type":"sightseeing", - "location":[ - 48.5861007, - 7.749314 - ], - "osm_type":"relation", - "osm_id":216512, - "attractiveness":109, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"f6195e25-5a9a-4041-894a-c65d20f995ad", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "450":{ - "name":"Le Gruber", - "type":"sightseeing", - "location":[ - 48.5806321, - 7.7505316 - ], - "osm_type":"relation", - "osm_id":223820, - "attractiveness":463, - "n_tags":21, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1170087d-2162-48be-8387-47efcdb95b51", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "451":{ - "name":"Société Générale", - "type":"sightseeing", - "location":[ - 48.6048403, - 7.7036217 - ], - "osm_type":"relation", - "osm_id":224236, - "attractiveness":223, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"7d0a6124-c2dc-4d4a-8286-791a2f348a30", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "452":{ - "name":"Direction régionale des Finances Publiques d'Alsace et du département du Bas-Rhin", - "type":"sightseeing", - "location":[ - 48.5883877, - 7.754041 - ], - "osm_type":"relation", - "osm_id":227003, - "attractiveness":279, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fb1fb274-e37e-4037-adad-27fada9411ef", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "453":{ - "name":"Palais de Justice", - "type":"sightseeing", - "location":[ - 48.5881911, - 7.7478698 - ], - "osm_type":"relation", - "osm_id":228029, - "attractiveness":230, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"e5e22c25-ecd5-42ff-9cbc-988a0c0f77b5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "454":{ - "name":"Institut national du service public", - "type":"sightseeing", - "location":[ - 48.5808026, - 7.7373507 - ], - "osm_type":"relation", - "osm_id":228395, - "attractiveness":376, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"dd10c634-5ac1-4fe6-8744-11073f53d3ec", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "455":{ - "name":"Hôtel du Département", - "type":"sightseeing", - "location":[ - 48.5784412, - 7.7380667 - ], - "osm_type":"relation", - "osm_id":228447, - "attractiveness":120, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"96035ac3-07f2-47ba-a6e6-2d89b64f35fe", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "456":{ - "name":"Faculté de Chirurgie Dentaire", - "type":"sightseeing", - "location":[ - 48.5773439, - 7.7449516 - ], - "osm_type":"relation", - "osm_id":230046, - "attractiveness":110, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"68b58da5-61ab-47f8-bb3e-ec9eca19a00b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "457":{ - "name":"Bibliothèque Nationale Universitaire de Strasbourg", - "type":"sightseeing", - "location":[ - 48.587169, - 7.7558213 - ], - "osm_type":"relation", - "osm_id":236931, - "attractiveness":671, - "n_tags":31, - "image_url":null, - "description":null, - "duration":0, - "uuid":"31488c2a-cf7e-4bd4-8354-7f0b2c00e04e", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "458":{ - "name":"Restaurant Universitaire Gallia", - "type":"sightseeing", - "location":[ - 48.5843491, - 7.7595883 - ], - "osm_type":"relation", - "osm_id":238063, - "attractiveness":234, - "n_tags":11, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6c399982-2f67-47cc-805d-aa1ccbdda7b0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "459":{ - "name":"Faculté des Langues", - "type":"sightseeing", - "location":[ - 48.5781106, - 7.7654182 - ], - "osm_type":"relation", - "osm_id":240864, - "attractiveness":251, - "n_tags":14, - "image_url":null, - "description":null, - "duration":0, - "uuid":"1cc31db2-a5f6-416d-80a6-7f0e7a10c141", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "460":{ - "name":"Institut de Géologie", - "type":"sightseeing", - "location":[ - 48.5834376, - 7.7629399 - ], - "osm_type":"relation", - "osm_id":241594, - "attractiveness":179, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a93acdfd-af2a-4c73-aadc-968fd0e15f88", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "461":{ - "name":"Institut Universitaire de Technologie Louis Pasteur", - "type":"sightseeing", - "location":[ - 48.6074836, - 7.7079621 - ], - "osm_type":"relation", - "osm_id":252831, - "attractiveness":111, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"6ed37369-5728-46d2-a743-42543effa536", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "462":{ - "name":"Parking Gare Wodli", - "type":"sightseeing", - "location":[ - 48.5873726, - 7.7367546 - ], - "osm_type":"relation", - "osm_id":259307, - "attractiveness":282, - "n_tags":13, - "image_url":null, - "description":null, - "duration":0, - "uuid":"9a5e9bd9-052e-49c1-ad33-2258da3afaf7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "463":{ - "name":"Direction Régionale de la SNCF", - "type":"sightseeing", - "location":[ - 48.5862571, - 7.7361786 - ], - "osm_type":"relation", - "osm_id":261658, - "attractiveness":113, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"af58b049-3dfa-45dc-8fa7-63d6286f9d39", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "464":{ - "name":"Mathématique, Informatique - Physique du Globe", - "type":"sightseeing", - "location":[ - 48.5798654, - 7.7632636 - ], - "osm_type":"relation", - "osm_id":366500, - "attractiveness":90, - "n_tags":5, - "image_url":null, - "description":null, - "duration":0, - "uuid":"2109f1ba-006b-4a0e-b6ae-5a72fc1f21bb", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "465":{ - "name":"Palais Universitaire", - "type":"sightseeing", - "location":[ - 48.5848129, - 7.7624991 - ], - "osm_type":"relation", - "osm_id":368604, - "attractiveness":399, - "n_tags":19, - "image_url":null, - "description":null, - "duration":0, - "uuid":"d0845932-207f-46d4-85dc-0f2a823c5906", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "466":{ - "name":"Collège Louis Pasteur", - "type":"sightseeing", - "location":[ - 48.5733055, - 7.7387487 - ], - "osm_type":"relation", - "osm_id":4460379, - "attractiveness":117, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b8657678-a0e5-41a1-a5a4-45d6e7d00e9d", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "467":{ - "name":"École primaire Exen Pire", - "type":"sightseeing", - "location":[ - 48.6052315, - 7.7495768 - ], - "osm_type":"relation", - "osm_id":6327072, - "attractiveness":158, - "n_tags":8, - "image_url":null, - "description":null, - "duration":0, - "uuid":"36841ce3-7fef-40af-b14e-bb31068bd839", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "468":{ - "name":"École primaire Exen Schweitzer", - "type":"sightseeing", - "location":[ - 48.6057675, - 7.7499638 - ], - "osm_type":"relation", - "osm_id":6327073, - "attractiveness":130, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"3c046f26-6007-4928-9956-75fb24879d77", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "469":{ - "name":"Restaurant Universitaire Paul Appell", - "type":"sightseeing", - "location":[ - 48.5759619, - 7.762996 - ], - "osm_type":"relation", - "osm_id":8240757, - "attractiveness":190, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"c7cee4a8-b74c-428f-838f-8dc69f3703d7", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "470":{ - "name":"Parking relais-tram P+R Parc des Romains", - "type":"sightseeing", - "location":[ - 48.5817024, - 7.7241421 - ], - "osm_type":"relation", - "osm_id":11668557, - "attractiveness":418, - "n_tags":20, - "image_url":null, - "description":null, - "duration":0, - "uuid":"a2195bec-4190-474f-96cd-8c735d6a21c2", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "471":{ - "name":"Groupe scolaire Sainte-Madeleine", - "type":"sightseeing", - "location":[ - 48.579786, - 7.7542586 - ], - "osm_type":"relation", - "osm_id":14103600, - "attractiveness":247, - "n_tags":12, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0877f1d4-83e9-40bb-bdd7-996062d4ceb0", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "472":{ - "name":"La Grenze", - "type":"sightseeing", - "location":[ - 48.5889655, - 7.7348998 - ], - "osm_type":"relation", - "osm_id":14211218, - "attractiveness":317, - "n_tags":16, - "image_url":null, - "description":null, - "duration":0, - "uuid":"0cddda65-3cd3-4eac-944f-bdc8bec91fd5", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "473":{ - "name":"École maternelle-élémentaire Rosa Parks", - "type":"sightseeing", - "location":[ - 48.6074934, - 7.7664371 - ], - "osm_type":"relation", - "osm_id":14254313, - "attractiveness":250, - "n_tags":10, - "image_url":null, - "description":null, - "duration":0, - "uuid":"45ef7d92-e3b9-4340-9f20-c5033211521b", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "474":{ - "name":"Toilettes publiques", - "type":"sightseeing", - "location":[ - 48.5846113, - 7.7336135 - ], - "osm_type":"relation", - "osm_id":16354356, - "attractiveness":197, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"5b8a3a59-9468-46bc-a30e-0a480daeebe1", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "475":{ - "name":"Canal de la Marne au Rhin", - "type":"sightseeing", - "location":[ - 48.5963838, - 7.7782303 - ], - "osm_type":"way", - "osm_id":10424914, - "attractiveness":100, - "n_tags":6, - "image_url":null, - "description":null, - "duration":0, - "uuid":"144c0f13-e60a-4970-a9b6-a401075b7a54", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "476":{ - "name":"Bassin de la Porte de l’Hôpital", - "type":"sightseeing", - "location":[ - 48.573628, - 7.7456353 - ], - "osm_type":"way", - "osm_id":43520883, - "attractiveness":136, - "n_tags":7, - "image_url":null, - "description":null, - "duration":0, - "uuid":"fb1a7576-2231-4083-a23a-4aa0052c93ca", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "477":{ - "name":"Le Rhin Tortu", - "type":"sightseeing", - "location":[ - 48.5656635, - 7.7460474 - ], - "osm_type":"way", - "osm_id":43570553, - "attractiveness":140, - "n_tags":9, - "image_url":null, - "description":null, - "duration":0, - "uuid":"43da5dc5-5f34-417c-a908-893a104a8e22", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "478":{ - "name":"Bassin d'Austerlitz", - "type":"sightseeing", - "location":[ - 48.5740949, - 7.7605279 - ], - "osm_type":"way", - "osm_id":43799886, - "attractiveness":68, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"756463c9-6c39-41b6-9324-a0b812b892cd", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - }, - "479":{ - "name":"Bras de l'Ill", - "type":"sightseeing", - "location":[ - 48.6034214, - 7.7660788 - ], - "osm_type":"way", - "osm_id":931979292, - "attractiveness":60, - "n_tags":4, - "image_url":null, - "description":null, - "duration":0, - "uuid":"b062cda1-9d52-4e66-b5bb-ed98de20d999", - "must_do":false, - "must_avoid":false, - "is_secondary":false, - "time_to_reach_next":0, - "next_uuid":null - } -} \ No newline at end of file diff --git a/backend/log_config.yaml b/backend/log_config.yaml new file mode 100644 index 0000000..3e9c977 --- /dev/null +++ b/backend/log_config.yaml @@ -0,0 +1,34 @@ +version: 1 +disable_existing_loggers: False +formatters: + simple: + format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' +handlers: + console: + class: rich.logging.RichHandler + formatter: simple + # access: + # class: logging.FileHandler + # filename: logs/access.log + # level: INFO + # formatter: simple + + + + +loggers: + uvicorn.error: + level: INFO + handlers: + - console + propagate: no + # uvicorn.access: + # level: INFO + # handlers: + # - access + # propagate: no +root: + level: INFO + handlers: + - console + propagate: yes diff --git a/backend/src/constants.py b/backend/src/constants.py index 2e66727..9bb628c 100644 --- a/backend/src/constants.py +++ b/backend/src/constants.py @@ -1,6 +1,6 @@ +import logging.config from pathlib import Path import os -import logging PARAMETERS_DIR = Path('src/parameters') AMENITY_SELECTORS_PATH = PARAMETERS_DIR / 'amenity_selectors.yaml' @@ -12,8 +12,15 @@ OPTIMIZER_PARAMETERS_PATH = PARAMETERS_DIR / 'optimizer_parameters.yaml' cache_dir_string = os.getenv('OSM_CACHE_DIR', './cache') OSM_CACHE_DIR = Path(cache_dir_string) -logger = logging.getLogger(__name__) -logging.basicConfig( - level = logging.INFO, - format = '%(asctime)s - %(name)s\t- %(levelname)s\t- %(message)s' -) + +import logging +import yaml + +LOGGING_CONFIG = Path('log_config.yaml') +config = yaml.safe_load(LOGGING_CONFIG.read_text()) + +logging.config.dictConfig(config) + +# if we are in a debug session, set the log level to debug +if os.getenv('DEBUG', False): + logging.getLogger().setLevel(logging.DEBUG) diff --git a/backend/src/main.py b/backend/src/main.py index 6a63300..cb245cb 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -18,7 +18,7 @@ refiner = Refiner(optimizer=optimizer) @app.post("/route/new") -def main1(preferences: Preferences, start: tuple[float, float], end: tuple[float, float] = None) -> str: +def get_route(preferences: Preferences, start: tuple[float, float], end: tuple[float, float] | None = None) -> str: ''' Main function to call the optimizer. :param preferences: the preferences specified by the user as the post body @@ -35,7 +35,7 @@ def main1(preferences: Preferences, start: tuple[float, float], end: tuple[float logger.info("No end coordinates provided. Using start=end.") start_landmark = Landmark(name='start', type='start', location=(start[0], start[1]), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) - end_landmark = Landmark(name='end', type='end', location=(end[0], end[1]), osm_type='end', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) + end_landmark = Landmark(name='end', type='finish', location=(end[0], end[1]), osm_type='end', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) # Generate the landmarks from the start location landmarks, landmarks_short = manager.generate_landmarks_list( diff --git a/backend/src/structs/linked_landmarks.py b/backend/src/structs/linked_landmarks.py index 72a260a..a0799f3 100644 --- a/backend/src/structs/linked_landmarks.py +++ b/backend/src/structs/linked_landmarks.py @@ -1,5 +1,4 @@ import uuid - from .landmark import Landmark from utils.get_time_separation import get_time @@ -45,4 +44,18 @@ class LinkedLandmarks: def __str__(self) -> str: - return f"LinkedLandmarks, total time: {self.total_time} minutes, {len(self._landmarks)} stops: [\n\t{'\n\t'.join([str(landmark) for landmark in self._landmarks])}\n]" \ No newline at end of file + return f"LinkedLandmarks, total time: {self.total_time} minutes, {len(self._landmarks)} stops: [{','.join([str(landmark) for landmark in self._landmarks])}]" + + + def asdict(self) -> dict: + """ + Convert the linked landmarks to a json serializable dictionary. + + Returns: + dict: A dictionary representation of the linked landmarks. + """ + return { + 'uuid': self.uuid, + 'total_time': self.total_time, + 'landmarks': [landmark.dict() for landmark in self._landmarks] + } diff --git a/backend/src/tester.py b/backend/src/tester.py index a3195a3..8a39967 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -1,6 +1,5 @@ -import pandas as pd import logging -from fastapi.encoders import jsonable_encoder +import yaml from utils.landmarks_manager import LandmarkManager from utils.optimizer import Optimizer @@ -12,17 +11,6 @@ from structs.preferences import Preferences, Preference logger = logging.getLogger(__name__) -# Helper function to create a .txt file with results -def write_data(L: list[Landmark], file_name: str): - - data = pd.DataFrame() - i = 0 - - for landmark in L : - data[i] = jsonable_encoder(landmark) - i += 1 - - data.to_json(file_name, indent = 2, force_ascii=False) def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = None) -> list[Landmark]: @@ -83,6 +71,9 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = linked_tour = LinkedLandmarks(refined_tour) logger.info(f"Optimized route: {linked_tour}") + # with open('linked_tour.yaml', 'w') as f: + # yaml.dump(linked_tour.asdict(), f) + return linked_tour diff --git a/backend/throttle.ctrl b/backend/throttle.ctrl deleted file mode 100644 index e69de29..0000000 From 3fa689fd163260e54346b2fedf162e577e61dbd5 Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Fri, 26 Jul 2024 19:11:26 +0200 Subject: [PATCH 7/7] a few docker-related fixes --- .gitea/workflows/backend_build-image.yaml | 6 +-- .gitea/workflows/frontend_build-android.yaml | 2 +- .gitea/workflows/frontend_build-web.yaml | 52 ++++++++++---------- backend/Dockerfile | 2 +- backend/src/constants.py | 5 +- backend/{ => src}/log_config.yaml | 0 6 files changed, 34 insertions(+), 33 deletions(-) rename backend/{ => src}/log_config.yaml (100%) diff --git a/.gitea/workflows/backend_build-image.yaml b/.gitea/workflows/backend_build-image.yaml index 1552c03..0a40ccd 100644 --- a/.gitea/workflows/backend_build-image.yaml +++ b/.gitea/workflows/backend_build-image.yaml @@ -14,13 +14,13 @@ jobs: steps: - uses: https://gitea.com/actions/checkout@v4 - + - name: Login to Docker Registry uses: docker/login-action@v3 with: registry: git.kluster.moll.re username: ${{ gitea.repository_owner }} - password: ${{ secrets.DOCKER_PUSH_TOKEN }} + password: ${{ secrets.PACKAGE_REGISTRY_ACCESS }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -29,5 +29,5 @@ jobs: uses: docker/build-push-action@v5 with: context: backend - tags: git.kluster.moll.re/remoll/fast_network_navigation/backend:latest + tags: git.kluster.moll.re/anydev/anyway-backend:latest push: true diff --git a/.gitea/workflows/frontend_build-android.yaml b/.gitea/workflows/frontend_build-android.yaml index 5856576..2979c23 100644 --- a/.gitea/workflows/frontend_build-android.yaml +++ b/.gitea/workflows/frontend_build-android.yaml @@ -44,7 +44,7 @@ jobs: - name: Add required secrets run: | - echo ${{ secrets.ANDROID_SECRETS_BASE64 }} | base64 -d > ./android/secrets.properties + echo ${{ secrets.ANDROID_SECRETS_PROPERTIES }} > ./android/secrets.properties working-directory: ./frontend - name: Sanity check diff --git a/.gitea/workflows/frontend_build-web.yaml b/.gitea/workflows/frontend_build-web.yaml index f5980fe..05f28d4 100644 --- a/.gitea/workflows/frontend_build-web.yaml +++ b/.gitea/workflows/frontend_build-web.yaml @@ -1,34 +1,34 @@ -on: - pull_request: - branches: - - main - paths: - - frontend/** +# on: +# pull_request: +# branches: +# - main +# paths: +# - frontend/** -name: Build web +# name: Build web -jobs: - build: - name: Build Web - runs-on: ubuntu-latest - steps: +# jobs: +# build: +# name: Build Web +# runs-on: ubuntu-latest +# steps: - - name: Install prerequisites - run: | - sudo apt-get update - sudo apt-get install -y xz-utils +# - name: Install prerequisites +# run: | +# sudo apt-get update +# sudo apt-get install -y xz-utils - - uses: actions/checkout@v4 +# - uses: actions/checkout@v4 - - uses: https://github.com/subosito/flutter-action@v2 - with: - channel: stable - flutter-version: 3.19.6 - cache: true +# - uses: https://github.com/subosito/flutter-action@v2 +# with: +# channel: stable +# flutter-version: 3.19.6 +# cache: true - - run: flutter pub get - working-directory: ./frontend +# - run: flutter pub get +# working-directory: ./frontend - - run: flutter build web - working-directory: ./frontend +# - run: flutter build web +# working-directory: ./frontend diff --git a/backend/Dockerfile b/backend/Dockerfile index b21b3c3..e399a4f 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -14,4 +14,4 @@ EXPOSE 8000 ENV NUM_WORKERS=1 ENV OSM_CACHE_DIR=/cache -CMD ["fastapi", "run", "src/main.py", "--port 8000", "--workers $NUM_WORKERS"] +CMD fastapi run src/main.py --port 8000 --workers $NUM_WORKERS diff --git a/backend/src/constants.py b/backend/src/constants.py index 9bb628c..1b57a3a 100644 --- a/backend/src/constants.py +++ b/backend/src/constants.py @@ -2,7 +2,8 @@ import logging.config from pathlib import Path import os -PARAMETERS_DIR = Path('src/parameters') +LOCATION_PREFIX = Path('src') +PARAMETERS_DIR = LOCATION_PREFIX / 'parameters' AMENITY_SELECTORS_PATH = PARAMETERS_DIR / 'amenity_selectors.yaml' LANDMARK_PARAMETERS_PATH = PARAMETERS_DIR / 'landmark_parameters.yaml' OPTIMIZER_PARAMETERS_PATH = PARAMETERS_DIR / 'optimizer_parameters.yaml' @@ -16,7 +17,7 @@ OSM_CACHE_DIR = Path(cache_dir_string) import logging import yaml -LOGGING_CONFIG = Path('log_config.yaml') +LOGGING_CONFIG = LOCATION_PREFIX / 'log_config.yaml' config = yaml.safe_load(LOGGING_CONFIG.read_text()) logging.config.dictConfig(config) diff --git a/backend/log_config.yaml b/backend/src/log_config.yaml similarity index 100% rename from backend/log_config.yaml rename to backend/src/log_config.yaml