From 7960114f71720f2c2fa86e74be4b80812edaef36 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 19 May 2019 08:55:23 +0200 Subject: [PATCH] Work in progress: show connections when arriving soon At the moment, the heuristic used to determine connection targets is quite simple: $station is a target iff there were at least two trips in the past 6 weeks with checkin at the current destination station and checkout at $station. Todo / enhanhement options: * Consider current origin station as well, i.e.: $station is a target iff there were at least two trips in the past 6 weeks which are preceded by a trip from the current origin station and (same as above) * Make connection links clickable once the current journey has ended. Connections need to be added to _checked_out as well for this to work. --- lib/Travelynx.pm | 111 ++++++++++++++++++++++++++++++++++ templates/_checked_in.html.ep | 35 ++++++++++- 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 8b8623d..9e00d3f 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -1482,6 +1482,117 @@ sub startup { } ); + $self->helper( + 'get_connection_targets' => sub { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid} // $self->current_user->{id}; + my $threshold = $opt{threshold} + // DateTime->now( time_zone => 'Europe/Berlin' ) + ->subtract( weeks => 60 ); + my $db = $opt{db} // $self->pg->db; + + my $journey = $db->select( 'in_transit', ['checkout_station_id'], + { user_id => $uid } )->hash; + if ( not $journey ) { + $journey = $db->select( + 'journeys', + ['checkout_station_id'], + { + user_id => $uid, + cancelled => 0 + }, + { + limit => 1, + order_by => { -desc => 'real_dep_ts' } + } + )->hash; + } + + if ( not $journey ) { + return; + } + + my $res = $db->query( + qq{ + select + count(stations.name) as count, + stations.name as dest + from journeys + left outer join stations on checkout_station_id = stations.id + where user_id = ? + and checkin_station_id = ? + and real_departure > ? + group by stations.name + order by count desc; + }, + $uid, + $journey->{checkout_station_id}, + $threshold + ); + my @destinations = $res->hashes->grep( sub { shift->{count} > 2 } ) + ->map( sub { shift->{dest} } )->each; + return @destinations; + } + ); + + $self->helper( + 'get_connecting_trains' => sub { + my ( $self, %opt ) = @_; + + my $status = $self->get_user_status; + + if ( not $status->{arr_ds100} ) { + return; + } + + my @destinations = $self->get_connection_targets(%opt); + my $stationboard + = $self->get_departures( $status->{arr_ds100}, 0, 60 ); + + @destinations = grep { $_ ne $status->{dep_name} } @destinations; + + if ( $stationboard->{errstr} ) { + return; + } + my @results; + my %via_count = map { $_ => 0 } @destinations; + for my $train ( @{ $stationboard->{results} } ) { + if ( not $train->departure ) { + next; + } + if ( $train->departure->epoch < $status->{real_arrival}->epoch ) + { + next; + } + if ( $train->train_id eq $status->{train_id} ) { + next; + } + my @via = ( $train->route_post, $train->route_end ); + for my $dest (@destinations) { + if ( $via_count{$dest} < 3 + and List::Util::any { $_ eq $dest } @via ) + { + push( @results, [ $train, $dest ] ); + $via_count{$dest}++; + next; + } + } + } + + @results = map { $_->[0] } + sort { $a->[1] <=> $b->[1] } + map { + [ + $_, + $_->[0]->departure->epoch // $_->[0]->sched_departur->epoch + ] + } @results; + + return @results; + } + ); + $self->helper( 'get_user_travels' => sub { my ( $self, %opt ) = @_; diff --git a/templates/_checked_in.html.ep b/templates/_checked_in.html.ep index 48e866c..39bc1e3 100644 --- a/templates/_checked_in.html.ep +++ b/templates/_checked_in.html.ep @@ -77,8 +77,41 @@

% } + % if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} < (20*60)) { + % if (my @connections = get_connecting_trains()) { + Verbindungen +
+ % for my $res (@connections) { + % my ($train, $via) = @{$res}; + + + + + + % } +
<%= $train->line %><%= $via %><%= $train->departure->strftime('%H:%M') %> + % if ($train->departure_delay) { + %= sprintf('(%+d)', $train->departure_delay) + % } +
Gleis <%= $train->platform %>
+
+ % for my $res (@connections) { + % my ($train, $via) = @{$res}; + + + + + + % } +
<%= $train->line %><%= $via %><%= $train->departure->strftime('%H:%M') %> + % if ($train->departure_delay) { + %= sprintf('(%+d)', $train->departure_delay) + % } + Gleis <%= $train->platform %>
+ % } + % } % if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) { -

+

Der automatische Checkout erfolgt in wenigen Minuten. Zum Umsteigen: Aktuelle Station erneut in der Liste auswählen. Zum Weiterfahren im aktuellen Zug: Neues Ziel wählen.