Commit 7960114f authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

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.
parent 7486920a
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -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 ) = @_;
+34 −1
Original line number Diff line number Diff line
@@ -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.