From 528f59dbd2be3c58ebdec16a3e047df7796452a2 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sat, 5 Nov 2022 22:01:51 +0100 Subject: obtain polylines via mgate (T-S-DE-HAFAS) --- lib/Travelynx.pm | 133 +++++++++++++++++------------------------ lib/Travelynx/Helper/HAFAS.pm | 135 +++++++++++++----------------------------- 2 files changed, 95 insertions(+), 173 deletions(-) diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 7f1295e..7c8b48e 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -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( diff --git a/lib/Travelynx/Helper/HAFAS.pm b/lib/Travelynx/Helper/HAFAS.pm index 62814b6..7b42384 100644 --- a/lib/Travelynx/Helper/HAFAS.pm +++ b/lib/Travelynx/Helper/HAFAS.pm @@ -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}, }, - cache => $self->{realtime_cache}, - promise => 'Mojo::Promise', - user_agent => $self->{user_agent}->request_timeout(10) + with_polyline => $opt{with_polyline}, + cache => $self->{realtime_cache}, + promise => 'Mojo::Promise', + 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( -- cgit v1.2.3