2020-08-06 14:04:12 +00:00
|
|
|
package Travelynx::Helper::IRIS;
|
2020-12-09 20:12:10 +00:00
|
|
|
|
2023-07-03 15:59:25 +00:00
|
|
|
# Copyright (C) 2020-2023 Birte Kristina Friesel
|
2020-11-27 21:12:56 +00:00
|
|
|
#
|
2021-01-29 17:32:13 +00:00
|
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
2020-08-06 14:04:12 +00:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use 5.020;
|
|
|
|
|
2020-12-09 20:12:10 +00:00
|
|
|
use utf8;
|
|
|
|
|
2022-07-26 08:41:44 +00:00
|
|
|
use Mojo::Promise;
|
|
|
|
use Mojo::UserAgent;
|
2020-08-06 14:04:12 +00:00
|
|
|
use Travel::Status::DE::IRIS;
|
2022-12-07 18:42:48 +00:00
|
|
|
use Travel::Status::DE::IRIS::Stations;
|
2020-08-06 14:04:12 +00:00
|
|
|
|
|
|
|
sub new {
|
|
|
|
my ( $class, %opt ) = @_;
|
|
|
|
|
|
|
|
return bless( \%opt, $class );
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_departures {
|
|
|
|
my ( $self, %opt ) = @_;
|
|
|
|
my $station = $opt{station};
|
2022-07-26 08:41:44 +00:00
|
|
|
my $lookbehind = $opt{lookbehind} // 180;
|
|
|
|
my $lookahead = $opt{lookahead} // 30;
|
2020-08-06 14:04:12 +00:00
|
|
|
my $with_related = $opt{with_related} // 0;
|
|
|
|
|
2024-02-25 05:50:03 +00:00
|
|
|
# Berlin Hbf exists twice:
|
|
|
|
# - BLS / 8011160
|
|
|
|
# - BL / 8098160 (formerly "Berlin Hbf (tief)")
|
|
|
|
# Right now, travelynx assumes that station name -> EVA / DS100 is a unique
|
|
|
|
# map. This is not the case. Work around it here until travelynx has been
|
|
|
|
# adjusted properly.
|
|
|
|
if ( $station eq 'Berlin Hbf' or $station eq '8011160' ) {
|
|
|
|
$with_related = 1;
|
|
|
|
}
|
|
|
|
|
2020-08-06 14:04:12 +00:00
|
|
|
my @station_matches
|
|
|
|
= Travel::Status::DE::IRIS::Stations::get_station($station);
|
|
|
|
|
2024-08-25 14:36:02 +00:00
|
|
|
if ( $station =~ m{ ^ \d+ $ }x ) {
|
|
|
|
@station_matches = ( [ undef, undef, $station ] );
|
|
|
|
}
|
|
|
|
|
2020-08-06 14:04:12 +00:00
|
|
|
if ( @station_matches == 1 ) {
|
2024-06-23 14:27:54 +00:00
|
|
|
$station = $station_matches[0][2];
|
2020-08-06 14:04:12 +00:00
|
|
|
my $status = Travel::Status::DE::IRIS->new(
|
|
|
|
station => $station,
|
|
|
|
main_cache => $self->{main_cache},
|
|
|
|
realtime_cache => $self->{realtime_cache},
|
|
|
|
keep_transfers => 1,
|
|
|
|
lookbehind => 20,
|
|
|
|
datetime => DateTime->now( time_zone => 'Europe/Berlin' )
|
|
|
|
->subtract( minutes => $lookbehind ),
|
|
|
|
lookahead => $lookbehind + $lookahead,
|
|
|
|
lwp_options => {
|
|
|
|
timeout => 10,
|
|
|
|
agent => 'travelynx/'
|
|
|
|
. $self->{version}
|
|
|
|
. ' +https://travelynx.de',
|
|
|
|
},
|
|
|
|
with_related => $with_related,
|
|
|
|
);
|
|
|
|
return {
|
2022-07-26 08:41:44 +00:00
|
|
|
results => [ $status->results ],
|
|
|
|
errstr => $status->errstr,
|
2020-08-06 14:04:12 +00:00
|
|
|
station_ds100 =>
|
|
|
|
( $status->station ? $status->station->{ds100} : undef ),
|
|
|
|
station_eva =>
|
|
|
|
( $status->station ? $status->station->{uic} : undef ),
|
|
|
|
station_name =>
|
|
|
|
( $status->station ? $status->station->{name} : undef ),
|
|
|
|
related_stations => [ $status->related_stations ],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
elsif ( @station_matches > 1 ) {
|
|
|
|
return {
|
|
|
|
results => [],
|
2022-08-01 18:03:34 +00:00
|
|
|
errstr =>
|
|
|
|
"Mehrdeutiger Stationsname: '$station'. Mögliche Eingaben: "
|
2020-08-06 14:04:12 +00:00
|
|
|
. join( q{, }, map { $_->[1] } @station_matches ),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return {
|
|
|
|
results => [],
|
|
|
|
errstr => 'Unbekannte Station',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-26 08:41:44 +00:00
|
|
|
sub get_departures_p {
|
|
|
|
my ( $self, %opt ) = @_;
|
|
|
|
my $station = $opt{station};
|
|
|
|
my $lookbehind = $opt{lookbehind} // 180;
|
|
|
|
my $lookahead = $opt{lookahead} // 30;
|
|
|
|
my $with_related = $opt{with_related} // 0;
|
|
|
|
|
2024-02-25 05:50:03 +00:00
|
|
|
# Berlin Hbf exists twice:
|
|
|
|
# - BLS / 8011160
|
|
|
|
# - BL / 8098160 (formerly "Berlin Hbf (tief)")
|
|
|
|
# Right now, travelynx assumes that station name -> EVA / DS100 is a unique
|
|
|
|
# map. This is not the case. Work around it here until travelynx has been
|
|
|
|
# adjusted properly.
|
|
|
|
if ( $station eq 'Berlin Hbf' or $station eq '8011160' ) {
|
|
|
|
$with_related = 1;
|
|
|
|
}
|
|
|
|
|
2022-07-26 08:41:44 +00:00
|
|
|
my @station_matches
|
|
|
|
= Travel::Status::DE::IRIS::Stations::get_station($station);
|
|
|
|
|
2024-08-25 14:36:02 +00:00
|
|
|
if ( $station =~ m{ ^ \d+ $ }x ) {
|
|
|
|
@station_matches = ( [ undef, undef, $station ] );
|
|
|
|
}
|
|
|
|
|
2022-07-26 08:41:44 +00:00
|
|
|
if ( @station_matches == 1 ) {
|
2024-06-23 14:27:54 +00:00
|
|
|
$station = $station_matches[0][2];
|
2022-07-26 08:41:44 +00:00
|
|
|
my $promise = Mojo::Promise->new;
|
|
|
|
Travel::Status::DE::IRIS->new_p(
|
|
|
|
station => $station,
|
|
|
|
main_cache => $self->{main_cache},
|
|
|
|
realtime_cache => $self->{realtime_cache},
|
|
|
|
keep_transfers => 1,
|
|
|
|
lookbehind => 20,
|
|
|
|
datetime => DateTime->now( time_zone => 'Europe/Berlin' )
|
|
|
|
->subtract( minutes => $lookbehind ),
|
|
|
|
lookahead => $lookbehind + $lookahead,
|
|
|
|
lwp_options => {
|
|
|
|
timeout => 10,
|
|
|
|
agent => 'travelynx/'
|
|
|
|
. $self->{version}
|
|
|
|
. ' +https://travelynx.de',
|
|
|
|
},
|
|
|
|
with_related => $with_related,
|
|
|
|
promise => 'Mojo::Promise',
|
|
|
|
user_agent => Mojo::UserAgent->new,
|
|
|
|
get_station => \&Travel::Status::DE::IRIS::Stations::get_station,
|
|
|
|
meta => Travel::Status::DE::IRIS::Stations::get_meta(),
|
|
|
|
)->then(
|
|
|
|
sub {
|
|
|
|
my ($status) = @_;
|
|
|
|
$promise->resolve(
|
|
|
|
{
|
|
|
|
results => [ $status->results ],
|
|
|
|
errstr => $status->errstr,
|
|
|
|
station_ds100 => (
|
|
|
|
$status->station
|
|
|
|
? $status->station->{ds100}
|
|
|
|
: undef
|
|
|
|
),
|
|
|
|
station_eva => (
|
|
|
|
$status->station ? $status->station->{uic} : undef
|
|
|
|
),
|
|
|
|
station_name => (
|
|
|
|
$status->station ? $status->station->{name} : undef
|
|
|
|
),
|
|
|
|
related_stations => [ $status->related_stations ],
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
)->catch(
|
|
|
|
sub {
|
|
|
|
my ($err) = @_;
|
|
|
|
$promise->reject(
|
2023-07-09 15:41:47 +00:00
|
|
|
$err,
|
2022-07-26 08:41:44 +00:00
|
|
|
{
|
|
|
|
results => [],
|
|
|
|
errstr => "Error in promise: $err",
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
)->wait;
|
|
|
|
return $promise;
|
|
|
|
}
|
|
|
|
elsif ( @station_matches > 1 ) {
|
|
|
|
return Mojo::Promise->reject(
|
2023-07-09 15:41:47 +00:00
|
|
|
'ambiguous station name',
|
2022-07-26 08:41:44 +00:00
|
|
|
{
|
2023-08-24 19:26:00 +00:00
|
|
|
results => [],
|
|
|
|
errstr => "Mehrdeutiger Stationsname: '$station'",
|
|
|
|
suggestions => [
|
|
|
|
map { { name => $_->[1], eva => $_->[2] } }
|
|
|
|
@station_matches
|
|
|
|
],
|
2022-07-26 08:41:44 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return Mojo::Promise->reject(
|
2023-07-09 15:41:47 +00:00
|
|
|
'unknown station',
|
2022-07-26 08:41:44 +00:00
|
|
|
{
|
|
|
|
results => [],
|
|
|
|
errstr => 'Unbekannte Station',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-11 17:38:01 +00:00
|
|
|
sub route_diff {
|
|
|
|
my ( $self, $train ) = @_;
|
|
|
|
my @json_route;
|
|
|
|
my @route = $train->route;
|
|
|
|
my @sched_route = $train->sched_route;
|
|
|
|
|
|
|
|
my $route_idx = 0;
|
|
|
|
my $sched_idx = 0;
|
|
|
|
|
|
|
|
while ( $route_idx <= $#route and $sched_idx <= $#sched_route ) {
|
|
|
|
if ( $route[$route_idx] eq $sched_route[$sched_idx] ) {
|
2023-01-15 15:37:32 +00:00
|
|
|
push( @json_route, [ $route[$route_idx], undef, {} ] );
|
2020-10-11 17:38:01 +00:00
|
|
|
$route_idx++;
|
|
|
|
$sched_idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
# this branch is inefficient, but won't be taken frequently
|
|
|
|
elsif ( not( grep { $_ eq $route[$route_idx] } @sched_route ) ) {
|
2023-01-15 15:37:32 +00:00
|
|
|
push( @json_route,
|
2023-09-04 15:08:17 +00:00
|
|
|
[ $route[$route_idx], undef, { isAdditional => 1 } ], );
|
2020-10-11 17:38:01 +00:00
|
|
|
$route_idx++;
|
|
|
|
}
|
|
|
|
else {
|
2023-01-15 15:37:32 +00:00
|
|
|
push( @json_route,
|
2023-09-04 15:08:17 +00:00
|
|
|
[ $sched_route[$sched_idx], undef, { isCancelled => 1 } ], );
|
2020-10-11 17:38:01 +00:00
|
|
|
$sched_idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while ( $route_idx <= $#route ) {
|
2023-01-15 15:37:32 +00:00
|
|
|
push( @json_route,
|
2023-09-04 15:08:17 +00:00
|
|
|
[ $route[$route_idx], undef, { isAdditional => 1 } ], );
|
2020-10-11 17:38:01 +00:00
|
|
|
$route_idx++;
|
|
|
|
}
|
|
|
|
while ( $sched_idx <= $#sched_route ) {
|
2023-01-15 15:37:32 +00:00
|
|
|
push( @json_route,
|
2023-09-04 15:08:17 +00:00
|
|
|
[ $sched_route[$sched_idx], undef, { isCancelled => 1 } ], );
|
2020-10-11 17:38:01 +00:00
|
|
|
$sched_idx++;
|
|
|
|
}
|
|
|
|
return @json_route;
|
|
|
|
}
|
|
|
|
|
2020-08-06 14:04:12 +00:00
|
|
|
1;
|