From de074342de0bdc3604a0610a0c5f9cce5338bb85 Mon Sep 17 00:00:00 2001 From: Birte Kristina Friesel Date: Sun, 24 Sep 2023 18:19:17 +0200 Subject: add support for HAFAS connection suggestions; drop manual destination list Still TODO: handle stations that have several EVAs --- lib/Travelynx/Command/database.pm | 14 ++++ lib/Travelynx/Controller/Account.pm | 30 ++----- lib/Travelynx/Controller/Traveling.pm | 146 ++++++++++++++++------------------ lib/Travelynx/Model/Journeys.pm | 3 +- lib/Travelynx/Model/Users.pm | 27 +------ 5 files changed, 92 insertions(+), 128 deletions(-) (limited to 'lib/Travelynx') diff --git a/lib/Travelynx/Command/database.pm b/lib/Travelynx/Command/database.pm index c6880d0..b9074bc 100644 --- a/lib/Travelynx/Command/database.pm +++ b/lib/Travelynx/Command/database.pm @@ -1915,6 +1915,20 @@ my @migrations = ( } ); }, + + # v49 -> v50 + # travelynx 2.0 introduced proper HAFAS support, so there is no need for + # the 'FYI, here is some hAFAS data' kludge anymore. + sub { + my ($db) = @_; + $db->query( + qq{ + drop view user_transit; + drop table localtransit; + update schema_version set version = 50; + } + ); + }, ); sub sync_stations { diff --git a/lib/Travelynx/Controller/Account.pm b/lib/Travelynx/Controller/Account.pm index 2664329..0d12fb8 100644 --- a/lib/Travelynx/Controller/Account.pm +++ b/lib/Travelynx/Controller/Account.pm @@ -799,11 +799,8 @@ sub profile { sub insight { my ($self) = @_; - my $user = $self->current_user; - my ( $use_history, $destinations ) = $self->users->use_history( - uid => $user->{id}, - with_local_transit => 1 - ); + my $user = $self->current_user; + my $use_history = $self->users->use_history( uid => $user->{id} ); if ( $self->param('action') and $self->param('action') eq 'save' ) { if ( $self->param('on_departure') ) { @@ -820,31 +817,16 @@ sub insight { $use_history &= ~0x02; } - if ( $self->param('local_transit') ) { - $use_history |= 0x04; - } - else { - $use_history &= ~0x04; - } - - if ( $self->param('destinations') ) { - $destinations - = [ split( qr{\r?\n\r?}, $self->param('destinations') ) ]; - } - $self->users->use_history( - uid => $user->{id}, - set => $use_history, - destinations => $destinations + uid => $user->{id}, + set => $use_history ); $self->flash( success => 'use_history' ); $self->redirect_to('account'); } - $self->param( on_departure => $use_history & 0x01 ? 1 : 0 ); - $self->param( on_arrival => $use_history & 0x02 ? 1 : 0 ); - $self->param( local_transit => $use_history & 0x04 ? 1 : 0 ); - $self->param( destinations => join( "\n", @{$destinations} ) ); + $self->param( on_departure => $use_history & 0x01 ? 1 : 0 ); + $self->param( on_arrival => $use_history & 0x02 ? 1 : 0 ); $self->render('use_history'); } diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index 28427ad..35e8222 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -27,11 +27,8 @@ sub has_str_in_list { sub get_connecting_trains_p { my ( $self, %opt ) = @_; - my $uid = $opt{uid} //= $self->current_user->{id}; - my ( $use_history, $lt_stops ) = $self->users->use_history( - uid => $uid, - with_local_transit => 1 - ); + my $uid = $opt{uid} //= $self->current_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; @@ -68,13 +65,14 @@ sub get_connecting_trains_p { return $promise->reject; } - my @destinations = $self->journeys->get_connection_targets(%opt); + my @destinations + = uniq_by { $_->{name} } $self->journeys->get_connection_targets(%opt); if ($exclude_via) { - @destinations = grep { $_ ne $exclude_via } @destinations; + @destinations = grep { $_->{name} ne $exclude_via } @destinations; } - if ( not( @destinations or $use_history & 0x04 and @{$lt_stops} ) ) { + if ( not @destinations ) { return $promise->reject; } @@ -83,8 +81,11 @@ sub get_connecting_trains_p { = $can_check_in ? 40 : ( ( ${arr_countdown} // 0 ) / 60 + 40 ); my $iris_promise = Mojo::Promise->new; + my %via_count = map { $_->{name} => 0 } @destinations; - if (@destinations) { + if ( $eva >= 8000000 + and List::Util::any { $_->{eva} >= 8000000 } @destinations ) + { $self->iris->get_departures_p( station => $eva, lookbehind => 10, @@ -94,7 +95,7 @@ sub get_connecting_trains_p { sub { my ($stationboard) = @_; if ( $stationboard->{errstr} ) { - $iris_promise->reject( $stationboard->{errstr} ); + $iris_promise->resolve( [] ); return; } @@ -105,7 +106,6 @@ sub get_connecting_trains_p { my @results; my @cancellations; my $excluded_train; - my %via_count = map { $_ => 0 } @destinations; for my $train ( @{ $stationboard->{results} } ) { if ( not $train->departure ) { next; @@ -144,7 +144,7 @@ sub get_connecting_trains_p { $train->sched_route_post, $train->sched_route_end ); for my $dest (@destinations) { - if ( has_str_in_list( $dest, @via ) ) { + if ( has_str_in_list( $dest->{name}, @via ) ) { push( @cancellations, [ $train, $dest ] ); next; } @@ -153,8 +153,8 @@ sub get_connecting_trains_p { else { my @via = ( $train->route_post, $train->route_end ); for my $dest (@destinations) { - if ( $via_count{$dest} < 2 - and has_str_in_list( $dest, @via ) ) + if ( $via_count{ $dest->{name} } < 2 + and has_str_in_list( $dest->{name}, @via ) ) { push( @results, [ $train, $dest ] ); @@ -162,7 +162,7 @@ sub get_connecting_trains_p { if ( not $train->departure or $train->departure->epoch >= $now ) { - $via_count{$dest}++; + $via_count{ $dest->{name} }++; } next; } @@ -234,7 +234,7 @@ sub get_connecting_trains_p { } )->catch( sub { - $iris_promise->reject(@_); + $iris_promise->resolve( [] ); return; } )->wait; @@ -266,9 +266,9 @@ sub get_connecting_trains_p { Mojo::Promise->all( $iris_promise, $hafas_promise )->then( sub { my ( $iris, $hafas ) = @_; - my @iris_trains = @{ $iris->[0] }; - my @hafas_trains = @{ $hafas->[0] }; - my @transit_fyi; + my @iris_trains = @{ $iris->[0] }; + my @all_hafas_trains = @{ $hafas->[0] }; + my @hafas_trains; # We've already got a list of connecting trains; this function # only adds further information to them. We ignore errors, as @@ -278,11 +278,12 @@ sub get_connecting_trains_p { if ( $iris_train->[0]->departure_is_cancelled ) { next; } - for my $hafas_train (@hafas_trains) { + for my $hafas_train (@all_hafas_trains) { if ( $hafas_train->number and $hafas_train->number == $iris_train->[0]->train_no ) { + $hafas_train->{iris_seen} = 1; if ( $hafas_train->load and $hafas_train->load->{SECOND} ) { @@ -290,7 +291,8 @@ sub get_connecting_trains_p { } for my $stop ( $hafas_train->route ) { if ( $stop->{name} - and $stop->{name} eq $iris_train->[1] + and $stop->{name} eq + $iris_train->[1]->{name} and $stop->{arr} ) { $iris_train->[2] = $stop->{arr}; @@ -308,39 +310,29 @@ sub get_connecting_trains_p { } } } - if ( $use_history & 0x04 and @{$lt_stops} ) { - my %via_count = map { $_ => 0 } @{$lt_stops}; - for my $hafas_train (@hafas_trains) { - for my $stop ( $hafas_train->route ) { - for my $dest ( @{$lt_stops} ) { - if ( $stop->{name} - and $stop->{name} eq $dest - and $via_count{$dest} < 2 - and $hafas_train->datetime ) + for my $hafas_train (@all_hafas_trains) { + if ( $hafas_train->{iris_seen} ) { + next; + } + for my $stop ( $hafas_train->route ) { + for my $dest (@destinations) { + if ( $stop->{name} + and $stop->{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} ) { - 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}++; - push( - @transit_fyi, - [ - { - line => $hafas_train->line, - departure => $departure, - departure_delay => $delay - }, - $dest, $arrival - ] - ); - } + $arrival->add( minutes => $delay ); + } + if ( $departure->epoch >= $exclude_before ) { + $via_count{ $dest->{name} }++; + push( @hafas_trains, + [ $hafas_train, $dest, $arrival ] ); } } } @@ -353,14 +345,12 @@ sub get_connecting_trains_p { ); } - $promise->resolve( \@iris_trains, \@transit_fyi ); + $promise->resolve( \@iris_trains, \@hafas_trains ); return; } )->catch( sub { my ($err) = @_; - - # TODO logging. HAFAS errors should never happen, IRIS errors are noteworthy too. $promise->reject($err); return; } @@ -401,13 +391,13 @@ sub homepage { $self->render_later; $self->get_connecting_trains_p->then( sub { - my ( $connecting_trains, $transit_fyi ) = @_; + my ( $connections_iris, $connections_hafas ) = @_; $self->render( 'landingpage', user_status => $status, journey_visibility => $journey_visibility, - connections => $connecting_trains, - transit_fyi => $transit_fyi, + connections_iris => $connections_iris, + connections_hafas => $connections_hafas, ); $self->users->mark_seen( uid => $uid ); } @@ -474,13 +464,13 @@ sub status_card { $self->render_later; $self->get_connecting_trains_p->then( sub { - my ( $connecting_trains, $transit_fyi ) = @_; + my ( $connections_iris, $connections_hafas ) = @_; $self->render( '_checked_in', journey => $status, journey_visibility => $journey_visibility, - connections => $connecting_trains, - transit_fyi => $transit_fyi + connections_iris => $connections_iris, + connections_hafas => $connections_hafas, ); } )->catch( @@ -510,8 +500,8 @@ sub status_card { my ($connecting_trains) = @_; $self->render( '_cancelled_departure', - journey => $status->{cancellation}, - connections => $connecting_trains + journey => $status->{cancellation}, + connections_iris => $connecting_trains ); } )->catch( @@ -529,11 +519,12 @@ sub status_card { $self->render_later; $self->get_connecting_trains_p->then( sub { - my ($connecting_trains) = @_; + my ( $connections_iris, $connections_hafas ) = @_; $self->render( '_checked_out', - journey => $status, - connections => $connecting_trains + journey => $status, + connections_iris => $connections_iris, + connections_hafas => $connections_hafas, ); } )->catch( @@ -1028,18 +1019,19 @@ sub station { if ($connections_p) { $connections_p->then( sub { - my ($connecting_trains) = @_; + my ( $connections_iris, $connections_hafas ) = @_; $self->render( 'departures', - eva => $status->{station_eva}, - results => \@results, - hafas => $use_hafas, - station => $status->{station_name}, - related_stations => $status->{related_stations}, - user_status => $user_status, - can_check_out => $can_check_out, - connections => $connecting_trains, - api_link => $api_link, + eva => $status->{station_eva}, + results => \@results, + hafas => $use_hafas, + 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, + api_link => $api_link, title => "travelynx: $status->{station_name}", ); } diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm index 1c975f4..3fa2d96 100755 --- a/lib/Travelynx/Model/Journeys.pm +++ b/lib/Travelynx/Model/Journeys.pm @@ -1726,7 +1726,7 @@ sub get_connection_targets { my $min_count = $opt{min_count} // 3; if ( $opt{destination_name} ) { - return ( $opt{destination_name} ); + return ( { eva => $opt{eva}, name => $opt{destination_name} } ); } my $dest_id = $opt{eva} // $self->get_latest_dest_id(%opt); @@ -1755,7 +1755,6 @@ sub get_connection_targets { = $res->hashes->grep( sub { shift->{count} >= $min_count } ) ->map( sub { shift->{dest} } )->each; @destinations = $self->{stations}->get_by_evas(@destinations); - @destinations = map { $_->{name} } @destinations; return @destinations; } diff --git a/lib/Travelynx/Model/Users.pm b/lib/Travelynx/Model/Users.pm index 4b108d4..4602fa2 100644 --- a/lib/Travelynx/Model/Users.pm +++ b/lib/Travelynx/Model/Users.pm @@ -567,7 +567,6 @@ sub delete { $res{transit} = $db->delete( 'in_transit', { user_id => $uid } ); $res{hooks} = $db->delete( 'webhooks', { user_id => $uid } ); $res{trwl} = $db->delete( 'traewelling', { user_id => $uid } ); - $res{lt} = $db->delete( 'localtransit', { user_id => $uid } ); $res{password} = $db->delete( 'pending_passwords', { user_id => $uid } ); $res{relations} = $db->delete( 'relations', [ { subject_id => $uid }, { object_id => $uid } ] ); @@ -651,34 +650,12 @@ sub use_history { my $uid = $opt{uid}; my $value = $opt{set}; - if ( $opt{destinations} ) { - $db->insert( - 'localtransit', - { - user_id => $uid, - data => - JSON->new->encode( { destinations => $opt{destinations} } ) - }, - { on_conflict => \'(user_id) do update set data = EXCLUDED.data' } - ); - } - if ($value) { $db->update( 'users', { use_history => $value }, { id => $uid } ); } else { - if ( $opt{with_local_transit} ) { - my $res = $db->select( - 'user_transit', - [ 'use_history', 'data' ], - { id => $uid } - )->expand->hash; - return ( $res->{use_history}, $res->{data}{destinations} // [] ); - } - else { - return $db->select( 'users', ['use_history'], { id => $uid } ) - ->hash->{use_history}; - } + return $db->select( 'users', ['use_history'], { id => $uid } ) + ->hash->{use_history}; } } -- cgit v1.2.3