travelynx/lib/Travelynx/Helper/IRIS.pm

238 lines
5.9 KiB
Perl
Raw Normal View History

package Travelynx::Helper::IRIS;
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
use strict;
use warnings;
use 5.020;
use utf8;
2022-07-26 08:41:44 +00:00
use Mojo::Promise;
use Mojo::UserAgent;
use Travel::Status::DE::IRIS;
use Travel::Status::DE::IRIS::Stations;
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;
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;
}
my @station_matches
= Travel::Status::DE::IRIS::Stations::get_station($station);
if ( @station_matches == 1 ) {
$station = $station_matches[0][0];
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,
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 => [],
errstr =>
"Mehrdeutiger Stationsname: '$station'. Mögliche Eingaben: "
. 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);
if ( @station_matches == 1 ) {
$station = $station_matches[0][0];
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(
$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(
'ambiguous station name',
2022-07-26 08:41:44 +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(
'unknown station',
2022-07-26 08:41:44 +00:00
{
results => [],
errstr => 'Unbekannte Station',
}
);
}
}
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] ) {
push( @json_route, [ $route[$route_idx], undef, {} ] );
$route_idx++;
$sched_idx++;
}
# this branch is inefficient, but won't be taken frequently
elsif ( not( grep { $_ eq $route[$route_idx] } @sched_route ) ) {
push( @json_route,
2023-09-04 15:08:17 +00:00
[ $route[$route_idx], undef, { isAdditional => 1 } ], );
$route_idx++;
}
else {
push( @json_route,
2023-09-04 15:08:17 +00:00
[ $sched_route[$sched_idx], undef, { isCancelled => 1 } ], );
$sched_idx++;
}
}
while ( $route_idx <= $#route ) {
push( @json_route,
2023-09-04 15:08:17 +00:00
[ $route[$route_idx], undef, { isAdditional => 1 } ], );
$route_idx++;
}
while ( $sched_idx <= $#sched_route ) {
push( @json_route,
2023-09-04 15:08:17 +00:00
[ $sched_route[$sched_idx], undef, { isCancelled => 1 } ], );
$sched_idx++;
}
return @json_route;
}
1;