From 694bde71f8d6abc6c0cfcc7f96ba850abf597a90 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Fri, 29 Apr 2016 21:26:09 +0200 Subject: Use iterative related-station fetch instead of recursive approach --- lib/Travel/Status/DE/IRIS.pm | 94 ++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/lib/Travel/Status/DE/IRIS.pm b/lib/Travel/Status/DE/IRIS.pm index 347b68a..4e3cad4 100644 --- a/lib/Travel/Status/DE/IRIS.pm +++ b/lib/Travel/Status/DE/IRIS.pm @@ -160,65 +160,55 @@ sub get_station { my ( $self, %opt ) = @_; my @ret; - my $recursion_depth = $opt{recursion_depth} // 0; - - my ( $raw, $err ) - = $self->get_with_cache( $self->{main_cache}, - $self->{iris_base} . '/station/' . $opt{name} ); - if ($err) { - $self->{errstr} = "Failed to fetch station data: $err"; - return; - } - - my $xml_st = XML::LibXML->load_xml( string => $raw ); + my @queue = ( $opt{name} ); + my @seen; + + while (@queue) { + my $station = shift(@queue); + push( @seen, $station ); + + my ( $raw, $err ) + = $self->get_with_cache( $self->{main_cache}, + $self->{iris_base} . '/station/' . $station ); + if ($err) { + $self->{errstr} = "Failed to fetch station data: $err"; + return; + } - my $station_node = ( $xml_st->findnodes('//station') )[0]; + my $xml_st = XML::LibXML->load_xml( string => $raw ); - if ( not $station_node ) { - if ( $opt{root} ) { - $self->{errstr} - = "The station '$opt{name}' has no associated timetable"; - } - return; - } - if ( $recursion_depth > 5 ) { - cluck("Reached recursion depth $recursion_depth while tracking IDs"); - return; - } + my $station_node = ( $xml_st->findnodes('//station') )[0]; - push( - @ret, - { - uic => $station_node->getAttribute('eva'), - name => $station_node->getAttribute('name'), - ds100 => $station_node->getAttribute('ds100'), + if ( not $station_node ) { + if ( $opt{root} ) { + $self->{errstr} + = "The station '$opt{name}' has no associated timetable"; + return; + } + next; } - ); - if ( $self->{developer_mode} ) { - printf( " -> %s (%s / %s)\n", @{ $ret[0] }{qw{name uic ds100}} ); - } + push( @seen, $station_node->getAttribute('eva') ); - # TODO this approach is flawed, iterative is probably better - - if ( $opt{recursive} and $station_node->hasAttribute('meta') ) { - my @recursion_blacklist = @{ $opt{recursion_blacklist} // [] }; - my @refs = uniq(split( m{ \| }x, $station_node->getAttribute('meta') )); - - push( @recursion_blacklist, map { $_->{uic} } @ret ); - - for my $ref (@refs) { - if ( not( $ref ~~ \@recursion_blacklist ) ) { - push( - @ret, - $self->get_station( - name => $ref, - recursive => 1, - recursion_depth => $recursion_depth + 1, - recursion_blacklist => \@recursion_blacklist, - ) - ); + push( + @ret, + { + uic => $station_node->getAttribute('eva'), + name => $station_node->getAttribute('name'), + ds100 => $station_node->getAttribute('ds100'), } + ); + + if ( $self->{developer_mode} ) { + printf( " -> %s (%s / %s)\n", @{ $ret[-1] }{qw{name uic ds100}} ); + } + + if ( $opt{recursive} ) { + my @refs + = uniq( split( m{ \| }x, $station_node->getAttribute('meta') ) ); + @refs = grep { not( $_ ~~ \@seen or $_ ~~ \@queue ) } @refs; + push( @queue, @refs ); + $opt{root} = 0; } } -- cgit v1.2.3