Compare commits
	
		
			4 Commits
		
	
	
		
			v0.0.25
			...
			c1a855e84a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c1a855e84a | |||
| 40edd923c3 | |||
| 6ad749eeed | |||
| c20ebf3d63 | 
| @@ -9,7 +9,6 @@ name = "pypi" | |||||||
| numpy = "*" | numpy = "*" | ||||||
| fastapi = "*" | fastapi = "*" | ||||||
| pydantic = "*" | pydantic = "*" | ||||||
| geopy = "*" |  | ||||||
| shapely = "*" | shapely = "*" | ||||||
| scipy = "*" | scipy = "*" | ||||||
| osmpythontools = "*" | osmpythontools = "*" | ||||||
|   | |||||||
							
								
								
									
										2073
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2073
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							 Submodule backend/deployment updated: 8927f278f3...bb27ca2c86
									
								
							| @@ -16,7 +16,7 @@ OSM_CACHE_DIR = Path(cache_dir_string) | |||||||
|  |  | ||||||
| import logging | import logging | ||||||
| # if we are in a debug session, set verbose and rich logging | # if we are in a debug session, set verbose and rich logging | ||||||
| if os.getenv('DEBUG', False): | if os.getenv('DEBUG', "false") == "true": | ||||||
|     from rich.logging import RichHandler |     from rich.logging import RichHandler | ||||||
|     logging.basicConfig( |     logging.basicConfig( | ||||||
|         level=logging.DEBUG, |         level=logging.DEBUG, | ||||||
|   | |||||||
| @@ -1,3 +1,6 @@ | |||||||
|  | # Tags were picked mostly arbitrarily, based on the OSM wiki and the OSM tags page. | ||||||
|  | # See https://taginfo.openstreetmap.org for more inspiration. | ||||||
|  |  | ||||||
| nature: | nature: | ||||||
|   leisure: park |   leisure: park | ||||||
|   geological: '' |   geological: '' | ||||||
| @@ -11,7 +14,24 @@ nature: | |||||||
|     - alpine_hut |     - alpine_hut | ||||||
|     - viewpoint |     - viewpoint | ||||||
|     - zoo |     - zoo | ||||||
|   waterway: waterfall |     - resort | ||||||
|  |     - picnic_site | ||||||
|  |   water: | ||||||
|  |     - pond | ||||||
|  |     - lake | ||||||
|  |     - river | ||||||
|  |     - basin | ||||||
|  |     - stream | ||||||
|  |     - lagoon | ||||||
|  |     - rapids | ||||||
|  |   waterway: | ||||||
|  |     - waterfall | ||||||
|  |     - river | ||||||
|  |     - canal | ||||||
|  |     - dam | ||||||
|  |     - dock | ||||||
|  |     - boatyard | ||||||
|  |  | ||||||
|  |  | ||||||
| shopping: | shopping: | ||||||
|   shop: |   shop: | ||||||
| @@ -23,10 +43,50 @@ sightseeing: | |||||||
|     - museum |     - museum | ||||||
|     - attraction |     - attraction | ||||||
|     - gallery |     - gallery | ||||||
|  |     - artwork | ||||||
|  |     - aquarium | ||||||
|  |  | ||||||
|   historic: '' |   historic: '' | ||||||
|   amenity: |   amenity: | ||||||
|     - planetarium |     - planetarium | ||||||
|     - place_of_worship |     - place_of_worship | ||||||
|     - fountain |     - fountain | ||||||
|  |     - townhall | ||||||
|   water: |   water: | ||||||
|     - reflecting_pool |     - reflecting_pool | ||||||
|  |   bridge: | ||||||
|  |     # needs to be in quotes because it gets interpreted as True otherwise | ||||||
|  |     - 'yes' | ||||||
|  |     - aqueduct | ||||||
|  |     - viaduct | ||||||
|  |     - boardwalk | ||||||
|  |     - cantilever | ||||||
|  |     - abandoned | ||||||
|  |   building: | ||||||
|  |     - church | ||||||
|  |     - chapel | ||||||
|  |     - mosque | ||||||
|  |     - synagogue | ||||||
|  |     - ruins | ||||||
|  |     - temple | ||||||
|  |     - government | ||||||
|  |     - cathedral | ||||||
|  |     - castle | ||||||
|  |     - museum | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # to be used later on | ||||||
|  | restauration: | ||||||
|  |   shop: | ||||||
|  |     - coffee | ||||||
|  |     - bakery | ||||||
|  |     - restaurant | ||||||
|  |     - pastry | ||||||
|  |   amenity: | ||||||
|  |     - restaurant | ||||||
|  |     - cafe | ||||||
|  |     - ice_cream | ||||||
|  |     - food_court | ||||||
|  |     - biergarten | ||||||
|   | |||||||
| @@ -21,8 +21,8 @@ if constants.MEMCACHED_HOST_PATH is None: | |||||||
| else: | else: | ||||||
|     client = Client( |     client = Client( | ||||||
|         constants.MEMCACHED_HOST_PATH, |         constants.MEMCACHED_HOST_PATH, | ||||||
|         timeout=1, |         timeout = 1, | ||||||
|         allow_unicode_keys=True, |         allow_unicode_keys = True, | ||||||
|         encoding='utf-8', |         encoding = 'utf-8', | ||||||
|         serde=serde.pickle_serde |         serde = serde.pickle_serde | ||||||
|     ) |     ) | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ from uuid import uuid4 | |||||||
|  |  | ||||||
| # Output to frontend | # Output to frontend | ||||||
| class Landmark(BaseModel) : | class Landmark(BaseModel) : | ||||||
|      |  | ||||||
|     # Properties of the landmark |     # Properties of the landmark | ||||||
|     name : str |     name : str | ||||||
|     type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] |     type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] | ||||||
| @@ -22,22 +22,22 @@ class Landmark(BaseModel) : | |||||||
|  |  | ||||||
|     # Unique ID of a given landmark |     # Unique ID of a given landmark | ||||||
|     uuid: str = Field(default_factory=uuid4) |     uuid: str = Field(default_factory=uuid4) | ||||||
|      |  | ||||||
|     # Additional properties depending on specific tour |     # Additional properties depending on specific tour | ||||||
|     must_do : Optional[bool] = False |     must_do : Optional[bool] = False | ||||||
|     must_avoid : Optional[bool] = False |     must_avoid : Optional[bool] = False | ||||||
|     is_secondary : Optional[bool] = False                       # TODO future    |     is_secondary : Optional[bool] = False                       # TODO future    | ||||||
|      |  | ||||||
|     time_to_reach_next : Optional[int] = 0 |     time_to_reach_next : Optional[int] = 0 | ||||||
|     next_uuid : Optional[str] = None |     next_uuid : Optional[str] = None | ||||||
|      |  | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|         time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" |         time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" | ||||||
|         is_secondary_str = f", secondary" if self.is_secondary else "" |         is_secondary_str = f", secondary" if self.is_secondary else "" | ||||||
|         type_str = '(' + self.type + ')' |         type_str = '(' + self.type + ')' | ||||||
|         if self.type in ["start", "finish", "nature", "shopping"] : type_str += '\t ' |         if self.type in ["start", "finish", "nature", "shopping"] : type_str += '\t ' | ||||||
|         return f'Landmark{type_str}: [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}{is_secondary_str}]' |         return f'Landmark{type_str}: [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}{is_secondary_str}]' | ||||||
|      |  | ||||||
|     def distance(self, value: 'Landmark') -> float: |     def distance(self, value: 'Landmark') -> float: | ||||||
|         return (self.location[0] - value.location[0])**2 + (self.location[1] - value.location[1])**2 |         return (self.location[0] - value.location[0])**2 + (self.location[1] - value.location[1])**2 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,7 +22,8 @@ class Trip(BaseModel): | |||||||
|  |  | ||||||
|         # Store the trip in the cache |         # Store the trip in the cache | ||||||
|         cache_client.set(f"trip_{trip.uuid}", trip) |         cache_client.set(f"trip_{trip.uuid}", trip) | ||||||
|         cache_client.set_many({f"landmark_{landmark.uuid}": landmark for landmark in landmarks}, expire=3600) |         # make sure to await the result (noreply=False). Otherwise the cache might not be inplace when the trip is actually requested | ||||||
|  |         cache_client.set_many({f"landmark_{landmark.uuid}": landmark for landmark in landmarks}, expire=3600, noreply=False) | ||||||
|         # is equivalent to: |         # is equivalent to: | ||||||
|         # for landmark in landmarks: |         # for landmark in landmarks: | ||||||
|         #     cache_client.set(f"landmark_{landmark.uuid}", landmark, expire=3600) |         #     cache_client.set(f"landmark_{landmark.uuid}", landmark, expire=3600) | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import yaml | import yaml | ||||||
| from geopy.distance import geodesic | from math import sin, cos, sqrt, atan2, radians | ||||||
|  |  | ||||||
| import constants | import constants | ||||||
|  |  | ||||||
| @@ -8,6 +8,7 @@ with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: | |||||||
|     DETOUR_FACTOR = parameters['detour_factor'] |     DETOUR_FACTOR = parameters['detour_factor'] | ||||||
|     AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] |     AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] | ||||||
|  |  | ||||||
|  | EARTH_RADIUS_KM = 6373 | ||||||
|  |  | ||||||
| def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: | def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: | ||||||
|     """ |     """ | ||||||
| @@ -22,16 +23,28 @@ def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: | |||||||
|     """ |     """ | ||||||
|  |  | ||||||
|  |  | ||||||
|     # Compute the straight-line distance in km |     if p1 == p2: | ||||||
|     if p1 == p2 : |  | ||||||
|         return 0 |         return 0 | ||||||
|     else:  |     else: | ||||||
|         dist = geodesic(p1, p2).kilometers |         # Compute the distance in km along the surface of the Earth | ||||||
|  |         # (assume spherical Earth) | ||||||
|  |         # this is the haversine formula, stolen from stackoverflow | ||||||
|  |         # in order to not use any external libraries | ||||||
|  |         lat1, lon1 = radians(p1[0]), radians(p1[1]) | ||||||
|  |         lat2, lon2 = radians(p2[0]), radians(p2[1]) | ||||||
|  |  | ||||||
|     # Consider the detour factor for average cityto deterline walking distance (in km) |         dlon = lon2 - lon1 | ||||||
|     walk_dist = dist*DETOUR_FACTOR |         dlat = lat2 - lat1 | ||||||
|  |  | ||||||
|  |         a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 | ||||||
|  |         c = 2 * atan2(sqrt(a), sqrt(1 - a)) | ||||||
|  |  | ||||||
|  |         distance = EARTH_RADIUS_KM * c | ||||||
|  |  | ||||||
|  |     # Consider the detour factor for average an average city | ||||||
|  |     walk_distance = distance * DETOUR_FACTOR | ||||||
|  |  | ||||||
|     # Time to walk this distance (in minutes) |     # Time to walk this distance (in minutes) | ||||||
|     walk_time = walk_dist/AVERAGE_WALKING_SPEED*60 |     walk_time = walk_distance / AVERAGE_WALKING_SPEED * 60 | ||||||
|  |  | ||||||
|     return round(walk_time) |     return round(walk_time) | ||||||
|   | |||||||
| @@ -10,7 +10,8 @@ from structs.landmark import Landmark | |||||||
| from .take_most_important import take_most_important | from .take_most_important import take_most_important | ||||||
| import constants | import constants | ||||||
|  |  | ||||||
|  | # silence the overpass logger | ||||||
|  | logging.getLogger('OSMPythonTools').setLevel(level=logging.CRITICAL) | ||||||
|  |  | ||||||
|  |  | ||||||
| class LandmarkManager: | class LandmarkManager: | ||||||
| @@ -206,11 +207,15 @@ class LandmarkManager: | |||||||
|             query = overpassQueryBuilder( |             query = overpassQueryBuilder( | ||||||
|                 bbox = bbox, |                 bbox = bbox, | ||||||
|                 elementType = ['way', 'relation'], |                 elementType = ['way', 'relation'], | ||||||
|  |                 # selector can in principle be a list already, | ||||||
|  |                 # but it generates the intersection of the queries | ||||||
|  |                 # we want the union | ||||||
|                 selector = sel, |                 selector = sel, | ||||||
|                 # conditions = [], |                 conditions = ['count_tags()>5'], | ||||||
|                 includeCenter = True, |                 includeCenter = True, | ||||||
|                 out = 'body' |                 out = 'body' | ||||||
|                 ) |                 ) | ||||||
|  |             self.logger.debug(f"Query: {query}") | ||||||
|  |  | ||||||
|             try: |             try: | ||||||
|                 result = self.overpass.query(query) |                 result = self.overpass.query(query) | ||||||
| @@ -336,7 +341,7 @@ def dict_to_selector_list(d: dict) -> list: | |||||||
|     for key, value in d.items(): |     for key, value in d.items(): | ||||||
|         if type(value) == list: |         if type(value) == list: | ||||||
|             val = '|'.join(value) |             val = '|'.join(value) | ||||||
|             return_list.append(f'{key}~"{val}"') |             return_list.append(f'{key}~"^({val})$"') | ||||||
|         elif type(value) == str and len(value) == 0: |         elif type(value) == str and len(value) == 0: | ||||||
|             return_list.append(f'{key}') |             return_list.append(f'{key}') | ||||||
|         else: |         else: | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ import numpy as np | |||||||
|  |  | ||||||
| from scipy.optimize import linprog | from scipy.optimize import linprog | ||||||
| from collections import defaultdict, deque | from collections import defaultdict, deque | ||||||
| from geopy.distance import geodesic |  | ||||||
|  |  | ||||||
| from structs.landmark import Landmark | from structs.landmark import Landmark | ||||||
| from .get_time_separation import get_time | from .get_time_separation import get_time | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ jobs: | |||||||
|       - name: Load secrets from github |       - name: Load secrets from github | ||||||
|         run: | |         run: | | ||||||
|           echo "${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties |           echo "${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties | ||||||
|           echo "${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > fastlane/google-key.json |           echo "${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > google-key.json | ||||||
|           echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore |           echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore | ||||||
|         working-directory: android |         working-directory: android | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user