22# Licensed under the MIT license.
33
44from math import ceil
5+ from typing import List
56
67from .entities import CimBaseDataCollection , Stop
78
@@ -24,6 +25,7 @@ def __init__(self, data: CimBaseDataCollection):
2425 self ._route_mapping = data .route_mapping
2526 self ._port_mapping = data .port_mapping
2627 self ._stop_number = data .future_stop_number
28+ self ._vessel_start_port_offsets = self ._make_vessel_start_port_offset ()
2729
2830 def __getitem__ (self , key ):
2931 """Used to support querying future stops by vessel index, last location index, next location index."""
@@ -37,41 +39,40 @@ def __getitem__(self, key):
3739 # ignore current port if parking
3840 last_stop_idx = loc_idx + (0 if last_loc_idx == loc_idx else - 1 )
3941
40- last_stop = self ._stops [vessel_idx ][last_stop_idx ]
41- last_port_idx = last_stop .port_idx
42- last_port_arrival_tick = last_stop .arrival_tick
42+ return self ._predict_future_stops (vessel_idx , last_stop_idx , self ._stop_number )
4343
44- return self ._predict_future_stops (vessel_idx , last_port_idx , last_port_arrival_tick , self ._stop_number )
44+ def _make_vessel_start_port_offset (self ) -> List [int ]:
45+ vessel_start_port_offsets = []
46+ for vessel in self ._vessels :
47+ route_points = self ._routes [self ._route_mapping [vessel .route_name ]]
48+ route_point_names = [rp .port_name for rp in route_points ]
49+ vessel_start_port_offset = route_point_names .index (vessel .start_port_name )
50+ vessel_start_port_offsets .append (vessel_start_port_offset )
51+ return vessel_start_port_offsets
4552
46- def _predict_future_stops (self , vessel_idx : int , last_port_idx : int , last_port_arrival_tick : int , stop_number : int ):
53+ def _predict_future_stops (self , vessel_idx : int , last_stop_idx : int , stop_number : int ):
4754 """Do predict future stops.
4855 """
4956 vessel = self ._vessels [vessel_idx ]
50- speed = vessel .sailing_speed
51- duration = vessel .parking_duration
52- route_name = vessel .route_name
53- route_points = self ._routes [self ._route_mapping [route_name ]]
57+ speed , duration = vessel .sailing_speed , vessel .parking_duration
58+ route_points = self ._routes [self ._route_mapping [vessel .route_name ]]
5459 route_length = len (route_points )
5560
56- last_loc_idx = - 1
57-
58- # try to find the last location index from route
59- for loc_idx , route_point in enumerate (route_points ):
60- if self ._port_mapping [route_point .port_name ] == last_port_idx :
61- last_loc_idx = loc_idx
62- break
61+ last_stop = self ._stops [vessel_idx ][last_stop_idx ]
62+ last_port_arrival_tick = last_stop .arrival_tick
6363
64- # return if not in current route
65- if last_loc_idx < 0 :
66- return []
64+ vessel_start_port_offset = self ._vessel_start_port_offsets [vessel_idx ]
65+ last_loc_idx = (vessel_start_port_offset + last_stop_idx ) % len (route_points )
6766
6867 predicted_future_stops = []
6968 arrival_tick = last_port_arrival_tick
7069
7170 # predict from configured sailing plan, not from stops
7271 for loc_idx in range (last_loc_idx + 1 , last_loc_idx + stop_number + 1 ):
73- route_info = route_points [loc_idx % route_length ]
74- port_idx , distance_to_next_port = self ._port_mapping [route_info .port_name ], route_info .distance_to_next_port
72+ next_route_info = route_points [loc_idx % route_length ]
73+ last_route_info = route_points [(loc_idx - 1 ) % route_length ]
74+ port_idx = self ._port_mapping [next_route_info .port_name ]
75+ distance_to_next_port = last_route_info .distance_to_next_port
7576
7677 # NO noise for speed
7778 arrival_tick += duration + ceil (distance_to_next_port / speed )
0 commit comments