Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m46s
Run linting on the backend code / Build (pull_request) Successful in 2m31s
Run testing on the backend code / Build (pull_request) Failing after 12m37s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 29s
118 lines
4.0 KiB
Python
118 lines
4.0 KiB
Python
"""Main app for backend api"""
|
|
import logging
|
|
import time
|
|
import random
|
|
from fastapi import HTTPException, APIRouter
|
|
|
|
from ..structs.landmark import Landmark
|
|
from ..structs.preferences import Preferences, Preference
|
|
from ..landmarks.landmarks_manager import LandmarkManager
|
|
|
|
|
|
# Setup the logger and the Landmarks Manager
|
|
logger = logging.getLogger(__name__)
|
|
manager = LandmarkManager()
|
|
|
|
|
|
# Start the router
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/get/landmarks")
|
|
def get_landmarks(
|
|
preferences: Preferences,
|
|
start: tuple[float, float],
|
|
) -> list[Landmark]:
|
|
"""
|
|
Function that returns all available landmarks given some preferences and a start position.
|
|
|
|
Args:
|
|
preferences : the preferences specified by the user as the post body
|
|
start : the coordinates of the starting point
|
|
Returns:
|
|
list[Landmark] : The full list of fetched landmarks
|
|
"""
|
|
if preferences is None:
|
|
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")
|
|
if not (-90 <= start[0] <= 90 or -180 <= start[1] <= 180):
|
|
raise HTTPException(status_code=422, detail="Start coordinates not in range")
|
|
|
|
logger.info(f"Requested new trip generation. Details:\n\tCoordinates: {start}\n\tTime: {preferences.max_time_minute}\n\tSightseeing: {preferences.sightseeing.score}\n\tNature: {preferences.nature.score}\n\tShopping: {preferences.shopping.score}")
|
|
|
|
start_time = time.time()
|
|
|
|
# Generate the landmarks from the start location
|
|
landmarks, _ = manager.generate_landmarks_list(
|
|
center_coordinates = start,
|
|
preferences = preferences
|
|
)
|
|
|
|
if len(landmarks) == 0 :
|
|
raise HTTPException(status_code=500, detail="No landmarks were found.")
|
|
|
|
t_generate_landmarks = time.time() - start_time
|
|
logger.info(f'Fetched {len(landmarks)} landmarks in \t: {round(t_generate_landmarks,3)} seconds')
|
|
|
|
return landmarks
|
|
|
|
|
|
@router.post("/landmarks/get-nearby/{lat}/{lon}")
|
|
def get_landmarks_nearby(
|
|
lat: float,
|
|
lon: float
|
|
) -> list[Landmark] :
|
|
"""
|
|
Suggests nearby landmarks based on a given latitude and longitude.
|
|
|
|
This endpoint returns a curated list of up to 5 landmarks around the given geographical coordinates. It uses fixed preferences for
|
|
sightseeing, shopping, and nature, with a maximum time constraint of 30 minutes to limit the number of landmarks returned.
|
|
|
|
Args:
|
|
lat (float): Latitude of the user's current location.
|
|
lon (float): Longitude of the user's current location.
|
|
|
|
Returns:
|
|
list[Landmark]: A list of selected nearby landmarks.
|
|
"""
|
|
logger.info(f'Fetching landmarks nearby ({lat}, {lon}).')
|
|
# Define fixed preferences:
|
|
prefs = Preferences(
|
|
sightseeing = Preference(
|
|
type='sightseeing',
|
|
score=5
|
|
),
|
|
shopping = Preference(
|
|
type='shopping',
|
|
score=2
|
|
),
|
|
nature = Preference(
|
|
type='nature',
|
|
score=5
|
|
),
|
|
max_time_minute=30,
|
|
detour_tolerance_minute=0,
|
|
)
|
|
|
|
# Find the landmarks around the location
|
|
_, landmarks_around = manager.generate_landmarks_list(
|
|
center_coordinates = (lat, lon),
|
|
preferences = prefs,
|
|
allow_clusters=False,
|
|
)
|
|
if len(landmarks_around) == 0 :
|
|
raise HTTPException(status_code=500, detail="No landmarks were found.")
|
|
|
|
# select 5 landmarks from there
|
|
if len(landmarks_around) > 6 :
|
|
landmarks_around = landmarks_around[:2] + random.sample(landmarks_around[3:], 2)
|
|
|
|
logger.info(f'Found {len(landmarks_around)} landmarks nearby ({lat}, {lon}).')
|
|
logger.debug('Suggested landmarks :\n\t' + '\n\t'.join(f'{landmark}' for landmark in landmarks_around))
|
|
return landmarks_around
|