Unverified Commit 528f59db authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

obtain polylines via mgate (T-S-DE-HAFAS)

parent 087d3871
Loading
Loading
Loading
Loading
+55 −78
Original line number Diff line number Diff line
@@ -994,82 +994,6 @@ sub startup {
				return;
			}

			if ( $journey->{data}{trip_id}
				and not $journey->{polyline} )
			{
				my ( $origin_eva, $destination_eva, $polyline_str );
				$self->hafas->get_polyline_p( $train,
					$journey->{data}{trip_id} )->then(
					sub {
						my ($ret) = @_;
						my $polyline = $ret->{polyline};
						$origin_eva      = 0 + $ret->{raw}{origin}{id};
						$destination_eva = 0 + $ret->{raw}{destination}{id};

						# work around Cache::File turning floats into strings
						for my $coord ( @{$polyline} ) {
							@{$coord} = map { 0 + $_ } @{$coord};
						}

						$polyline_str = JSON->new->encode($polyline);

						my $pl_res = $db->select(
							'polylines',
							['id'],
							{
								origin_eva      => $origin_eva,
								destination_eva => $destination_eva,
								polyline        => $polyline_str
							},
							{ limit => 1 }
						);

						my $polyline_id;
						if ( my $h = $pl_res->hash ) {
							$polyline_id = $h->{id};
						}
						else {
							eval {
								$polyline_id = $db->insert(
									'polylines',
									{
										origin_eva      => $origin_eva,
										destination_eva => $destination_eva,
										polyline        => $polyline_str
									},
									{ returning => 'id' }
								)->hash->{id};
							};
							if ($@) {
								$self->app->log->warn(
									"add_route_timestamps: insert polyline: $@"
								);
							}
						}
						if ($polyline_id) {
							$self->in_transit->set_polyline_id(
								uid         => $uid,
								db          => $db,
								polyline_id => $polyline_id
							);
						}
						return;
					}
				)->catch(
					sub {
						my ($err) = @_;
						if ( $err =~ m{extra content at the end}i ) {
							$self->app->log->debug(
								"add_route_timestamps: $err");
						}
						else {
							$self->app->log->warn("add_route_timestamps: $err");
						}
						return;
					}
				)->wait;
			}

			my ($platform) = ( ( $train->platform // 0 ) =~ m{(\d+)} );

			my $route = $journey->{route};
@@ -1136,11 +1060,14 @@ sub startup {
					);

					return $self->hafas->get_route_timestamps_p(
						trip_id => $trip_id );
						train         => $train,
						trip_id       => $trip_id,
						with_polyline => not $journey->{polyline}
					);
				}
			)->then(
				sub {
					my ( $route_data, $journey ) = @_;
					my ( $route_data, $journey, $polyline ) = @_;

					for my $station ( @{$route} ) {
						$station->[1]
@@ -1172,6 +1099,56 @@ sub startup {
						],
						him_messages => \@messages,
					);

					if ($polyline) {
						my $coords   = $polyline->{coords};
						my $from_eva = $polyline->{from_eva};
						my $to_eva   = $polyline->{to_eva};

						my $polyline_str = JSON->new->encode($coords);

						my $pl_res = $db->select(
							'polylines',
							['id'],
							{
								origin_eva      => $from_eva,
								destination_eva => $to_eva,
								polyline        => $polyline_str
							},
							{ limit => 1 }
						);

						my $polyline_id;
						if ( my $h = $pl_res->hash ) {
							$polyline_id = $h->{id};
						}
						else {
							eval {
								$polyline_id = $db->insert(
									'polylines',
									{
										origin_eva      => $from_eva,
										destination_eva => $to_eva,
										polyline        => $polyline_str
									},
									{ returning => 'id' }
								)->hash->{id};
							};
							if ($@) {
								$self->app->log->warn(
									"add_route_timestamps: insert polyline: $@"
								);
							}
						}
						if ($polyline_id) {
							$self->in_transit->set_polyline_id(
								uid         => $uid,
								db          => $db,
								polyline_id => $polyline_id
							);
						}
					}

					return;
				}
			)->catch(
+40 −95
Original line number Diff line number Diff line
@@ -34,97 +34,6 @@ sub new {
	return bless( \%opt, $class );
}

sub get_polyline_p {
	my ( $self, $train, $trip_id ) = @_;

	my $line    = $train->line // 0;
	my $backend = $self->{hafas_rest_api};
	my $url     = "${backend}/trips/${trip_id}?lineName=${line}&polyline=true";
	my $cache   = $self->{main_cache};
	my $promise = Mojo::Promise->new;
	my $version = $self->{version};

	if ( my $content = $cache->thaw($url) ) {
		return $promise->resolve($content);
	}

	my $log_url = $url;
	$log_url =~ s{://\K[^:]+:[^@]+\@}{***@};

	$self->{user_agent}->request_timeout(5)->get_p( $url => $self->{header} )
	  ->then(
		sub {
			my ($tx) = @_;

			if ( my $err = $tx->error ) {
				$promise->reject(
"hafas->get_polyline_p($log_url) returned HTTP $err->{code} $err->{message}"
				);
				return;
			}

			my $body = decode( 'utf-8', $tx->res->body );
			my $json = JSON->new->decode($body);
			my @station_list;
			my @coordinate_list;

			for my $feature ( @{ $json->{polyline}{features} } ) {
				if ( exists $feature->{geometry}{coordinates} ) {
					my $coord = $feature->{geometry}{coordinates};
					if ( exists $feature->{properties}{type}
						and $feature->{properties}{type} eq 'stop' )
					{
						push( @{$coord},     $feature->{properties}{id} );
						push( @station_list, $feature->{properties}{name} );
					}
					push( @coordinate_list, $coord );
				}
			}

			my $ret = {
				name     => $json->{line}{name} // '?',
				polyline => [@coordinate_list],
				raw      => $json,
			};

			$cache->freeze( $url, $ret );

			# borders (Gr" as in "Grenze") are only returned by HAFAS.
			# They are not stations.
			my $iris_stations = join( '|', $train->route );
			my $hafas_stations
			  = join( '|', grep { $_ !~ m{(\(Gr\)|\)Gr)$} } @station_list );

			# Do not return polyline if it belongs to an entirely different
			# train. Trains with longer routes (e.g. due to train number
			# changes, which are handled by HAFAS but left out in IRIS)
			# are okay though.
			if ( $iris_stations ne $hafas_stations
				and index( $hafas_stations, $iris_stations ) == -1 )
			{
				$self->{log}->info( 'Ignoring polyline for '
					  . $train->line
					  . ": IRIS route does not agree with HAFAS route: $iris_stations != $hafas_stations"
				);
				$promise->reject(
					"hafas->get_polyline_p($log_url): polyline route mismatch");
			}
			else {
				$promise->resolve($ret);
			}
			return;
		}
	)->catch(
		sub {
			my ($err) = @_;
			$promise->reject("hafas->get_polyline_p($log_url): $err");
			return;
		}
	)->wait;

	return $promise;
}

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

@@ -186,14 +95,16 @@ sub get_route_timestamps_p {

			# name => $opt{train_no},
		},
		with_polyline => $opt{with_polyline},
		cache         => $self->{realtime_cache},
		promise       => 'Mojo::Promise',
		user_agent => $self->{user_agent}->request_timeout(10)
		user_agent    => $self->{user_agent}->request_timeout(10),
	)->then(
		sub {
			my ($hafas) = @_;
			my $journey = $hafas->result;
			my $ret     = {};
			my $polyline;

			my $station_is_past = 1;
			for my $stop ( $journey->route ) {
@@ -228,7 +139,41 @@ sub get_route_timestamps_p {
				$ret->{$name}{isPast} = $station_is_past;
			}

			$promise->resolve( $ret, $journey );
			if ( $journey->polyline ) {
				my @station_list;
				my @coordinate_list;

				for my $coord ( $journey->polyline ) {
					if ( $coord->{name} ) {
						push( @coordinate_list,
							[ $coord->{lon}, $coord->{lat}, $coord->{eva} ] );
						push( @station_list, $coord->{name} );
					}
					else {
						push( @coordinate_list,
							[ $coord->{lon}, $coord->{lat} ] );
					}
				}
				my $iris_stations  = join( '|', $opt{train}->route );
				my $hafas_stations = join( '|', @station_list );
				if ( $iris_stations eq $hafas_stations
					or index( $hafas_stations, $iris_stations ) != -1 )
				{
					$polyline = {
						from_eva => ( $journey->route )[0]{eva},
						to_eva   => ( $journey->route )[-1]{eva},
						coords   => \@coordinate_list,
					};
				}
				else {
					$self->{log}->info( 'Ignoring polyline for '
						  . $opt{train}->line
						  . ": IRIS route does not agree with HAFAS route: $iris_stations != $hafas_stations"
					);
				}
			}

			$promise->resolve( $ret, $journey, $polyline );
			return;
		}
	)->catch(