diff options
author | Daniel Friesel <derf@finalrewind.org> | 2019-05-19 08:55:23 +0200 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2019-05-19 08:55:23 +0200 |
commit | 7960114f71720f2c2fa86e74be4b80812edaef36 (patch) | |
tree | 82bdafef01c30b3ae3406a1c62e0d827a311c582 | |
parent | 7486920a6a40d706bb8c9e99ba129dbe3f89bff7 (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-x | lib/Travelynx.pm | 111 | ||||
-rw-r--r-- | templates/_checked_in.html.ep | 35 |
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. |