diff options
Diffstat (limited to 'lib')
| -rwxr-xr-x | lib/Travelynx.pm | 6 | ||||
| -rw-r--r-- | lib/Travelynx/Command/work.pm | 151 | ||||
| -rwxr-xr-x | lib/Travelynx/Controller/Traveling.pm | 681 | ||||
| -rw-r--r-- | lib/Travelynx/Helper/DBRIS.pm | 94 | ||||
| -rw-r--r-- | lib/Travelynx/Helper/EFA.pm | 80 | ||||
| -rw-r--r-- | lib/Travelynx/Helper/IRIS.pm | 80 | ||||
| -rwxr-xr-x | lib/Travelynx/Model/Journeys.pm | 4 |
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; } |
