summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2022-09-24 16:11:51 +0200
committerDaniel Friesel <derf@finalrewind.org>2022-09-24 16:11:51 +0200
commite83cfc5303bfd2625f067580df4c593b9a51af99 (patch)
treec74c713061ee8515796f5cad5afeca47e7157639
parent208b818d7c5c503149ecc0b662c02b0b4af63a41 (diff)
connections: show expected arrival at destination
-rwxr-xr-xlib/Travelynx/Controller/Traveling.pm133
-rw-r--r--templates/_connections.html.ep7
2 files changed, 115 insertions, 25 deletions
diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm
index 1e6a868..bdf57e2 100755
--- a/lib/Travelynx/Controller/Traveling.pm
+++ b/lib/Travelynx/Controller/Traveling.pm
@@ -77,19 +77,21 @@ sub get_connecting_trains_p {
}
my $can_check_in = not $arr_epoch || ( $arr_countdown // 1 ) < 0;
+ my $lookahead
+ = $can_check_in ? 40 : ( ( ${arr_countdown} // 0 ) / 60 + 40 );
+
+ my $iris_promise = Mojo::Promise->new;
$self->iris->get_departures_p(
- station => $eva,
- lookbehind => 10,
- lookahead => $can_check_in
- ? 40
- : ( ( ${arr_countdown} // 0 ) / 60 + 40 ),
+ station => $eva,
+ lookbehind => 10,
+ lookahead => $lookahead,
with_related => 1
)->then(
sub {
my ($stationboard) = @_;
if ( $stationboard->{errstr} ) {
- $promise->reject( $stationboard->{errstr} );
+ $iris_promise->reject( $stationboard->{errstr} );
return;
}
@@ -213,22 +215,107 @@ sub get_connecting_trains_p {
= 'Anschluss könnte knapp werden';
$train->{interchange_icon} = 'directions_run';
}
+ }
+ }
+
+ $iris_promise->resolve( [ @results, @cancellations ] );
+ return;
+ }
+ )->catch(
+ sub {
+ $iris_promise->reject(@_);
+ return;
+ }
+ )->wait;
- #else {
- # $train->{interchange_text} = 'Anschluss wird voraussichtlich erreicht';
- # $train->{interchange_icon} = 'check';
- #}
+ my $hafas_promise = Mojo::Promise->new;
+ my $rest_api = $self->config->{backend}{hafas_rest_api};
+ $self->hafas->get_json_p(
+"${rest_api}/stops/${eva}/departures?results=120&duration=${lookahead}&stopovers=true&when=10 minutes ago",
+ realtime => 1,
+ encoding => 'utf-8'
+ )->then(
+ sub {
+ my ($json) = @_;
+ $hafas_promise->resolve($json);
+ return;
+ }
+ )->catch(
+ sub {
+ # HAFAS data is optional.
+ # Errors are logged by get_json_p and can be silently ignored here.
+ $hafas_promise->resolve( [] );
+ return;
+ }
+ )->wait;
+
+ Mojo::Promise->all( $iris_promise, $hafas_promise )->then(
+ sub {
+ my ( $iris, $hafas ) = @_;
+ my @iris_trains = @{ $iris->[0] };
+ my @hafas_trains = @{ $hafas->[0] };
+
+ my $strp = DateTime::Format::Strptime->new(
+ pattern => '%Y-%m-%dT%H:%M:%S%z',
+ time_zone => 'Europe/Berlin',
+ );
+
+ # We've already got a list of connecting trains; this function
+ # only adds further information to them. We ignore errors, as
+ # partial data is better than no data.
+ eval {
+ for my $iris_train (@iris_trains) {
+ if ( $iris_train->[0]->departure_is_cancelled ) {
+ continue;
+ }
+ for my $hafas_train (@hafas_trains) {
+ if ( $hafas_train->{line}{fahrtNr}
+ == $iris_train->[0]->train_no )
+ {
+ for my $stop (
+ @{ $hafas_train->{nextStopovers} // [] } )
+ {
+ if ( $stop->{stop}{name}
+ and $stop->{stop}{name} eq $iris_train->[1]
+ and $stop->{arrival} )
+ {
+ $iris_train->[2] = $strp->parse_datetime(
+ $stop->{arrival} );
+ if ( $iris_train->[2]
+ and $iris_train->[0]->arrival_delay
+ and $stop->{arrival} eq
+ $stop->{plannedArrival} )
+ {
+# If the departure is delayed, but the arrival supposedly on time, we assume that this is an API issue and manually compute the expected arrival time.
+# This avoids cases where a connection is shown as arriving at its destination before having departed at a previous stop.
+ $iris_train->[2]->add( minutes =>
+ $iris_train->[0]->arrival_delay );
+ }
+ }
+ }
+ }
+ }
}
+ };
+ if ($@) {
+ $self->app->log->error(
+ "get_connecting_trains_p($uid): IRIS/HAFAS merge failed: $@"
+ );
}
- $promise->resolve( @results, @cancellations );
+ $promise->resolve( \@iris_trains );
+ return;
}
)->catch(
sub {
- $promise->reject(@_);
+ my ($err) = @_;
+
+# TODO logging. HAFAS errors should never happen, IRIS errors are noteworthy too.
+ $promise->reject($err);
return;
}
)->wait;
+
return $promise;
}
@@ -245,13 +332,14 @@ sub homepage {
$self->render_later;
$self->get_connecting_trains_p->then(
sub {
- my @connecting_trains = @_;
+ my ( $connecting_trains, $transit_fyi ) = @_;
$self->render(
'landingpage',
version => $self->app->config->{version}
// 'UNKNOWN',
user_status => $status,
- connections => \@connecting_trains,
+ connections => $connecting_trains,
+ transit_fyi => $transit_fyi,
with_autocomplete => 1,
with_geolocation => 1
);
@@ -617,11 +705,12 @@ sub status_card {
$self->render_later;
$self->get_connecting_trains_p->then(
sub {
- my @connecting_trains = @_;
+ my ( $connecting_trains, $transit_fyi ) = @_;
$self->render(
'_checked_in',
journey => $status,
- connections => \@connecting_trains
+ connections => $connecting_trains,
+ transit_fyi => $transit_fyi
);
}
)->catch(
@@ -640,11 +729,11 @@ sub status_card {
destination_name => $status->{cancellation}{arr_name}
)->then(
sub {
- my (@connecting_trains) = @_;
+ my ($connecting_trains) = @_;
$self->render(
'_cancelled_departure',
journey => $status->{cancellation},
- connections => \@connecting_trains
+ connections => $connecting_trains
);
}
)->catch(
@@ -662,11 +751,11 @@ sub status_card {
$self->render_later;
$self->get_connecting_trains_p->then(
sub {
- my @connecting_trains = @_;
+ my ($connecting_trains) = @_;
$self->render(
'_checked_out',
journey => $status,
- connections => \@connecting_trains
+ connections => $connecting_trains
);
}
)->catch(
@@ -968,14 +1057,14 @@ sub station {
if ($connections_p) {
$connections_p->then(
sub {
- my @connecting_trains = @_;
+ my ($connecting_trains) = @_;
$self->render(
'departures',
eva => $status->{station_eva},
results => \@results,
station => $status->{station_name},
related_stations => $status->{related_stations},
- connections => \@connecting_trains,
+ connections => $connecting_trains,
title => "travelynx: $status->{station_name}",
version => $self->app->config->{version}
// 'UNKNOWN',
diff --git a/templates/_connections.html.ep b/templates/_connections.html.ep
index d84ac76..a69b1fe 100644
--- a/templates/_connections.html.ep
+++ b/templates/_connections.html.ep
@@ -1,6 +1,7 @@
<div><table class="striped"><tbody>
% for my $res (@{$connections}) {
- % my ($train, $via) = @{$res};
+ % my ($train, $via, $via_arr) = @{$res};
+ % $via_arr = $via_arr ? $via_arr->strftime('%H:%M') : q{};
% my $td_class = '';
% my $link_class = 'action-checkin';
% if ($train->is_cancelled) {
@@ -23,10 +24,10 @@
</td>
<td class="<%= $td_class %>">
% if ($checkin_from) {
- <a><%= $via %></a>
+ <a><%= $via %><br/><%= $via_arr %></a>
% }
% else {
- %= $via
+ <%= $via %><br/><%= $via_arr %>
% }
% if ($train->{message_id}{96} or $train->{message_id}{97}) {
<i class="material-icons tiny" aria-label="Zug ist überbesetzt">warning</i>