diff --git a/backend/report.html b/backend/report.html index 806bcc0..7839f15 100644 --- a/backend/report.html +++ b/backend/report.html @@ -328,7 +328,7 @@ div.media { </head> <body> <h1 id="title">Backend Testing Report</h1> - <p>Report generated on 23-Jan-2025 at 16:01:46 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a> + <p>Report generated on 23-Jan-2025 at 16:22:05 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">8 tests took 00:01:50.</p> + <p class="run-count">8 tests took 00:01:51.</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) - 4 - Square Charles Grad (47 | 5) - 3 - Porte de France (157 | 5) - 5 - finish (0 | 0) - 0</td>", "<td>22 min</td>", "<td>20 min</td>", "<td class=\"col-duration\">117 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:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[historic](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[building=cathedral](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 1 landmarks of type sightseeing in (285.5, 48.084588, 7.280405)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:275, 48.085, 7.28););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:154 Detected 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:275, 48.085, 7.28);relation[leisure=park](around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:275, 48.085, 7.28);relation[geological](around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:275, 48.085, 7.28);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:275, 48.085, 7.28);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:275, 48.085, 7.28);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:275, 48.085, 7.28);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:275, 48.085, 7.28);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 6 landmarks of type nature in (285.5, 48.084588, 7.280405)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:275, 48.085, 7.28););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 0 landmarks of type shopping in (285.5, 48.084588, 7.280405)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:275, 48.085, 7.28););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:158 Detected 0 shopping clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 5 landmarks in \t: 0.012 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 0 times, objective value : 204\nDEBUG src.optimization.refiner:refiner.py:345 Using 1 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 0 times, objective value : 204\nDEBUG src.main:main.py:120 First stage optimization\t: 0.017 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 0.019 seconds\nINFO src.main:main.py:122 Total computation time\t: 0.037 seconds\nINFO src.main:main.py:127 Generated a trip of 22 minutes with 4 landmarks in 0.049 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_bellecour": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_bellecour", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_bellecour</td>", "<td>start (0 | 0) - 5 - H\u00f4tel de l'Europe (191 | 5) - 5 - Cath\u00e9drale Saint-Jean (305 | 5) - 5 - Impasse Turquet (228 | 5) - 7 - Basilique Notre-Dame de Fourvi\u00e8re (247 | 5) - 7 - Mus\u00e9es Gadagne (401 | 5) - 1 - Temple du Change (314 | 5) - 9 - Mus\u00e9e des Beaux-Arts de Lyon (170 | 5) - 8 - Basilique Saint-Bonaventure (364 | 5) - 4 - Mus\u00e9e de l'Imprimerie et de la communication graphique (357 | 5) - 13 - finish (0 | 0) - 0</td>", "<td>109 min</td>", "<td>120 min</td>", "<td class=\"col-duration\">00:00:08</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[historic](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[building=cathedral](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 139 landmarks of type sightseeing in (1714.0, 45.7576485, 4.8330241)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:1700, 45.76, 4.83););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 3 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:1700, 45.76, 4.83);relation[leisure=park](around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:1700, 45.76, 4.83);relation[geological](around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:1700, 45.76, 4.83);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:1700, 45.76, 4.83);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:1700, 45.76, 4.83);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:1700, 45.76, 4.83);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:1700, 45.76, 4.83);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 67 landmarks of type nature in (1714.0, 45.7576485, 4.8330241)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:1700, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 3 landmarks of type shopping in (1714.0, 45.7576485, 4.8330241)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:1700, 45.76, 4.83););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 5 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 182 landmarks in \t: 0.06 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 2 times, objective value : 3378\nDEBUG src.optimization.refiner:refiner.py:345 Using 15 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 8 times, objective value : 2577\nDEBUG src.main:main.py:120 First stage optimization\t: 1.902 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 5.968 seconds\nINFO src.main:main.py:122 Total computation time\t: 7.87 seconds\nINFO src.main:main.py:127 Generated a trip of 109 minutes with 11 landmarks in 7.93 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_cologne": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_cologne", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_cologne</td>", "<td>start (0 | 0) - 4 - R\u00f6misch-Germanisches Museum (698 | 5) - 5 - Gro\u00df St. Martin (512 | 5) - 10 - Trinitatiskirche (467 | 5) - 6 - St. Georg (404 | 5) - 11 - Wallraf-Richartz-Museum & Foundation Corboud (490 | 5) - 1 - Duftmuseum im Farina-Haus (539 | 5) - 7 - K\u00f6lner Dom (1141 | 5) - 3 - Excelsior Hotel Ernst (614 | 5) - 5 - Museum f\u00fcr Angewandte Kunst (514 | 5) - 6 - Oper der Stadt K\u00f6ln (465 | 5) - 6 - St. C\u00e4cilien (423 | 5) - 10 - St. Maria in der Kupfergasse (401 | 5) - 9 - St. Gereon (820 | 5) - 11 - St.Andreas (489 | 5) - 3 - St. Mari\u00e4 Himmelfahrt (401 | 5) - 10 - St. Kunibert (535 | 5) - 10 - finish (0 | 0) - 0</td>", "<td>197 min</td>", "<td>240 min</td>", "<td class=\"col-duration\">00:00:36</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x7e8480b32a50&gt;\nrequest = &lt;FixtureRequest for &lt;Function test_cologne&gt;&gt;\n\n def test_cologne(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in Lyon centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 240\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [50.942352665, 6.957777972392]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n&gt; assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\nE AssertionError: Computation time exceeded 30 seconds: 35.68 seconds\nE assert 35.68478322029114 &lt; 30\n\nsrc/tests/test_main.py:138: AssertionError\n\n------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[historic](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[building=cathedral](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 255 landmarks of type sightseeing in (2000, 50.942352665, 6.957777972392)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:2000, 50.94, 6.96););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:154 Detected 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:2000, 50.94, 6.96);relation[leisure=park](around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:2000, 50.94, 6.96);relation[geological](around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 50.94, 6.96);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 50.94, 6.96);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 50.94, 6.96);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 50.94, 6.96);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 50.94, 6.96);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 49 landmarks of type nature in (2000, 50.942352665, 6.957777972392)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 50.94, 6.96););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 4 landmarks of type shopping in (2000, 50.942352665, 6.957777972392)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:2000, 50.94, 6.96););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 4 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 244 landmarks in \t: 0.078 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 2 times, objective value : 7130\nDEBUG src.optimization.refiner:refiner.py:345 Using 15 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 9 times, objective value : 8913\nDEBUG src.main:main.py:120 First stage optimization\t: 0.494 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 35.107 seconds\nINFO src.main:main.py:122 Total computation time\t: 35.602 seconds\nINFO src.main:main.py:127 Generated a trip of 197 minutes with 18 landmarks in 35.68 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_strasbourg": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_strasbourg", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_strasbourg</td>", "<td>start (0 | 0) - 8 - \u00c9glise protestante Saint-Pierre-le-Jeune (305 | 5) - 9 - Cath\u00e9drale Notre-Dame (564 | 5) - 5 - H\u00f4tel de Ville (295 | 5) - 6 - Palais du Rhin (466 | 5) - 10 - \u00c9glise Saint-Paul (325 | 5) - 6 - Bains municipaux de Strasbourg (401 | 5) - 9 - \u00c9glise catholique Sainte-Madeleine (210 | 5) - 5 - Mus\u00e9e Historique (314 | 5) - 6 - Porte de l'H\u00f4pital (207 | 5) - 9 - Circuit \u00ab Petite France \u00bb (364 | 5) - 10 - \u00c9glise Catholique Saint-Jean-Baptiste (247 | 5) - 1 - finish (0 | 0) - 0</td>", "<td>139 min</td>", "<td>180 min</td>", "<td class=\"col-duration\">00:00:14</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x7e8480b32a50&gt;\nrequest = &lt;FixtureRequest for &lt;Function test_strasbourg&gt;&gt;\n\n def test_strasbourg(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in Lyon centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 180\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [48.5846589226, 7.74078715721]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\n&gt; assert duration_minutes*0.8 &lt; result[&#x27;total_time&#x27;], f&quot;Trip too short: {result[&#x27;total_time&#x27;]} instead of {duration_minutes}&quot;\nE AssertionError: Trip too short: 139 instead of 180\nE assert (180 * 0.8) &lt; 139\n\nsrc/tests/test_main.py:180: AssertionError\n\n------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[historic](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[building=cathedral](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 72 landmarks of type sightseeing in (2000, 48.5846589226, 7.74078715721)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:2000, 48.58, 7.74););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:154 Detected 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:2000, 48.58, 7.74);relation[leisure=park](around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:2000, 48.58, 7.74);relation[geological](around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 48.58, 7.74);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 48.58, 7.74);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 48.58, 7.74);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 48.58, 7.74);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 48.58, 7.74);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 99 landmarks of type nature in (2000, 48.5846589226, 7.74078715721)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.58, 7.74););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 3 landmarks of type shopping in (2000, 48.5846589226, 7.74078715721)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:2000, 48.58, 7.74););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 2 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 118 landmarks in \t: 0.038 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 4 times, objective value : 4128\nDEBUG src.optimization.refiner:refiner.py:345 Using 15 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 8 times, objective value : 3698\nDEBUG src.main:main.py:120 First stage optimization\t: 1.614 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 12.539 seconds\nINFO src.main:main.py:122 Total computation time\t: 14.153 seconds\nINFO src.main:main.py:127 Generated a trip of 139 minutes with 13 landmarks in 14.19 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_zurich": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_zurich", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_zurich</td>", "<td>start (0 | 0) - 3 - Schweizerisches Landesmuseum (336 | 5) - 7 - Liebfrauenkirche (247 | 5) - 9 - Anlage Z\u00fcrich (174 | 5) - 9 - Kunsthaus (357 | 5) - 4 - Museum Schweizer Hotellerie und Tourismus (191 | 5) - 3 - Wasserkirche (210 | 5) - 3 - Stadthaus (191 | 5) - 6 - Ganymed (191 | 5) - 7 - Fraum\u00fcnster Kreuzgang (174 | 5) - 8 - St. Anna-Kapelle (191 | 5) - 4 - Augustinerkirche (210 | 5) - 2 - St. Peter (379 | 5) - 3 - Fraum\u00fcnster (467 | 5) - 3 - Helmhaus (314 | 5) - 1 - Grossm\u00fcnster (425 | 5) - 8 - Predigerkirche (272 | 5) - 11 - finish (0 | 0) - 0</td>", "<td>171 min</td>", "<td>180 min</td>", "<td class=\"col-duration\">00:00:46</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x7e8480b32a50&gt;, request = &lt;FixtureRequest for &lt;Function test_zurich&gt;&gt;\n\n def test_zurich(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in Lyon centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 180\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [47.377884227, 8.5395114066]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n&gt; assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\nE AssertionError: Computation time exceeded 30 seconds: 45.55 seconds\nE assert 45.54829788208008 &lt; 30\n\nsrc/tests/test_main.py:220: AssertionError\n\n------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[historic](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[building=cathedral](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 72 landmarks of type sightseeing in (2000, 47.377884227, 8.5395114066)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:2000, 47.38, 8.54););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:154 Detected 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:2000, 47.38, 8.54);relation[leisure=park](around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:2000, 47.38, 8.54);relation[geological](around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 47.38, 8.54);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 47.38, 8.54);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 47.38, 8.54);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 47.38, 8.54);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 47.38, 8.54);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 62 landmarks of type nature in (2000, 47.377884227, 8.5395114066)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 47.38, 8.54););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 4 landmarks of type shopping in (2000, 47.377884227, 8.5395114066)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:2000, 47.38, 8.54););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 3 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 133 landmarks in \t: 0.038 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 5 times, objective value : 3604\nDEBUG src.optimization.refiner:refiner.py:345 Using 15 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 4 times, objective value : 4329\nDEBUG src.main:main.py:120 First stage optimization\t: 2.876 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 42.63 seconds\nINFO src.main:main.py:122 Total computation time\t: 45.506 seconds\nINFO src.main:main.py:127 Generated a trip of 171 minutes with 18 landmarks in 45.544 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_paris": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_paris", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_paris</td>", "<td>start (0 | 0) - 14 - Sainte-Chapelle (1138 | 5) - 8 - Cath\u00e9drale Notre-Dame de Paris (1138 | 5) - 4 - M\u00e9morial des Martyrs de la D\u00e9portation (364 | 5) - 20 - Bassin de l'Arsenal (827 | 5) - 22 - \u00c9glise Saint-Nicolas du Chardonnet (512 | 5) - 6 - Square Jean XXIII (367 | 5) - 6 - \u00c9glise Saint-S\u00e9verin (384 | 5) - 7 - Palais de Justice de Paris (467 | 5) - 9 - \u00c9glise Saint-Germain l'Auxerrois (512 | 5) - 8 - Pyramide du Louvre (490 | 5) - 3 - Tunnel des Tuileries (445 | 5) - 10 - Mus\u00e9e d'Orsay (890 | 5) - 13 - \u00c9glise Saint-Roch (490 | 5) - 8 - Palais du Louvre (690 | 5) - 1 - Mus\u00e9e du Louvre (698 | 5) - 5 - Temple de l'Oratoire du Louvre (651 | 5) - 4 - Bourse de Commerce \u2014 Pinault Collection (627 | 5) - 2 - Jardin Nelson Mandela (367 | 5) - 7 - \u00c9glise Saint-Leu - Saint-Gilles (423 | 5) - 6 - Centre Georges Pompidou (865 | 5) - 3 - \u00c9glise Saint-Merri (466 | 5) - 9 - finish (0 | 0) - 0</td>", "<td>280 min</td>", "<td>300 min</td>", "<td class=\"col-duration\">00:00:05</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[historic](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[building=cathedral](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 317 landmarks of type sightseeing in (2000, 48.86248803298562, 2.346451131285925)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:2000, 48.86, 2.35););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:154 Detected 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:2000, 48.86, 2.35);relation[leisure=park](around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:2000, 48.86, 2.35);relation[geological](around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 48.86, 2.35);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 48.86, 2.35);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 48.86, 2.35);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 48.86, 2.35);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 48.86, 2.35);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 127 landmarks of type nature in (2000, 48.86248803298562, 2.346451131285925)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 48.86, 2.35););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 8 landmarks of type shopping in (2000, 48.86248803298562, 2.346451131285925)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:2000, 48.86, 2.35););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 14 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 363 landmarks in \t: 0.111 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 1 times, objective value : 8744\nDEBUG src.optimization.refiner:refiner.py:345 Using 15 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 5 times, objective value : 12811\nDEBUG src.main:main.py:120 First stage optimization\t: 0.563 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 4.514 seconds\nINFO src.main:main.py:122 Total computation time\t: 5.078 seconds\nINFO src.main:main.py:127 Generated a trip of 280 minutes with 23 landmarks in 5.188 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_new_york": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_new_york", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_new_york</td>", "<td>start (0 | 0) - 6 - St. George's Church (344 | 5) - 7 - Grace Church (401 | 5) - 7 - Union Square Park (482 | 5) - 10 - Flatiron Building (604 | 5) - 5 - Cathedral of St. Sava (401 | 5) - 4 - Madison Square Park (482 | 5) - 7 - Calvary Church (357 | 5) - 17 - Saint Mark's in-the-Bowery (490 | 5) - 7 - Immaculate Conception Church (423 | 5) - 6 - St. Nicholas of Myra Orthodox Church (423 | 5) - 12 - Cathedral of the Holy Virgin Protection (344 | 5) - 9 - Saint Patrick's Old Cathedral (379 | 5) - 9 - Capitale (627 | 5) - 7 - Petrosino Square (334 | 5) - 13 - Tribeca Park (386 | 5) - 4 - Albert Capsouto Park (339 | 5) - 1 - Duarte Square (512 | 5) - 11 - St. Anthony of Padua Church (379 | 5) - 13 - Stonewall Inn State Historic Site (357 | 5) - 3 - St. Joseph's Church (364 | 5) - 6 - Judson Memorial Church (401 | 5) - 13 - finish (0 | 0) - 0</td>", "<td>282 min</td>", "<td>600 min</td>", "<td class=\"col-duration\">00:00:01</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x7e8480b32a50&gt;\nrequest = &lt;FixtureRequest for &lt;Function test_new_york&gt;&gt;\n\n def test_new_york(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in New York (les Halles) centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 600\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [40.72592726802, -73.9920434795]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\n&gt; assert duration_minutes*0.8 &lt; result[&#x27;total_time&#x27;], f&quot;Trip too short: {result[&#x27;total_time&#x27;]} instead of {duration_minutes}&quot;\nE AssertionError: Trip too short: 282 instead of 600\nE assert (600 * 0.8) &lt; 282\n\nsrc/tests/test_main.py:303: AssertionError\n\n------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:93 Fetching sightseeing landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[tourism~&quot;^(museum|attraction|gallery|artwork|aquarium)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[historic](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[historic](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[amenity~&quot;^(planetarium|place_of_worship|fountain|townhall)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[water=reflecting_pool](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[bridge~&quot;^(aqueduct|viaduct|boardwalk|cantilever|abandoned)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[building=cathedral](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[building=cathedral](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 117 landmarks of type sightseeing in (2000, 40.72592726802, -73.9920434795)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:96 Fetching sightseeing clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (way[&quot;historic&quot;~&quot;^(monument|building|yes)$&quot;](around:2000, 40.73, -73.99););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:154 Detected 0 sightseeing clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:102 Sightseeing clusters done\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:106 Fetching nature landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[leisure=park](around:2000, 40.73, -73.99);relation[leisure=park](around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[geological](around:2000, 40.73, -73.99);relation[geological](around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 40.73, -73.99);relation[natural~&quot;^(geyser|hot_spring|arch|volcano|stone)$&quot;](around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 40.73, -73.99);relation[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 40.73, -73.99);node[tourism~&quot;^(alpine_hut|viewpoint|zoo|resort|picnic_site)$&quot;](around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 40.73, -73.99);relation[water~&quot;^(pond|lake|river|basin|stream|lagoon|rapids)$&quot;](around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 40.73, -73.99);relation[waterway~&quot;^(waterfall|river|canal|dam|dock|boatyard)$&quot;](around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 94 landmarks of type nature in (2000, 40.72592726802, -73.9920434795)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 40.73, -73.99););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 4 landmarks of type shopping in (2000, 40.72592726802, -73.9920434795)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:2000, 40.73, -73.99););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 5 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 211 landmarks in \t: 0.041 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 5 times, objective value : 5136\nDEBUG src.optimization.refiner:refiner.py:345 Using 15 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 2 times, objective value : 8829\nDEBUG src.main:main.py:120 First stage optimization\t: 1.035 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 0.212 seconds\nINFO src.main:main.py:122 Total computation time\t: 1.247 seconds\nINFO src.main:main.py:127 Generated a trip of 282 minutes with 23 landmarks in 1.288 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_shopping": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_shopping", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_shopping</td>", "<td>start (0 | 0) - 5 - Grand H\u00f4tel-Dieu (423 | 30) - 8 - Shopping Area (538 | 40) - 4 - Grand Bazar (93 | 30) - 20 - Halles de Lyon Paul Bocuse (210 | 30) - 8 - Westfield La Part-Dieu (423 | 30) - 32 - finish (0 | 0) - 0</td>", "<td>237 min</td>", "<td>240 min</td>", "<td class=\"col-duration\">499 ms</td>", "<td class=\"col-links\"></td>"], "log": "----------------------------- Captured stdout call -----------------------------\nLandmark(start): [start @(45.7576485, 4.8330241), score=0, time_to_next=5]\nLandmark(shopping): [Grand H\u00f4tel-Dieu @(45.7586955, 4.8364597), score=423, time_to_next=8]\nLandmark(shopping): [Shopping Area @(np.float64(45.76223053940519), np.float64(4.833794685873603)), score=538, time_to_next=4]\nLandmark(shopping): [Grand Bazar @(45.7632141, 4.8361975), score=93, time_to_next=20]\nLandmark(shopping): [Halles de Lyon Paul Bocuse @(45.7628282, 4.8505601), score=210, time_to_next=8]\nLandmark(shopping): [Westfield La Part-Dieu @(45.761331, 4.855676), score=423, time_to_next=32]\nLandmark(finish): [finish @(45.7576485, 4.8330241), score=0]\n\n------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:81 Starting to fetch landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:113 Fetching shopping landmarks...\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:205 Query: (way[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 45.76, 4.83);relation[shop~&quot;^(department_store|mall)$&quot;](if: count_tags()&gt;5)(around:2000, 45.76, 4.83););out center;\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:215 Fetched 7 landmarks of type shopping in (2000, 45.7576485, 4.8330241)\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:115 Fetching shopping clusters...\nDEBUG src.utils.cluster_manager:cluster_manager.py:104 Cluster query: (node[&quot;shop&quot;~&quot;^(bag|boutique|clothes)$&quot;](around:2000, 45.76, 4.83););out ids center;\nDEBUG src.utils.cluster_manager:cluster_manager.py:146 Found 5 different clusters.\nDEBUG src.utils.landmarks_manager:landmarks_manager.py:126 Shopping clusters done\nINFO src.main:main.py:97 Fetched 7 landmarks in \t: 0.008 seconds\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 1 times, objective value : 1687\nDEBUG src.optimization.refiner:refiner.py:345 Using 2 minor landmarks around the predicted path\nDEBUG src.optimization.optimizer:optimizer.py:568 First results are out. Looking out for circles and correcting.\nDEBUG src.optimization.optimizer:optimizer.py:605 Re-optimized 1 times, objective value : 1687\nDEBUG src.main:main.py:120 First stage optimization\t: 0.282 seconds\nDEBUG src.main:main.py:121 Second stage optimization\t: 0.204 seconds\nINFO src.main:main.py:122 Total computation time\t: 0.486 seconds\nINFO src.main:main.py:127 Generated a trip of 237 minutes with 7 landmarks in 0.494 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> + <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) - 4 - Square Charles Grad (47 | 5) - 3 - Porte de France (157 | 5) - 5 - finish (0 | 0) - 0</td>", "<td>22 min</td>", "<td>20 min</td>", "<td class=\"col-duration\">104 ms</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 5 landmarks in \t: 0.004 seconds\nINFO src.main:main.py:122 Total computation time\t: 0.031 seconds\nINFO src.main:main.py:127 Generated a trip of 22 minutes with 4 landmarks in 0.035 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_bellecour": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_bellecour", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_bellecour</td>", "<td>start (0 | 0) - 7 - Grande Synagogue de Lyon (191 | 5) - 7 - Basilique Saint-Martin d'Ainay (314 | 5) - 8 - \u00c9glise Saint-Georges (357 | 5) - 7 - Cath\u00e9drale Saint-Jean (305 | 5) - 7 - Basilique de Fourvi\u00e8re (251 | 5) - 0 - Basilique Notre-Dame de Fourvi\u00e8re (247 | 5) - 7 - Mus\u00e9es Gadagne (401 | 5) - 1 - Temple du Change (314 | 5) - 8 - \u00c9glise Saint-Nizier (272 | 5) - 12 - H\u00f4tel de l'Europe (191 | 5) - 5 - finish (0 | 0) - 0</td>", "<td>119 min</td>", "<td>120 min</td>", "<td class=\"col-duration\">00:00:08</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 182 landmarks in \t: 0.044 seconds\nINFO src.main:main.py:122 Total computation time\t: 8.146 seconds\nINFO src.main:main.py:127 Generated a trip of 119 minutes with 12 landmarks in 8.19 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_cologne": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_cologne", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_cologne</td>", "<td>start (0 | 0) - 4 - R\u00f6misch-Germanisches Museum (698 | 5) - 6 - Wallraf-Richartz-Museum & Foundation Corboud (490 | 5) - 5 - Gro\u00df St. Martin (512 | 5) - 11 - St. Maria Lyskirchen (512 | 5) - 4 - Deutsches Sport- und Olympiamuseum (535 | 5) - 6 - Trinitatiskirche (467 | 5) - 4 - St. Maria im Kapitol (490 | 5) - 6 - Duftmuseum im Farina-Haus (539 | 5) - 5 - Minoritenkirche (379 | 5) - 6 - AntoniterCityKirche (423 | 5) - 4 - St. C\u00e4cilien (423 | 5) - 4 - Gesundheitsamt K\u00f6ln (364 | 5) - 5 - St. Aposteln (639 | 5) - 2 - Kreissparkasse K\u00f6ln (539 | 5) - 5 - Schauspielhaus K\u00f6ln (369 | 5) - 1 - Oper der Stadt K\u00f6ln (465 | 5) - 6 - Museum f\u00fcr Angewandte Kunst (514 | 5) - 5 - K\u00f6lner Dom (1141 | 5) - 3 - Excelsior Hotel Ernst (614 | 5) - 2 - St.Andreas (489 | 5) - 3 - St. Mari\u00e4 Himmelfahrt (401 | 5) - 2 - finish (0 | 0) - 0</td>", "<td>204 min</td>", "<td>240 min</td>", "<td class=\"col-duration\">00:00:09</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 244 landmarks in \t: 0.068 seconds\nINFO src.main:main.py:122 Total computation time\t: 8.817 seconds\nINFO src.main:main.py:127 Generated a trip of 204 minutes with 23 landmarks in 8.885 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_strasbourg": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_strasbourg", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_strasbourg</td>", "<td>start (0 | 0) - 10 - Grande \u00cele (228 | 5) - 11 - Palais du Rhin (466 | 5) - 11 - Cath\u00e9drale Notre-Dame (564 | 5) - 6 - \u00c9glise catholique Sainte-Madeleine (210 | 5) - 13 - Centre Administratif Ville et Eurom\u00e9tropole de Strasbourg (405 | 5) - 8 - Porte de l'H\u00f4pital (207 | 5) - 4 - Pont Saint-Nicolas (191 | 5) - 4 - \u00c9glise protestante Saint-Thomas (266 | 5) - 2 - Circuit \u00ab Petite France \u00bb (364 | 5) - 9 - Barrage Vauban (344 | 5) - 10 - \u00c9glise Catholique Saint-Jean-Baptiste (247 | 5) - 1 - finish (0 | 0) - 0</td>", "<td>144 min</td>", "<td>180 min</td>", "<td class=\"col-duration\">00:00:04</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x70221d7b4740&gt;\nrequest = &lt;FixtureRequest for &lt;Function test_strasbourg&gt;&gt;\n\n def test_strasbourg(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in Lyon centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 180\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [48.5846589226, 7.74078715721]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\n&gt; assert duration_minutes*0.8 &lt; result[&#x27;total_time&#x27;], f&quot;Trip too short: {result[&#x27;total_time&#x27;]} instead of {duration_minutes}&quot;\nE AssertionError: Trip too short: 144 instead of 180\nE assert (180 * 0.8) &lt; 144\n\nsrc/tests/test_main.py:180: AssertionError\n\n------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 118 landmarks in \t: 0.03 seconds\nINFO src.main:main.py:122 Total computation time\t: 4.096 seconds\nINFO src.main:main.py:127 Generated a trip of 144 minutes with 13 landmarks in 4.126 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_zurich": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_zurich", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_zurich</td>", "<td>start (0 | 0) - 3 - Schweizerisches Landesmuseum (336 | 5) - 7 - Globus (325 | 30) - 10 - St. Peter (379 | 5) - 3 - Fraum\u00fcnster (467 | 5) - 4 - Grossm\u00fcnster (425 | 5) - 9 - Friedenskirche (207 | 5) - 10 - Liebfrauenkirche (247 | 5) - 6 - Russisch-Orthodoxe Auferstehungskirche (325 | 5) - 13 - finish (0 | 0) - 0</td>", "<td>130 min</td>", "<td>180 min</td>", "<td class=\"col-duration\">00:00:16</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x70221d7b4740&gt;, request = &lt;FixtureRequest for &lt;Function test_zurich&gt;&gt;\n\n def test_zurich(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in Lyon centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 180\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [47.377884227, 8.5395114066]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\n&gt; assert duration_minutes*0.8 &lt; result[&#x27;total_time&#x27;], f&quot;Trip too short: {result[&#x27;total_time&#x27;]} instead of {duration_minutes}&quot;\nE AssertionError: Trip too short: 130 instead of 180\nE assert (180 * 0.8) &lt; 130\n\nsrc/tests/test_main.py:221: AssertionError\n\n------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 133 landmarks in \t: 0.027 seconds\nINFO src.main:main.py:122 Total computation time\t: 16.137 seconds\nINFO src.main:main.py:127 Generated a trip of 130 minutes with 10 landmarks in 16.164 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_paris": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_paris", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_paris</td>", "<td>start (0 | 0) - 5 - \u00c9glise Saint-Leu - Saint-Gilles (423 | 5) - 19 - Mus\u00e9e Carnavalet (490 | 5) - 14 - Centre Georges Pompidou (865 | 5) - 3 - \u00c9glise Saint-Merri (466 | 5) - 3 - Tour Saint-Jacques (614 | 5) - 10 - Cath\u00e9drale Notre-Dame de Paris (1138 | 5) - 8 - Sainte-Chapelle (1138 | 5) - 1 - Palais de Justice de Paris (467 | 5) - 9 - \u00c9glise Saint-Germain l'Auxerrois (512 | 5) - 6 - La Seine (447 | 5) - 5 - Pyramide du Louvre (490 | 5) - 12 - Mus\u00e9e d'Orsay (890 | 5) - 12 - Mus\u00e9e du Louvre (698 | 5) - 5 - Temple de l'Oratoire du Louvre (651 | 5) - 4 - Bourse de Commerce \u2014 Pinault Collection (627 | 5) - 2 - Jardin Nelson Mandela (367 | 5) - 3 - finish (0 | 0) - 0</td>", "<td>201 min</td>", "<td>300 min</td>", "<td class=\"col-duration\">00:01:12</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x70221d7b4740&gt;, request = &lt;FixtureRequest for &lt;Function test_paris&gt;&gt;\n\n def test_paris(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in Paris (les Halles) centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 300\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [48.86248803298562, 2.346451131285925]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n&gt; assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\nE AssertionError: Computation time exceeded 30 seconds: 72.07 seconds\nE assert 72.07316541671753 &lt; 30\n\nsrc/tests/test_main.py:261: AssertionError\n\n------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 363 landmarks in \t: 0.134 seconds\nINFO src.main:main.py:122 Total computation time\t: 71.935 seconds\nINFO src.main:main.py:127 Generated a trip of 201 minutes with 18 landmarks in 72.068 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_new_york": [{"extras": [], "result": "Failed", "testId": "src/tests/test_main.py::test_new_york", "resultsTableRow": ["<td class=\"col-result\">Failed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_new_york</td>", "<td>start (0 | 0) - 6 - St. George's Church (344 | 5) - 7 - Grace Church (401 | 5) - 7 - Union Square Park (482 | 5) - 10 - Flatiron Building (604 | 5) - 5 - Cathedral of St. Sava (401 | 5) - 4 - Madison Square Park (482 | 5) - 7 - Calvary Church (357 | 5) - 17 - Saint Mark's in-the-Bowery (490 | 5) - 7 - Immaculate Conception Church (423 | 5) - 6 - St. Nicholas of Myra Orthodox Church (423 | 5) - 12 - Cathedral of the Holy Virgin Protection (344 | 5) - 9 - Saint Patrick's Old Cathedral (379 | 5) - 9 - Capitale (627 | 5) - 10 - Columbus Park (482 | 5) - 3 - Thomas Paine Park (334 | 5) - 3 - Collect Pond Park (412 | 5) - 10 - Tribeca Park (386 | 5) - 4 - Albert Capsouto Park (339 | 5) - 1 - Duarte Square (512 | 5) - 11 - St. Anthony of Padua Church (379 | 5) - 7 - Judson Memorial Church (401 | 5) - 13 - finish (0 | 0) - 0</td>", "<td>273 min</td>", "<td>600 min</td>", "<td class=\"col-duration\">782 ms</td>", "<td class=\"col-links\"></td>"], "log": "client = &lt;starlette.testclient.TestClient object at 0x70221d7b4740&gt;\nrequest = &lt;FixtureRequest for &lt;Function test_new_york&gt;&gt;\n\n def test_new_york(client, request) : # pylint: disable=redefined-outer-name\n &quot;&quot;&quot;\n Test n\u00b02 : Custom test in New York (les Halles) centre to ensure proper decision making in crowded area.\n \n Args:\n client:\n request:\n &quot;&quot;&quot;\n start_time = time.time() # Start timer\n duration_minutes = 600\n \n response = client.post(\n &quot;/trip/new&quot;,\n json={\n &quot;preferences&quot;: {&quot;sightseeing&quot;: {&quot;type&quot;: &quot;sightseeing&quot;, &quot;score&quot;: 5},\n &quot;nature&quot;: {&quot;type&quot;: &quot;nature&quot;, &quot;score&quot;: 5},\n &quot;shopping&quot;: {&quot;type&quot;: &quot;shopping&quot;, &quot;score&quot;: 5},\n &quot;max_time_minute&quot;: duration_minutes,\n &quot;detour_tolerance_minute&quot;: 0},\n &quot;start&quot;: [40.72592726802, -73.9920434795]\n }\n )\n result = response.json()\n landmarks = load_trip_landmarks(client, result[&#x27;first_landmark_uuid&#x27;])\n \n # Get computation time\n comp_time = time.time() - start_time\n \n # Add details to report\n log_trip_details(request, landmarks, result[&#x27;total_time&#x27;], duration_minutes)\n \n # for elem in landmarks :\n # print(elem)\n \n # checks :\n assert response.status_code == 200 # check for successful planning\n assert comp_time &lt; 30, f&quot;Computation time exceeded 30 seconds: {comp_time:.2f} seconds&quot;\n&gt; assert duration_minutes*0.8 &lt; result[&#x27;total_time&#x27;], f&quot;Trip too short: {result[&#x27;total_time&#x27;]} instead of {duration_minutes}&quot;\nE AssertionError: Trip too short: 273 instead of 600\nE assert (600 * 0.8) &lt; 273\n\nsrc/tests/test_main.py:303: AssertionError\n\n------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 211 landmarks in \t: 0.038 seconds\nINFO src.main:main.py:122 Total computation time\t: 0.739 seconds\nINFO src.main:main.py:127 Generated a trip of 273 minutes with 23 landmarks in 0.777 seconds.\nINFO httpx:_client.py:1025 HTTP Request: POST http://testserver/trip/new &quot;HTTP/1.1 200 OK&quot;\n\n"}], "src/tests/test_main.py::test_shopping": [{"extras": [], "result": "Passed", "testId": "src/tests/test_main.py::test_shopping", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_main.py::test_shopping</td>", "<td>start (0 | 0) - 5 - Grand H\u00f4tel-Dieu (423 | 30) - 8 - Shopping Area (538 | 40) - 4 - Grand Bazar (93 | 30) - 20 - Halles de Lyon Paul Bocuse (210 | 30) - 8 - Westfield La Part-Dieu (423 | 30) - 32 - finish (0 | 0) - 0</td>", "<td>237 min</td>", "<td>240 min</td>", "<td class=\"col-duration\">424 ms</td>", "<td class=\"col-links\"></td>"], "log": "----------------------------- Captured stdout call -----------------------------\nLandmark(start): [start @(45.7576485, 4.8330241), score=0, time_to_next=5]\nLandmark(shopping): [Grand H\u00f4tel-Dieu @(45.7586955, 4.8364597), score=423, time_to_next=8]\nLandmark(shopping): [Shopping Area @(np.float64(45.76223053940519), np.float64(4.833794685873603)), score=538, time_to_next=4]\nLandmark(shopping): [Grand Bazar @(45.7632141, 4.8361975), score=93, time_to_next=20]\nLandmark(shopping): [Halles de Lyon Paul Bocuse @(45.7628282, 4.8505601), score=210, time_to_next=8]\nLandmark(shopping): [Westfield La Part-Dieu @(45.761331, 4.855676), score=423, time_to_next=32]\nLandmark(finish): [finish @(45.7576485, 4.8330241), score=0]\n\n------------------------------ Captured log call -------------------------------\nINFO src.main:main.py:65 No end coordinates provided. Using start=end.\nINFO src.main:main.py:97 Fetched 7 landmarks in \t: 0.01 seconds\nINFO src.main:main.py:122 Total computation time\t: 0.409 seconds\nINFO src.main:main.py:127 Generated a trip of 237 minutes with 7 landmarks in 0.419 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') diff --git a/backend/src/overpass/overpass.py b/backend/src/overpass/overpass.py index f46b966..505053c 100644 --- a/backend/src/overpass/overpass.py +++ b/backend/src/overpass/overpass.py @@ -25,8 +25,9 @@ class Overpass : self.caching_strategy = CachingStrategy.use(caching_strategy, cache_dir=cache_dir) + @classmethod def build_query(self, area: tuple, osm_types: osm_types, - selector: str, conditions=[], out='center'): + selector: str, conditions=[], out='center') -> str: """ Constructs a query string for the Overpass API to retrieve OpenStreetMap (OSM) data. @@ -83,7 +84,7 @@ class Overpass : return query - def send_query(self, query: str) -> dict: + def send_query(self, query: str) -> ET: """ Sends the Overpass QL query to the Overpass API and returns the parsed JSON response. @@ -124,3 +125,47 @@ class Overpass : except urllib.error.URLError as e: raise ConnectionError(f"Error connecting to Overpass API: {e}") from e + + +def get_base_info(elem: ET.Element, osm_type: osm_types, with_name=False) : + """ + Extracts base information (coordinates, OSM ID, and optionally a name) from an OSM element. + + This function retrieves the latitude and longitude coordinates, OSM ID, and optionally the name + of a given OpenStreetMap (OSM) element. It handles different OSM types (e.g., 'node', 'way') by + extracting coordinates either directly or from a center tag, depending on the element type. + + Args: + elem (ET.Element): The XML element representing the OSM entity. + osm_type (str): The type of the OSM entity (e.g., 'node', 'way'). If 'node', the coordinates + are extracted directly from the element; otherwise, from the 'center' tag. + with_name (bool): Whether to extract and return the name of the element. If True, it attempts + to find the 'name' tag within the element and return its value. Defaults to False. + + Returns: + tuple: A tuple containing: + - osm_id (str): The OSM ID of the element. + - coords (tuple): A tuple of (latitude, longitude) coordinates. + - name (str, optional): The name of the element if `with_name` is True; otherwise, not included. + """ + # 1. extract coordinates + if osm_type != 'node' : + center = elem.find('center') + lat = float(center.get('lat')) + lon = float(center.get('lon')) + + else : + lat = float(elem.get('lat')) + lon = float(elem.get('lon')) + + coords = tuple((lat, lon)) + + # 2. Extract OSM id + osm_id = elem.get('id') + + # 3. Extract name if specified and return + if with_name : + name = elem.find("tag[@k='name']").get('v') if elem.find("tag[@k='name']") is not None else None + return osm_id, coords, name + else : + return osm_id, coords diff --git a/backend/src/utils/cluster_manager.py b/backend/src/utils/cluster_manager.py index 8c8abfe..95d3f14 100644 --- a/backend/src/utils/cluster_manager.py +++ b/backend/src/utils/cluster_manager.py @@ -6,7 +6,7 @@ import numpy as np from sklearn.cluster import DBSCAN from pydantic import BaseModel -from ..overpass.overpass import Overpass +from ..overpass.overpass import Overpass, get_base_info from ..structs.landmark import Landmark from .get_time_distance import get_distance from ..constants import OSM_CACHE_DIR @@ -116,17 +116,11 @@ class ClusterManager: points = [] for osm_type in osm_types : for elem in result.findall(osm_type): - - if osm_type != 'node' : - center = elem.find('center') - lat = float(center.get('lat')) - lon = float(center.get('lon')) - points.append(tuple((lat, lon))) - - else : - lat = float(elem.get('lat')) - lon = float(elem.get('lon')) - points.append(tuple((lat, lon))) + + # Get coordinates and append them to the points list + _, coords = get_base_info(elem, osm_type) + if coords is not None : + points.append(coords) if points : self.all_points = np.array(points) @@ -263,32 +257,18 @@ class ClusterManager: for osm_type in osm_types : for elem in result.findall(osm_type): - name = elem.find("tag[@k='name']").get('v') if elem.find("tag[@k='name']") is not None else None - center = elem.find('center') - # Extract the center latitude and longitude if available. - if name is None : - continue + id, coords, name = get_base_info(elem, osm_type, with_name=True) - if osm_type != 'node' : - lat = float(center.get('lat')) - lon = float(center.get('lon')) - - else : - lat = float(elem.get('lat')) - lon = float(elem.get('lon')) - - coords = tuple((lat, lon)) - - if coords is None : + if name is None or coords is None : continue d = get_distance(cluster.centroid, coords) if d < min_dist : min_dist = d new_name = name - osm_type = osm_type # Add type: 'way' or 'relation' - osm_id = elem.get('id') # Add OSM id + osm_type = osm_type # Add type: 'way' or 'relation' + osm_id = id # Add OSM id return Landmark( name=new_name, diff --git a/backend/src/utils/landmarks_manager.py b/backend/src/utils/landmarks_manager.py index e981929..d9a10f1 100644 --- a/backend/src/utils/landmarks_manager.py +++ b/backend/src/utils/landmarks_manager.py @@ -8,7 +8,7 @@ from ..structs.preferences import Preferences from ..structs.landmark import Landmark from .take_most_important import take_most_important from .cluster_manager import ClusterManager -from ..overpass.overpass import Overpass +from ..overpass.overpass import Overpass, get_base_info from ..constants import AMENITY_SELECTORS_PATH, LANDMARK_PARAMETERS_PATH, OPTIMIZER_PARAMETERS_PATH, OSM_CACHE_DIR @@ -239,28 +239,19 @@ class LandmarkManager: landmarks = [] for osm_type in ['node', 'way', 'relation'] : for elem in root.findall(osm_type): - name = elem.find("tag[@k='name']").get('v') if elem.find("tag[@k='name']") is not None else None - tags = elem.findall('tag') - if osm_type != 'node' : - center = elem.find('center') - lat = float(center.get('lat')) - lon = float(center.get('lon')) - coords = tuple((lat, lon)) - - else : - lat = float(elem.get('lat')) - lon = float(elem.get('lon')) - coords = tuple((lat, lon)) + id, coords, name = get_base_info(elem, osm_type, with_name=True) if name is None or coords is None : continue + tags = elem.findall('tag') + # Convert this to Landmark object landmark = Landmark(name=name, type=landmarktype, location=coords, - osm_id=elem.get('id'), + osm_id=id, osm_type=osm_type, attractiveness=0, n_tags=len(tags)) diff --git a/backend/src/utils/toilets_manager.py b/backend/src/utils/toilets_manager.py index ec59d9f..e15dd0a 100644 --- a/backend/src/utils/toilets_manager.py +++ b/backend/src/utils/toilets_manager.py @@ -2,7 +2,7 @@ import logging import xml.etree.ElementTree as ET -from ..overpass.overpass import Overpass +from ..overpass.overpass import Overpass, get_base_info from ..structs.landmark import Toilets from ..constants import OSM_CACHE_DIR @@ -98,23 +98,12 @@ class ToiletsManager: toilets_list = [] for osm_type in ['node', 'way', 'relation'] : for elem in root.findall(osm_type): - center = elem.find('center') - - # Extract the center latitude and longitude if available. - if osm_type != 'node' : - lat = float(center.get('lat')) - lon = float(center.get('lon')) - location = tuple((lat, lon)) - - else : - lat = float(elem.get('lat')) - lon = float(elem.get('lon')) - location = tuple((lat, lon)) - - if location is None : + # Get coordinates and append them to the points list + _, coords = get_base_info(elem, osm_type) + if coords is None : continue - toilets = Toilets(location=location) + toilets = Toilets(location=coords) # Extract tags as a dictionary tags = {tag.get('k'): tag.get('v') for tag in elem.findall('tag')}