@@ -218,36 +218,59 @@ fn load_world_graph_data() -> anyhow::Result<WorldGraphData> {
218218 let mut hub_names = HashMap :: new ( ) ;
219219 let mut hub_specs = HashMap :: new ( ) ;
220220
221- // Sort hubs by their names to ensure deterministic HubId assignment
222- let mut sorted_hubs: Vec < ( & String , & HubSpec ) > = world_graph. hubs . iter ( ) . collect ( ) ;
223- sorted_hubs. sort_by_key ( |( name, _) | * name) ;
224-
225- for ( i, ( hub_name, hub_spec) ) in sorted_hubs. into_iter ( ) . enumerate ( ) {
226- let hub_id = HubId ( i as u16 ) ;
227- hub_names. insert ( hub_name. clone ( ) , hub_id) ;
228- hub_specs. insert ( hub_id, hub_spec. clone ( ) ) ;
221+ // Parse hub IDs from names (e.g., "H01" -> 1, "H02" -> 2) to preserve stable IDs
222+ for ( hub_name, hub_spec) in & world_graph. hubs {
223+ if hub_name. starts_with ( 'H' ) && hub_name. len ( ) >= 2 {
224+ if let Ok ( hub_num) = hub_name[ 1 ..] . parse :: < u16 > ( ) {
225+ let hub_id = HubId ( hub_num) ;
226+ hub_names. insert ( hub_name. clone ( ) , hub_id) ;
227+ hub_specs. insert ( hub_id, hub_spec. clone ( ) ) ;
228+ } else {
229+ return Err ( anyhow:: anyhow!( "invalid hub name format: {}" , hub_name) ) ;
230+ }
231+ } else {
232+ return Err ( anyhow:: anyhow!(
233+ "hub name must start with 'H': {}" ,
234+ hub_name
235+ ) ) ;
236+ }
229237 }
230238
231239 let mut neighbors: HashMap < HubId , SmallVec < [ RouteId ; 6 ] > > = HashMap :: new ( ) ;
232240 let mut route_weather = HashMap :: new ( ) ;
233241
234- // Sort links by their names to ensure deterministic RouteId assignment
242+ // Create a mapping from link names to RouteIds by parsing the numeric suffix (e.g., "L01" -> 1, "L02" -> 2)
243+ let mut link_to_route_id = HashMap :: new ( ) ;
244+
245+ for ( link_name, _) in & world_graph. links {
246+ if link_name. starts_with ( 'L' ) && link_name. len ( ) >= 2 {
247+ if let Ok ( route_num) = link_name[ 1 ..] . parse :: < u16 > ( ) {
248+ let route_id = RouteId ( route_num) ;
249+ link_to_route_id. insert ( link_name, route_id) ;
250+ } else {
251+ return Err ( anyhow:: anyhow!( "invalid link name format: {}" , link_name) ) ;
252+ }
253+ } else {
254+ return Err ( anyhow:: anyhow!(
255+ "link name must start with 'L': {}" ,
256+ link_name
257+ ) ) ;
258+ }
259+ }
260+
261+ // Process links in alphabetical order to ensure deterministic weather resolution and processing order
235262 let mut sorted_links: Vec < ( & String , & LinkSpec ) > = world_graph. links . iter ( ) . collect ( ) ;
236263 sorted_links. sort_by_key ( |( name, _) | * name) ;
237264
238- // Create a mapping from link names to RouteIds
239- let mut link_to_route_id = HashMap :: new ( ) ;
240-
241- for ( i, ( link_name, link_spec) ) in sorted_links. into_iter ( ) . enumerate ( ) {
265+ for ( link_name, link_spec) in sorted_links {
242266 let from_hub_id = hub_names
243267 . get ( & link_spec. from )
244268 . ok_or_else ( || anyhow:: anyhow!( "unknown hub in link: {}" , link_spec. from) ) ?;
245269 let to_hub_id = hub_names
246270 . get ( & link_spec. to )
247271 . ok_or_else ( || anyhow:: anyhow!( "unknown hub in link: {}" , link_spec. to) ) ?;
248272
249- let route_id = RouteId ( i as u16 ) ;
250- link_to_route_id. insert ( link_name, route_id) ;
273+ let route_id = * link_to_route_id. get ( link_name) . unwrap ( ) ;
251274
252275 neighbors. entry ( * from_hub_id) . or_default ( ) . push ( route_id) ;
253276 neighbors. entry ( * to_hub_id) . or_default ( ) . push ( route_id) ;
0 commit comments