linting
Some checks failed
Run linting on the backend code / Build (pull_request) Has been cancelled
Run testing on the backend code / Build (pull_request) Has been cancelled
Build and deploy the backend to staging / Deploy to staging (pull_request) Has been cancelled
Build and deploy the backend to staging / Build and push image (pull_request) Has been cancelled
Some checks failed
Run linting on the backend code / Build (pull_request) Has been cancelled
Run testing on the backend code / Build (pull_request) Has been cancelled
Build and deploy the backend to staging / Deploy to staging (pull_request) Has been cancelled
Build and deploy the backend to staging / Build and push image (pull_request) Has been cancelled
This commit is contained in:
parent
05092e55f1
commit
73f0dc8361
0
backend/src/landmarks/__init__.py
Normal file
0
backend/src/landmarks/__init__.py
Normal file
@ -113,7 +113,7 @@ class ClusterManager:
|
|||||||
points = []
|
points = []
|
||||||
for elem in result:
|
for elem in result:
|
||||||
osm_type = elem.get('type')
|
osm_type = elem.get('type')
|
||||||
|
|
||||||
# Get coordinates and append them to the points list
|
# Get coordinates and append them to the points list
|
||||||
_, coords = get_base_info(elem, osm_type)
|
_, coords = get_base_info(elem, osm_type)
|
||||||
if coords is not None :
|
if coords is not None :
|
||||||
@ -217,7 +217,7 @@ class ClusterManager:
|
|||||||
|
|
||||||
# Define the bounding box for a given radius around the coordinates
|
# Define the bounding box for a given radius around the coordinates
|
||||||
bbox = create_bbox(cluster.centroid, 300)
|
bbox = create_bbox(cluster.centroid, 300)
|
||||||
|
|
||||||
# Query neighborhoods and shopping malls
|
# Query neighborhoods and shopping malls
|
||||||
selectors = ['"place"~"^(suburb|neighborhood|neighbourhood|quarter|city_block)$"']
|
selectors = ['"place"~"^(suburb|neighborhood|neighbourhood|quarter|city_block)$"']
|
||||||
|
|
||||||
|
@ -298,6 +298,16 @@ class LandmarkManager:
|
|||||||
|
|
||||||
def description_and_keywords(self, tags: dict):
|
def description_and_keywords(self, tags: dict):
|
||||||
"""
|
"""
|
||||||
|
Generates a description and a set of keywords for a given landmark based on its tags.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
tags (dict): A dictionary containing metadata about the landmark, including its name,
|
||||||
|
importance, height, date of construction, and visitor information.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
description (str): A string description of the landmark.
|
||||||
|
keywords (dict): A dictionary of keywords with fields such as 'importance', 'height',
|
||||||
|
'place_type', and 'date'.
|
||||||
"""
|
"""
|
||||||
# Extract relevant fields
|
# Extract relevant fields
|
||||||
name = tags.get('name')
|
name = tags.get('name')
|
||||||
@ -314,7 +324,7 @@ class LandmarkManager:
|
|||||||
if importance is None :
|
if importance is None :
|
||||||
if len(tags.keys()) < 5 :
|
if len(tags.keys()) < 5 :
|
||||||
return None, None
|
return None, None
|
||||||
elif len(tags.keys()) < 10 :
|
if len(tags.keys()) < 10 :
|
||||||
description = f"{name} is a well known {place_type}."
|
description = f"{name} is a well known {place_type}."
|
||||||
elif len(tags.keys()) < 17 :
|
elif len(tags.keys()) < 17 :
|
||||||
importance = 'national'
|
importance = 'national'
|
||||||
@ -350,6 +360,17 @@ class LandmarkManager:
|
|||||||
|
|
||||||
|
|
||||||
def get_place_type(self, data):
|
def get_place_type(self, data):
|
||||||
|
"""
|
||||||
|
Determines the type of the place based on available tags such as 'amenity', 'building',
|
||||||
|
'historic', and 'leisure'. The priority order is: 'historic' > 'building' (if not generic) >
|
||||||
|
'amenity' > 'leisure'.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
data (dict): A dictionary containing metadata about the place.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
place_type (str): The determined type of the place, or None if no relevant type is found.
|
||||||
|
"""
|
||||||
amenity = data.get('amenity', None)
|
amenity = data.get('amenity', None)
|
||||||
building = data.get('building', None)
|
building = data.get('building', None)
|
||||||
historic = data.get('historic', None)
|
historic = data.get('historic', None)
|
||||||
@ -369,6 +390,16 @@ class LandmarkManager:
|
|||||||
|
|
||||||
|
|
||||||
def get_date(self, data):
|
def get_date(self, data):
|
||||||
|
"""
|
||||||
|
Extracts the most relevant date from the available tags, prioritizing 'construction_date',
|
||||||
|
'start_date', 'year_of_construction', and 'opening_date' in that order.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
data (dict): A dictionary containing metadata about the place.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
date (str): The most relevant date found, or None if no date is available.
|
||||||
|
"""
|
||||||
construction_date = data.get('construction_date', None)
|
construction_date = data.get('construction_date', None)
|
||||||
opening_date = data.get('opening_date', None)
|
opening_date = data.get('opening_date', None)
|
||||||
start_date = data.get('start_date', None)
|
start_date = data.get('start_date', None)
|
||||||
|
@ -94,6 +94,7 @@ def new_trip(preferences: Preferences,
|
|||||||
n_tags=0)
|
n_tags=0)
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
# Generate the landmarks from the start location
|
# Generate the landmarks from the start location
|
||||||
landmarks, landmarks_short = manager.generate_landmarks_list(
|
landmarks, landmarks_short = manager.generate_landmarks_list(
|
||||||
center_coordinates = start,
|
center_coordinates = start,
|
||||||
@ -103,15 +104,6 @@ def new_trip(preferences: Preferences,
|
|||||||
if len(landmarks) == 0 :
|
if len(landmarks) == 0 :
|
||||||
raise HTTPException(status_code=500, detail="No landmarks were found.")
|
raise HTTPException(status_code=500, detail="No landmarks were found.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###################### store landmarks in json file for debug ######################
|
|
||||||
landmarks_list = [jsonable_encoder(item) for item in landmarks]
|
|
||||||
with open('landmarks.json', 'w+') as file:
|
|
||||||
json.dump(landmarks_list, file, indent=4)
|
|
||||||
####################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
# insert start and finish to the landmarks list
|
# insert start and finish to the landmarks list
|
||||||
landmarks_short.insert(0, start_landmark)
|
landmarks_short.insert(0, start_landmark)
|
||||||
landmarks_short.append(end_landmark)
|
landmarks_short.append(end_landmark)
|
||||||
|
@ -278,7 +278,7 @@ class Refiner :
|
|||||||
better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish
|
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
|
xs, ys = better_tour_poly.exterior.xy
|
||||||
"""
|
"""
|
||||||
ERROR HERE :
|
FIXED : ERROR HERE :
|
||||||
Exception has occurred: AttributeError
|
Exception has occurred: AttributeError
|
||||||
'LineString' object has no attribute 'exterior'
|
'LineString' object has no attribute 'exterior'
|
||||||
"""
|
"""
|
||||||
|
@ -65,14 +65,12 @@ class Overpass :
|
|||||||
self.logger.debug(f'Query string: {query_str}')
|
self.logger.debug(f'Query string: {query_str}')
|
||||||
return self.fetch_data_from_api(query_str)
|
return self.fetch_data_from_api(query_str)
|
||||||
|
|
||||||
# Hybrid cache: some data from Overpass, some data from cache.
|
# Resize the bbox for smaller search area and build new query string.
|
||||||
else :
|
non_cached_bbox = Overpass._get_non_cached_bbox(non_cached_cells, bbox)
|
||||||
# Resize the bbox for smaller search area and build new query string.
|
query_str = Overpass.build_query(non_cached_bbox, osm_types, selector, conditions, out)
|
||||||
non_cached_bbox = Overpass._get_non_cached_bbox(non_cached_cells, bbox)
|
self.logger.debug(f'Query string: {query_str}')
|
||||||
query_str = Overpass.build_query(non_cached_bbox, osm_types, selector, conditions, out)
|
non_cached_responses = self.fetch_data_from_api(query_str)
|
||||||
self.logger.debug(f'Query string: {query_str}')
|
return Overpass._filter_landmarks(cached_responses, bbox) + non_cached_responses
|
||||||
non_cached_responses = self.fetch_data_from_api(query_str)
|
|
||||||
return Overpass._filter_landmarks(cached_responses, bbox) + non_cached_responses
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_data_from_api(self, query_str: str) -> List[dict]:
|
def fetch_data_from_api(self, query_str: str) -> List[dict]:
|
||||||
@ -97,8 +95,8 @@ class Overpass :
|
|||||||
return elements
|
return elements
|
||||||
|
|
||||||
except urllib.error.URLError as e:
|
except urllib.error.URLError as e:
|
||||||
self.logger.error(f"Error connecting to Overpass API: {e}")
|
self.logger.error(f"Error connecting to Overpass API: {str(exc)}")
|
||||||
raise ConnectionError(f"Error connecting to Overpass API: {e}") from e
|
raise ConnectionError(f"Error connecting to Overpass API: {str(exc)}") from e
|
||||||
except Exception as exc :
|
except Exception as exc :
|
||||||
raise Exception(f'An unexpected error occured: {str(exc)}') from exc
|
raise Exception(f'An unexpected error occured: {str(exc)}') from exc
|
||||||
|
|
||||||
@ -389,8 +387,8 @@ def get_base_info(elem: dict, osm_type: OSM_TYPES, with_name=False) :
|
|||||||
if with_name :
|
if with_name :
|
||||||
name = elem.get('tags', {}).get('name')
|
name = elem.get('tags', {}).get('name')
|
||||||
return osm_id, coords, name
|
return osm_id, coords, name
|
||||||
else :
|
|
||||||
return osm_id, coords
|
return osm_id, coords
|
||||||
|
|
||||||
|
|
||||||
def fill_cache():
|
def fill_cache():
|
||||||
@ -421,4 +419,4 @@ def fill_cache():
|
|||||||
except Exception as exc :
|
except Exception as exc :
|
||||||
overpass.logger.error(f'An error occured while parsing file {entry.path} as .json file: {str(exc)}')
|
overpass.logger.error(f'An error occured while parsing file {entry.path} as .json file: {str(exc)}')
|
||||||
|
|
||||||
overpass.logger.info(f"Successfully filled {n_files}/{total} cache files.")
|
overpass.logger.info(f"Successfully filled {n_files}/{total} cache files.")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Definition of the Landmark class to handle visitable objects across the world."""
|
"""Definition of the Landmark class to handle visitable objects across the world."""
|
||||||
from typing import Optional, Literal, List
|
from typing import Optional, Literal
|
||||||
from uuid import uuid4, UUID
|
from uuid import uuid4, UUID
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
# Output to frontend
|
# Output to frontend
|
||||||
@ -70,11 +70,6 @@ class Landmark(BaseModel) :
|
|||||||
is_place_of_worship : Optional[bool] = False
|
is_place_of_worship : Optional[bool] = False
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
json_encoders = {
|
|
||||||
UUID: lambda v: str(v) # Ensure UUID is serialized as a string
|
|
||||||
}
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
"""
|
"""
|
||||||
String representation of the Landmark object.
|
String representation of the Landmark object.
|
||||||
|
@ -341,5 +341,3 @@ def test_shopping(client, request) : # pylint: disable=redefined-outer-name
|
|||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||||
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
|||||||
"""Helper methods for testing."""
|
"""Helper methods for testing."""
|
||||||
import logging
|
import logging
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from pydantic import ValidationError
|
|
||||||
|
|
||||||
from ..structs.landmark import Landmark
|
from ..structs.landmark import Landmark
|
||||||
from ..cache import client as cache_client
|
from ..cache import client as cache_client
|
||||||
|
0
backend/src/toilets/__init__.py
Normal file
0
backend/src/toilets/__init__.py
Normal file
@ -1,3 +1,4 @@
|
|||||||
|
"""Defines the endpoint for fetching toilet locations."""
|
||||||
from fastapi import HTTPException, APIRouter, Query
|
from fastapi import HTTPException, APIRouter, Query
|
||||||
|
|
||||||
from ..structs.toilets import Toilets
|
from ..structs.toilets import Toilets
|
||||||
@ -33,5 +34,5 @@ def get_toilets(location: tuple[float, float] = Query(...), radius: int = 500) -
|
|||||||
toilets_list = toilets_manager.generate_toilet_list()
|
toilets_list = toilets_manager.generate_toilet_list()
|
||||||
except KeyError as exc:
|
except KeyError as exc:
|
||||||
raise HTTPException(status_code=404, detail="No toilets found") from exc
|
raise HTTPException(status_code=404, detail="No toilets found") from exc
|
||||||
|
|
||||||
return toilets_list
|
return toilets_list
|
||||||
|
@ -24,4 +24,4 @@ def create_bbox(coords: tuple[float, float], radius: int):
|
|||||||
lon_min = lon - d_lon * 180 / m.pi
|
lon_min = lon - d_lon * 180 / m.pi
|
||||||
lon_max = lon + d_lon * 180 / m.pi
|
lon_max = lon + d_lon * 180 / m.pi
|
||||||
|
|
||||||
return (lat_min, lon_min, lat_max, lon_max)
|
return (lat_min, lon_min, lat_max, lon_max)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user