Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 3m29s
Run linting on the backend code / Build (pull_request) Successful in 27s
Run testing on the backend code / Build (pull_request) Failing after 12m29s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 34s
85 lines
3.4 KiB
Python
85 lines
3.4 KiB
Python
"""Linked and ordered list of Landmarks that represents the visiting order."""
|
|
|
|
from .landmark import Landmark
|
|
from ..utils.get_time_distance import get_time
|
|
from ..utils.description import description_and_keywords
|
|
|
|
class LinkedLandmarks:
|
|
"""
|
|
A list of landmarks that are linked together, e.g. in a route.
|
|
Each landmark serves as a node in the linked list, but since we expect
|
|
these to be consumed through the rest API, a pythonic reference to the next
|
|
landmark is not well suited. Instead we use the uuid of the next landmark
|
|
to reference the next landmark in the list. This is not very efficient,
|
|
but appropriate for the expected use case
|
|
("short" trips with onyl few landmarks).
|
|
"""
|
|
|
|
_landmarks = list[Landmark]
|
|
total_time: int = 0
|
|
|
|
def __init__(self, data: list[Landmark] = None) -> None:
|
|
"""
|
|
Initialize a new LinkedLandmarks object. This expects an ORDERED list of landmarks,
|
|
where the first landmark is the starting point and the last landmark is the end point.
|
|
|
|
Args:
|
|
data (list[Landmark], optional): The list of landmarks that are linked together.
|
|
Defaults to None.
|
|
"""
|
|
self._landmarks = data if data else []
|
|
self._link_landmarks()
|
|
|
|
|
|
def _link_landmarks(self) -> None:
|
|
"""
|
|
Create the links between the landmarks in the list by setting their
|
|
.next_uuid and the .time_to_next attributes.
|
|
"""
|
|
# Mark secondary landmarks as such
|
|
self.update_secondary_landmarks()
|
|
|
|
for i, landmark in enumerate(self._landmarks[:-1]):
|
|
# Set uuid of the next landmark
|
|
landmark.next_uuid = self._landmarks[i + 1].uuid
|
|
|
|
# Adjust time to reach and total time
|
|
time_to_next = get_time(landmark.location, self._landmarks[i + 1].location)
|
|
landmark.time_to_reach_next = time_to_next
|
|
self.total_time += time_to_next
|
|
self.total_time += landmark.duration
|
|
|
|
# Fill in the keywords and description. GOOD IDEA, BAD EXECUTION, tags aren't available anymore at this stage
|
|
# landmark.description, landmark.keywords = description_and_keywords(tags)
|
|
|
|
|
|
self._landmarks[-1].next_uuid = None
|
|
self._landmarks[-1].time_to_reach_next = 0
|
|
|
|
def update_secondary_landmarks(self) -> None:
|
|
"""
|
|
Mark landmarks with lower importance as secondary.
|
|
"""
|
|
# Extract the attractiveness scores and sort them in descending order
|
|
scores = sorted([landmark.attractiveness for landmark in self._landmarks], reverse=True)
|
|
|
|
# Determine the 10th highest score
|
|
if len(scores) >= 10:
|
|
threshold_score = scores[9]
|
|
else:
|
|
# If there are fewer than 10 landmarks, use the lowest score as the threshold
|
|
threshold_score = min(scores) if scores else 0
|
|
|
|
# Update 'is_secondary' for landmarks with attractiveness below the threshold score
|
|
for landmark in self._landmarks:
|
|
if (landmark.attractiveness < threshold_score and landmark.type not in ["start", "finish"]):
|
|
landmark.is_secondary = True
|
|
|
|
|
|
def __getitem__(self, index: int) -> Landmark:
|
|
return self._landmarks[index]
|
|
|
|
|
|
def __str__(self) -> str:
|
|
return f"LinkedLandmarks [{' ->'.join([str(landmark) for landmark in self._landmarks])}]"
|