]> git.michaelhowe.org Git - pub/michael/national-rail-ticket-split.git/commitdiff
It works!
authorMichael Howe <michael@michaelhowe.org>
Tue, 8 Apr 2014 21:16:56 +0000 (22:16 +0100)
committerMichael Howe <michael@michaelhowe.org>
Tue, 8 Apr 2014 21:16:56 +0000 (22:16 +0100)
Needs lots of tidying up and error- and sanity-checking adding, but it
seems to be returning the information I expect.

parse-route.pl

index 6eeebca05956128e4e01feea82553024e623e0cb..63ebd060ec0fa5805ba3f6727fed4d94905a6a49 100755 (executable)
@@ -7,6 +7,7 @@ use HTML::TreeBuilder;
 
 use Data::Dumper;
 use List::Util qw(sum);
+use Graph;
 
 use 5.14.0;
 
@@ -17,11 +18,11 @@ my $query_site = "http://traintimes.org.uk";
 die "Usage: $0 <source> <dest> <date> <departure time>\n"
     unless( scalar( @ARGV ) == 4 );
 
-my ( $src, $dest, $date, $depart ) = @ARGV;
+my ( $src_in, $dest_in, $date, $depart ) = @ARGV;
 
-say "Finding routes from $src to $dest on $date at $depart";
+say "Finding routes from $src_in to $dest_in on $date at $depart";
 
-my $url = "${query_site}/${src}/${dest}/${depart}/${date}";
+my $url = "${query_site}/${src_in}/${dest_in}/${depart}/${date}";
 say "Checking $url";
 
 # This is the overall route
@@ -29,22 +30,33 @@ my $route = get_stops( $url );
 
 print Dumper( $route );
 
-my @options;
+# Give me some more useful variables.  Note that we need the array because we need the order.
+my @all_stops = map { $_->{abbr} } @{$route->{stops}};
+my %stop_details = map { $_->{abbr} => { departs => $_->{departs}, arrives => $_->{arrives}, point => $_->{point} } } @{$route->{stops}};
 
-# We can't find the time to the start point, obviously
-for( my $i = 1; $i <= $#{$route->{stops}}; $i++ ){
-    my $current_stop = $route->{stops}[$i];
-    my $prev_stop = $route->{stops}[$i - 1];
-    say "Checking $prev_stop->{point} -> $current_stop->{point}";
-#    
-    my $stop_url = sprintf "%s/%s/%s/%s/%s", $query_site, $prev_stop->{abbr}, $current_stop->{abbr}, $prev_stop->{departs}, $date;
-    push @options, get_stops( $stop_url );
-}
+print Dumper( \%stop_details );
+my $graph = Graph->new();
+my %journeys;
+
+$graph->add_weighted_edge( $all_stops[0], $all_stops[-1], $route->{price} );
+get_substops( \@all_stops );
+
+print Dumper( \%journeys );
 
-say Dumper( \@options );
+my @best_route = $graph->SP_Dijkstra( $all_stops[0], $all_stops[-1] );
 
-say sum( map { $_->{price} } @options );
+say "Best route:";
+my $sum = 0;
+for(my $i = 0; $i < $#best_route; $i++ ){
+    my $journey = $journeys{$best_route[$i]}->{$best_route[$i+1]};
+    printf "%s -> %s: %s (%s)\n", $best_route[$i], $best_route[$i+1], $journey->{price}, $journey->{type};
+    $sum += $journey->{price};
+}
+say "Total price: $sum";
+say "Direct price: " . $route->{price};
 
+##
+## functions below here
 sub get_stops {
     my ( $url ) = @_;
     say "get_stops( $url )";
@@ -120,3 +132,25 @@ sub _parse_stopping_points {
     $tree = $tree->delete();
     return \@stops;
 }
+
+sub get_substops {
+    my ( $stop_list ) = @_;
+
+    for( my $i = 0; $i <= $#{$stop_list}; $i++ ){
+        for( my $j = $i + 1; $j <= $#{$stop_list}; $j++ ){
+            # skip src-dest as we've already calculated that
+            next if( 0 == $i and $#{$stop_list} == $j );
+            my $src = $stop_list->[$i];
+            my $dst = $stop_list->[$j];
+
+            say "checking $src -> $dst ($i -> $j)";
+
+            my $depart = $stop_details{$src}->{departs};
+            my $url = "${query_site}/${src}/${dst}/${depart}/${date}";
+            my $journey = get_stops( $url );
+
+            $graph->add_weighted_edge($src, $dst, $journey->{price} );
+            $journeys{$src}->{$dst} = $journey;
+        }
+    }
+}