summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/Travelynx.pm6
-rw-r--r--lib/Travelynx/Command/work.pm151
-rwxr-xr-xlib/Travelynx/Controller/Traveling.pm681
-rw-r--r--lib/Travelynx/Helper/DBRIS.pm94
-rw-r--r--lib/Travelynx/Helper/EFA.pm80
-rw-r--r--lib/Travelynx/Helper/IRIS.pm80
-rwxr-xr-xlib/Travelynx/Model/Journeys.pm4
7 files changed, 494 insertions, 602 deletions
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm
index 39899c7..7b5cf99 100755
--- a/lib/Travelynx.pm
+++ b/lib/Travelynx.pm
@@ -2026,10 +2026,10 @@ sub startup {
for my $stop ( $journey->route ) {
$self->stations->add_or_update(
- stop => $stop,
- db => $db,
+ stop => $stop,
+ db => $db,
keep_name => 1,
- iris => 1,
+ iris => 1,
);
}
diff --git a/lib/Travelynx/Command/work.pm b/lib/Travelynx/Command/work.pm
index dc58a48..41325d2 100644
--- a/lib/Travelynx/Command/work.pm
+++ b/lib/Travelynx/Command/work.pm
@@ -53,6 +53,9 @@ sub run {
my $arr = $entry->{arr_eva};
my $train_id = $entry->{train_id};
+ my $use_history = $self->app->users->use_history( uid => $uid );
+ my $suggestions_enabled = $use_history & 0x02;
+
if ( $train_id eq 'manual' ) {
if ( $arr
and $entry->{real_arr_ts}
@@ -190,16 +193,54 @@ 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 ( $suggestions_enabled
+ and $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->dbris->get_connections_p(
+ station => $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_dbris =>
+ $suggestions
+ },
+ );
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $self->app->log->debug(
+"work($uid) @ DBRIS $entry->{backend_name}: get_departures_p($arr): $err"
+ );
+ return;
+ }
+ )->wait;
+ }
}
};
if ($@) {
@@ -285,16 +326,55 @@ 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 ( $suggestions_enabled
+ and $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 ($@) {
@@ -702,6 +782,41 @@ sub run {
$self->app->add_stationinfo( $uid, 0, $train->train_id,
$dep, $arr );
}
+ if ( $now->epoch - $entry->{real_arr_ts} < 900 ) {
+ my @destinations
+ = $self->app->journeys->get_connection_targets(
+ uid => $uid,
+ backend_id => $entry->{backend_id},
+ eva => $arr,
+ exclude => $dep,
+ );
+ $self->app->iris->get_connections_p(
+ station => $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_iris =>
+ $suggestions
+ },
+ );
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $self->app->log->debug(
+"work($uid) @ DBRIS $entry->{backend_name}: get_departures_p($arr): $err"
+ );
+ return;
+ }
+ )->wait;
+ }
}
elsif ( $entry->{real_arr_ts} ) {
my ( undef, $error ) = $self->app->checkout_p(
diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm
index 30c579e..28d7bfd 100755
--- a/lib/Travelynx/Controller/Traveling.pm
+++ b/lib/Travelynx/Controller/Traveling.pm
@@ -28,324 +28,6 @@ sub has_str_in_list {
return;
}
-# when called with "eva" provided: look up connections from eva, either
-# for provided backend_id / hafas or (if not provided) for user backend id.
-# When calld without "eva": look up connections from current/latest arrival
-# eva, using the checkin's backend id.
-sub get_connecting_trains_p {
- my ( $self, %opt ) = @_;
-
- my $user = $self->current_user;
- my $uid = $opt{uid} //= $user->{id};
- my $use_history = $self->users->use_history( uid => $uid );
-
- my ( $eva, $exclude_via, $exclude_train_id, $exclude_before );
- my $now = $self->now->epoch;
- my ( $stationinfo, $arr_epoch, $arr_platform, $arr_countdown );
-
- my $promise = Mojo::Promise->new;
-
- if ( $user->{backend_dbris} ) {
-
- # We do get a little bit of via information, so this might work in some
- # cases. But not reliably. Probably best to leave it out entirely then.
- return $promise->reject;
- }
- if ( $user->{backend_efa} ) {
-
- # TODO
- return $promise->reject;
- }
- if ( $user->{backend_motis} ) {
-
- # FIXME: The following code can't handle external_ids currently
- return $promise->reject;
- }
-
- if ( $opt{eva} ) {
- if ( $use_history & 0x01 ) {
- $eva = $opt{eva};
- }
- elsif ( $opt{destination_name} ) {
- $eva = $opt{eva};
- }
- if ( not defined $opt{backend_id} ) {
- if ( $opt{hafas} ) {
- $opt{backend_id}
- = $self->stations->get_backend_id( hafas => $opt{hafas} );
- }
- else {
- $opt{backend_id} = $user->{backend_id};
- }
- }
- }
- else {
- if ( $use_history & 0x02 ) {
- my $status = $self->get_user_status;
- $opt{backend_id} = $status->{backend_id};
- $eva = $status->{arr_eva};
- $exclude_via = $status->{dep_name};
- $exclude_train_id = $status->{train_id};
- $arr_platform = $status->{arr_platform};
- $stationinfo = $status->{extra_data}{stationinfo_arr};
- if ( $status->{real_arrival} ) {
- $exclude_before = $arr_epoch = $status->{real_arrival}->epoch;
- $arr_countdown = $status->{arrival_countdown};
- }
- }
- }
-
- $exclude_before //= $now - 300;
-
- if ( not $eva ) {
- return $promise->reject;
- }
-
- $self->log->debug(
- "get_connecting_trains_p(backend_id => $opt{backend_id}, eva => $eva)");
-
- my @destinations = $self->journeys->get_connection_targets(%opt);
-
- @destinations = uniq_by { $_->{name} } @destinations;
-
- if ($exclude_via) {
- @destinations = grep { $_->{name} ne $exclude_via } @destinations;
- }
-
- if ( not @destinations ) {
- return $promise->reject;
- }
-
- $self->log->debug( 'get_connection_targets returned '
- . join( q{, }, map { $_->{name} } @destinations ) );
-
- 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;
- my %via_count = map { $_->{name} => 0 } @destinations;
-
- my $backend
- = $self->stations->get_backend( backend_id => $opt{backend_id} );
- if ( $opt{backend_id} == 0 ) {
- $self->iris->get_departures_p(
- station => $eva,
- lookbehind => 10,
- lookahead => $lookahead,
- with_related => 1
- )->then(
- sub {
- my ($stationboard) = @_;
- if ( $stationboard->{errstr} ) {
- $promise->resolve( [], [] );
- return;
- }
-
- @{ $stationboard->{results} } = map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- map { [ $_, $_->departure ? $_->departure->epoch : 0 ] }
- @{ $stationboard->{results} };
- my @results;
- my @cancellations;
- my $excluded_train;
- for my $train ( @{ $stationboard->{results} } ) {
- if ( not $train->departure ) {
- next;
- }
- if ( $exclude_before
- and $train->departure
- and $train->departure->epoch < $exclude_before )
- {
- next;
- }
- if ( $exclude_train_id
- and $train->train_id eq $exclude_train_id )
- {
- $excluded_train = $train;
- next;
- }
-
- # In general, this function is meant to return feasible
- # connections. However, cancelled connections may also be of
- # interest and are also useful for logging cancellations.
- # To satisfy both demands with (hopefully) little confusion and
- # UI clutter, this function returns two concatenated arrays:
- # actual connections (ordered by actual departure time) followed
- # by cancelled connections (ordered by scheduled departure time).
- # This is easiest to achieve in two separate loops.
- #
- # Note that a cancelled train may still have a matching destination
- # in its route_post, e.g. if it leaves out $eva due to
- # unscheduled route changes but continues on schedule afterwards
- # -- so it is only cancelled at $eva, not on the remainder of
- # the route. Also note that this specific case is not yet handled
- # properly by the cancellation logic etc.
-
- if ( $train->departure_is_cancelled ) {
- my @via = (
- $train->sched_route_post, $train->sched_route_end
- );
- for my $dest (@destinations) {
- if ( has_str_in_list( $dest->{name}, @via ) ) {
- push( @cancellations, [ $train, $dest ] );
- next;
- }
- }
- }
- else {
- my @via = ( $train->route_post, $train->route_end );
- for my $dest (@destinations) {
- if ( $via_count{ $dest->{name} } < 2
- and has_str_in_list( $dest->{name}, @via ) )
- {
- push( @results, [ $train, $dest ] );
-
- # Show all past and up to two future departures per destination
- if ( not $train->departure
- or $train->departure->epoch >= $now )
- {
- $via_count{ $dest->{name} }++;
- }
- next;
- }
- }
- }
- }
-
- @results = map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- map {
- [
- $_,
- $_->[0]->departure->epoch
- // $_->[0]->sched_departure->epoch
- ]
- } @results;
- @cancellations = map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- map { [ $_, $_->[0]->sched_departure->epoch ] }
- @cancellations;
-
- # remove trains whose route matches the excluded one's
- if ($excluded_train) {
- my $route_pre
- = join( '|', reverse $excluded_train->route_pre );
- @results
- = grep { join( '|', $_->[0]->route_post ) ne $route_pre }
- @results;
- my $route_post = join( '|', $excluded_train->route_post );
- @results
- = grep { join( '|', $_->[0]->route_post ) ne $route_post }
- @results;
- }
-
- # add message IDs and 'transfer short' hints
- for my $result (@results) {
- my $train = $result->[0];
- my @message_ids
- = List::Util::uniq map { $_->[1] } $train->raw_messages;
- $train->{message_id} = { map { $_ => 1 } @message_ids };
- my $interchange_duration;
- if ( exists $stationinfo->{i} ) {
- if ( defined $arr_platform
- and defined $train->platform )
- {
- $interchange_duration
- = $stationinfo->{i}{$arr_platform}
- { $train->platform };
- }
- $interchange_duration //= $stationinfo->{i}{"*"};
- }
- if ( defined $interchange_duration ) {
- my $interchange_time
- = ( $train->departure->epoch - $arr_epoch ) / 60;
- if ( $interchange_time < $interchange_duration ) {
- $train->{interchange_text} = 'Anschluss knapp';
- $train->{interchange_icon} = 'directions_run';
- }
- elsif ( $interchange_time == $interchange_duration ) {
- $train->{interchange_text}
- = 'Anschluss könnte knapp werden';
- $train->{interchange_icon} = 'directions_run';
- }
- }
- }
-
- $promise->resolve( [ @results, @cancellations ], [] );
- return;
- }
- )->catch(
- sub {
- $promise->resolve( [], [] );
- return;
- }
- )->wait;
- }
- elsif ( $backend->{dbris} ) {
- return $promise->reject;
- }
- elsif ( $backend->{efa} ) {
- return $promise->reject;
- }
- elsif ( $backend->{hafas} ) {
- my $hafas_service = $backend->{name};
- $self->hafas->get_departures_p(
- service => $hafas_service,
- eva => $eva,
- lookbehind => 10,
- lookahead => $lookahead
- )->then(
- sub {
- my ($status) = @_;
- my @hafas_trains;
- my @all_hafas_trains = $status->results;
- for my $hafas_train (@all_hafas_trains) {
- for my $stop ( $hafas_train->route ) {
- for my $dest (@destinations) {
- if ( $stop->loc->name
- and $stop->loc->name eq $dest->{name}
- and $via_count{ $dest->{name} } < 2
- and $hafas_train->datetime )
- {
- my $departure = $hafas_train->datetime;
- my $arrival = $stop->arr;
- my $delay = $hafas_train->delay;
- if ( $delay
- and $stop->arr == $stop->sched_arr )
- {
- $arrival->add( minutes => $delay );
- }
- if ( $departure->epoch >= $exclude_before ) {
- $via_count{ $dest->{name} }++;
- push(
- @hafas_trains,
- [
- $hafas_train, $dest,
- $arrival, $hafas_service
- ]
- );
- }
- }
- }
- }
- }
- $promise->resolve( [], \@hafas_trains );
- return;
- }
- )->catch(
- sub {
- my ($err) = @_;
- $self->log->debug("get_connection_trains: hafas: $err");
- $promise->resolve( [], [] );
- return;
- }
- )->wait;
- }
-
- return $promise;
-}
-
sub compute_effective_visibility {
my ( $self, $default_visibility, $journey_visibility ) = @_;
if ( $journey_visibility eq 'default' ) {
@@ -381,52 +63,16 @@ sub homepage {
= $self->compute_effective_visibility(
$user->{default_visibility_str},
$status->{visibility_str} );
- if ( defined $status->{arrival_countdown}
- and $status->{arrival_countdown} < ( 40 * 60 ) )
- {
- $self->render_later;
- $self->get_connecting_trains_p->then(
- sub {
- my ( $connections_iris, $connections_hafas ) = @_;
- $self->render(
- 'landingpage',
- user => $user,
- user_status => $status,
- journey_visibility => $journey_visibility,
- connections_iris => $connections_iris,
- connections_hafas => $connections_hafas,
- with_map => 1,
- %{$map_data},
- );
- $self->users->mark_seen( uid => $uid );
- }
- )->catch(
- sub {
- $self->render(
- 'landingpage',
- user => $user,
- user_status => $status,
- journey_visibility => $journey_visibility,
- with_map => 1,
- %{$map_data},
- );
- $self->users->mark_seen( uid => $uid );
- }
- )->wait;
- return;
- }
- else {
- $self->render(
- 'landingpage',
- user => $user,
- user_status => $status,
- journey_visibility => $journey_visibility,
- with_map => 1,
- %{$map_data},
- );
- $self->users->mark_seen( uid => $uid );
- return;
- }
+ $self->render(
+ 'landingpage',
+ user => $user,
+ user_status => $status,
+ journey_visibility => $journey_visibility,
+ with_map => 1,
+ %{$map_data},
+ );
+ $self->users->mark_seen( uid => $uid );
+ return;
}
else {
@recent_targets = uniq_by { $_->{external_id_or_eva} }
@@ -450,12 +96,14 @@ sub homepage {
sub status_card {
my ($self) = @_;
+ my $user = $self->current_user;
my $status = $self->get_user_status;
+ my $uid = $user->{id};
delete $self->stash->{layout};
my @timeline = $self->in_transit->get_timeline(
- uid => $self->current_user->{id},
+ uid => $uid,
short => 1
);
$self->stash( timeline => [@timeline] );
@@ -471,36 +119,8 @@ sub status_card {
}
my $journey_visibility
= $self->compute_effective_visibility(
- $self->current_user->{default_visibility_str},
+ $user->{default_visibility_str},
$status->{visibility_str} );
- if ( defined $status->{arrival_countdown}
- and $status->{arrival_countdown} < ( 40 * 60 ) )
- {
- $self->render_later;
- $self->get_connecting_trains_p->then(
- sub {
- my ( $connections_iris, $connections_hafas ) = @_;
- $self->render(
- '_checked_in',
- journey => $status,
- journey_visibility => $journey_visibility,
- connections_iris => $connections_iris,
- connections_hafas => $connections_hafas,
- %{$map_data},
- );
- }
- )->catch(
- sub {
- $self->render(
- '_checked_in',
- journey => $status,
- journey_visibility => $journey_visibility,
- %{$map_data},
- );
- }
- )->wait;
- return;
- }
$self->render(
'_checked_in',
journey => $status,
@@ -509,50 +129,10 @@ sub status_card {
);
}
elsif ( $status->{cancellation} ) {
- $self->render_later;
- $self->get_connecting_trains_p(
- backend_id => $status->{backend_id},
- eva => $status->{cancellation}{dep_eva},
- destination_name => $status->{cancellation}{arr_name}
- )->then(
- sub {
- my ($connecting_trains) = @_;
- $self->render(
- '_cancelled_departure',
- journey => $status->{cancellation},
- connections_iris => $connecting_trains
- );
- }
- )->catch(
- sub {
- $self->render( '_cancelled_departure',
- journey => $status->{cancellation} );
- }
- )->wait;
- return;
+ $self->render( '_cancelled_departure',
+ journey => $status->{cancellation} );
}
else {
- my @connecting_trains;
- my $now = DateTime->now( time_zone => 'Europe/Berlin' );
- if ( $now->epoch - $status->{timestamp}->epoch < ( 30 * 60 ) ) {
- $self->render_later;
- $self->get_connecting_trains_p->then(
- sub {
- my ( $connections_iris, $connections_hafas ) = @_;
- $self->render(
- '_checked_out',
- journey => $status,
- connections_iris => $connections_iris,
- connections_hafas => $connections_hafas,
- );
- }
- )->catch(
- sub {
- $self->render( '_checked_out', journey => $status );
- }
- )->wait;
- return;
- }
$self->render( '_checked_out', journey => $status );
}
}
@@ -1204,6 +784,8 @@ sub station {
}
my @suggestions;
+ my $use_history = $self->users->use_history( uid => $uid );
+ my $suggestions_enabled = $use_history & 0x01;
my $promise;
if ($dbris_service) {
@@ -1298,6 +880,28 @@ sub station {
sort { $b->[1] <=> $a->[1] }
map { [ $_, $_->dep->epoch ] } $status->results;
+ if ($suggestions_enabled) {
+ my ($eva) = ( $station =~ m{ [@] L = (\d+) }x );
+ my $backend_id
+ = $self->stations->get_backend_id(
+ dbris => $dbris_service );
+
+ my @destinations = $self->journeys->get_connection_targets(
+ uid => $uid,
+ backend_id => $backend_id,
+ eva => $eva
+ );
+
+ @suggestions = $self->dbris->grep_suggestions(
+ status => $status,
+ destinations => \@destinations
+ );
+
+ @suggestions
+ = sort { $a->[0]{sort_ts} <=> $b->[0]{sort_ts} }
+ grep { $_->[0]{sort_ts} >= $now - 300 } @suggestions;
+ }
+
$status = {
station_eva => $station,
related_stations => [],
@@ -1306,37 +910,6 @@ sub station {
if ( $station =~ m{ [@] O = (?<name> [^@]+ ) [@] }x ) {
$status->{station_name} = $+{name};
}
-
- my ($eva) = ( $station =~ m{ [@] L = (\d+) }x );
- my $backend_id
- = $self->stations->get_backend_id( dbris => $dbris_service );
- my @destinations = $self->journeys->get_connection_targets(
- uid => $uid,
- backend_id => $backend_id,
- eva => $eva
- );
-
- for my $dep (@results) {
- destination: for my $dest (@destinations) {
- if ( $dep->destination
- and $dep->destination eq $dest->{name} )
- {
- push( @suggestions, [ $dep, $dest ] );
- next destination;
- }
- for my $via_name ( $dep->via ) {
- if ( $via_name eq $dest->{name} ) {
- push( @suggestions, [ $dep, $dest ] );
- next destination;
- }
- }
- }
- }
-
- @suggestions = map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- grep { $_->[1] >= $now - 300 }
- map { [ $_, $_->[0]->dep->epoch ] } @suggestions;
}
elsif ($hafas_service) {
@@ -1363,34 +936,35 @@ sub station {
@results = map { $_->[0] }
sort { $b->[1] <=> $a->[1] }
map { [ $_, $_->datetime->epoch ] } $status->results;
+
+ if ($suggestions_enabled) {
+ my $backend_id
+ = $self->stations->get_backend_id( efa => $efa_service );
+
+ my @destinations = $self->journeys->get_connection_targets(
+ uid => $uid,
+ backend_id => $backend_id,
+ eva => $status->stop->id_num,
+ );
+
+ @suggestions = $self->efa->grep_suggestions(
+ status => $status,
+ destinations => \@destinations
+ );
+
+ @suggestions
+ = sort { $a->[0]{sort_ts} <=> $b->[0]{sort_ts} }
+ grep {
+ $_->[0]{sort_ts} >= $now - 300
+ and $_->[0]{sort_ts} <= $now + 1800
+ } @suggestions;
+ }
+
$status = {
station_eva => $status->stop->id_num,
station_name => $status->stop->full_name,
related_stations => [],
};
- my $backend_id
- = $self->stations->get_backend_id( efa => $efa_service );
- my @destinations = $self->journeys->get_connection_targets(
- uid => $uid,
- backend_id => $backend_id,
- eva => $status->{station_eva},
- );
- for my $dep (@results) {
- destination: for my $dest (@destinations) {
- for my $stop ( $dep->route_post ) {
- if ( $stop->full_name eq $dest->{name} ) {
- push( @suggestions,
- [ $dep, $dest, $stop->arr ] );
- next destination;
- }
- }
- }
- }
-
- @suggestions = map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- grep { $_->[1] >= $now - 300 and $_->[1] <= $now + 1800 }
- map { [ $_, $_->[0]->datetime->epoch ] } @suggestions;
}
elsif ($motis_service) {
@results = map { $_->[0] }
@@ -1415,6 +989,24 @@ sub station {
map {
[ $_, $_->departure->epoch // $_->sched_departure->epoch ]
} @results;
+
+ if ($suggestions_enabled) {
+ my @destinations = $self->journeys->get_connection_targets(
+ uid => $uid,
+ backend_id => 0,
+ eva => $status->{station_eva},
+ );
+ @suggestions = $self->iris->grep_suggestions(
+ results => \@results,
+ destinations => \@destinations
+ );
+ @suggestions
+ = sort { $a->[0]{sort_ts} <=> $b->[0]{sort_ts} }
+ grep {
+ $_->[0]{sort_ts} >= $now - 300
+ and $_->[0]{sort_ts} <= $now + 1800
+ } @suggestions;
+ }
}
my $user_status = $self->get_user_status;
@@ -1436,7 +1028,6 @@ sub station {
}
}
- my $connections_p;
if ( $trip_id and ( $dbris_service or $hafas_service ) ) {
@results = grep { $_->id eq $trip_id } @results;
}
@@ -1444,95 +1035,25 @@ sub station {
@results
= grep { $_->type . ' ' . $_->train_no eq $train } @results;
}
- else {
- if ( $user_status->{cancellation}
- and $status->{station_eva} eq
- $user_status->{cancellation}{dep_eva} )
- {
- $connections_p = $self->get_connecting_trains_p(
- eva => $user_status->{cancellation}{dep_eva},
- destination_name =>
- $user_status->{cancellation}{arr_name},
- efa => $efa_service,
- hafas => $hafas_service,
- );
- }
- else {
- $connections_p = $self->get_connecting_trains_p(
- eva => $status->{station_eva},
- efa => $efa_service,
- hafas => $hafas_service
- );
- }
- }
- if ($connections_p) {
- $connections_p->then(
- sub {
- my ( $connections_iris, $connections_hafas ) = @_;
- $self->render(
- 'departures',
- user => $user,
- dbris => $dbris_service,
- efa => $efa_service,
- hafas => $hafas_service,
- motis => $motis_service,
- eva => $status->{station_eva},
- datetime => $timestamp,
- now_in_range => $now_within_range,
- results => \@results,
- station => $status->{station_name},
- related_stations => $status->{related_stations},
- user_status => $user_status,
- can_check_out => $can_check_out,
- connections_iris => $connections_iris,
- connections_hafas => $connections_hafas,
- title => "travelynx: $status->{station_name}",
- );
- }
- )->catch(
- sub {
- $self->render(
- 'departures',
- user => $user,
- dbris => $dbris_service,
- efa => $efa_service,
- hafas => $hafas_service,
- motis => $motis_service,
- eva => $status->{station_eva},
- datetime => $timestamp,
- now_in_range => $now_within_range,
- results => \@results,
- station => $status->{station_name},
- related_stations => $status->{related_stations},
- user_status => $user_status,
- can_check_out => $can_check_out,
- suggestions => \@suggestions,
- title => "travelynx: $status->{station_name}",
- );
- }
- )->wait;
- }
- else {
- $self->render(
- 'departures',
- user => $user,
- dbris => $dbris_service,
- efa => $efa_service,
- hafas => $hafas_service,
- motis => $motis_service,
- eva => $status->{station_eva},
- datetime => $timestamp,
- now_in_range => $now_within_range,
- results => \@results,
- station => $status->{station_name},
- related_stations => $status->{related_stations},
- user_status => $user_status,
- can_check_out => $can_check_out,
- suggestions => \@suggestions,
- title => "travelynx: $status->{station_name}",
- );
- }
+ $self->render(
+ 'departures',
+ user => $user,
+ dbris => $dbris_service,
+ efa => $efa_service,
+ hafas => $hafas_service,
+ motis => $motis_service,
+ eva => $status->{station_eva},
+ datetime => $timestamp,
+ now_in_range => $now_within_range,
+ results => \@results,
+ station => $status->{station_name},
+ related_stations => $status->{related_stations},
+ user_status => $user_status,
+ can_check_out => $can_check_out,
+ suggestions => \@suggestions,
+ title => "travelynx: $status->{station_name}",
+ );
}
)->catch(
sub {
@@ -2762,8 +2283,6 @@ sub set_polyline {
my $context = XML::LibXML::XPathContext->new($root);
$context->registerNs( 'gpx', 'http://www.topografix.com/GPX/1/1' );
- use Data::Dumper;
-
my @polyline;
for my $point (
$context->findnodes('/gpx:gpx/gpx:trk/gpx:trkseg/gpx:trkpt') )
diff --git a/lib/Travelynx/Helper/DBRIS.pm b/lib/Travelynx/Helper/DBRIS.pm
index deeed65..edf8812 100644
--- a/lib/Travelynx/Helper/DBRIS.pm
+++ b/lib/Travelynx/Helper/DBRIS.pm
@@ -127,6 +127,39 @@ sub get_departures_p {
);
}
+sub get_connections_p {
+ my ( $self, %opt ) = @_;
+ my $promise = Mojo::Promise->new;
+ my $destinations = $opt{destinations};
+
+ $self->get_departures_p(
+ station => '@L=' . $opt{station},
+ timestamp => $opt{timestamp},
+ lookbehind => 0,
+ lookahead => 60,
+ )->then(
+ sub {
+ my ($status) = @_;
+ my @suggestions = $self->grep_suggestions(
+ status => $status,
+ destinations => $destinations,
+ max_per_dest => 2
+ );
+ @suggestions
+ = sort { $a->[0]{sort_ts} <=> $b->[0]{sort_ts} } @suggestions;
+ $promise->resolve( \@suggestions );
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $promise->reject("get_departures_p($opt{station}): $err");
+ return;
+ }
+ )->wait;
+ return $promise;
+}
+
sub get_journey_p {
my ( $self, %opt ) = @_;
@@ -186,4 +219,65 @@ sub get_wagonorder_p {
);
}
+sub grep_suggestions {
+ my ( $self, %opt ) = @_;
+ my $status = $opt{status};
+ my $destinations = $opt{destinations};
+ my $max_per_dest = $opt{max_per_dest};
+
+ my @suggestions;
+ my %via_count;
+
+ for my $dep ( $status->results ) {
+ my $dep_json = {
+ id => $dep->id,
+ ts => ( $dep->sched_dep // $dep->dep )->epoch,
+ sort_ts => $dep->dep->epoch,
+ is_cancelled => $dep->is_cancelled,
+ stop_eva => $dep->stop_eva,
+ maybe_line_no => $dep->maybe_line_no,
+ sched_hhmm => $dep->sched_dep->strftime('%H:%M'),
+ rt_hhmm => $dep->dep->strftime('%H:%M'),
+ delay => $dep->delay,
+ platform => $dep->platform,
+ type => $dep->type,
+ line => $dep->line,
+ };
+ destination: for my $dest ( @{$destinations} ) {
+ if ( $dep->destination
+ and $dep->destination eq $dest->{name} )
+ {
+ if ( not $dep->is_cancelled ) {
+ $via_count{ $dest->{name} } += 1;
+ }
+ if ( $max_per_dest
+ and $via_count{ $dest->{name} }
+ and $via_count{ $dest->{name} } > $max_per_dest )
+ {
+ next destination;
+ }
+ push( @suggestions, [ $dep_json, $dest ] );
+ next destination;
+ }
+ for my $via_name ( $dep->via ) {
+ if ( $via_name eq $dest->{name} ) {
+ if ( not $dep->is_cancelled ) {
+ $via_count{ $dest->{name} } += 1;
+ }
+ if ( $max_per_dest
+ and $via_count{ $dest->{name} }
+ and $via_count{ $dest->{name} } > $max_per_dest )
+ {
+ next destination;
+ }
+ push( @suggestions, [ $dep_json, $dest ] );
+ next destination;
+ }
+ }
+ }
+ }
+
+ return @suggestions;
+}
+
1;
diff --git a/lib/Travelynx/Helper/EFA.pm b/lib/Travelynx/Helper/EFA.pm
index 5cae51b..70894df 100644
--- a/lib/Travelynx/Helper/EFA.pm
+++ b/lib/Travelynx/Helper/EFA.pm
@@ -48,6 +48,86 @@ sub get_departures_p {
);
}
+sub grep_suggestions {
+ my ( $self, %opt ) = @_;
+ my $status = $opt{status};
+ my $destinations = $opt{destinations};
+ my $max_per_dest = $opt{max_per_dest};
+
+ 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{ $dest->{name} } += 1;
+ }
+ if ( $max_per_dest
+ and $via_count{ $dest->{name} }
+ and $via_count{ $dest->{name} } > $max_per_dest )
+ {
+ next destination;
+ }
+ my $dep_json = {
+ id => $dep->id,
+ ts => ( $dep->sched_datetime // $dep->datetime )->epoch,
+ sort_ts => $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;
+ }
+ }
+ }
+ }
+ return @suggestions;
+}
+
+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 = $self->grep_suggestions(
+ status => $status,
+ destinations => $destinations,
+ max_per_dest => 2
+ );
+ @suggestions
+ = sort { $a->[0]{sort_ts} <=> $b->[0]{sort_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/Helper/IRIS.pm b/lib/Travelynx/Helper/IRIS.pm
index 34739eb..9a5aa87 100644
--- a/lib/Travelynx/Helper/IRIS.pm
+++ b/lib/Travelynx/Helper/IRIS.pm
@@ -201,6 +201,86 @@ sub get_departures_p {
}
}
+sub get_connections_p {
+ my ( $self, %opt ) = @_;
+ my $promise = Mojo::Promise->new;
+ my $destinations = $opt{destinations};
+
+ $self->get_departures_p(
+ station => $opt{station},
+ timestamp => $opt{timestamp},
+ lookbehind => 0,
+ lookahead => 60,
+ with_related => 1,
+ )->then(
+ sub {
+ my ($res) = @_;
+ my @suggestions = $self->grep_suggestions(
+ results => $res->{results},
+ destinations => $destinations,
+ max_per_dest => 2
+ );
+ @suggestions
+ = sort { $a->[0]{sort_ts} <=> $b->[0]{sort_ts} } @suggestions;
+ $promise->resolve( \@suggestions );
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $promise->reject("get_departures_p($opt{station}): $err");
+ return;
+ }
+ )->wait;
+ return $promise;
+}
+
+sub grep_suggestions {
+ my ( $self, %opt ) = @_;
+ my $results = $opt{results};
+ my $destinations = $opt{destinations};
+ my $max_per_dest = $opt{max_per_dest};
+
+ my @suggestions;
+ my %via_count;
+
+ for my $dep ( @{$results} ) {
+ destination: for my $dest ( @{$destinations} ) {
+ for my $via_name ( $dep->route_post ) {
+ if ( $via_name eq $dest->{name} ) {
+ if ( not $dep->departure_is_cancelled ) {
+ $via_count{ $dest->{name} } += 1;
+ }
+ if ( $max_per_dest
+ and $via_count{ $dest->{name} }
+ and $via_count{ $dest->{name} } > $max_per_dest )
+ {
+ next destination;
+ }
+ my $dep_json = {
+ id => $dep->train_id,
+ ts =>
+ ( $dep->sched_departure // $dep->departure )->epoch,
+ sort_ts => $dep->departure->epoch,
+ station_uic => $dep->station_uic,
+ departure_is_cancelled => $dep->departure_is_cancelled,
+ sched_hhmm => $dep->sched_departure->strftime('%H:%M'),
+ rt_hhmm => $dep->departure->strftime('%H:%M'),
+ departure_delay => $dep->departure_delay,
+ platform => $dep->platform,
+ type => $dep->type,
+ line => $dep->line,
+ };
+ push( @suggestions, [ $dep_json, $dest ] );
+ next destination;
+ }
+ }
+ }
+ }
+
+ return @suggestions;
+}
+
sub route_diff {
my ( $self, $train ) = @_;
my @json_route;
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;
}