Tentatively enable communication between front + backend #15
@@ -13,5 +13,6 @@ EXPOSE 8000
 | 
				
			|||||||
# Set environment variables used by the deployment. These can be overridden by the user using this image.
 | 
					# Set environment variables used by the deployment. These can be overridden by the user using this image.
 | 
				
			||||||
ENV NUM_WORKERS=1
 | 
					ENV NUM_WORKERS=1
 | 
				
			||||||
ENV OSM_CACHE_DIR=/cache
 | 
					ENV OSM_CACHE_DIR=/cache
 | 
				
			||||||
 | 
					ENV MEMCACHED_HOST=none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CMD fastapi run src/main.py --port 8000 --workers $NUM_WORKERS
 | 
					CMD fastapi run src/main.py --port 8000 --workers $NUM_WORKERS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,3 +14,4 @@ shapely = "*"
 | 
				
			|||||||
scipy = "*"
 | 
					scipy = "*"
 | 
				
			||||||
osmpythontools = "*"
 | 
					osmpythontools = "*"
 | 
				
			||||||
pywikibot = "*"
 | 
					pywikibot = "*"
 | 
				
			||||||
 | 
					pymemcache = "*"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										25
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
        "hash": {
 | 
					        "hash": {
 | 
				
			||||||
            "sha256": "f0de801038593d42d8b780d14c2c72bb4f5f5e66df02f72244917ede5d5ebce6"
 | 
					            "sha256": "4f8b3f0395b4e5352330616870da13acf41e16d1b69ba31b15fd688e90b8b628"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "pipfile-spec": 6,
 | 
					        "pipfile-spec": 6,
 | 
				
			||||||
        "requires": {},
 | 
					        "requires": {},
 | 
				
			||||||
@@ -1102,6 +1102,15 @@
 | 
				
			|||||||
            "markers": "python_version >= '3.8'",
 | 
					            "markers": "python_version >= '3.8'",
 | 
				
			||||||
            "version": "==2.18.0"
 | 
					            "version": "==2.18.0"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "pymemcache": {
 | 
				
			||||||
 | 
					            "hashes": [
 | 
				
			||||||
 | 
					                "sha256:27bf9bd1bbc1e20f83633208620d56de50f14185055e49504f4f5e94e94aff94",
 | 
				
			||||||
 | 
					                "sha256:f507bc20e0dc8d562f8df9d872107a278df049fa496805c1431b926f3ddd0eab"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "index": "pypi",
 | 
				
			||||||
 | 
					            "markers": "python_version >= '3.7'",
 | 
				
			||||||
 | 
					            "version": "==4.0.0"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "pyparsing": {
 | 
					        "pyparsing": {
 | 
				
			||||||
            "hashes": [
 | 
					            "hashes": [
 | 
				
			||||||
                "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad",
 | 
					                "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad",
 | 
				
			||||||
@@ -1142,12 +1151,12 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        "pywikibot": {
 | 
					        "pywikibot": {
 | 
				
			||||||
            "hashes": [
 | 
					            "hashes": [
 | 
				
			||||||
                "sha256:3f4fbc57f1765aa0fa1ccf84125bcfa475cae95b9cc0291867b751f3d4ac8fa2",
 | 
					                "sha256:0dd8291f1a26abb9fce2c2108a90dc338274988e60d21723aec1d3b0de321b5e",
 | 
				
			||||||
                "sha256:a26d918cf88ef56fdb1421b65b09def200cc28031cdc922d72a4198fbfddd225"
 | 
					                "sha256:7953fc4a6c498057e6eb7d9b762bbccb61348af0a599b89d7e246d5175b20a9b"
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "index": "pypi",
 | 
					            "index": "pypi",
 | 
				
			||||||
            "markers": "python_full_version >= '3.7.0'",
 | 
					            "markers": "python_full_version >= '3.7.0'",
 | 
				
			||||||
            "version": "==9.2.1"
 | 
					            "version": "==9.3.0"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "pyyaml": {
 | 
					        "pyyaml": {
 | 
				
			||||||
            "hashes": [
 | 
					            "hashes": [
 | 
				
			||||||
@@ -1349,7 +1358,7 @@
 | 
				
			|||||||
                "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
 | 
					                "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
 | 
				
			||||||
                "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
 | 
					                "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "markers": "python_version >= '3.8'",
 | 
					            "markers": "python_version < '3.13'",
 | 
				
			||||||
            "version": "==4.12.2"
 | 
					            "version": "==4.12.2"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "tzdata": {
 | 
					        "tzdata": {
 | 
				
			||||||
@@ -1658,11 +1667,11 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        "xarray": {
 | 
					        "xarray": {
 | 
				
			||||||
            "hashes": [
 | 
					            "hashes": [
 | 
				
			||||||
                "sha256:0b91e0bc4dc0296947947640fe31ec6e867ce258d2f7cbc10bedf4a6d68340c7",
 | 
					                "sha256:1b0fd51ec408474aa1f4a355d75c00cc1c02bd425d97b2c2e551fd21810e7f64",
 | 
				
			||||||
                "sha256:721a7394e8ec3d592b2d8ebe21eed074ac077dc1bb1bd777ce00e41700b4866c"
 | 
					                "sha256:4cae512d121a8522d41e66d942fb06c526bc1fd32c2c181d5fe62fe65b671638"
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "markers": "python_version >= '3.9'",
 | 
					            "markers": "python_version >= '3.9'",
 | 
				
			||||||
            "version": "==2024.6.0"
 | 
					            "version": "==2024.7.0"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "develop": {}
 | 
					    "develop": {}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,3 +25,7 @@ logging.config.dictConfig(config)
 | 
				
			|||||||
# if we are in a debug session, set the log level to debug
 | 
					# if we are in a debug session, set the log level to debug
 | 
				
			||||||
if os.getenv('DEBUG', False):
 | 
					if os.getenv('DEBUG', False):
 | 
				
			||||||
    logging.getLogger().setLevel(logging.DEBUG)
 | 
					    logging.getLogger().setLevel(logging.DEBUG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MEMCACHE_HOST = os.getenv('MEMCACHE_HOST', None)
 | 
				
			||||||
 | 
					if MEMCACHE_HOST == "none":
 | 
				
			||||||
 | 
					    MEMCACHE_HOST = None
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
import logging
 | 
					import logging
 | 
				
			||||||
from fastapi import FastAPI, Query, Body
 | 
					from fastapi import FastAPI, Query, Body, HTTPException
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from structs.landmark import Landmark
 | 
					from structs.landmark import Landmark
 | 
				
			||||||
from structs.preferences import Preferences
 | 
					from structs.preferences import Preferences
 | 
				
			||||||
from structs.linked_landmarks import LinkedLandmarks
 | 
					from structs.linked_landmarks import LinkedLandmarks
 | 
				
			||||||
 | 
					from structs.trip import Trip
 | 
				
			||||||
from utils.landmarks_manager import LandmarkManager
 | 
					from utils.landmarks_manager import LandmarkManager
 | 
				
			||||||
from utils.optimizer import Optimizer
 | 
					from utils.optimizer import Optimizer
 | 
				
			||||||
from utils.refiner import Refiner
 | 
					from utils.refiner import Refiner
 | 
				
			||||||
 | 
					from persistence import client as cache_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger(__name__)
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
@@ -17,8 +19,8 @@ optimizer = Optimizer()
 | 
				
			|||||||
refiner = Refiner(optimizer=optimizer)
 | 
					refiner = Refiner(optimizer=optimizer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.post("/route/new")
 | 
					@app.post("/trip/new")
 | 
				
			||||||
def get_route(preferences: Preferences, start: tuple[float, float], end: tuple[float, float] | None = None) -> str:
 | 
					def new_trip(preferences: Preferences, start: tuple[float, float], end: tuple[float, float] | None = None) -> Trip:
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    Main function to call the optimizer.
 | 
					    Main function to call the optimizer.
 | 
				
			||||||
    :param preferences: the preferences specified by the user as the post body
 | 
					    :param preferences: the preferences specified by the user as the post body
 | 
				
			||||||
@@ -47,22 +49,32 @@ def get_route(preferences: Preferences, start: tuple[float, float], end: tuple[f
 | 
				
			|||||||
    landmarks_short.insert(0, start_landmark)
 | 
					    landmarks_short.insert(0, start_landmark)
 | 
				
			||||||
    landmarks_short.append(end_landmark)
 | 
					    landmarks_short.append(end_landmark)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # TODO infer these parameters from the preferences
 | 
					 | 
				
			||||||
    max_walking_time = 4    # hours
 | 
					 | 
				
			||||||
    detour = 30             # minutes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # First stage optimization
 | 
					    # First stage optimization
 | 
				
			||||||
    base_tour = optimizer.solve_optimization(max_walking_time*60, landmarks_short)
 | 
					    base_tour = optimizer.solve_optimization(preferences.max_time_minute, landmarks_short)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # Second stage optimization
 | 
					    # Second stage optimization
 | 
				
			||||||
    refined_tour = refiner.refine_optimization(landmarks, base_tour, max_walking_time*60, detour)
 | 
					    refined_tour = refiner.refine_optimization(landmarks, base_tour, preferences.max_time_minute, preferences.detour_tolerance_minute)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    linked_tour = LinkedLandmarks(refined_tour)
 | 
					    linked_tour = LinkedLandmarks(refined_tour)
 | 
				
			||||||
    return linked_tour[0].uuid
 | 
					    # upon creation of the trip, persistence of both the trip and its landmarks is ensured. Ca
 | 
				
			||||||
 | 
					    trip = Trip.from_linked_landmarks(linked_tour, cache_client)
 | 
				
			||||||
 | 
					    return trip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### For already existing trips/landmarks
 | 
				
			||||||
 | 
					@app.get("/trip/{trip_uuid}")
 | 
				
			||||||
 | 
					def get_trip(trip_uuid: str) -> Trip:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        trip = cache_client.get(f"trip_{trip_uuid}")
 | 
				
			||||||
 | 
					        return trip
 | 
				
			||||||
 | 
					    except KeyError:
 | 
				
			||||||
 | 
					        raise HTTPException(status_code=404, detail="Trip not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.get("/landmark/{landmark_uuid}")
 | 
					@app.get("/landmark/{landmark_uuid}")
 | 
				
			||||||
def get_landmark(landmark_uuid: str) -> Landmark:
 | 
					def get_landmark(landmark_uuid: str) -> Landmark:
 | 
				
			||||||
    #cherche dans linked_tour et retourne le landmark correspondant
 | 
					    try:
 | 
				
			||||||
    pass
 | 
					        landmark = cache_client.get(f"landmark_{landmark_uuid}")
 | 
				
			||||||
 | 
					        return landmark
 | 
				
			||||||
 | 
					    except KeyError:
 | 
				
			||||||
 | 
					        raise HTTPException(status_code=404, detail="Landmark not found")
 | 
				
			||||||
							
								
								
									
										18
									
								
								backend/src/persistence.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								backend/src/persistence.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					from pymemcache.client.base import Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import constants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DummyClient:
 | 
				
			||||||
 | 
					    _data = {}
 | 
				
			||||||
 | 
					    def set(self, key, value, **kwargs):
 | 
				
			||||||
 | 
					        self._data[key] = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get(self, key, **kwargs):
 | 
				
			||||||
 | 
					        return self._data[key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if constants.MEMCACHE_HOST is None:
 | 
				
			||||||
 | 
					    client = DummyClient()
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    client = Client(constants.MEMCACHE_HOST, timeout=1)
 | 
				
			||||||
@@ -1,4 +1,3 @@
 | 
				
			|||||||
import uuid
 | 
					 | 
				
			||||||
from .landmark import Landmark
 | 
					from .landmark import Landmark
 | 
				
			||||||
from utils.get_time_separation import get_time
 | 
					from utils.get_time_separation import get_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9,8 +8,7 @@ class LinkedLandmarks:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    _landmarks = list[Landmark]
 | 
					    _landmarks = list[Landmark]
 | 
				
			||||||
    total_time = int
 | 
					    total_time: int = 0
 | 
				
			||||||
    uuid = str
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, data: list[Landmark] = None) -> None:
 | 
					    def __init__(self, data: list[Landmark] = None) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -19,7 +17,6 @@ class LinkedLandmarks:
 | 
				
			|||||||
        Args:
 | 
					        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.uuid = uuid.uuid4()
 | 
					 | 
				
			||||||
        self._landmarks = data if data else []
 | 
					        self._landmarks = data if data else []
 | 
				
			||||||
        self._link_landmarks()
 | 
					        self._link_landmarks()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,7 +25,6 @@ class LinkedLandmarks:
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        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.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.total_time = 0
 | 
					 | 
				
			||||||
        for i, landmark in enumerate(self._landmarks[:-1]):
 | 
					        for i, landmark in enumerate(self._landmarks[:-1]):
 | 
				
			||||||
            landmark.next_uuid = self._landmarks[i + 1].uuid
 | 
					            landmark.next_uuid = self._landmarks[i + 1].uuid
 | 
				
			||||||
            time_to_next = get_time(landmark.location, self._landmarks[i + 1].location)
 | 
					            time_to_next = get_time(landmark.location, self._landmarks[i + 1].location)
 | 
				
			||||||
@@ -44,18 +40,4 @@ class LinkedLandmarks:
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self) -> str:
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
        return f"LinkedLandmarks, total time: {self.total_time} minutes, {len(self._landmarks)} stops: [{','.join([str(landmark) for landmark in self._landmarks])}]"
 | 
					        return f"LinkedLandmarks [{' ->'.join([str(landmark) for landmark in self._landmarks])}]"
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def asdict(self) -> dict:
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Convert the linked landmarks to a json serializable dictionary.
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        Returns:
 | 
					 | 
				
			||||||
            dict: A dictionary representation of the linked landmarks.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            'uuid': self.uuid,
 | 
					 | 
				
			||||||
            'total_time': self.total_time,
 | 
					 | 
				
			||||||
            'landmarks': [landmark.dict() for landmark in self._landmarks]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@ from pydantic import BaseModel
 | 
				
			|||||||
from typing import Optional, Literal
 | 
					from typing import Optional, Literal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Preference(BaseModel) :
 | 
					class Preference(BaseModel) :
 | 
				
			||||||
    name: str
 | 
					 | 
				
			||||||
    type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish']
 | 
					    type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish']
 | 
				
			||||||
    score: int          # score could be from 1 to 5
 | 
					    score: int          # score could be from 1 to 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								backend/src/structs/trip.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								backend/src/structs/trip.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					from pydantic import BaseModel, Field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .landmark import Landmark
 | 
				
			||||||
 | 
					from .linked_landmarks import LinkedLandmarks
 | 
				
			||||||
 | 
					import uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Trip(BaseModel):
 | 
				
			||||||
 | 
					    uuid: str = Field(default_factory=uuid.uuid4)
 | 
				
			||||||
 | 
					    total_time: int
 | 
				
			||||||
 | 
					    first_landmark_uuid: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def from_linked_landmarks(self, landmarks: LinkedLandmarks, cache_client) -> "Trip":
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Initialize a new Trip object and ensure it is stored in the cache.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        trip = Trip(
 | 
				
			||||||
 | 
					            total_time = landmarks.total_time,
 | 
				
			||||||
 | 
					            first_landmark_uuid = str(landmarks[0].uuid)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Store the trip in the cache
 | 
				
			||||||
 | 
					        cache_client.set(f"trip_{trip.uuid}", trip)
 | 
				
			||||||
 | 
					        for landmark in landmarks:
 | 
				
			||||||
 | 
					            cache_client.set(f"landmark_{landmark.uuid}", landmark)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return trip
 | 
				
			||||||
@@ -20,18 +20,9 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    preferences = Preferences(
 | 
					    preferences = Preferences(
 | 
				
			||||||
                    sightseeing=Preference(
 | 
					        sightseeing=Preference(type='sightseeing', score = 5),
 | 
				
			||||||
                                  name='sightseeing', 
 | 
					        nature=Preference(type='nature', score = 5),
 | 
				
			||||||
                                  type='sightseeing',
 | 
					        shopping=Preference(type='shopping', score = 5),
 | 
				
			||||||
                                  score = 5),
 | 
					 | 
				
			||||||
                    nature=Preference(
 | 
					 | 
				
			||||||
                                  name='nature', 
 | 
					 | 
				
			||||||
                                  type='nature',
 | 
					 | 
				
			||||||
                                  score = 5),
 | 
					 | 
				
			||||||
                    shopping=Preference(
 | 
					 | 
				
			||||||
                                  name='shopping', 
 | 
					 | 
				
			||||||
                                  type='shopping',
 | 
					 | 
				
			||||||
                                  score = 5),
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        max_time_minute=180,
 | 
					        max_time_minute=180,
 | 
				
			||||||
        detour_tolerance_minute=30
 | 
					        detour_tolerance_minute=30
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,10 +15,6 @@ from .take_most_important import take_most_important
 | 
				
			|||||||
import constants
 | 
					import constants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SIGHTSEEING = 'sightseeing'
 | 
					 | 
				
			||||||
NATURE = 'nature'
 | 
					 | 
				
			||||||
SHOPPING = 'shopping'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LandmarkManager:
 | 
					class LandmarkManager:
 | 
				
			||||||
@@ -74,25 +70,25 @@ class LandmarkManager:
 | 
				
			|||||||
        # list for sightseeing
 | 
					        # list for sightseeing
 | 
				
			||||||
        if preferences.sightseeing.score != 0:
 | 
					        if preferences.sightseeing.score != 0:
 | 
				
			||||||
            score_function = lambda loc, n_tags: int((self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff) )*self.church_coeff)  
 | 
					            score_function = lambda loc, n_tags: int((self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff) )*self.church_coeff)  
 | 
				
			||||||
            L1 = self.fetch_landmarks(bbox, self.amenity_selectors['sightseeing'], SIGHTSEEING, score_function)
 | 
					            L1 = self.fetch_landmarks(bbox, self.amenity_selectors['sightseeing'], preferences.sightseeing.type, score_function)
 | 
				
			||||||
            self.correct_score(L1, preferences.sightseeing)
 | 
					 | 
				
			||||||
            L += L1
 | 
					            L += L1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # list for nature
 | 
					        # list for nature
 | 
				
			||||||
        if preferences.nature.score != 0:
 | 
					        if preferences.nature.score != 0:
 | 
				
			||||||
            score_function = lambda loc, n_tags: int((self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff) )*self.park_coeff)  
 | 
					            score_function = lambda loc, n_tags: int((self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff) )*self.park_coeff)  
 | 
				
			||||||
            L2 = self.fetch_landmarks(bbox, self.amenity_selectors['nature'], NATURE, score_function)
 | 
					            L2 = self.fetch_landmarks(bbox, self.amenity_selectors['nature'], preferences.nature.type, score_function)
 | 
				
			||||||
            self.correct_score(L2, preferences.nature)
 | 
					 | 
				
			||||||
            L += L2
 | 
					            L += L2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # list for shopping
 | 
					        # list for shopping
 | 
				
			||||||
        if preferences.shopping.score != 0:
 | 
					        if preferences.shopping.score != 0:
 | 
				
			||||||
            score_function = lambda loc, n_tags: int(self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff))
 | 
					            score_function = lambda loc, n_tags: int(self.count_elements_close_to(loc) + ((n_tags**1.2)*self.tag_coeff))
 | 
				
			||||||
            L3 = self.fetch_landmarks(bbox, self.amenity_selectors['shopping'], SHOPPING, score_function)
 | 
					            L3 = self.fetch_landmarks(bbox, self.amenity_selectors['shopping'], preferences.shopping.type, score_function)
 | 
				
			||||||
            self.correct_score(L3, preferences.shopping)
 | 
					 | 
				
			||||||
            L += L3
 | 
					            L += L3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        L = self.remove_duplicates(L)
 | 
					        L = self.remove_duplicates(L)
 | 
				
			||||||
 | 
					        self.correct_score(L, preferences)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        L_constrained = take_most_important(L, self.N_important)
 | 
					        L_constrained = take_most_important(L, self.N_important)
 | 
				
			||||||
        self.logger.info(f'Generated {len(L)} landmarks around {center_coordinates}, and constrained to {len(L_constrained)} most important ones.')
 | 
					        self.logger.info(f'Generated {len(L)} landmarks around {center_coordinates}, and constrained to {len(L_constrained)} most important ones.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,7 +119,7 @@ class LandmarkManager:
 | 
				
			|||||||
        return L_clean
 | 
					        return L_clean
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def correct_score(self, landmarks: list[Landmark], preference: Preference):
 | 
					    def correct_score(self, landmarks: list[Landmark], preferences: Preferences) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Adjust the attractiveness score of each landmark in the list based on user preferences.
 | 
					        Adjust the attractiveness score of each landmark in the list based on user preferences.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -132,20 +128,16 @@ class LandmarkManager:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Args:
 | 
					        Args:
 | 
				
			||||||
            landmarks (list[Landmark]): A list of landmarks whose scores need to be corrected.
 | 
					            landmarks (list[Landmark]): A list of landmarks whose scores need to be corrected.
 | 
				
			||||||
            preference (Preference): The user's preference settings that influence the attractiveness score adjustment.
 | 
					            preferences (Preferences): The user's preference settings that influence the attractiveness score adjustment.
 | 
				
			||||||
 | 
					 | 
				
			||||||
        Raises:
 | 
					 | 
				
			||||||
            TypeError: If the type of any landmark in the list does not match the expected type in the preference.
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if len(landmarks) == 0:
 | 
					        score_dict = {
 | 
				
			||||||
            return
 | 
					            preferences.sightseeing.type: preferences.sightseeing.score,
 | 
				
			||||||
        
 | 
					            preferences.nature.type: preferences.nature.score,
 | 
				
			||||||
        if landmarks[0].type != preference.type:
 | 
					            preferences.shopping.type: preferences.shopping.score
 | 
				
			||||||
            raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {landmarks[0].name}")
 | 
					        }
 | 
				
			||||||
 | 
					        for landmark in landmarks:
 | 
				
			||||||
        for elem in landmarks:
 | 
					            landmark.attractiveness = int(landmark.attractiveness * score_dict[landmark.type] / 5)        
 | 
				
			||||||
            elem.attractiveness = int(elem.attractiveness*preference.score/5)     # arbitrary computation
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def count_elements_close_to(self, coordinates: tuple[float, float]) -> int:
 | 
					    def count_elements_close_to(self, coordinates: tuple[float, float]) -> int:
 | 
				
			||||||
@@ -310,7 +302,7 @@ class LandmarkManager:
 | 
				
			|||||||
                        if "leisure" in tag and elem.tag('leisure') == "park":
 | 
					                        if "leisure" in tag and elem.tag('leisure') == "park":
 | 
				
			||||||
                            elem_type = "nature"
 | 
					                            elem_type = "nature"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if landmarktype != SHOPPING:
 | 
					                    if landmarktype != "shopping":
 | 
				
			||||||
                        if "shop" in tag:
 | 
					                        if "shop" in tag:
 | 
				
			||||||
                            skip = True
 | 
					                            skip = True
 | 
				
			||||||
                            break
 | 
					                            break
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user