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

This commit is contained in:
Daniel Friesel 2022-11-05 22:01:51 +01:00
parent 087d3871e1
commit 528f59dbd2
No known key found for this signature in database
GPG key ID: 100D5BFB5166E005
2 changed files with 95 additions and 173 deletions

View file

@ -994,82 +994,6 @@ sub startup {
return; 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 ($platform) = ( ( $train->platform // 0 ) =~ m{(\d+)} );
my $route = $journey->{route}; my $route = $journey->{route};
@ -1136,11 +1060,14 @@ sub startup {
); );
return $self->hafas->get_route_timestamps_p( return $self->hafas->get_route_timestamps_p(
trip_id => $trip_id ); train => $train,
trip_id => $trip_id,
with_polyline => not $journey->{polyline}
);
} }
)->then( )->then(
sub { sub {
my ( $route_data, $journey ) = @_; my ( $route_data, $journey, $polyline ) = @_;
for my $station ( @{$route} ) { for my $station ( @{$route} ) {
$station->[1] $station->[1]
@ -1172,6 +1099,56 @@ sub startup {
], ],
him_messages => \@messages, 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; return;
} }
)->catch( )->catch(

View file

@ -34,97 +34,6 @@ sub new {
return bless( \%opt, $class ); 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 { sub get_json_p {
my ( $self, $url, %opt ) = @_; my ( $self, $url, %opt ) = @_;
@ -186,14 +95,16 @@ sub get_route_timestamps_p {
# name => $opt{train_no}, # name => $opt{train_no},
}, },
cache => $self->{realtime_cache}, with_polyline => $opt{with_polyline},
promise => 'Mojo::Promise', cache => $self->{realtime_cache},
user_agent => $self->{user_agent}->request_timeout(10) promise => 'Mojo::Promise',
user_agent => $self->{user_agent}->request_timeout(10),
)->then( )->then(
sub { sub {
my ($hafas) = @_; my ($hafas) = @_;
my $journey = $hafas->result; my $journey = $hafas->result;
my $ret = {}; my $ret = {};
my $polyline;
my $station_is_past = 1; my $station_is_past = 1;
for my $stop ( $journey->route ) { for my $stop ( $journey->route ) {
@ -228,7 +139,41 @@ sub get_route_timestamps_p {
$ret->{$name}{isPast} = $station_is_past; $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; return;
} }
)->catch( )->catch(