summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/Travelynx.pm6
-rwxr-xr-xlib/Travelynx/Controller/Traveling.pm581
2 files changed, 59 insertions, 528 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/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm
index 30c579e..02559e8 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 );
}
}
@@ -1415,6 +995,28 @@ sub station {
map {
[ $_, $_->departure->epoch // $_->sched_departure->epoch ]
} @results;
+
+ my @destinations = $self->journeys->get_connection_targets(
+ uid => $uid,
+ backend_id => 0,
+ eva => $status->{station_eva},
+ );
+
+ for my $dep (@results) {
+ destination: for my $dest (@destinations) {
+ for my $via_name ( $dep->route_post ) {
+ 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]->departure->epoch ] } @suggestions;
}
my $user_status = $self->get_user_status;
@@ -1436,7 +1038,6 @@ sub station {
}
}
- my $connections_p;
if ( $trip_id and ( $dbris_service or $hafas_service ) ) {
@results = grep { $_->id eq $trip_id } @results;
}
@@ -1444,95 +1045,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 {