summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBirte Kristina Friesel <derf@finalrewind.org>2025-12-27 14:35:30 +0100
committerBirte Kristina Friesel <derf@finalrewind.org>2025-12-27 14:35:30 +0100
commit831e851f840588e1401ab92c43175decd0195f5a (patch)
treef7135aef779d24d08132e39cce7c94c6b664ae31
parent43c191fc9435a11f4349be86fe6844354f5bbca0 (diff)
EFA: show connections while checked in
implemented via background worker; connections are only checked <15 minutes before arrival
-rw-r--r--lib/Travelynx/Command/work.pm55
-rw-r--r--lib/Travelynx/Helper/EFA.pm69
-rwxr-xr-xlib/Travelynx/Model/Journeys.pm4
-rw-r--r--templates/_checked_in.html.ep7
-rw-r--r--templates/_connections_efa.html.ep56
5 files changed, 182 insertions, 9 deletions
diff --git a/lib/Travelynx/Command/work.pm b/lib/Travelynx/Command/work.pm
index dc58a48..69e9bd2 100644
--- a/lib/Travelynx/Command/work.pm
+++ b/lib/Travelynx/Command/work.pm
@@ -285,16 +285,53 @@ sub run {
)->wait;
if ( $arr
- and $entry->{real_arr_ts}
- and $now->epoch - $entry->{real_arr_ts} > 900 )
+ and $entry->{real_arr_ts} )
{
- $self->app->checkout_p(
- station => $arr,
- force => 2,
- dep_eva => $dep,
- arr_eva => $arr,
- uid => $uid
- )->wait;
+ if ( $now->epoch - $entry->{real_arr_ts} > 900 ) {
+ $self->app->checkout_p(
+ station => $arr,
+ force => 2,
+ dep_eva => $dep,
+ arr_eva => $arr,
+ uid => $uid
+ )->wait;
+ }
+ elsif ( $entry->{real_arr_ts} - $now->epoch < 900 ) {
+ my @destinations
+ = $self->app->journeys->get_connection_targets(
+ uid => $uid,
+ backend_id => $entry->{backend_id},
+ eva => $arr,
+ exclude => $dep,
+ );
+ $self->app->efa->get_connections_p(
+ service => $entry->{backend_name},
+ name => $arr,
+ timestamp => $entry->{real_arr},
+ destinations => \@destinations
+ )->then(
+ sub {
+ my ($suggestions) = @_;
+ $self->app->in_transit->update_data(
+ uid => $uid,
+ train_id => $train_id,
+ data => {
+ connection_suggestions_efa =>
+ $suggestions
+ },
+ );
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $self->app->log->debug(
+"work($uid) @ EFA $entry->{backend_name}: get_departures_p($arr): $err"
+ );
+ return;
+ }
+ )->wait;
+ }
}
};
if ($@) {
diff --git a/lib/Travelynx/Helper/EFA.pm b/lib/Travelynx/Helper/EFA.pm
index 5cae51b..a280388 100644
--- a/lib/Travelynx/Helper/EFA.pm
+++ b/lib/Travelynx/Helper/EFA.pm
@@ -48,6 +48,75 @@ sub get_departures_p {
);
}
+sub get_connections_p {
+ my ( $self, %opt ) = @_;
+ my $promise = Mojo::Promise->new;
+ my @destinations = @{ $opt{destinations} };
+
+ $self->get_departures_p(
+ service => $opt{service},
+ name => $opt{name},
+ timestamp => $opt{timestamp},
+ lookbehind => 0,
+ lookahead => 60,
+ )->then(
+ sub {
+ my ($status) = @_;
+ my @suggestions;
+ my %via_count;
+ for my $dep ( $status->results ) {
+ destination: for my $dest (@destinations) {
+ for my $stop ( $dep->route_post ) {
+ if ( $stop->full_name eq $dest->{name} ) {
+ if ( not $dep->is_cancelled ) {
+ $via_count{ $dep->stop_id_num } += 1;
+ }
+ if ( $via_count{ $dep->stop_id_num } > 2 ) {
+ next destination;
+ }
+ my $dep_json = {
+ id => $dep->id,
+ ts => ( $dep->sched_datetime // $dep->datetime )
+ ->epoch,
+ is_cancelled => $dep->is_cancelled,
+ stop_id_num => $dep->stop_id_num,
+ sched_hhmm =>
+ $dep->sched_datetime->strftime('%H:%M'),
+ rt_hhmm => $dep->datetime->strftime('%H:%M'),
+ delay => $dep->delay,
+ platform => $dep->platform,
+ type => $dep->type,
+ line => $dep->line,
+ };
+ push(
+ @suggestions,
+ [
+ $dep_json, $dest,
+ $stop->arr->strftime('%H:%M')
+ ]
+ );
+ next destination;
+ }
+ }
+ }
+ }
+ @suggestions = map { $_->[0] }
+ sort { $a->[1] <=> $b->[1] }
+ map { [ $_, $_->[0]->{ts} ] } @suggestions;
+ $promise->resolve( \@suggestions );
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $promise->reject(
+ "get_departures_p($opt{service}, $opt{name}): $err");
+ return;
+ }
+ )->wait;
+ return $promise;
+}
+
sub get_journey_p {
my ( $self, %opt ) = @_;
diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm
index f532b8b..744e7ae 100755
--- a/lib/Travelynx/Model/Journeys.pm
+++ b/lib/Travelynx/Model/Journeys.pm
@@ -2108,6 +2108,7 @@ sub get_connection_targets {
my $min_count = $opt{min_count} // 3;
my $backend_id = $opt{backend_id};
my $dest_id = $opt{eva};
+ my $exclude_id = $opt{exclude};
$self->{log}->debug(
"get_connection_targets(uid => $uid, backend_id => $backend_id, dest_id => $dest_id)"
@@ -2163,6 +2164,9 @@ sub get_connection_targets {
backend_id => $opt{backend_id},
evas => [@destinations]
);
+ if ( defined $exclude_id ) {
+ @destinations = grep { $_->{eva} != $exclude_id } @destinations;
+ }
return @destinations;
}
diff --git a/templates/_checked_in.html.ep b/templates/_checked_in.html.ep
index f057a0a..b590fdd 100644
--- a/templates/_checked_in.html.ep
+++ b/templates/_checked_in.html.ep
@@ -221,6 +221,13 @@
</ul>
</p>
% }
+ % if (my @suggestions = @{$journey->{extra_data}{connection_suggestions_efa} // []}) {
+ <span class="card-title" style="margin-top: 2ex;">Verbindungen</span>
+ % if ($journey->{arrival_countdown} < 0) {
+ <p>Fahrt auswählen zum Einchecken mit Zielwahl.</p>
+ % }
+ %= include '_connections_efa', efa => $journey->{backend_name}, suggestions => \@suggestions, checkin_from => $journey->{arrival_countdown} < 0 ? $journey->{arr_eva} : undef
+ % }
% if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) {
<p style="margin-top: 2ex;">
%= L('status.delayed-auto-checkout')
diff --git a/templates/_connections_efa.html.ep b/templates/_connections_efa.html.ep
new file mode 100644
index 0000000..4800adb
--- /dev/null
+++ b/templates/_connections_efa.html.ep
@@ -0,0 +1,56 @@
+<ul class="collection departures connections">
+ % for my $res (@{$suggestions}) {
+ % my ($dep, $dest, $via_arr) = @{$res};
+ % my $row_class = '';
+ % my $link_class = 'action-checkin';
+ % if ($dep->{is_cancelled}) {
+ % $row_class = 'cancelled';
+ % $link_class = 'action-cancelled-from';
+ % }
+ % if ($checkin_from) {
+ <li class="collection-item <%= $row_class %> <%= $link_class %>"
+ data-efa="<%= $efa %>"
+ data-station="<%= $dep->{stop_id_num} %>"
+ data-train="<%= $dep->{id} %>"
+ data-ts="<%= $dep->{ts} %>"
+ data-dest="<%= $dest->{name} %>">
+ % }
+ % else {
+ <li class="collection-item <%= $row_class %>">
+ % }
+ <a class="dep-time" href="#">
+ % if ($dep->{is_cancelled}) {
+ %= $dep->{sched_hhmm}
+ % }
+ % else {
+ %= $dep->{rt_hhmm}
+ % }
+ % if ($via_arr) {
+ → <%= $via_arr %>
+ % }
+ % if ($dep->{delay}) {
+ %= sprintf('(%+d)', $dep->{delay})
+ % }
+ </a>
+ <span class="connect-platform-wrapper">
+ % if ($dep->{platform}) {
+ <span>
+ % if (($dep->{type} // q{}) =~ m{ ast | bus | ruf }ix) {
+ Steig
+ % }
+ % else {
+ Gleis
+ % }
+ %= $dep->{platform}
+ </span>
+ % }
+ <span class="dep-line <%= ($dep->{type} // q{}) =~ tr{a-zA-Z_-}{}cdr %>">
+ %= $dep->{line}
+ </span>
+ </span>
+ <span class="dep-dest">
+ %= $dest->{name}
+ </span>
+ </li>
+ % }
+</ul>