"""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