optionally show local transit connections as well
This commit is contained in:
parent
1c7779e94e
commit
e54130ad6e
9 changed files with 292 additions and 126 deletions
|
@ -1083,6 +1083,29 @@ my @migrations = (
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# v25 -> v26
|
||||||
|
# travelynx 1.24 adds local transit connections and needs to know targets
|
||||||
|
# for that to work, as local transit does not support checkins yet.
|
||||||
|
sub {
|
||||||
|
my ($db) = @_;
|
||||||
|
$db->query(
|
||||||
|
qq{
|
||||||
|
create table localtransit (
|
||||||
|
user_id integer not null references users (id) primary key,
|
||||||
|
data jsonb
|
||||||
|
);
|
||||||
|
create view user_transit as select
|
||||||
|
id,
|
||||||
|
use_history,
|
||||||
|
localtransit.data as data
|
||||||
|
from users
|
||||||
|
left join localtransit on localtransit.user_id = id
|
||||||
|
;
|
||||||
|
update schema_version set version = 26;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
sub setup_db {
|
sub setup_db {
|
||||||
|
|
|
@ -149,6 +149,7 @@ sub run {
|
||||||
my $transit_res = $db->delete( 'in_transit', { user_id => $uid } );
|
my $transit_res = $db->delete( 'in_transit', { user_id => $uid } );
|
||||||
my $hooks_res = $db->delete( 'webhooks', { user_id => $uid } );
|
my $hooks_res = $db->delete( 'webhooks', { user_id => $uid } );
|
||||||
my $trwl_res = $db->delete( 'traewelling', { user_id => $uid } );
|
my $trwl_res = $db->delete( 'traewelling', { user_id => $uid } );
|
||||||
|
my $lt_res = $db->delete( 'localtransit', { user_id => $uid } );
|
||||||
my $password_res
|
my $password_res
|
||||||
= $db->delete( 'pending_passwords', { user_id => $uid } );
|
= $db->delete( 'pending_passwords', { user_id => $uid } );
|
||||||
my $user_res = $db->delete( 'users', { id => $uid } );
|
my $user_res = $db->delete( 'users', { id => $uid } );
|
||||||
|
|
|
@ -499,7 +499,10 @@ sub insight {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
my $user = $self->current_user;
|
my $user = $self->current_user;
|
||||||
my $use_history = $self->users->use_history( uid => $user->{id} );
|
my ( $use_history, $destinations ) = $self->users->use_history(
|
||||||
|
uid => $user->{id},
|
||||||
|
with_local_transit => 1
|
||||||
|
);
|
||||||
|
|
||||||
if ( $self->param('action') and $self->param('action') eq 'save' ) {
|
if ( $self->param('action') and $self->param('action') eq 'save' ) {
|
||||||
if ( $self->param('on_departure') ) {
|
if ( $self->param('on_departure') ) {
|
||||||
|
@ -516,9 +519,22 @@ sub insight {
|
||||||
$use_history &= ~0x02;
|
$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(
|
$self->users->use_history(
|
||||||
uid => $user->{id},
|
uid => $user->{id},
|
||||||
set => $use_history
|
set => $use_history,
|
||||||
|
destinations => $destinations
|
||||||
);
|
);
|
||||||
$self->flash( success => 'use_history' );
|
$self->flash( success => 'use_history' );
|
||||||
$self->redirect_to('account');
|
$self->redirect_to('account');
|
||||||
|
@ -526,6 +542,8 @@ sub insight {
|
||||||
|
|
||||||
$self->param( on_departure => $use_history & 0x01 ? 1 : 0 );
|
$self->param( on_departure => $use_history & 0x01 ? 1 : 0 );
|
||||||
$self->param( on_arrival => $use_history & 0x02 ? 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->render('use_history');
|
$self->render('use_history');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,10 @@ sub get_connecting_trains_p {
|
||||||
my ( $self, %opt ) = @_;
|
my ( $self, %opt ) = @_;
|
||||||
|
|
||||||
my $uid = $opt{uid} //= $self->current_user->{id};
|
my $uid = $opt{uid} //= $self->current_user->{id};
|
||||||
my $use_history = $self->users->use_history( uid => $uid );
|
my ( $use_history, $lt_stops ) = $self->users->use_history(
|
||||||
|
uid => $uid,
|
||||||
|
with_local_transit => 1
|
||||||
|
);
|
||||||
|
|
||||||
my ( $eva, $exclude_via, $exclude_train_id, $exclude_before );
|
my ( $eva, $exclude_via, $exclude_train_id, $exclude_before );
|
||||||
my $now = $self->now->epoch;
|
my $now = $self->now->epoch;
|
||||||
|
@ -72,7 +75,7 @@ sub get_connecting_trains_p {
|
||||||
@destinations = grep { $_ ne $exclude_via } @destinations;
|
@destinations = grep { $_ ne $exclude_via } @destinations;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( not @destinations ) {
|
if ( not( @destinations or $use_history & 0x04 and @{$lt_stops} ) ) {
|
||||||
return $promise->reject;
|
return $promise->reject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +85,7 @@ sub get_connecting_trains_p {
|
||||||
|
|
||||||
my $iris_promise = Mojo::Promise->new;
|
my $iris_promise = Mojo::Promise->new;
|
||||||
|
|
||||||
|
if (@destinations) {
|
||||||
$self->iris->get_departures_p(
|
$self->iris->get_departures_p(
|
||||||
station => $eva,
|
station => $eva,
|
||||||
lookbehind => 10,
|
lookbehind => 10,
|
||||||
|
@ -137,8 +141,9 @@ sub get_connecting_trains_p {
|
||||||
# properly by the cancellation logic etc.
|
# properly by the cancellation logic etc.
|
||||||
|
|
||||||
if ( $train->departure_is_cancelled ) {
|
if ( $train->departure_is_cancelled ) {
|
||||||
my @via
|
my @via = (
|
||||||
= ( $train->sched_route_post, $train->sched_route_end );
|
$train->sched_route_post, $train->sched_route_end
|
||||||
|
);
|
||||||
for my $dest (@destinations) {
|
for my $dest (@destinations) {
|
||||||
if ( has_str_in_list( $dest, @via ) ) {
|
if ( has_str_in_list( $dest, @via ) ) {
|
||||||
push( @cancellations, [ $train, $dest ] );
|
push( @cancellations, [ $train, $dest ] );
|
||||||
|
@ -177,11 +182,13 @@ sub get_connecting_trains_p {
|
||||||
} @results;
|
} @results;
|
||||||
@cancellations = map { $_->[0] }
|
@cancellations = map { $_->[0] }
|
||||||
sort { $a->[1] <=> $b->[1] }
|
sort { $a->[1] <=> $b->[1] }
|
||||||
map { [ $_, $_->[0]->sched_departure->epoch ] } @cancellations;
|
map { [ $_, $_->[0]->sched_departure->epoch ] }
|
||||||
|
@cancellations;
|
||||||
|
|
||||||
# remove trains whose route matches the excluded one's
|
# remove trains whose route matches the excluded one's
|
||||||
if ($excluded_train) {
|
if ($excluded_train) {
|
||||||
my $route_pre = join( '|', reverse $excluded_train->route_pre );
|
my $route_pre
|
||||||
|
= join( '|', reverse $excluded_train->route_pre );
|
||||||
@results
|
@results
|
||||||
= grep { join( '|', $_->[0]->route_post ) ne $route_pre }
|
= grep { join( '|', $_->[0]->route_post ) ne $route_pre }
|
||||||
@results;
|
@results;
|
||||||
|
@ -200,7 +207,8 @@ sub get_connecting_trains_p {
|
||||||
my $interchange_duration;
|
my $interchange_duration;
|
||||||
if ( exists $stationinfo->{i} ) {
|
if ( exists $stationinfo->{i} ) {
|
||||||
$interchange_duration
|
$interchange_duration
|
||||||
= $stationinfo->{i}{$arr_platform}{ $train->platform };
|
= $stationinfo->{i}{$arr_platform}
|
||||||
|
{ $train->platform };
|
||||||
$interchange_duration //= $stationinfo->{i}{"*"};
|
$interchange_duration //= $stationinfo->{i}{"*"};
|
||||||
}
|
}
|
||||||
if ( defined $interchange_duration ) {
|
if ( defined $interchange_duration ) {
|
||||||
|
@ -227,6 +235,10 @@ sub get_connecting_trains_p {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
)->wait;
|
)->wait;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$iris_promise->resolve( [] );
|
||||||
|
}
|
||||||
|
|
||||||
my $hafas_promise = Mojo::Promise->new;
|
my $hafas_promise = Mojo::Promise->new;
|
||||||
my $rest_api = $self->config->{backend}{hafas_rest_api};
|
my $rest_api = $self->config->{backend}{hafas_rest_api};
|
||||||
|
@ -254,6 +266,7 @@ sub get_connecting_trains_p {
|
||||||
my ( $iris, $hafas ) = @_;
|
my ( $iris, $hafas ) = @_;
|
||||||
my @iris_trains = @{ $iris->[0] };
|
my @iris_trains = @{ $iris->[0] };
|
||||||
my @hafas_trains = @{ $hafas->[0] };
|
my @hafas_trains = @{ $hafas->[0] };
|
||||||
|
my @transit_fyi;
|
||||||
|
|
||||||
my $strp = DateTime::Format::Strptime->new(
|
my $strp = DateTime::Format::Strptime->new(
|
||||||
pattern => '%Y-%m-%dT%H:%M:%S%z',
|
pattern => '%Y-%m-%dT%H:%M:%S%z',
|
||||||
|
@ -296,6 +309,44 @@ 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->{nextStopovers} // [] } )
|
||||||
|
{
|
||||||
|
for my $dest ( @{$lt_stops} ) {
|
||||||
|
if ( $stop->{stop}{name}
|
||||||
|
and $stop->{stop}{name} eq $dest
|
||||||
|
and $via_count{$dest} < 2
|
||||||
|
and $hafas_train->{when} )
|
||||||
|
{
|
||||||
|
my $departure = $strp->parse_datetime(
|
||||||
|
$hafas_train->{when} );
|
||||||
|
my $arrival
|
||||||
|
= $strp->parse_datetime(
|
||||||
|
$stop->{arrival} );
|
||||||
|
if ( $departure->epoch >= $exclude_before )
|
||||||
|
{
|
||||||
|
$via_count{$dest}++;
|
||||||
|
push(
|
||||||
|
@transit_fyi,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
line =>
|
||||||
|
$hafas_train->{line}
|
||||||
|
{name},
|
||||||
|
departure => $departure,
|
||||||
|
},
|
||||||
|
$dest, $arrival
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->app->log->error(
|
$self->app->log->error(
|
||||||
|
@ -303,7 +354,7 @@ sub get_connecting_trains_p {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$promise->resolve( \@iris_trains );
|
$promise->resolve( \@iris_trains, \@transit_fyi );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
)->catch(
|
)->catch(
|
||||||
|
|
|
@ -9,6 +9,7 @@ use warnings;
|
||||||
use 5.020;
|
use 5.020;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use JSON;
|
||||||
|
|
||||||
my @sb_templates = (
|
my @sb_templates = (
|
||||||
undef,
|
undef,
|
||||||
|
@ -483,14 +484,36 @@ sub use_history {
|
||||||
my $uid = $opt{uid};
|
my $uid = $opt{uid};
|
||||||
my $value = $opt{set};
|
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) {
|
if ($value) {
|
||||||
$db->update( 'users', { use_history => $value }, { id => $uid } );
|
$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 {
|
else {
|
||||||
return $db->select( 'users', ['use_history'], { id => $uid } )
|
return $db->select( 'users', ['use_history'], { id => $uid } )
|
||||||
->hash->{use_history};
|
->hash->{use_history};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub use_external_services {
|
sub use_external_services {
|
||||||
my ( $self, %opt ) = @_;
|
my ( $self, %opt ) = @_;
|
||||||
|
|
|
@ -200,6 +200,13 @@
|
||||||
% }
|
% }
|
||||||
%= include '_connections', connections => \@connections, checkin_from => $journey->{arrival_countdown} < 0 ? $journey->{arr_ds100} : undef;
|
%= include '_connections', connections => \@connections, checkin_from => $journey->{arrival_countdown} < 0 ? $journey->{arr_ds100} : undef;
|
||||||
% }
|
% }
|
||||||
|
% if (my @transit_fyi = @{stash('transit_fyi') // []}) {
|
||||||
|
<span class="card-title" style="margin-top: 2ex;">Nahverkehr</span>
|
||||||
|
% if ($journey->{arrival_countdown} < 0) {
|
||||||
|
<p>Nur zur Information – kein Checkin möglich.</p>
|
||||||
|
% }
|
||||||
|
%= include '_transit_fyi', transit_fyi => \@transit_fyi;
|
||||||
|
% }
|
||||||
% if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) {
|
% if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) {
|
||||||
<p style="margin-top: 2ex;">
|
<p style="margin-top: 2ex;">
|
||||||
Der automatische Checkout erfolgt wegen gelegentlich veralteter
|
Der automatische Checkout erfolgt wegen gelegentlich veralteter
|
||||||
|
|
19
templates/_transit_fyi.html.ep
Normal file
19
templates/_transit_fyi.html.ep
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<table class="striped"><tbody>
|
||||||
|
% for my $res (@{$transit_fyi}) {
|
||||||
|
% my ($info, $via, $via_arr) = @{$res};
|
||||||
|
% $via_arr = $via_arr ? $via_arr->strftime('%H:%M') : q{};
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
%= $info->{line}
|
||||||
|
<br/>
|
||||||
|
%= $info->{departure}->strftime('%H:%M')
|
||||||
|
% if ($info->{departure_delay}) {
|
||||||
|
%= sprintf('(%+d)', $info->{departure_delay})
|
||||||
|
% }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= $via %><br/><%= $via_arr %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
% }
|
||||||
|
</tbody></table>
|
|
@ -61,7 +61,7 @@
|
||||||
<th scope="row">Verbindungen</th>
|
<th scope="row">Verbindungen</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="/account/insight"><i class="material-icons">edit</i></a>
|
<a href="/account/insight"><i class="material-icons">edit</i></a>
|
||||||
% if ($use_history & 0x03) {
|
% if ($use_history & 0x07) {
|
||||||
Vorschläge aktiv
|
Vorschläge aktiv
|
||||||
% }
|
% }
|
||||||
% else {
|
% else {
|
||||||
|
|
|
@ -47,6 +47,30 @@
|
||||||
ohne Umweg über die Abfahrtstafel möglich.
|
ohne Umweg über die Abfahrtstafel möglich.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<label>
|
||||||
|
%= check_box local_transit => 1
|
||||||
|
<span>Nahverkehr</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
Zeige beim Reisestatus zusätzlich Anschlussmöglichkeiten an den
|
||||||
|
Nahverkehr. Diese dienen lediglich zur Information; ein Checkin ist
|
||||||
|
nicht möglich. Es werden nur Anschlussmöglichkeiten zu Zielen
|
||||||
|
angezeigt, die im folgenden Feld gelistet sind (ein Ziel pro
|
||||||
|
Zeile, z.B. „Eichlinghofen H-Bahn, Dortmund“). Falls travelynx in
|
||||||
|
Zukunft eine Möglichkeit für Checkins in Nahverkehrsmittel erhält,
|
||||||
|
wird diese Liste ggf. gelöscht.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
%= text_area 'destinations', id => 'destinations', class => 'materialize-textarea'
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s3 m3 l3">
|
<div class="col s3 m3 l3">
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue