shorter lines
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Build and deploy the backend to staging / Build and push image (pull_request) Successful in 2m27s
				
			
		
			
				
	
				Run linting on the backend code / Build (pull_request) Failing after 36s
				
			
		
			
				
	
				Run testing on the backend code / Build (pull_request) Failing after 1m25s
				
			
		
			
				
	
				Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 15s
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Build and deploy the backend to staging / Build and push image (pull_request) Successful in 2m27s
				
			Run linting on the backend code / Build (pull_request) Failing after 36s
				
			Run testing on the backend code / Build (pull_request) Failing after 1m25s
				
			Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 15s
				
			This commit is contained in:
		| @@ -22,31 +22,54 @@ refiner = Refiner(optimizer=optimizer) | ||||
|  | ||||
|  | ||||
| @app.post("/trip/new") | ||||
| def new_trip(preferences: Preferences, start: tuple[float, float], end: tuple[float, float] | None = None) -> Trip: | ||||
| def new_trip(preferences: Preferences, | ||||
|              start: tuple[float, float], | ||||
|              end: tuple[float, float] | None = None) -> Trip: | ||||
|     """ | ||||
|     Main function to call the optimizer. | ||||
|  | ||||
|     Args: | ||||
|         preferences (Preferences)   : the preferences specified by the user as the post body | ||||
|         start (tuple)   : the coordinates of the starting point as a tuple of floats (as url query parameters) | ||||
|         end (tuple)     : the coordinates of the finishing point as a tuple of floats (as url query parameters) | ||||
|         preferences : the preferences specified by the user as the post body | ||||
|         start       : the coordinates of the starting point | ||||
|         end         : the coordinates of the finishing point | ||||
|     Returns:  | ||||
|         (uuid) : The uuid of the first landmark in the optimized route | ||||
|     """ | ||||
|     if preferences is None: | ||||
|         raise HTTPException(status_code=406, detail="Preferences not provided") | ||||
|     if preferences.shopping.score == 0 and preferences.sightseeing.score == 0 and preferences.nature.score == 0: | ||||
|         raise HTTPException(status_code=406, detail="All preferences are 0.") | ||||
|         raise HTTPException(status_code=406, | ||||
|                             detail="Preferences not provided or incomplete.") | ||||
|     if (preferences.shopping.score == 0 and | ||||
|         preferences.sightseeing.score == 0 and | ||||
|         preferences.nature.score == 0) : | ||||
|         raise HTTPException(status_code=406, | ||||
|                             detail="All preferences are 0.") | ||||
|     if start is None: | ||||
|         raise HTTPException(status_code=406, detail="Start coordinates not provided") | ||||
|         raise HTTPException(status_code=406, | ||||
|                             detail="Start coordinates not provided") | ||||
|     if not (-90 <= start[0] <= 90 or -180 <= start[1] <= 180): | ||||
|         raise HTTPException(status_code=423, detail="Start coordinates not in range") | ||||
|         raise HTTPException(status_code=423, | ||||
|                             detail="Start coordinates not in range") | ||||
|     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='finish', type='finish', 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='start', | ||||
|                               location=(start[0], start[1]), | ||||
|                               osm_type='start', | ||||
|                               osm_id=0, | ||||
|                               attractiveness=0, | ||||
|                               must_do=True, | ||||
|                               n_tags = 0) | ||||
|      | ||||
|     end_landmark = Landmark(name='finish', | ||||
|                             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( | ||||
| @@ -67,10 +90,12 @@ def new_trip(preferences: Preferences, start: tuple[float, float], end: tuple[fl | ||||
|         raise HTTPException(status_code=500, detail="Optimzation took too long") from exc | ||||
|  | ||||
|     # Second stage optimization | ||||
|     refined_tour = refiner.refine_optimization(landmarks, base_tour, preferences.max_time_minute, preferences.detour_tolerance_minute) | ||||
|     refined_tour = refiner.refine_optimization(landmarks, base_tour, | ||||
|                                                preferences.max_time_minute, | ||||
|                                                preferences.detour_tolerance_minute) | ||||
|  | ||||
|     linked_tour = LinkedLandmarks(refined_tour) | ||||
|     # upon creation of the trip, persistence of both the trip and its landmarks is ensured | ||||
|     # upon creation of the trip, persistence of both the trip and its landmarks is ensured. | ||||
|     trip = Trip.from_linked_landmarks(linked_tour, cache_client) | ||||
|     return trip | ||||
|  | ||||
| @@ -109,4 +134,5 @@ def get_landmark(landmark_uuid: str) -> Landmark: | ||||
|         landmark = cache_client.get(f"landmark_{landmark_uuid}") | ||||
|         return landmark | ||||
|     except KeyError as exc: | ||||
|         raise HTTPException(status_code=404, detail="Landmark not found") from exc | ||||
|         raise HTTPException(status_code=404, | ||||
|                             detail="Landmark not found") from exc | ||||
|   | ||||
| @@ -70,13 +70,14 @@ class Landmark(BaseModel) : | ||||
|             str: A formatted string with the landmark's type, name, location, attractiveness score, | ||||
|             time to the next landmark (if available), and whether the landmark is secondary. | ||||
|         """ | ||||
|         time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" | ||||
|         t_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" | ||||
|         is_secondary_str = ", secondary" if self.is_secondary else "" | ||||
|         type_str = '(' + self.type + ')' | ||||
|         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}, ' | ||||
|                 f'score={self.attractiveness}{t_to_next_str}{is_secondary_str}]') | ||||
|  | ||||
|     def distance(self, value: 'Landmark') -> float: | ||||
|         """ | ||||
| @@ -113,4 +114,6 @@ class Landmark(BaseModel) : | ||||
|         # in particular, if two objects are equal, their hash must be equal | ||||
|         # uuid and osm_id are just shortcuts to avoid comparing all the properties | ||||
|         # if they are equal, we know that the name is also equal and in turn the hash is equal | ||||
|         return self.uuid == value.uuid or self.osm_id == value.osm_id or (self.name == value.name and self.distance(value) < 0.001) | ||||
|         return (self.uuid == value.uuid or | ||||
|                 self.osm_id == value.osm_id or | ||||
|                 (self.name == value.name and self.distance(value) < 0.001)) | ||||
|   | ||||
| @@ -6,9 +6,11 @@ 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 | ||||
|     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). | ||||
|     """ | ||||
|  | ||||
| @@ -21,7 +23,8 @@ class LinkedLandmarks: | ||||
|         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. | ||||
|             data (list[Landmark], optional):    The list of landmarks that are linked together. | ||||
|                                                 Defaults to None. | ||||
|         """ | ||||
|         self._landmarks = data if data else [] | ||||
|         self._link_landmarks() | ||||
| @@ -29,7 +32,8 @@ class LinkedLandmarks: | ||||
|  | ||||
|     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. | ||||
|         Create the links between the landmarks in the list by setting their  | ||||
|         .next_uuid and the .time_to_next attributes. | ||||
|         """ | ||||
|  | ||||
|         # Mark secondary landmarks as such | ||||
| @@ -57,12 +61,12 @@ class LinkedLandmarks: | ||||
|         if len(scores) >= 10: | ||||
|             threshold_score = scores[9] | ||||
|         else: | ||||
|             # If there are fewer than 10 landmarks, use the lowest score in the list as the threshold | ||||
|             # If there are fewer than 10 landmarks, use the lowest score as the threshold | ||||
|             threshold_score = min(scores) if scores else 0 | ||||
|  | ||||
|         # Update 'is_secondary' for landmarks with attractiveness below the threshold score | ||||
|         for landmark in self._landmarks: | ||||
|             if landmark.attractiveness < threshold_score and landmark.type not in ["start", "finish"]: | ||||
|             if (landmark.attractiveness < threshold_score and landmark.type not in ["start", "finish"]): | ||||
|                 landmark.is_secondary = True | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -36,8 +36,11 @@ class Trip(BaseModel): | ||||
|  | ||||
|         # Store the trip in the cache | ||||
|         cache_client.set(f"trip_{trip.uuid}", trip) | ||||
|         # 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) | ||||
|  | ||||
|         # 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: | ||||
|         # for landmark in landmarks: | ||||
|         #     cache_client.set(f"landmark_{landmark.uuid}", landmark, expire=3600) | ||||
|   | ||||
| @@ -57,7 +57,11 @@ def test_bellecour(client, request) :   # pylint: disable=redefined-outer-name | ||||
|     response = client.post( | ||||
|         "/trip/new", | ||||
|         json={ | ||||
|             "preferences": {"sightseeing": {"type": "sightseeing", "score": 5}, "nature": {"type": "nature", "score": 5}, "shopping": {"type": "shopping", "score": 5}, "max_time_minute": duration_minutes, "detour_tolerance_minute": 0}, | ||||
|             "preferences": {"sightseeing": {"type": "sightseeing", "score": 5}, | ||||
|                             "nature": {"type": "nature", "score": 5}, | ||||
|                             "shopping": {"type": "shopping", "score": 5}, | ||||
|                             "max_time_minute": duration_minutes, | ||||
|                             "detour_tolerance_minute": 0}, | ||||
|             "start": [45.7576485, 4.8330241] | ||||
|             } | ||||
|         ) | ||||
| @@ -79,7 +83,11 @@ def test_bellecour(client, request) :   # pylint: disable=redefined-outer-name | ||||
| #     response = client.post( | ||||
| #         "/trip/new", | ||||
| #         json={ | ||||
| #             "preferences": {"sightseeing": {"type": "sightseeing", "score": 1}, "nature": {"type": "nature", "score": 1}, "shopping": {"type": "shopping", "score": 1}, "max_time_minute": 360, "detour_tolerance_minute": 0}, | ||||
| #             "preferences": {"sightseeing": {"type": "sightseeing", "score": 1}, | ||||
| #             "nature": {"type": "nature", "score": 1}, | ||||
| #             "shopping": {"type": "shopping", "score": 1}, | ||||
| #             "max_time_minute": 360, | ||||
| #             "detour_tolerance_minute": 0}, | ||||
| #             "start": [48.8566, 2.3522] | ||||
| #             } | ||||
| #         ) | ||||
|   | ||||
| @@ -34,7 +34,8 @@ def fetch_landmark(client, landmark_uuid: str): | ||||
|     response = client.get(f"/landmark/{landmark_uuid}") | ||||
|  | ||||
|     if response.status_code != 200: | ||||
|         raise HTTPException(status_code=999, detail=f"Failed to fetch landmark with UUID {landmark_uuid}: {response.status_code}") | ||||
|         raise HTTPException(status_code=999, | ||||
|                             detail=f"Failed to fetch landmark with UUID {landmark_uuid}: {response.status_code}") | ||||
|  | ||||
|     json_data = response.json() | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user