diff options
Diffstat (limited to 'bin/efa-m')
-rwxr-xr-x | bin/efa-m | 165 |
1 files changed, 102 insertions, 63 deletions
@@ -4,25 +4,22 @@ use warnings; use 5.010; use utf8; -no if $] >= 5.018, warnings => 'experimental::smartmatch'; - -our $VERSION = '1.20'; +our $VERSION = '2.00'; binmode( STDOUT, ':encoding(utf-8)' ); -use Encode qw(decode); +use Encode qw(decode); use Getopt::Long qw(:config no_ignore_case bundling); -use List::Util qw(first max); +use List::Util qw(first max none); use Travel::Status::DE::EFA; my $efa_url = 'https://efa.vrr.de/vrr/XSLT_DM_REQUEST'; my $efa_encoding; -my ( $date, $time, $input_type, $list_lines, $offset, $relative_times ); -my ($full_routes); -my ( $filter_via, $track_via ); -my ( $timeout, $developer_mode ); -my ( @grep_lines, @grep_platforms, @grep_mots ); -my ( %edata, @edata_pre ); +my ( $date, $time, $input_type, $list_lines, $offset, $relative_times ); +my ( $full_routes, $filter_via ); +my ( $timeout, $developer_mode ); +my ( @grep_lines, @grep_platforms, @grep_mots ); +my ( %edata, @edata_pre ); my ( $list_services, $service, $discover_and_print, $discover ); my $efa; @@ -46,7 +43,7 @@ GetOptions( 'timeout=i' => \$timeout, 'u|efa-url=s' => \$efa_url, 'v|via=s' => \$filter_via, - 'V|track-via=s' => sub { $filter_via = $track_via = $_[1] }, + 'V|track-via=s' => \$filter_via, 'version' => \&show_version, 'devmode' => \$developer_mode, @@ -80,13 +77,12 @@ if ( $input =~ s{ ^ (?<type> address|poi|stop|stopID) : }{}x ) { } for my $efield (@edata_pre) { - given ($efield) { - when ('a') { $edata{route_after} = 1; $full_routes = 1 } - when ('b') { $edata{route_before} = 1; $full_routes = 1 } - when ('f') { $edata{fullroute} = 1; $full_routes = 1 } - when ('r') { $edata{route} = 1; $full_routes = 1 } - default { $edata{$efield} = 1 } - } + if ( $efield eq 'a' ) { $edata{route_after} = 1; $full_routes = 1 } + elsif ( $efield eq 'b' ) { $edata{route_before} = 1; $full_routes = 1 } + elsif ( $efield eq 'f' ) { $edata{fullroute} = 1; $full_routes = 1 } + elsif ( $efield eq 'r' ) { $edata{route} = 1; $full_routes = 1 } + elsif ( $efield eq 'm' ) { $edata{messages} = 1 } + else { $edata{$efield} = 1 } } if ($filter_via) { $full_routes = 1; @@ -94,7 +90,7 @@ if ($filter_via) { if ($service) { my $service_ref = first { lc( $_->{shortname} ) eq lc($service) } - Travel::Status::DE::EFA::get_efa_urls(); + Travel::Status::DE::EFA::get_efa_urls(); if ( not $service_ref ) { printf STDERR ( "Error: Unknown service '%s'. See 'efa-m --list' for a " @@ -149,6 +145,14 @@ sub show_version { exit 0; } +sub format_delay { + my ( $delay, $len ) = @_; + if ( $delay and $len ) { + return sprintf( "(%+${len}d)", $delay ); + } + return q{}; +} + sub format_route { my (@route) = @_; @@ -159,23 +163,35 @@ sub format_route { say 'BUG'; next; } - if ( not defined $stop->arr_time ) { - $output .= sprintf( " %5s %40s %s\n", - $stop->dep_time, $stop->name, $stop->platform, ); - } - elsif ( not defined $stop->dep_time ) { - $output .= sprintf( "%5s %40s %s\n", - $stop->arr_time, $stop->name, $stop->platform, ); + if ( defined $stop->arr and defined $stop->dep ) { + if ( $stop->arr->epoch == $stop->dep->epoch ) { + $output .= sprintf( + " %5s %40s %s\n", + $stop->arr->strftime('%H:%M'), + $stop->name, $stop->platform, + ); + } + else { + $output .= sprintf( + "%5s → %5s %40s %s\n", + $stop->arr->strftime('%H:%M'), + $stop->dep->strftime('%H:%M'), + $stop->name, $stop->platform, + ); + } } - elsif ( $stop->arr_time eq $stop->dep_time ) { - $output .= sprintf( " %5s %40s %s\n", - $stop->dep_time, $stop->name, $stop->platform, ); + elsif ( defined $stop->arr ) { + $output .= sprintf( + "%5s %40s %s\n", + $stop->arr->strftime('%H:%M'), + $stop->name, $stop->platform, + ); } - else { + elsif ( defined $stop->dep ) { $output .= sprintf( - "%5s → %5s %40s %s\n", - $stop->arr_time, $stop->dep_time, - $stop->name, $stop->platform, + " %5s %40s %s\n", + $stop->dep->strftime('%H:%M'), + $stop->name, $stop->platform, ); } } @@ -197,7 +213,7 @@ sub display_result { for my $line (@lines) { - if ( length( $line->[5] ) ) { + if ( $edata{messages} and length( $line->[5] ) ) { $line->[5] =~ tr{\n\x0d}{ }s; chomp $line->[5]; print "\n"; @@ -224,13 +240,13 @@ sub show_lines { for my $l ( $efa->lines ) { - if ( ( @grep_lines and not( $l->name ~~ \@grep_lines ) ) - or ( @grep_mots and not( $l->mot_name ~~ \@grep_mots ) ) ) + if ( ( @grep_lines and none { $l->name eq $_ } @grep_lines ) + or ( @grep_mots and none { $l->mot_name eq $_ } @grep_mots ) ) { next; } - if ( @grep_mots and not( $l->mot_name ~~ \@grep_mots ) ) { + if ( @grep_mots and none { $l->mot_name eq $_ } @grep_mots ) { next; } @@ -247,6 +263,17 @@ sub show_lines { sub show_results { my @output; + my $delay_len = 0; + my $delay_fmt = 0; + for my $d ( $efa->results ) { + if ( $d->delay ) { + $delay_len = max( $delay_len, length( $d->delay ) + 1 ); + } + } + if ($delay_len) { + $delay_fmt = $delay_len + 3; + } + for my $d ( $efa->results ) { my @output_line; @@ -254,7 +281,7 @@ sub show_results { my $dtime = ( $relative_times ? sprintf( '%2d min', $d->countdown ) - : $d->sched_time + : $d->datetime->strftime('%H:%M') ); if ( $d->platform_db ) { @@ -262,10 +289,10 @@ sub show_results { } if ( - ( @grep_lines and not( $d->line ~~ \@grep_lines ) ) - or ( @grep_mots and not( $d->mot_name ~~ \@grep_mots ) ) + ( @grep_lines and none { $d->line eq $_ } @grep_lines ) + or ( @grep_mots and none { $d->mot_name eq $_ } @grep_mots ) or ( @grep_platforms - and not( $platform ~~ \@grep_platforms ) ) + and none { $platform eq $_ } @grep_platforms ) or ( $offset and $d->countdown < $offset ) or ( $filter_via and @@ -280,24 +307,27 @@ sub show_results { next; } else { - $dtime .= ' CANCELED'; + $dtime = '--:--'; } } - elsif ($track_via) { + elsif ($filter_via) { my $via = first { $_->name =~ m{$filter_via}io } $d->route_post; - $dtime .= ' → ' . $via->arr_time; + $dtime + .= ' → ' + . $via->arr->clone->add( minutes => $d->delay // 0 ) + ->strftime('%H:%M'); } if ( $d->delay ) { - if ($relative_times) { - $dtime .= ' (+' . $d->delay . ')'; - } - else { - $dtime .= ' +' . $d->delay; - } + $dtime .= ' ' . format_delay( $d->delay, $delay_len ); + } + + my $line = $d->line; + if ( length($line) > 10 and $d->train_type and $d->train_no ) { + $line = $d->train_type . ' ' . $d->train_no; } @output_line - = ( $dtime, $platform, $d->line, q{}, $d->destination, $d->info ); + = ( $dtime, $platform, $line, q{}, $d->destination, $d->info ); if ( $edata{route} ) { $output_line[3] @@ -396,7 +426,7 @@ B<efa-m> [B<-Lr>] [B<-d> I<dd.mm.yyyy>] [B<-t> I<hh:mm>] =head1 VERSION -version 1.20 +version 2.00 =head1 DESCRIPTION @@ -513,6 +543,12 @@ Show up to three stops between the requested station and the departure's destination. B<efa-m> tries to display the three most important stops, however these are heuristically determined and may not be optimal. +=item m / messages + +Show free-text messages associated with individual departures. These can +include generic information such is bicycle transportation options or Wi-Fi +availability, delay reasons, and more. + =back =item B<-p>, B<--platform> I<platforms> @@ -549,15 +585,10 @@ value to disable it. =item B<-v>, B<--via> I<station> -Only show trains serving I<station> after the requseted stop. I<station> -is matched against the "I<city> I<stop>" fields in each line's route. -Regular expressions are also supported. - -=item B<-V>, B<--track-via> I<station> - -Lik B<--via>: Only show trains serving I<station> after the requseted stop. -Also, show the arrival time at I<station> after the departure time at the -current stop. +Only show trains serving I<station> after the requseted stop, and show the +arrival time at I<station> after the departure time at the current stop. +I<station> is matched against the "I<city> I<stop>" fields in each line's +route. Regular expressions are also supported. =item B<--version> @@ -597,9 +628,17 @@ choose the appropriate EFA URL for these by itself. In these cases, you should find an appropriate EFA service using the B<-D>/B<--discover> option and then use B<-s> I<service> when making requests. +=over + +=item * EFA does not provide real-time data for the routes of requested +departures. Hence, B<--via> estimates the arrival time from scheduled +departure and departure delay + +=back + =head1 AUTHOR -Copyright (C) 2011-2020 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt> +Copyright (C) 2011-2023 by Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt> =head1 LICENSE |