Unverified Commit 3a955c01 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

EFA: checkin support

worker support and cancellations are still missing
parent 19dea1ad
Loading
Loading
Loading
Loading
+141 −5
Original line number Diff line number Diff line
@@ -507,15 +507,18 @@ sub startup {
				return Mojo::Promise->reject('You are already checked in');
			}

			if ( $opt{motis} ) {
				return $self->_checkin_motis_p(%opt);
			}
			if ( $opt{dbris} ) {
				return $self->_checkin_dbris_p(%opt);
			}
			if ( $opt{efa} ) {
				return $self->_checkin_efa_p(%opt);
			}
			if ( $opt{hafas} ) {
				return $self->_checkin_hafas_p(%opt);
			}
			if ( $opt{motis} ) {
				return $self->_checkin_motis_p(%opt);
			}

			my $promise = Mojo::Promise->new;

@@ -885,6 +888,136 @@ sub startup {
		}
	);

	$self->helper(
		'_checkin_efa_p' => sub {
			my ( $self, %opt ) = @_;
			my $station = $opt{station};
			my $trip_id = $opt{train_id};
			my $ts      = $opt{ts};
			my $uid     = $opt{uid} // $self->current_user->{id};
			my $db      = $opt{db}  // $self->pg->db;

			my $promise = Mojo::Promise->new;
			$self->efa->get_journey_p(
				service => $opt{efa},
				trip_id => $trip_id
			)->then(
				sub {
					my ($journey) = @_;

					my $found;
					for my $stop ( $journey->route ) {
						if ( $stop->id_num == $station ) {
							$found = $stop;

							# Lines may serve the same stop several times.
							# Keep looking until the scheduled departure
							# matches the one passed while checking in.
							if ( $ts and $stop->sched_dep->epoch == $ts ) {
								last;
							}
						}
					}
					if ( not $found ) {
						$promise->reject(
"Did not find stop '$station' within journey '$trip_id'"
						);
						return;
					}

					for my $stop ( $journey->route ) {
						$self->stations->add_or_update(
							stop => $stop,
							db   => $db,
							efa  => $opt{efa},
						);
					}

					eval {
						$self->in_transit->add(
							uid        => $uid,
							db         => $db,
							journey    => $journey,
							stop       => $found,
							backend_id => $self->stations->get_backend_id(
								efa => $opt{efa}
							),
						);
					};
					if ($@) {
						$self->app->log->error(
							"Checkin($uid): INSERT failed: $@");
						$promise->reject( 'INSERT failed: ' . $@ );
						return;
					}

					my $polyline;
					if ( $journey->polyline ) {
						my @station_list;
						my @coordinate_list;
						for my $coord ( $journey->polyline ) {
							if ( $coord->{stop} ) {
								push(
									@coordinate_list,
									[
										$coord->{lon}, $coord->{lat},
										$coord->{stop}->id_num
									]
								);
								push( @station_list,
									$coord->{stop}->full_name );
							}
							else {
								push( @coordinate_list,
									[ $coord->{lon}, $coord->{lat} ] );
							}
						}

						# equal length → polyline only consists of straight
						# lines between stops. that's not helpful.
						if ( @station_list == @coordinate_list ) {
							$self->log->debug( 'Ignoring polyline for '
								  . $journey->line
								  . ' as it only consists of straight lines between stops.'
							);
						}
						else {
							$polyline = {
								from_eva => ( $journey->route )[0]->id_num,
								to_eva   => ( $journey->route )[-1]->id_num,
								coords   => \@coordinate_list,
							};
						}
					}

					if ($polyline) {
						$self->in_transit->set_polyline(
							uid      => $uid,
							db       => $db,
							polyline => $polyline,
						);
					}

					# mustn't be called during a transaction
					if ( not $opt{in_transaction} ) {
						$self->run_hook( $uid, 'checkin' );
					}

					$promise->resolve($journey);

					return;
				}
			)->catch(
				sub {
					my ($err) = @_;
					$promise->reject($err);
					return;
				}
			)->wait;
			return $promise;
		}
	);

	$self->helper(
		'_checkin_hafas_p' => sub {
			my ( $self, %opt ) = @_;
@@ -894,7 +1027,6 @@ sub startup {
			my $ts       = $opt{ts};
			my $uid      = $opt{uid} // $self->current_user->{id};
			my $db       = $opt{db}  // $self->pg->db;
			my $hafas;

			my $promise = Mojo::Promise->new;

@@ -1153,7 +1285,11 @@ sub startup {
				return $promise->resolve( 0, 'race condition' );
			}

			if ( $user->{is_dbris} or $user->{is_hafas} or $user->{is_motis} ) {
			if (   $user->{is_dbris}
				or $user->{is_efa}
				or $user->{is_hafas}
				or $user->{is_motis} )
			{
				return $self->_checkout_journey_p(%opt);
			}

+2 −1
Original line number Diff line number Diff line
@@ -1085,6 +1085,7 @@ sub backend_form {
				$backend->{regions}  = [ map { $place_map{$_} // $_ }
					  @{ $s->{coverage}{regions} // [] } ];
				$backend->{has_area}    = $s->{coverage}{area} ? 1 : 0;
				$backend->{association} = 1;

				if (
					    $s->{coverage}{area}
+22 −8
Original line number Diff line number Diff line
@@ -841,6 +841,7 @@ sub travel_action {
			sub {
				return $self->checkin_p(
					dbris        => $params->{dbris},
					efa          => $params->{efa},
					hafas        => $params->{hafas},
					motis        => $params->{motis},
					station      => $params->{station},
@@ -877,6 +878,9 @@ sub travel_action {
					if ( $status->{is_dbris} ) {
						$station_link .= '?dbris=' . $status->{backend_name};
					}
					elsif ( $status->{is_efa} ) {
						$station_link .= '?efa=' . $status->{backend_name};
					}
					elsif ( $status->{is_hafas} ) {
						$station_link .= '?hafas=' . $status->{backend_name};
					}
@@ -916,6 +920,9 @@ sub travel_action {
				if ( $status->{is_dbris} ) {
					$station_link .= '?dbris=' . $status->{backend_name};
				}
				elsif ( $status->{is_efa} ) {
					$station_link .= '?efa=' . $status->{backend_name};
				}
				elsif ( $status->{is_hafas} ) {
					$station_link .= '?hafas=' . $status->{backend_name};
				}
@@ -974,6 +981,12 @@ sub travel_action {
					  . '?dbris='
					  . $status->{backend_name};
				}
				elsif ( $status->{is_efa} ) {
					$redir
					  = '/s/'
					  . $status->{dep_eva} . '?efa='
					  . $status->{backend_name};
				}
				elsif ( $status->{is_hafas} ) {
					$redir
					  = '/s/'
@@ -1004,6 +1017,7 @@ sub travel_action {
		$self->render_later;
		$self->checkin_p(
			dbris    => $params->{dbris},
			efa      => $params->{efa},
			hafas    => $params->{hafas},
			motis    => $params->{motis},
			station  => $params->{station},
@@ -1165,19 +1179,19 @@ sub station {
			lookbehind => 30,
		);
	}
	elsif ($hafas_service) {
		$promise = $self->hafas->get_departures_p(
			service    => $hafas_service,
			eva        => $station,
	elsif ($efa_service) {
		$promise = $self->efa->get_departures_p(
			service    => $efa_service,
			name       => $station,
			timestamp  => $timestamp,
			lookbehind => 30,
			lookahead  => 30,
		);
	}
	elsif ($efa_service) {
		$promise = $self->efa->get_departures_p(
			service    => $efa_service,
			name       => $station,
	elsif ($hafas_service) {
		$promise = $self->hafas->get_departures_p(
			service    => $hafas_service,
			eva        => $station,
			timestamp  => $timestamp,
			lookbehind => 30,
			lookahead  => 30,
+0 −1
Original line number Diff line number Diff line
@@ -94,7 +94,6 @@ sub get_journey_p {
	my ( $self, %opt ) = @_;

	my $promise = Mojo::Promise->new;
	my $now     = DateTime->now( time_zone => 'Europe/Berlin' );

	my $agent = $self->{user_agent};
	my $proxy;
+51 −0
Original line number Diff line number Diff line
@@ -48,4 +48,55 @@ sub get_departures_p {
	);
}

sub get_journey_p {
	my ( $self, %opt ) = @_;

	my $promise = Mojo::Promise->new;
	my $agent   = $self->{user_agent};
	my $stopseq;

	if ( $opt{trip_id} =~ m{ ^ ([^@]*) @ ([^@]*) [(] ([^)]*) [)] (.*)  $ }x ) {
		$stopseq = {
			stateless => $1,
			stop_id   => $2,
			date      => $3,
			key       => $4
		};
	}
	else {
		return $promise->reject("Invalid trip_id: $opt{trip_id}");
	}

	Travel::Status::DE::EFA->new_p(
		service    => $opt{service},
		stopseq    => $stopseq,
		cache      => $self->{realtime_cache},
		promise    => 'Mojo::Promise',
		user_agent => $agent->request_timeout(10),
	)->then(
		sub {
			my ($efa) = @_;
			my $journey = $efa->result;

			if ($journey) {
				$self->{log}->debug("get_journey_p($opt{trip_id}): success");
				$promise->resolve($journey);
				return;
			}
			$self->{log}->debug("get_journey_p($opt{trip_id}): no journey");
			$promise->reject('no journey');
			return;
		}
	)->catch(
		sub {
			my ($err) = @_;
			$self->{log}->debug("get_journey_p($opt{trip_id}): error $err");
			$promise->reject($err);
			return;
		}
	)->wait;

	return $promise;
}

1;
Loading