# Path: gtfspy/routing/node_profile_c.py
# class NodeProfileC:
#     """
#     In the connection scan algorithm, each stop has a profile entry
#     that stores information on the Pareto-Optimal (departure_time_this_node, arrival_time_target_node) tuples.
#     """
# 
#     def __init__(self, walk_to_target_duration=float('inf')):
#         self._labels = []  # list[LabelTime] # always ordered by decreasing departure_time
#         self._walk_to_target_duration = walk_to_target_duration
# 
#     def get_walk_to_target_duration(self):
#         return self._walk_to_target_duration
# 
#     def update_pareto_optimal_tuples(self, new_label):
#         """
#         Parameters
#         ----------
#         new_label: LabelTime
# 
#         Returns
#         -------
#         updated: bool
#         """
#         assert (isinstance(new_label, LabelTime))
#         if self._labels:
#             assert (new_label.departure_time <= self._labels[-1].departure_time)
#             best_later_departing_arrival_time = self._labels[-1].arrival_time_target
#         else:
#             best_later_departing_arrival_time = float('inf')
# 
#         walk_to_target_arrival_time = new_label.departure_time + self._walk_to_target_duration
# 
#         best_arrival_time = min(walk_to_target_arrival_time,
#                                 best_later_departing_arrival_time,
#                                 new_label.arrival_time_target)
#         # this should be changed to get constant time insertions / additions
#         # (with time-indexing)
#         if (new_label.arrival_time_target < walk_to_target_arrival_time and
#                 new_label.arrival_time_target < best_later_departing_arrival_time):
#             self._labels.append(LabelTime(new_label.departure_time, best_arrival_time))
#             return True
#         else:
#             return False
# 
#     def evaluate_earliest_arrival_time_at_target(self, dep_time, transfer_margin):
#         """
#         Get the earliest arrival time at the target, given a departure time.
# 
#         Parameters
#         ----------
#         dep_time : float, int
#             time in unix seconds
#         transfer_margin: float, int
#             transfer margin in seconds
# 
#         Returns
#         -------
#         arrival_time : float
#             Arrival time in the given time unit (seconds after unix epoch).
#         """
#         minimum = dep_time + self._walk_to_target_duration
#         for label in self._labels[::-1]:
#             if label.departure_time >= dep_time + transfer_margin:
#                 minimum = min(minimum, label.arrival_time_target)
#                 break
#         return float(minimum)
# 
#     def get_final_optimal_labels(self):
#         non_walk_valid_labels = []
#         for label in self._labels:
#             if label.duration() < self._walk_to_target_duration:
#                 non_walk_valid_labels.append(label)
#         return [label.get_copy() for label in compute_pareto_front_naive(non_walk_valid_labels)]


from unittest import TestCase
from gtfspy.routing.label import LabelTime
from gtfspy.routing.node_profile_c import NodeProfileC



class TestNodeProfileC(TestCase):

    def test_earliest_arrival_time(self):
        node_profile = NodeProfileC()
        self.assertEquals(float("inf"), node_profile.evaluate_earliest_arrival_time_at_target(0, 0))

        node_profile.update_pareto_optimal_tuples(LabelTime(departure_time=3, arrival_time_target=4))
        self.assertEquals(4, node_profile.evaluate_earliest_arrival_time_at_target(2, 0))

        node_profile.update_pareto_optimal_tuples(LabelTime(departure_time=1, arrival_time_target=1))
        self.assertEquals(1, node_profile.evaluate_earliest_arrival_time_at_target(0, 0))

    def test_pareto_optimality(self):
        node_profile = NodeProfileC()

        pair3 = LabelTime(departure_time=2, arrival_time_target=3)
        node_profile.update_pareto_optimal_tuples(pair3)
        pair2 = LabelTime(departure_time=1, arrival_time_target=2)
        node_profile.update_pareto_optimal_tuples(pair2)
        pair1 = LabelTime(departure_time=1, arrival_time_target=1)
        node_profile.update_pareto_optimal_tuples(pair1)
        self.assertEqual(2, len(node_profile.get_final_optimal_labels()))

    def test_pareto_optimality2(self):

# Path: gtfspy/routing/node_profile_c.py
# class NodeProfileC:
#     """
#     In the connection scan algorithm, each stop has a profile entry
#     that stores information on the Pareto-Optimal (departure_time_this_node, arrival_time_target_node) tuples.
#     """
# 
#     def __init__(self, walk_to_target_duration=float('inf')):
#         self._labels = []  # list[LabelTime] # always ordered by decreasing departure_time
#         self._walk_to_target_duration = walk_to_target_duration
# 
#     def get_walk_to_target_duration(self):
#         return self._walk_to_target_duration
# 
#     def update_pareto_optimal_tuples(self, new_label):
#         """
#         Parameters
#         ----------
#         new_label: LabelTime
# 
#         Returns
#         -------
#         updated: bool
#         """
#         assert (isinstance(new_label, LabelTime))
#         if self._labels:
#             assert (new_label.departure_time <= self._labels[-1].departure_time)
#             best_later_departing_arrival_time = self._labels[-1].arrival_time_target
#         else:
#             best_later_departing_arrival_time = float('inf')
# 
#         walk_to_target_arrival_time = new_label.departure_time + self._walk_to_target_duration
# 
#         best_arrival_time = min(walk_to_target_arrival_time,
#                                 best_later_departing_arrival_time,
#                                 new_label.arrival_time_target)
#         # this should be changed to get constant time insertions / additions
#         # (with time-indexing)
#         if (new_label.arrival_time_target < walk_to_target_arrival_time and
#                 new_label.arrival_time_target < best_later_departing_arrival_time):
#             self._labels.append(LabelTime(new_label.departure_time, best_arrival_time))
#             return True
#         else:
#             return False
# 
#     def evaluate_earliest_arrival_time_at_target(self, dep_time, transfer_margin):
#         """
#         Get the earliest arrival time at the target, given a departure time.
# 
#         Parameters
#         ----------
#         dep_time : float, int
#             time in unix seconds
#         transfer_margin: float, int
#             transfer margin in seconds
# 
#         Returns
#         -------
#         arrival_time : float
#             Arrival time in the given time unit (seconds after unix epoch).
#         """
#         minimum = dep_time + self._walk_to_target_duration
#         for label in self._labels[::-1]:
#             if label.departure_time >= dep_time + transfer_margin:
#                 minimum = min(minimum, label.arrival_time_target)
#                 break
#         return float(minimum)
# 
#     def get_final_optimal_labels(self):
#         non_walk_valid_labels = []
#         for label in self._labels:
#             if label.duration() < self._walk_to_target_duration:
#                 non_walk_valid_labels.append(label)
#         return [label.get_copy() for label in compute_pareto_front_naive(non_walk_valid_labels)]


# Path: gtfspy/routing/test/test_node_profile_c.py
from unittest import TestCase
from gtfspy.routing.label import LabelTime
from gtfspy.routing.node_profile_c import NodeProfileC




class TestNodeProfileC(TestCase):

    def test_earliest_arrival_time(self):
        node_profile = NodeProfileC()
        self.assertEquals(float("inf"), node_profile.evaluate_earliest_arrival_time_at_target(0, 0))

        node_profile.update_pareto_optimal_tuples(LabelTime(departure_time=3, arrival_time_target=4))
        self.assertEquals(4, node_profile.evaluate_earliest_arrival_time_at_target(2, 0))

        node_profile.update_pareto_optimal_tuples(LabelTime(departure_time=1, arrival_time_target=1))
        self.assertEquals(1, node_profile.evaluate_earliest_arrival_time_at_target(0, 0))

    def test_pareto_optimality(self):
        node_profile = NodeProfileC()

        pair3 = LabelTime(departure_time=2, arrival_time_target=3)
        node_profile.update_pareto_optimal_tuples(pair3)
        pair2 = LabelTime(departure_time=1, arrival_time_target=2)
        node_profile.update_pareto_optimal_tuples(pair2)
        pair1 = LabelTime(departure_time=1, arrival_time_target=1)
        node_profile.update_pareto_optimal_tuples(pair1)
        self.assertEqual(2, len(node_profile.get_final_optimal_labels()))

    def test_pareto_optimality2(self):

        node_profile = NodeProfileC()