diff --git a/lib/App/FrameUtils.pm b/lib/App/FrameUtils.pm index 7bbc620f06e38522eb11bf17321cddc699bc3995..7d6b4cccf8b021bbf022315bed346ffd81ec46ba 100644 --- a/lib/App/FrameUtils.pm +++ b/lib/App/FrameUtils.pm @@ -9,7 +9,7 @@ BEGIN unshift @INC, '.'; } -use App::Utils; +use App::TimeUtils; use App::MasterUtils; sub get_syubetsu @@ -75,7 +75,7 @@ sub hassya_hyou if ($ts{'mode'} != 1) { next; } # Format: time (tab) destination (tab) type (with eventual name) my $syubetsu = get_syubetsu $master, $rosen_id, $data{'syubetsu'}; - print ((Utils::format_time $time) + print ((TimeUtils::format_time_simple $time) . "\tfor " . (get_destination $master, $rosen_id, \@jikoku, $target_relative, $is_down) . "\t$syubetsu") diff --git a/lib/App/Log.pm b/lib/App/Log.pm index 11fdfc209c61e595155a78cefc16396935f865af..f2f3c09666b5835243f17e405263c09021bf8976 100644 --- a/lib/App/Log.pm +++ b/lib/App/Log.pm @@ -5,11 +5,11 @@ use warnings; use Time::HiRes qw(gettimeofday); -our $DEBUG_MODE = 1; +our $LOG_MODE = 0; sub d { - if (!$DEBUG_MODE) { return; } + if (!$LOG_MODE) { return; } print 'DEBUG ||| ' . $_[0] . "\n"; } diff --git a/lib/App/Navi.pm b/lib/App/Navi.pm index 5f16ca849aa5c1eab2ec100f0ec47695b34ddd0b..093c3b91f4fd6de83a6fb13681c64a9b183a2bb8 100644 --- a/lib/App/Navi.pm +++ b/lib/App/Navi.pm @@ -9,9 +9,11 @@ BEGIN } use App::NaviUtils; +use App::FrameUtils; use App::MasterUtils; use App::Log; use App::Ressya; +use App::TimeUtils; use List::Util qw(min); use Data::Printer; @@ -28,13 +30,20 @@ sub Raptor_simple my $from = MasterUtils::sta_from_id $master, $from_id; my $to = MasterUtils::sta_from_id $master, $to_id; - print "Calculating fastest routes from $from->{'ekimei'} to $to->{'ekimei'} leaving at $dep_time\n"; + print "Calculating fastest routes from $from->{'ekimei'} to $to->{'ekimei'} leaving at $dep_time with $MAX_LEGS maximum legs\n"; # From now on we are just blindly following the algorithm from the paper... # Use ~0 as a substitute to infty, not that travel times would exceed this anyway my %taus; my %taustar; my @marked; + + + # We add two more hashes: + # one to keep track of the last used service to arrive at a station + my %earliest; + # and one to save the station used to board this last used service + my %from; sub earliest_trip { @@ -74,6 +83,7 @@ sub Raptor_simple my @a = (~0) x $MAX_LEGS; $taus{$key} = \@a; $taustar{$key} = ~0; + $earliest{$key} = (); } $taus{$from_id}[0] = $dep_time; @@ -127,7 +137,6 @@ sub Raptor_simple my $d = $triplet->[1]; my $p = $triplet->[2]; my $trip; - my @path = undef; # We do two runs starting from $p, one towards each end of the route. my @r_ekis = @{ (MasterUtils::get_rosen_frame $master, $r)->{'eki'} }; @@ -158,6 +167,10 @@ sub Raptor_simple Log::d "Updating ETA($k) for $pi >> $trip_arrival"; $taus{$pi}->[$k] = $trip_arrival; $taustar{$pi} = $trip_arrival; + $earliest{$pi}{'rosen'} = $r; + $earliest{$pi}{'dir'} = $d; + $earliest{$pi}{'service'} = $trip; + $from{$pi} = $p; # Check if the target station is not already marked my $mark = 1; @@ -194,8 +207,89 @@ sub Raptor_simple return; } } - p %taus; - p %taustar; + + # Print results by backtracking + my $pos = $to_id; + my @path; + push @path, $pos; + my @jikoku; + my @legs; + + while ($pos ne $from_id) + { + unshift @legs, $earliest{$pos}; + + my $source = $from{$pos}; + $pos = $source; + unshift @path, $pos; + } + + # First crawl: build a list of arrival/departure times + for (my $i = 0; $i <= $#path; $i++) + { + my %eki_jikoku = ( 'chaku' => undef, 'hatsu' => undef ); + + if ($i != $#path) + { + my $next_frame = $earliest{$path[$i+1]}; + my $next_eki_pos = $next_frame->{'dir'} + ? $master->{'rosen'}->{$next_frame->{'rosen'}}->{'eki_num'} - (MasterUtils::get_eki_position $master, $next_frame->{'rosen'}, $path[$i]) - 1 + : MasterUtils::get_eki_position $master, $next_frame->{'rosen'}, $path[$i]; + + my $dep = Ressya::dep_time $next_frame->{'service'}, $next_eki_pos; + $eki_jikoku{'hatsu'} = $dep; + } + + if ($i != 0) + { + my $previous_frame = $earliest{$path[$i]}; + my $previous_eki_pos = $previous_frame->{'dir'} + ? $master->{'rosen'}->{$previous_frame->{'rosen'}}->{'eki_num'} - (MasterUtils::get_eki_position $master, $previous_frame->{'rosen'}, $path[$i]) - 1 + : MasterUtils::get_eki_position $master, $previous_frame->{'rosen'}, $path[$i]; + + my $arr = Ressya::arr_time $previous_frame->{'service'}, $previous_eki_pos; + $eki_jikoku{'chaku'} = $arr; + } + + push @jikoku, \%eki_jikoku; + } + + # Second crawl: visual output + for (my $i = 0; $i < $#path; $i++) + { + my $u = $legs[$i]->{'service'}; + my $r = $legs[$i]->{'rosen'}; + my $m = (defined $u->{'meisyo'}) ? ' ' . $u->{'meisyo'} : ''; + + my $from_what = MasterUtils::get_ekimei $master, $path[$i]; + my $from_dep = $jikoku[$i]->{'hatsu'}; + my $to_what = MasterUtils::get_ekimei $master, $path[$i+1]; + my $to_arr = $jikoku[$i+1]->{'chaku'}; + + print ((TimeUtils::format_time $from_dep) + . "\t$from_what\n" + . "\t|\n" + . '(' . (TimeUtils::format_time_simple (TimeUtils::subtract_from $from_dep, $to_arr)) . ')' + . "\t| " + . (MasterUtils::get_rosenmei $master, $r) + . ' ' + . (FrameUtils::get_syubetsu $master, $r, $u->{'syubetsu'}) + . "$m" + . ' for ' + . (FrameUtils::get_destination $master, $r, $u->{'jikoku'}, 0, ($legs[$i]->{'dir'} == 0 ? 1 : 0)) + . "\n\tV\n" + . (TimeUtils::format_time $to_arr) + . "\t$to_what\n" + ); + if ($i != $#path - 1) + { + my $to_dep = $jikoku[$i+1]->{'hatsu'}; + print ('(' + . TimeUtils::format_time_simple (TimeUtils::subtract_from $to_arr, $to_dep) + . ")\n" + ) + } + } } 1; diff --git a/lib/App/TimeUtils.pm b/lib/App/TimeUtils.pm new file mode 100644 index 0000000000000000000000000000000000000000..89037252f99a89be7877233a949ed3c78117b27b --- /dev/null +++ b/lib/App/TimeUtils.pm @@ -0,0 +1,26 @@ +package TimeUtils; + +use strict; +use warnings; + +sub format_time +{ + my $time = $_[0]; + return sprintf "%02d:%02d", ($time / 100), (substr $time, -2); +} + +sub format_time_simple +{ + my $time = $_[0]; + return sprintf "%d:%02d", ($time / 100), (substr $time, -2); +} + +sub subtract_from +{ + # Syntax: subtract $a from $b + my ($a, $b) = @_; + my $diff = int($b / 100) * 60 + $b % 100 - int($a / 100) * 60 - $a % 100; + return int($diff / 60) * 100 + $diff % 60; +} + +1; diff --git a/lib/App/Utils.pm b/lib/App/Utils.pm deleted file mode 100644 index 066f3a8914c917378fa2365b86679bffbbf46fe2..0000000000000000000000000000000000000000 --- a/lib/App/Utils.pm +++ /dev/null @@ -1,12 +0,0 @@ -package Utils; - -use strict; -use warnings; - -sub format_time -{ - my $time = $_[0]; - return sprintf "%02d:%02d", ($time / 100), (substr $time, -2); -} - -1; diff --git a/src/oud2_parser.pl b/src/oud2_parser.pl index 908146cd810eb3678b209f659e7c5b79dafd9b53..85716e30b2934cec55bf6a8114ab161fb61f3e10 100644 --- a/src/oud2_parser.pl +++ b/src/oud2_parser.pl @@ -329,4 +329,4 @@ foreach my $frame (values %{ $master{'rosen'} }) # MasterUtils::get_routes \%master, 'konpoku_9'; # FrameUtils::hassya_hyou \%master, 'konpoku_9'; -Navi::Raptor_simple \%master, 'konpoku_3', 'sibetu_6', 1111; +Navi::Raptor_simple \%master, 'konpoku_3', 'senmo_21', 1111;