summaryrefslogtreecommitdiff
path: root/bin/efa-m
diff options
context:
space:
mode:
Diffstat (limited to 'bin/efa-m')
-rwxr-xr-xbin/efa-m165
1 files changed, 102 insertions, 63 deletions
diff --git a/bin/efa-m b/bin/efa-m
index 0bea51f..769960a 100755
--- a/bin/efa-m
+++ b/bin/efa-m
@@ -4,25 +4,22 @@ use warnings;
use 5.010;
use utf8;
-no if $] >= 5.018, warnings => 'experimental::smartmatch';
-
-our $VERSION = '1.19';
+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.19
+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