Compare commits
	
		
			6 Commits
		
	
	
		
			v0.0.37
			...
			86187d9069
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 86187d9069 | |||
| 4e07c10969 | |||
| bc63b57154 | |||
| fa083a1080 | |||
| c448e2dfb7 | |||
| d9061388dd | 
@@ -25,8 +25,6 @@ jobs:
 | 
				
			|||||||
        ls -la
 | 
					        ls -la
 | 
				
			||||||
        # only install dev-packages
 | 
					        # only install dev-packages
 | 
				
			||||||
        pipenv install --categories=dev-packages
 | 
					        pipenv install --categories=dev-packages
 | 
				
			||||||
        pipenv run pip freeze        
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      working-directory: backend
 | 
					      working-directory: backend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Run linter
 | 
					    - name: Run linter
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,6 @@ jobs:
 | 
				
			|||||||
        ls -la
 | 
					        ls -la
 | 
				
			||||||
        # install all packages, including dev-packages
 | 
					        # install all packages, including dev-packages
 | 
				
			||||||
        pipenv install --dev
 | 
					        pipenv install --dev
 | 
				
			||||||
        pipenv run pip freeze        
 | 
					 | 
				
			||||||
      working-directory: backend
 | 
					      working-directory: backend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Run Tests
 | 
					    - name: Run Tests
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							@@ -9,18 +9,16 @@
 | 
				
			|||||||
            "name": "Backend - debug",
 | 
					            "name": "Backend - debug",
 | 
				
			||||||
            "type": "debugpy",
 | 
					            "type": "debugpy",
 | 
				
			||||||
            "request": "launch",
 | 
					            "request": "launch",
 | 
				
			||||||
            "module": "uvicorn",
 | 
					 | 
				
			||||||
            "env": {
 | 
					            "env": {
 | 
				
			||||||
                "DEBUG": "true"
 | 
					                "DEBUG": "true"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "args": [
 | 
					 | 
				
			||||||
                // "--app-dir",
 | 
					 | 
				
			||||||
                // "src",
 | 
					 | 
				
			||||||
                "src.main:app",
 | 
					 | 
				
			||||||
                "--reload",
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            "jinja": true,
 | 
					            "jinja": true,
 | 
				
			||||||
            "cwd": "${workspaceFolder}/backend"
 | 
					            "cwd": "${workspaceFolder}/backend",
 | 
				
			||||||
 | 
					            "module": "fastapi",
 | 
				
			||||||
 | 
					            "args": [
 | 
				
			||||||
 | 
					                "dev",
 | 
				
			||||||
 | 
					                "src/main.py"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "Backend - tester",
 | 
					            "name": "Backend - tester",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
    "cmake.ignoreCMakeListsMissing": true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -14,5 +14,7 @@ EXPOSE 8000
 | 
				
			|||||||
ENV NUM_WORKERS=1
 | 
					ENV NUM_WORKERS=1
 | 
				
			||||||
ENV OSM_CACHE_DIR=/cache
 | 
					ENV OSM_CACHE_DIR=/cache
 | 
				
			||||||
ENV MEMCACHED_HOST_PATH=none
 | 
					ENV MEMCACHED_HOST_PATH=none
 | 
				
			||||||
 | 
					ENV LOKI_URL=none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# explicitly use a string instead of an argument list to force a shell and variable expansion
 | 
				
			||||||
CMD fastapi run src/main.py --port 8000 --workers $NUM_WORKERS
 | 
					CMD fastapi run src/main.py --port 8000 --workers $NUM_WORKERS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,3 +25,4 @@ pymemcache = "*"
 | 
				
			|||||||
fastapi-cli = "*"
 | 
					fastapi-cli = "*"
 | 
				
			||||||
scikit-learn = "*"
 | 
					scikit-learn = "*"
 | 
				
			||||||
pyqt6 = "*"
 | 
					pyqt6 = "*"
 | 
				
			||||||
 | 
					loki-logger-handler = "*"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										11
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
        "hash": {
 | 
					        "hash": {
 | 
				
			||||||
            "sha256": "bb22b4e28c7aa199c94b688ad93d3ab0ccf1089a172131f4aec03b78e7bd7f1c"
 | 
					            "sha256": "6edd6644586e8814a0b4526adb3352dfc17828ca129de7a68c1d5929efe94daa"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "pipfile-spec": 6,
 | 
					        "pipfile-spec": 6,
 | 
				
			||||||
        "requires": {},
 | 
					        "requires": {},
 | 
				
			||||||
@@ -507,6 +507,15 @@
 | 
				
			|||||||
            "markers": "python_version >= '3.8'",
 | 
					            "markers": "python_version >= '3.8'",
 | 
				
			||||||
            "version": "==1.4.7"
 | 
					            "version": "==1.4.7"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "loki-logger-handler": {
 | 
				
			||||||
 | 
					            "hashes": [
 | 
				
			||||||
 | 
					                "sha256:aa1a9c933282c134a1e4271aba3cbaa2a3660eab6ea415bad7a072444ab98aa8",
 | 
				
			||||||
 | 
					                "sha256:f6114727a9e5e6f3f2058b9b5324d1cab6d1a04e802079f7b57a8aeb7bd0a112"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "index": "pypi",
 | 
				
			||||||
 | 
					            "markers": "python_version >= '2.7'",
 | 
				
			||||||
 | 
					            "version": "==1.0.2"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "lxml": {
 | 
					        "lxml": {
 | 
				
			||||||
            "hashes": [
 | 
					            "hashes": [
 | 
				
			||||||
                "sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e",
 | 
					                "sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e",
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule backend/deployment updated: 718df09e88...904f16bfc0
									
								
							
							
								
								
									
										1094
									
								
								backend/report.html
									
									
									
									
									
								
							
							
						
						
									
										1094
									
								
								backend/report.html
									
									
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,6 +1,5 @@
 | 
				
			|||||||
"""Module allowing to access the parameters of route generation"""
 | 
					"""Module setting global parameters for the application such as cache, route generation, etc."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import logging
 | 
					 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,21 +15,6 @@ cache_dir_string = os.getenv('OSM_CACHE_DIR', './cache')
 | 
				
			|||||||
OSM_CACHE_DIR = Path(cache_dir_string)
 | 
					OSM_CACHE_DIR = Path(cache_dir_string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# if we are in a debug session, set verbose and rich logging
 | 
					 | 
				
			||||||
if os.getenv('DEBUG', "false") == "true":
 | 
					 | 
				
			||||||
    from rich.logging import RichHandler
 | 
					 | 
				
			||||||
    logging.basicConfig(
 | 
					 | 
				
			||||||
        level=logging.DEBUG,
 | 
					 | 
				
			||||||
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
 | 
					 | 
				
			||||||
        handlers=[RichHandler()]
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
    logging.basicConfig(
 | 
					 | 
				
			||||||
        level=logging.INFO,
 | 
					 | 
				
			||||||
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MEMCACHED_HOST_PATH = os.getenv('MEMCACHED_HOST_PATH', None)
 | 
					MEMCACHED_HOST_PATH = os.getenv('MEMCACHED_HOST_PATH', None)
 | 
				
			||||||
if MEMCACHED_HOST_PATH == "none":
 | 
					if MEMCACHED_HOST_PATH == "none":
 | 
				
			||||||
    MEMCACHED_HOST_PATH = None
 | 
					    MEMCACHED_HOST_PATH = None
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										58
									
								
								backend/src/logging_config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								backend/src/logging_config.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					"""Sets up global logging configuration for the application."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def configure_logging():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Called at startup of a FastAPI application instance to setup logging. Depending on the environment, it will log to stdout or to Loki.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    is_debug = os.getenv('DEBUG', "false") == "true"
 | 
				
			||||||
 | 
					    is_kubernetes = os.getenv('KUBERNETES_SERVICE_HOST') is not None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if is_kubernetes:
 | 
				
			||||||
 | 
					        # in that case we want to log to stdout and also to loki
 | 
				
			||||||
 | 
					        from loki_logger_handler.loki_logger_handler import LokiLoggerHandler
 | 
				
			||||||
 | 
					        loki_url = os.getenv('LOKI_URL')
 | 
				
			||||||
 | 
					        loki_url = "http://localhost:3100/loki/api/v1/push"
 | 
				
			||||||
 | 
					        if loki_url is None:
 | 
				
			||||||
 | 
					            raise ValueError("LOKI_URL environment variable is not set")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        loki_handler = LokiLoggerHandler(
 | 
				
			||||||
 | 
					            url = loki_url,
 | 
				
			||||||
 | 
					            labels = {'app': 'anyway', 'environment': 'staging' if is_debug else 'production'}
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        logger.info(f"Logging to Loki at {loki_url} with {loki_handler.labels} and {is_debug=}")
 | 
				
			||||||
 | 
					        logging_handlers = [loki_handler, logging.StreamHandler()]
 | 
				
			||||||
 | 
					        logging_level = logging.DEBUG if is_debug else logging.INFO
 | 
				
			||||||
 | 
					        # silence the chatty logs loki generates itself
 | 
				
			||||||
 | 
					        logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
 | 
				
			||||||
 | 
					        # no need for time since it's added by loki or can be shown in kube logs
 | 
				
			||||||
 | 
					        logging_format = '%(name)s - %(levelname)s - %(message)s'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        # if we are in a debug (local) session, set verbose and rich logging
 | 
				
			||||||
 | 
					        from rich.logging import RichHandler
 | 
				
			||||||
 | 
					        logging_handlers = [RichHandler()]
 | 
				
			||||||
 | 
					        logging_level = logging.DEBUG if is_debug else logging.INFO
 | 
				
			||||||
 | 
					        logging_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    logging.basicConfig(
 | 
				
			||||||
 | 
					        level = logging_level,
 | 
				
			||||||
 | 
					        format = logging_format,
 | 
				
			||||||
 | 
					        handlers = logging_handlers
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # also overwrite the uvicorn loggers
 | 
				
			||||||
 | 
					    logging.getLogger('uvicorn').handlers = logging_handlers
 | 
				
			||||||
 | 
					    logging.getLogger('uvicorn.access').handlers = logging_handlers
 | 
				
			||||||
 | 
					    logging.getLogger('uvicorn.error').handlers = logging_handlers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2,7 +2,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
from fastapi import FastAPI, HTTPException, Query
 | 
					from fastapi import FastAPI, HTTPException, Query
 | 
				
			||||||
 | 
					from contextlib import asynccontextmanager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .logging_config import configure_logging
 | 
				
			||||||
from .structs.landmark import Landmark, Toilets
 | 
					from .structs.landmark import Landmark, Toilets
 | 
				
			||||||
from .structs.preferences import Preferences
 | 
					from .structs.preferences import Preferences
 | 
				
			||||||
from .structs.linked_landmarks import LinkedLandmarks
 | 
					from .structs.linked_landmarks import LinkedLandmarks
 | 
				
			||||||
@@ -11,17 +13,28 @@ from .utils.landmarks_manager import LandmarkManager
 | 
				
			|||||||
from .utils.toilets_manager import ToiletsManager
 | 
					from .utils.toilets_manager import ToiletsManager
 | 
				
			||||||
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
 | 
					from .cache import client as cache_client
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger(__name__)
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app = FastAPI()
 | 
					 | 
				
			||||||
manager = LandmarkManager()
 | 
					manager = LandmarkManager()
 | 
				
			||||||
optimizer = Optimizer()
 | 
					optimizer = Optimizer()
 | 
				
			||||||
refiner = Refiner(optimizer=optimizer)
 | 
					refiner = Refiner(optimizer=optimizer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@asynccontextmanager
 | 
				
			||||||
 | 
					async def lifespan(app: FastAPI):
 | 
				
			||||||
 | 
					    """Function to run at the start of the app"""
 | 
				
			||||||
 | 
					    logger.info("Setting up logging")
 | 
				
			||||||
 | 
					    configure_logging()
 | 
				
			||||||
 | 
					    yield
 | 
				
			||||||
 | 
					    logger.info("Shutting down logging")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app = FastAPI(lifespan=lifespan)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.post("/trip/new")
 | 
					@app.post("/trip/new")
 | 
				
			||||||
def new_trip(preferences: Preferences,
 | 
					def new_trip(preferences: Preferences,
 | 
				
			||||||
             start: tuple[float, float],
 | 
					             start: tuple[float, float],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					from typing import Optional, Literal
 | 
				
			||||||
from uuid import uuid4
 | 
					from uuid import uuid4, UUID
 | 
				
			||||||
from pydantic import BaseModel, Field
 | 
					from pydantic import BaseModel, Field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,12 +29,12 @@ class Landmark(BaseModel) :
 | 
				
			|||||||
        description (Optional[str]): A text description of the landmark.
 | 
					        description (Optional[str]): A text description of the landmark.
 | 
				
			||||||
        duration (Optional[int]): The estimated time to visit the landmark (in minutes).
 | 
					        duration (Optional[int]): The estimated time to visit the landmark (in minutes).
 | 
				
			||||||
        name_en (Optional[str]): The English name of the landmark.
 | 
					        name_en (Optional[str]): The English name of the landmark.
 | 
				
			||||||
        uuid (str): A unique identifier for the landmark, generated by default using uuid4.
 | 
					        uuid (UUID): A unique identifier for the landmark, generated by default using uuid4.
 | 
				
			||||||
        must_do (Optional[bool]): Whether the landmark is a "must-do" attraction.
 | 
					        must_do (Optional[bool]): Whether the landmark is a "must-do" attraction.
 | 
				
			||||||
        must_avoid (Optional[bool]): Whether the landmark should be avoided.
 | 
					        must_avoid (Optional[bool]): Whether the landmark should be avoided.
 | 
				
			||||||
        is_secondary (Optional[bool]): Whether the landmark is secondary or less important.
 | 
					        is_secondary (Optional[bool]): Whether the landmark is secondary or less important.
 | 
				
			||||||
        time_to_reach_next (Optional[int]): Estimated time (in minutes) to reach the next landmark.
 | 
					        time_to_reach_next (Optional[int]): Estimated time (in minutes) to reach the next landmark.
 | 
				
			||||||
        next_uuid (Optional[str]): UUID of the next landmark in sequence (if applicable).
 | 
					        next_uuid (Optional[UUID]): UUID of the next landmark in sequence (if applicable).
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Properties of the landmark
 | 
					    # Properties of the landmark
 | 
				
			||||||
@@ -52,7 +52,7 @@ class Landmark(BaseModel) :
 | 
				
			|||||||
    name_en : Optional[str] = None
 | 
					    name_en : Optional[str] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Unique ID of a given landmark
 | 
					    # Unique ID of a given landmark
 | 
				
			||||||
    uuid: str = Field(default_factory=uuid4)
 | 
					    uuid: UUID = Field(default_factory=uuid4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Additional properties depending on specific tour
 | 
					    # Additional properties depending on specific tour
 | 
				
			||||||
    must_do : Optional[bool] = False
 | 
					    must_do : Optional[bool] = False
 | 
				
			||||||
@@ -60,7 +60,7 @@ class Landmark(BaseModel) :
 | 
				
			|||||||
    is_secondary : Optional[bool] = False
 | 
					    is_secondary : Optional[bool] = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    time_to_reach_next : Optional[int] = 0
 | 
					    time_to_reach_next : Optional[int] = 0
 | 
				
			||||||
    next_uuid : Optional[str] = None
 | 
					    next_uuid : Optional[UUID] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self) -> str:
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -139,4 +139,4 @@ class Toilets(BaseModel) :
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    class Config:
 | 
					    class Config:
 | 
				
			||||||
        # This allows us to easily convert the model to and from dictionaries
 | 
					        # This allows us to easily convert the model to and from dictionaries
 | 
				
			||||||
        orm_mode = True
 | 
					        from_attributes = True
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
"""Definition of the Trip class."""
 | 
					"""Definition of the Trip class."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import uuid
 | 
					from uuid import uuid4, UUID
 | 
				
			||||||
from pydantic import BaseModel, Field
 | 
					from pydantic import BaseModel, Field
 | 
				
			||||||
from pymemcache.client.base import Client
 | 
					from pymemcache.client.base import Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,9 +19,9 @@ class Trip(BaseModel):
 | 
				
			|||||||
    Methods:
 | 
					    Methods:
 | 
				
			||||||
        from_linked_landmarks: create a Trip from LinkedLandmarks object.
 | 
					        from_linked_landmarks: create a Trip from LinkedLandmarks object.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    uuid: str = Field(default_factory=uuid.uuid4)
 | 
					    uuid: UUID = Field(default_factory=uuid4)
 | 
				
			||||||
    total_time: int
 | 
					    total_time: int
 | 
				
			||||||
    first_landmark_uuid: str
 | 
					    first_landmark_uuid: UUID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
@@ -31,7 +31,7 @@ class Trip(BaseModel):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        trip = Trip(
 | 
					        trip = Trip(
 | 
				
			||||||
            total_time = landmarks.total_time,
 | 
					            total_time = landmarks.total_time,
 | 
				
			||||||
            first_landmark_uuid = str(landmarks[0].uuid)
 | 
					            first_landmark_uuid = landmarks[0].uuid
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Store the trip in the cache
 | 
					        # Store the trip in the cache
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ from fastapi import HTTPException
 | 
				
			|||||||
from pydantic import ValidationError
 | 
					from pydantic import ValidationError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ..structs.landmark import Landmark
 | 
					from ..structs.landmark import Landmark
 | 
				
			||||||
from ..persistence import client as cache_client
 | 
					from ..cache import client as cache_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def landmarks_to_osmid(landmarks: list[Landmark]) -> list[int] :
 | 
					def landmarks_to_osmid(landmarks: list[Landmark]) -> list[int] :
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user