summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2019-05-19 08:55:23 +0200
committerDaniel Friesel <derf@finalrewind.org>2019-05-19 08:55:23 +0200
commit7960114f71720f2c2fa86e74be4b80812edaef36 (patch)
tree82bdafef01c30b3ae3406a1c62e0d827a311c582
parent7486920a6a40d706bb8c9e99ba129dbe3f89bff7 (diff)
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.
-rwxr-xr-xlib/Travelynx.pm111
-rw-r--r--templates/_checked_in.html.ep35
2 files changed, 145 insertions, 1 deletions
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm
index 8b8623d..9e00d3f 100755
--- a/lib/Travelynx.pm
+++ b/lib/Travelynx.pm
@@ -1483,6 +1483,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 @@
</ul>
</p>
% }
+ % if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} < (20*60)) {
+ % if (my @connections = get_connecting_trains()) {
+ <span class="card-title" style="margin-top: 2ex;">Verbindungen</span>
+ <div class="hide-on-med-and-up"><table><tbody>
+ % for my $res (@connections) {
+ % my ($train, $via) = @{$res};
+ <tr>
+ <td><%= $train->line %></td>
+ <td><%= $via %></td>
+ <td><%= $train->departure->strftime('%H:%M') %>
+ % if ($train->departure_delay) {
+ %= sprintf('(%+d)', $train->departure_delay)
+ % }
+ <br/>Gleis <%= $train->platform %></td>
+ </tr>
+ % }
+ </tbody></table></div>
+ <div class="hide-on-small-only"><table><tbody>
+ % for my $res (@connections) {
+ % my ($train, $via) = @{$res};
+ <tr>
+ <td><%= $train->line %></td>
+ <td><%= $via %></td>
+ <td><%= $train->departure->strftime('%H:%M') %>
+ % if ($train->departure_delay) {
+ %= sprintf('(%+d)', $train->departure_delay)
+ % }
+ </td><td>Gleis <%= $train->platform %></td>
+ </tr>
+ % }
+ </tbody></table></div>
+ % }
+ % }
% if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) {
- <p>
+ <p style="margin-top: 2ex;">
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.