hybrid cache now
Some checks failed
Run testing on the backend code / Build (pull_request) Has been cancelled
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m37s
Run linting on the backend code / Build (pull_request) Successful in 28s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 24s
Some checks failed
Run testing on the backend code / Build (pull_request) Has been cancelled
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m37s
Run linting on the backend code / Build (pull_request) Successful in 28s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 24s
This commit is contained in:
parent
83c1533e78
commit
21706ea7e6
@ -328,7 +328,7 @@ div.media {
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="title">Backend Testing Report</h1>
|
||||
<p>Report generated on 28-Jan-2025 at 16:30:56 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
|
||||
<p>Report generated on 29-Jan-2025 at 09:35:03 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
|
||||
v4.1.1</p>
|
||||
<div id="environment-header">
|
||||
<h2>Environment</h2>
|
||||
@ -382,7 +382,7 @@ div.media {
|
||||
<h2>Summary</h2>
|
||||
<div class="additional-summary prefix">
|
||||
</div>
|
||||
<p class="run-count">1 test took 00:00:10.</p>
|
||||
<p class="run-count">1 test took 97 ms.</p>
|
||||
<p class="filter">(Un)check the boxes to filter the results.</p>
|
||||
<div class="summary__reload">
|
||||
<div class="summary__reload__button hidden" onclick="location.reload()">
|
||||
@ -432,7 +432,7 @@ div.media {
|
||||
</table>
|
||||
</body>
|
||||
<footer>
|
||||
<div id="data-container" data-jsonblob="{"environment": {"Python": "3.12.3", "Platform": "Linux-6.8.0-51-generic-x86_64-with-glibc2.39", "Packages": {"pytest": "8.3.4", "pluggy": "1.5.0"}, "Plugins": {"html": "4.1.1", "anyio": "4.8.0", "metadata": "3.1.1"}}, "tests": {"src/tests/test_main.py::test_turckheim": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_turckheim", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_turckheim</td>", "<td>start (0 | 0) - 6 - H\u00f4tel des Deux-Clefs (217 | 5) - 1 - H\u00f4tel de ville (238 | 5) - 6 - finish (0 | 0) - 0</td>", "<td>23 min</td>", "<td>20 min</td>", "<td class=\"col-duration\">00:00:10</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:67 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:76 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:88 Fetching sightseeing landmarks...\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:59 Cache miss for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:204 Fetched 20 landmarks of type sightseeing in (48.079458619727674, 7.272726663391359, 48.08971738027232, 7.288083336608641)\nINFO src.utils.landmarks_manager:landmarks_manager.py:91 Found 20 sightseeing landmarks\nINFO src.overpass.overpass:overpass.py:59 Cache miss for 1 quadrants.\nINFO src.utils.cluster_manager:cluster_manager.py:145 Found 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:100 Fetching nature landmarks...\nINFO src.overpass.overpass:overpass.py:59 Cache miss for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:59 Cache miss for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:59 Cache miss for 1 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 1 quadrants.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:204 Fetched 10 landmarks of type nature in (48.079458619727674, 7.272726663391359, 48.08971738027232, 7.288083336608641)\nINFO src.utils.landmarks_manager:landmarks_manager.py:103 Found 10 nature landmarks\nINFO src.main:main.py:104 Fetched 22 landmarks in \t: 5.367 seconds\nDEBUG src.optimization.optimizer:optimizer.py:597 First results are out. Looking out for circles and correcting.\nINFO src.optimization.optimizer:optimizer.py:637 Re-optimized 0 times, objective value : 455\nDEBUG src.optimization.refiner:refiner.py:345 Using 5 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:597 First results are out. Looking out for circles and correcting.\nINFO src.optimization.optimizer:optimizer.py:637 Re-optimized 0 times, objective value : 455\nDEBUG src.main:main.py:130 First stage optimization\t: 0.126 seconds\nDEBUG src.main:main.py:131 Second stage optimization\t: 0.033 seconds\nINFO src.main:main.py:132 Total computation time\t: 0.159 seconds\nINFO src.main:main.py:137 Generated a trip of 23 minutes with 4 landmarks in 5.526 seconds.\nDEBUG src.overpass.overpass:overpass.py:112 Cache set for b2fd047a07f9563c8c0925aad9d61052\nDEBUG src.overpass.overpass:overpass.py:112 Cache set for 7ee38297ba20e3bc47b984dce2785e22\nDEBUG src.overpass.overpass:overpass.py:112 Cache set for 7f98015c7bc3a9100e10bc1c1ddfa572\nDEBUG src.overpass.overpass:overpass.py:112 Cache set for 43424dbebba69d06a66a34728c3bb93e\nDEBUG src.overpass.overpass:overpass.py:112 Cache set for b7d4ee874adac132bc9e80d7172fab8e\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}]}, "renderCollapsed": ["passed"], "initialSort": "result", "title": "Backend Testing Report"}"></div>
|
||||
<div id="data-container" data-jsonblob="{"environment": {"Python": "3.12.3", "Platform": "Linux-6.8.0-51-generic-x86_64-with-glibc2.39", "Packages": {"pytest": "8.3.4", "pluggy": "1.5.0"}, "Plugins": {"html": "4.1.1", "anyio": "4.8.0", "metadata": "3.1.1"}}, "tests": {"src/tests/test_main.py::test_turckheim": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_turckheim", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_turckheim</td>", "<td>start (0 | 0) - 3 - Mairie du 2e arrondissement (78 | 5) - 1 - Basilique Saint-Martin d'Ainay (406 | 5) - 3 - Chapelle Paul Couturier (109 | 5) - 1 - finish (0 | 0) - 0</td>", "<td>23 min</td>", "<td>20 min</td>", "<td class=\"col-duration\">97 ms</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:67 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:76 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:88 Fetching sightseeing landmarks...\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:204 Fetched 16 landmarks of type sightseeing in (45.74643460077641, 4.819803369760263, 45.756693361321055, 4.834505559895031)\nINFO src.utils.landmarks_manager:landmarks_manager.py:91 Found 16 sightseeing landmarks\nINFO src.overpass.overpass:overpass.py:55 Cache hit for 2/2 quadrants.\nINFO src.utils.cluster_manager:cluster_manager.py:145 Found 0 sightseeing clusters.\nINFO src.main:main.py:104 Fetched 12 landmarks in \t: 0.011 seconds\nDEBUG src.optimization.optimizer:optimizer.py:597 First results are out. Looking out for circles and correcting.\nINFO src.optimization.optimizer:optimizer.py:637 Re-optimized 0 times, objective value : 593\nDEBUG src.optimization.refiner:refiner.py:345 Using 2 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:597 First results are out. Looking out for circles and correcting.\nINFO src.optimization.optimizer:optimizer.py:637 Re-optimized 0 times, objective value : 593\nDEBUG src.main:main.py:130 First stage optimization\t: 0.045 seconds\nDEBUG src.main:main.py:131 Second stage optimization\t: 0.025 seconds\nINFO src.main:main.py:132 Total computation time\t: 0.071 seconds\nINFO src.main:main.py:137 Generated a trip of 23 minutes with 5 landmarks in 0.082 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}]}, "renderCollapsed": ["passed"], "initialSort": "result", "title": "Backend Testing Report"}"></div>
|
||||
<script>
|
||||
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
const { getCollapsedCategory, setCollapsedIds } = require('./storage.js')
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import List, Literal
|
||||
from typing import List, Literal, Tuple
|
||||
|
||||
|
||||
LOCATION_PREFIX = Path('src')
|
||||
@ -16,6 +16,7 @@ cache_dir_string = os.getenv('OSM_CACHE_DIR', './cache')
|
||||
OSM_CACHE_DIR = Path(cache_dir_string)
|
||||
|
||||
OSM_TYPES = List[Literal['way', 'node', 'relation']]
|
||||
BBOX = Tuple[float, float, float, float]
|
||||
|
||||
MEMCACHED_HOST_PATH = os.getenv('MEMCACHED_HOST_PATH', None)
|
||||
if MEMCACHED_HOST_PATH == "none":
|
||||
|
@ -54,7 +54,8 @@ class JSONCache(CachingStrategyBase):
|
||||
# Open and parse the cached JSON data
|
||||
with open(filename, 'r', encoding='utf-8') as file:
|
||||
data = json.load(file)
|
||||
return data # Return the parsed JSON data
|
||||
# Return the data as a list of dicts.
|
||||
return data
|
||||
except json.JSONDecodeError:
|
||||
return None # Return None if parsing fails
|
||||
return None
|
||||
|
@ -4,12 +4,14 @@ import urllib
|
||||
import math
|
||||
import logging
|
||||
import json
|
||||
from typing import List, Tuple
|
||||
|
||||
from .caching_strategy import get_cache_key, CachingStrategy
|
||||
from ..constants import OSM_CACHE_DIR, OSM_TYPES
|
||||
from ..constants import OSM_CACHE_DIR, OSM_TYPES, BBOX
|
||||
|
||||
|
||||
RESOLUTION = 0.05
|
||||
CELL = Tuple[int, int]
|
||||
|
||||
|
||||
class Overpass :
|
||||
@ -29,8 +31,8 @@ class Overpass :
|
||||
self.caching_strategy = CachingStrategy.use(caching_strategy, cache_dir=cache_dir)
|
||||
|
||||
|
||||
def send_query(self, bbox: tuple, osm_types: OSM_TYPES,
|
||||
selector: str, conditions: list=None, out='center'):
|
||||
def send_query(self, bbox: BBOX, osm_types: OSM_TYPES,
|
||||
selector: str, conditions: list=None, out='center') -> List[dict]:
|
||||
"""
|
||||
Sends the Overpass QL query to the Overpass API and returns the parsed json response.
|
||||
|
||||
@ -42,28 +44,35 @@ class Overpass :
|
||||
out (str): Output format ('center', 'body', etc.). Defaults to 'center'.
|
||||
|
||||
Returns:
|
||||
dict: Parsed json response from the Overpass API, or cached data if available.
|
||||
list: Parsed json response from the Overpass API, or cached data if available.
|
||||
"""
|
||||
# Determine which grid cells overlap with this bounding box.
|
||||
overlapping_cells = Overpass._get_overlapping_cells(bbox)
|
||||
|
||||
# Retrieve cached data and identify missing cache entries
|
||||
cached_responses, hollow_cache_keys = self._retrieve_cached_data(overlapping_cells, osm_types, selector, conditions, out)
|
||||
cached_responses, non_cached_cells = self._retrieve_cached_data(overlapping_cells, osm_types, selector, conditions, out)
|
||||
|
||||
# If there is no missing data, return the cached responses
|
||||
if not hollow_cache_keys :
|
||||
self.logger.info(f'Cache hit for {len(cached_responses)} quadrants.')
|
||||
return self._combine_cached_data(cached_responses)
|
||||
self.logger.info(f'Cache hit for {len(overlapping_cells)-len(non_cached_cells)}/{len(overlapping_cells)} quadrants.')
|
||||
|
||||
# TODO If there is SOME missing data : hybrid stuff with partial cache
|
||||
self.logger.info(f'Cache miss for {len(hollow_cache_keys)} quadrants.')
|
||||
# If there is no missing data, return the cached responses after filtering.
|
||||
if not non_cached_cells :
|
||||
return Overpass._filter_landmarks(cached_responses, bbox)
|
||||
|
||||
# Missing data: Make a query to Overpass API
|
||||
query_str = Overpass.build_query(bbox, osm_types, selector, conditions, out)
|
||||
return self.fetch_data_from_api(query_str)
|
||||
# If there is no cached data, fetch all from Overpass.
|
||||
elif not cached_responses :
|
||||
query_str = Overpass.build_query(bbox, osm_types, selector, conditions, out)
|
||||
return self.fetch_data_from_api(query_str)
|
||||
|
||||
# Hybrid cache: some data from Overpass, some data from cache.
|
||||
else :
|
||||
# Resize the bbox for smaller search area and build new query string.
|
||||
non_cached_bbox = Overpass._get_non_cached_bbox(non_cached_cells, bbox)
|
||||
query_str = Overpass.build_query(non_cached_bbox, osm_types, selector, conditions, out)
|
||||
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:
|
||||
def fetch_data_from_api(self, query_str: str) -> List[dict]:
|
||||
"""
|
||||
Fetch data from the Overpass API and return the json data.
|
||||
|
||||
@ -117,7 +126,7 @@ class Overpass :
|
||||
|
||||
|
||||
@staticmethod
|
||||
def build_query(bbox: tuple, osm_types: OSM_TYPES,
|
||||
def build_query(bbox: BBOX, osm_types: OSM_TYPES,
|
||||
selector: str, conditions: list=None, out='center') -> str:
|
||||
"""
|
||||
Constructs a query string for the Overpass API to retrieve OpenStreetMap (OSM) data.
|
||||
@ -160,9 +169,10 @@ class Overpass :
|
||||
return query
|
||||
|
||||
|
||||
def _retrieve_cached_data(self, overlapping_cells: list, osm_types: OSM_TYPES, selector: str, conditions: list, out: str):
|
||||
def _retrieve_cached_data(self, overlapping_cells: CELL, osm_types: OSM_TYPES,
|
||||
selector: str, conditions: list, out: str) -> Tuple[List[dict], list[CELL]]:
|
||||
"""
|
||||
Retrieve cached data and identify missing cache entries.
|
||||
Retrieve cached data and identify missing cache quadrants.
|
||||
|
||||
Args:
|
||||
overlapping_cells (list): Cells to check for cached data.
|
||||
@ -174,7 +184,7 @@ class Overpass :
|
||||
Returns:
|
||||
tuple: A tuple containing:
|
||||
- cached_responses (list): List of cached data found.
|
||||
- hollow_cache_keys (list): List of keys with missing data.
|
||||
- non_cached_cells (list(tuple)): List of cells with missing data.
|
||||
"""
|
||||
cell_key_dict = {}
|
||||
for cell in overlapping_cells :
|
||||
@ -184,29 +194,29 @@ class Overpass :
|
||||
cell_key_dict[cell] = get_cache_key(key_str)
|
||||
|
||||
cached_responses = []
|
||||
hollow_cache_keys = []
|
||||
non_cached_cells = []
|
||||
|
||||
# Retrieve the cached data and mark the missing entries as hollow
|
||||
for cell, key in cell_key_dict.items():
|
||||
cached_data = self.caching_strategy.get(key)
|
||||
if cached_data is not None :
|
||||
cached_responses.append(cached_data)
|
||||
cached_responses += cached_data
|
||||
else:
|
||||
self.caching_strategy.set_hollow(key, cell, osm_types, selector, conditions, out)
|
||||
hollow_cache_keys.append(key)
|
||||
non_cached_cells.append(cell)
|
||||
|
||||
return cached_responses, hollow_cache_keys
|
||||
return cached_responses, non_cached_cells
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _build_query_from_hollow(json_data: dict):
|
||||
def _build_query_from_hollow(json_data: dict) -> Tuple[str, str]:
|
||||
"""
|
||||
Build query string using information from a hollow cache entry.
|
||||
"""
|
||||
# Extract values from the JSON object
|
||||
key = json_data.get('key')
|
||||
cell = tuple(json_data.get('cell'))
|
||||
bbox = Overpass._get_bbox_from_grid_cell(cell[0], cell[1])
|
||||
bbox = Overpass._get_bbox_from_grid_cell(cell)
|
||||
osm_types = json_data.get('osm_types')
|
||||
selector = json_data.get('selector')
|
||||
conditions = json_data.get('conditions')
|
||||
@ -218,7 +228,7 @@ class Overpass :
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _get_overlapping_cells(query_bbox: tuple):
|
||||
def _get_overlapping_cells(query_bbox: tuple) -> List[CELL]:
|
||||
"""
|
||||
Returns a set of all grid cells that overlap with the given bounding box.
|
||||
"""
|
||||
@ -237,7 +247,7 @@ class Overpass :
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _get_grid_cell(lat: float, lon: float):
|
||||
def _get_grid_cell(lat: float, lon: float) -> CELL:
|
||||
"""
|
||||
Returns the grid cell coordinates for a given latitude and longitude.
|
||||
Each grid cell is 0.05°lat x 0.05°lon resolution in size.
|
||||
@ -248,7 +258,7 @@ class Overpass :
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _get_bbox_from_grid_cell(lat_index: int, lon_index: int):
|
||||
def _get_bbox_from_grid_cell(cell: CELL) -> BBOX:
|
||||
"""
|
||||
Returns the bounding box for a given grid cell index.
|
||||
Each grid cell is resolution x resolution in size.
|
||||
@ -256,26 +266,84 @@ class Overpass :
|
||||
The bounding box is returned as (min_lat, min_lon, max_lat, max_lon).
|
||||
"""
|
||||
# Calculate the southwest (min_lat, min_lon) corner of the bounding box
|
||||
min_lat = round(lat_index * RESOLUTION, 2)
|
||||
min_lon = round(lon_index * RESOLUTION, 2)
|
||||
min_lat = round(cell[0] * RESOLUTION, 2)
|
||||
min_lon = round(cell[1] * RESOLUTION, 2)
|
||||
|
||||
# Calculate the northeast (max_lat, max_lon) corner of the bounding box
|
||||
max_lat = round((lat_index + 1) * RESOLUTION, 2)
|
||||
max_lon = round((lon_index + 1) * RESOLUTION, 2)
|
||||
max_lat = round((cell[0] + 1) * RESOLUTION, 2)
|
||||
max_lon = round((cell[1] + 1) * RESOLUTION, 2)
|
||||
|
||||
return (min_lat, min_lon, max_lat, max_lon)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _combine_cached_data(cached_data_list):
|
||||
def _get_non_cached_bbox(non_cached_cells: List[CELL], original_bbox: BBOX):
|
||||
"""
|
||||
Combines data from multiple cached responses into a single result.
|
||||
Calculate the non-cached bounding box by excluding cached cells.
|
||||
|
||||
Args:
|
||||
non_cached_cells (list): The list of cells that were not found in the cache.
|
||||
original_bbox (tuple): The original bounding box (min_lat, min_lon, max_lat, max_lon).
|
||||
|
||||
Returns:
|
||||
tuple: The new bounding box that excludes cached cells, or None if all cells are cached.
|
||||
"""
|
||||
combined_data = []
|
||||
for cached_data in cached_data_list:
|
||||
for element in cached_data:
|
||||
combined_data.append(element)
|
||||
return combined_data
|
||||
if not non_cached_cells:
|
||||
return None # All cells were cached
|
||||
|
||||
# Initialize the non-cached bounding box with extreme values
|
||||
min_lat, min_lon, max_lat, max_lon = float('inf'), float('inf'), float('-inf'), float('-inf')
|
||||
|
||||
# Iterate over non-cached cells to find the new bounding box
|
||||
for cell in non_cached_cells:
|
||||
cell_min_lat, cell_min_lon, cell_max_lat, cell_max_lon = Overpass._get_bbox_from_grid_cell(cell)
|
||||
|
||||
min_lat = min(min_lat, cell_min_lat)
|
||||
min_lon = min(min_lon, cell_min_lon)
|
||||
max_lat = max(max_lat, cell_max_lat)
|
||||
max_lon = max(max_lon, cell_max_lon)
|
||||
|
||||
# If no update to bounding box, return the original
|
||||
if min_lat == float('inf') or min_lon == float('inf'):
|
||||
return None
|
||||
|
||||
return (max(min_lat, original_bbox[0]),
|
||||
max(min_lon, original_bbox[1]),
|
||||
min(max_lat, original_bbox[2]),
|
||||
min(max_lon, original_bbox[3]))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _filter_landmarks(elements: List[dict], bbox: BBOX) -> List[dict]:
|
||||
"""
|
||||
Filters elements based on whether their coordinates are inside the given bbox.
|
||||
|
||||
Args:
|
||||
- elements (list of dict): List of elements containing coordinates.
|
||||
- bbox (tuple): A bounding box defined as (min_lat, min_lon, max_lat, max_lon).
|
||||
|
||||
Returns:
|
||||
- list: A list of elements whose coordinates are inside the bounding box.
|
||||
"""
|
||||
|
||||
filtered_elements = []
|
||||
min_lat, min_lon, max_lat, max_lon = bbox
|
||||
|
||||
for elem in elements:
|
||||
# Extract coordinates based on the 'type' of element
|
||||
if elem.get('type') != 'node':
|
||||
center = elem.get('center', {})
|
||||
lat = float(center.get('lat', 0))
|
||||
lon = float(center.get('lon', 0))
|
||||
else:
|
||||
lat = float(elem.get('lat', 0))
|
||||
lon = float(elem.get('lon', 0))
|
||||
|
||||
# Check if the coordinates fall within the given bounding box
|
||||
if min_lat <= lat <= max_lat and min_lon <= lon <= max_lon:
|
||||
filtered_elements.append(elem)
|
||||
|
||||
return filtered_elements
|
||||
|
||||
|
||||
def get_base_info(elem: dict, osm_type: OSM_TYPES, with_name=False) :
|
||||
|
@ -27,11 +27,13 @@ def test_turckheim(client, request): # pylint: disable=redefined-outer-name
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 0},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [48.084588, 7.280405]
|
||||
# "start": [48.084588, 7.280405]
|
||||
# "start": [45.74445023349939, 4.8222687890538865]
|
||||
"start": [45.75156398104873, 4.827154464827647]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
@ -56,7 +58,7 @@ def test_turckheim(client, request): # pylint: disable=redefined-outer-name
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
# assert 2!= 3
|
||||
|
||||
|
||||
'''
|
||||
def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°2 : Custom test in Lyon centre to ensure proper decision making in crowded area.
|
||||
@ -342,3 +344,4 @@ 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 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}"
|
||||
'''
|
Loading…
x
Reference in New Issue
Block a user