Switch to new carriage formation API

This commit is contained in:
Birte Kristina Friesel 2024-08-08 21:13:39 +02:00
parent 7fb0d48d80
commit 45dc2e4e2a
No known key found for this signature in database
GPG key ID: 19E6E524EBB177BA
6 changed files with 191 additions and 102 deletions

View file

@ -14,7 +14,7 @@ requires 'Mojolicious::Plugin::OAuth2';
requires 'Mojo::Pg'; requires 'Mojo::Pg';
requires 'Text::CSV'; requires 'Text::CSV';
requires 'Text::Markdown'; requires 'Text::Markdown';
requires 'Travel::Status::DE::DBWagenreihung', '== 0.12'; requires 'Travel::Status::DE::DBWagenreihung', '== 0.16';
requires 'Travel::Status::DE::HAFAS', '>= 5.03'; requires 'Travel::Status::DE::HAFAS', '>= 5.03';
requires 'Travel::Status::DE::IRIS'; requires 'Travel::Status::DE::IRIS';
requires 'UUID::Tiny'; requires 'UUID::Tiny';

View file

@ -497,8 +497,15 @@ sub startup {
# mustn't be called during a transaction # mustn't be called during a transaction
if ( not $opt{in_transaction} ) { if ( not $opt{in_transaction} ) {
$self->add_route_timestamps( $uid, $train, 1 ); $self->add_route_timestamps( $uid, $train, 1 );
$self->add_wagonorder( $uid, 1, $train->train_id, $self->add_wagonorder(
$train->sched_departure, $train->train_no ); uid => $uid,
train_id => $train->train_id,
is_departure => 1,
eva => $eva,
datetime => $train->sched_departure,
train_type => $train->type,
train_no => $train->train_no
);
$self->add_stationinfo( $uid, 1, $train->train_id, $self->add_stationinfo( $uid, 1, $train->train_id,
$eva ); $eva );
$self->run_hook( $uid, 'checkin' ); $self->run_hook( $uid, 'checkin' );
@ -628,8 +635,15 @@ sub startup {
if ( not $opt{in_transaction} ) { if ( not $opt{in_transaction} ) {
$self->run_hook( $uid, 'checkin' ); $self->run_hook( $uid, 'checkin' );
if ( $opt{hafas} eq 'DB' and $journey->class <= 16 ) { if ( $opt{hafas} eq 'DB' and $journey->class <= 16 ) {
$self->add_wagonorder( $uid, 1, $journey->id, $self->add_wagonorder(
$found->sched_dep, $journey->number ); uid => $uid,
train_id => $journey->id,
is_departure => 1,
eva => $found->loc->eva,
datetime => $found->sched_dep,
train_type => $journey->type,
train_no => $journey->number
);
$self->add_stationinfo( $uid, 1, $journey->id, $self->add_stationinfo( $uid, 1, $journey->id,
$found->loc->eva ); $found->loc->eva );
} }
@ -995,8 +1009,15 @@ sub startup {
if ( not $opt{in_transaction} ) { if ( not $opt{in_transaction} ) {
$self->run_hook( $uid, 'update' ); $self->run_hook( $uid, 'update' );
$self->add_route_timestamps( $uid, $train, 0, 1 ); $self->add_route_timestamps( $uid, $train, 0, 1 );
$self->add_wagonorder( $uid, 0, $train->train_id, $self->add_wagonorder(
$train->sched_departure, $train->train_no ); uid => $uid,
train_id => $train->train_id,
is_arrival => 1,
eva => $new_checkout_station_id,
datetime => $train->sched_departure,
train_type => $train->type,
train_no => $train->train_no
);
$self->add_stationinfo( $uid, 0, $train->train_id, $self->add_stationinfo( $uid, 0, $train->train_id,
$dep_eva, $new_checkout_station_id ); $dep_eva, $new_checkout_station_id );
} }
@ -1227,21 +1248,23 @@ sub startup {
$self->helper( $self->helper(
'add_wagonorder' => sub { 'add_wagonorder' => sub {
my ( $self, $uid, $is_departure, $train_id, $sched_departure, my ( $self, %opt ) = @_;
$train_no )
= @_; my $uid = $opt{uid};
my $train_id = $opt{train_id};
my $train_type = $opt{train_type};
my $train_no = $opt{train_no};
my $eva = $opt{eva};
my $datetime = $opt{datetime};
$uid //= $self->current_user->{id}; $uid //= $self->current_user->{id};
my $db = $self->pg->db; my $db = $self->pg->db;
if ( $sched_departure and $train_no ) { if ( $datetime and $train_no ) {
$self->dbdb->has_wagonorder_p( $sched_departure, $train_no ) $self->dbdb->has_wagonorder_p(%opt)->then(
->then(
sub { sub {
my ($api) = @_; return $self->dbdb->get_wagonorder_p(%opt);
return $self->dbdb->get_wagonorder_p( $api,
$sched_departure, $train_no );
} }
)->then( )->then(
sub { sub {
@ -1250,46 +1273,39 @@ sub startup {
my $data = {}; my $data = {};
my $user_data = {}; my $user_data = {};
if ( $is_departure and not exists $wagonorder->{error} ) if ( $opt{is_departure}
and not exists $wagonorder->{error} )
{ {
$data->{wagonorder_dep} = $wagonorder; $data->{wagonorder_dep} = $wagonorder;
$user_data->{wagongroups} = []; $user_data->{wagongroups} = [];
for my $group ( for my $group ( @{ $wagonorder->{groups} // [] } ) {
@{
$wagonorder->{data}{istformation}
{allFahrzeuggruppe} // []
}
)
{
my @wagons; my @wagons;
for for my $wagon ( @{ $group->{vehicles} // [] } )
my $wagon ( @{ $group->{allFahrzeug} // [] } )
{ {
push( push(
@wagons, @wagons,
{ {
id => $wagon->{fahrzeugnummer}, id => $wagon->{vehicleID},
number => number => $wagon
$wagon->{wagenordnungsnummer}, ->{wagonIdentificationNumber},
type => $wagon->{fahrzeugtyp}, type =>
$wagon->{type}{constructionType},
} }
); );
} }
push( push(
@{ $user_data->{wagongroups} }, @{ $user_data->{wagongroups} },
{ {
name => name => $group->{name},
$group->{fahrzeuggruppebezeichnung}, to => $group->{transport}{destination}
from => {name},
$group->{startbetriebsstellename}, type => $group->{transport}{category},
to => $group->{zielbetriebsstellename}, no => $group->{transport}{number},
no => $group->{verkehrlichezugnummer},
wagons => [@wagons], wagons => [@wagons],
} }
); );
if ( $group->{fahrzeuggruppebezeichnung} if ( $group->{name}
and $group->{fahrzeuggruppebezeichnung} eq and $group->{name} eq 'ICE0304' )
'ICE0304' )
{ {
$data->{wagonorder_pride} = 1; $data->{wagonorder_pride} = 1;
} }
@ -1307,7 +1323,7 @@ sub startup {
train_id => $train_id, train_id => $train_id,
); );
} }
elsif ( not $is_departure elsif ( $opt{is_arrival}
and not exists $wagonorder->{error} ) and not exists $wagonorder->{error} )
{ {
$data->{wagonorder_arr} = $wagonorder; $data->{wagonorder_arr} = $wagonorder;
@ -1580,10 +1596,10 @@ sub startup {
from_json => $wagonorder ); from_json => $wagonorder );
}; };
if ( $wr if ( $wr
and $wr->sections and $wr->sectors
and defined $wr->direction ) and defined $wr->direction )
{ {
my $section_0 = ( $wr->sections )[0]; my $section_0 = ( $wr->sectors )[0];
my $direction = $wr->direction; my $direction = $wr->direction;
if ( $section_0->name eq 'A' if ( $section_0->name eq 'A'
and $direction == 0 ) and $direction == 0 )
@ -1726,7 +1742,7 @@ sub startup {
from_json => $in_transit->{data}{wagonorder_dep} ); from_json => $in_transit->{data}{wagonorder_dep} );
}; };
if ( $wr if ( $wr
and $wr->wagons and $wr->carriages
and defined $wr->direction ) and defined $wr->direction )
{ {
$ret->{wagonorder} = $wr; $ret->{wagonorder} = $wr;

View file

@ -84,8 +84,15 @@ sub run {
if ( $journey->class <= 16 if ( $journey->class <= 16
and $found_dep->rt_dep->epoch > $now->epoch ) and $found_dep->rt_dep->epoch > $now->epoch )
{ {
$self->app->add_wagonorder( $uid, 1, $train_id, $self->app->add_wagonorder(
$found_dep->sched_dep, $journey->number ); uid => $uid,
train_id => $journey->id,
is_departure => 1,
eva => $dep,
datetime => $found_dep->sched_dep,
train_type => $journey->type,
train_no => $journey->number,
);
$self->app->add_stationinfo( $uid, 1, $journey->id, $self->app->add_stationinfo( $uid, 1, $journey->id,
$found_dep->loc->eva ); $found_dep->loc->eva );
} }
@ -102,8 +109,15 @@ sub run {
if ( $journey->class <= 16 if ( $journey->class <= 16
and $found_arr->rt_arr->epoch - $now->epoch < 600 ) and $found_arr->rt_arr->epoch - $now->epoch < 600 )
{ {
$self->app->add_wagonorder( $uid, 0, $train_id, $self->app->add_wagonorder(
$found_dep->sched_dep, $journey->number ); uid => $uid,
train_id => $journey->id,
is_arrival => 1,
eva => $arr,
datetime => $found_arr->sched_dep,
train_type => $journey->type,
train_no => $journey->number,
);
$self->app->add_stationinfo( $uid, 0, $journey->id, $self->app->add_stationinfo( $uid, 0, $journey->id,
$found_dep->loc->eva, $found_arr->loc->eva ); $found_dep->loc->eva, $found_arr->loc->eva );
} }
@ -203,8 +217,15 @@ sub run {
} }
else { else {
$self->app->add_route_timestamps( $uid, $train, 1 ); $self->app->add_route_timestamps( $uid, $train, 1 );
$self->app->add_wagonorder( $uid, 1, $train->train_id, $self->app->add_wagonorder(
$train->sched_departure, $train->train_no ); uid => $uid,
train_id => $train->train_id,
is_departure => 1,
eva => $dep,
datetime => $train->sched_departure,
train_type => $train->type,
train_no => $train->train_no
);
$self->app->add_stationinfo( $uid, 1, $train->train_id, $self->app->add_stationinfo( $uid, 1, $train->train_id,
$dep, $arr ); $dep, $arr );
} }
@ -279,8 +300,15 @@ sub run {
and $now->epoch > $entry->{real_arr_ts} and $now->epoch > $entry->{real_arr_ts}
) ? 1 : 0 ) ? 1 : 0
); );
$self->app->add_wagonorder( $uid, 0, $train->train_id, $self->app->add_wagonorder(
$train->sched_departure, $train->train_no ); uid => $uid,
train_id => $train->train_id,
is_arrival => 1,
eva => $arr,
datetime => $train->sched_departure,
train_type => $train->type,
train_no => $train->train_no
);
$self->app->add_stationinfo( $uid, 0, $train->train_id, $self->app->add_stationinfo( $uid, 0, $train->train_id,
$dep, $arr ); $dep, $arr );
} }

View file

@ -27,39 +27,53 @@ sub new {
} }
sub has_wagonorder_p { sub has_wagonorder_p {
my ( $self, $ts, $train_no ) = @_; my ( $self, %opt ) = @_;
my $api_ts = $ts->strftime('%Y%m%d%H%M');
my $url my $datetime = $opt{datetime}->clone->set_time_zone('UTC');
= "https://ist-wr.noncd.db.de/wagenreihung/1.0/${train_no}/${api_ts}"; my %param = (
administrationId => 80,
category => $opt{train_type},
date => $datetime->strftime('%Y-%m-%d'),
evaNumber => $opt{eva},
number => $opt{train_no},
time => $datetime->rfc3339 =~ s{(?=Z)}{.000}r
);
my $url = sprintf( '%s?%s',
'https://www.bahn.de/web/api/reisebegleitung/wagenreihung/vehicle-sequence',
join( '&', map { $_ . '=' . $param{$_} } keys %param ) );
my $cache = $self->{realtime_cache}; my $cache = $self->{realtime_cache};
my $promise = Mojo::Promise->new; my $promise = Mojo::Promise->new;
my $debug_prefix
= "has_wagonorder_p($opt{train_type} $opt{train_no} @ $opt{eva})";
if ( my $content = $cache->get("HEAD $url") ) { if ( my $content = $cache->get("HEAD $url") ) {
if ( $content eq 'n' ) { if ( $content eq 'n' ) {
$self->{log} $self->{log}->debug("${debug_prefix}: n (cached)");
->debug("has_wagonorder_p(${train_no}/${api_ts}): n (cached)");
return $promise->reject; return $promise->reject;
} }
else { else {
$self->{log} $self->{log}->debug("${debug_prefix}: y (cached)");
->debug("has_wagonorder_p(${train_no}/${api_ts}): y (cached)");
return $promise->resolve($content); return $promise->resolve($content);
} }
} }
$self->{user_agent}->request_timeout(5)->head_p( $url => $self->{header} ) $self->{user_agent}->request_timeout(5)->get_p( $url => $self->{header} )
->then( ->then(
sub { sub {
my ($tx) = @_; my ($tx) = @_;
if ( $tx->result->is_success ) { if ( $tx->result->is_success ) {
$self->{log} $self->{log}->debug("${debug_prefix}: a");
->debug("has_wagonorder_p(${train_no}/${api_ts}): a");
$cache->set( "HEAD $url", 'a' ); $cache->set( "HEAD $url", 'a' );
my $body = decode( 'utf-8', $tx->res->body );
my $json = JSON->new->decode($body);
$cache->freeze( $url, $json );
$promise->resolve('a'); $promise->resolve('a');
} }
else { else {
$self->{log} my $code = $tx->code;
->debug("has_wagonorder_p(${train_no}/${api_ts}): n"); $self->{log}->debug("${debug_prefix}: n (HTTP $code)");
$cache->set( "HEAD $url", 'n' ); $cache->set( "HEAD $url", 'n' );
$promise->reject; $promise->reject;
} }
@ -67,7 +81,8 @@ sub has_wagonorder_p {
} }
)->catch( )->catch(
sub { sub {
$self->{log}->debug("has_wagonorder_p(${train_no}/${api_ts}): n"); my ($err) = @_;
$self->{log}->debug("${debug_prefix}: n ($err)");
$cache->set( "HEAD $url", 'n' ); $cache->set( "HEAD $url", 'n' );
$promise->reject; $promise->reject;
return; return;
@ -77,17 +92,29 @@ sub has_wagonorder_p {
} }
sub get_wagonorder_p { sub get_wagonorder_p {
my ( $self, $api, $ts, $train_no ) = @_; my ( $self, %opt ) = @_;
my $api_ts = $ts->strftime('%Y%m%d%H%M');
my $url my $datetime = $opt{datetime}->clone->set_time_zone('UTC');
= "https://ist-wr.noncd.db.de/wagenreihung/1.0/${train_no}/${api_ts}"; my %param = (
administrationId => 80,
category => $opt{train_type},
date => $datetime->strftime('%Y-%m-%d'),
evaNumber => $opt{eva},
number => $opt{train_no},
time => $datetime->rfc3339 =~ s{(?=Z)}{.000}r
);
my $url = sprintf( '%s?%s',
'https://www.bahn.de/web/api/reisebegleitung/wagenreihung/vehicle-sequence',
join( '&', map { $_ . '=' . $param{$_} } keys %param ) );
my $debug_prefix
= "get_wagonorder_p($opt{train_type} $opt{train_no} @ $opt{eva})";
my $cache = $self->{realtime_cache}; my $cache = $self->{realtime_cache};
my $promise = Mojo::Promise->new; my $promise = Mojo::Promise->new;
if ( my $content = $cache->thaw($url) ) { if ( my $content = $cache->thaw($url) ) {
$self->{log} $self->{log}->debug("${debug_prefix}: (cached)");
->debug("get_wagonorder_p(${train_no}/${api_ts}): (cached)");
$promise->resolve($content); $promise->resolve($content);
return $promise; return $promise;
} }
@ -100,15 +127,13 @@ sub get_wagonorder_p {
if ( $tx->result->is_success ) { if ( $tx->result->is_success ) {
my $body = decode( 'utf-8', $tx->res->body ); my $body = decode( 'utf-8', $tx->res->body );
my $json = JSON->new->decode($body); my $json = JSON->new->decode($body);
$self->{log} $self->{log}->debug("${debug_prefix}: success");
->debug("get_wagonorder_p(${train_no}/${api_ts}): success");
$cache->freeze( $url, $json ); $cache->freeze( $url, $json );
$promise->resolve($json); $promise->resolve($json);
} }
else { else {
my $code = $tx->code; my $code = $tx->code;
$self->{log}->debug( $self->{log}->debug("${debug_prefix}: HTTP ${code}");
"get_wagonorder_p(${train_no}/${api_ts}): HTTP ${code}");
$promise->reject("HTTP ${code}"); $promise->reject("HTTP ${code}");
} }
return; return;
@ -116,8 +141,7 @@ sub get_wagonorder_p {
)->catch( )->catch(
sub { sub {
my ($err) = @_; my ($err) = @_;
$self->{log} $self->{log}->debug("${debug_prefix}: error ${err}");
->debug("get_wagonorder_p(${train_no}/${api_ts}): error ${err}");
$promise->reject($err); $promise->reject($err);
return; return;
} }

View file

@ -68,33 +68,48 @@
% } % }
% if (my $wr = $journey->{wagonorder}) { % if (my $wr = $journey->{wagonorder}) {
<br/> <br/>
% my @wagons = $wr->wagons; <!-- <a href="https://dbf.finalrewind.org/carriage-formation?<%= $journey->{train_no} %>/<%= $journey->{sched_departure}->strftime('%Y%m%d%H%M') %>?e=<%= $journey->{dep_direction} // q{} %>"> -->
% my $direction = $wr->direction == 100 ? '→' : '←'; % my $direction = $wr->direction == 100 ? '→' : '←';
% if ($journey->{dep_direction}) { % if ($journey->{dep_direction}) {
% $direction = $journey->{dep_direction} eq 'l' ? '◀' : '▶'; % $direction = $journey->{dep_direction} eq 'l' ? '◀' : '▶';
% if (($journey->{dep_direction} eq 'l' ? 0 : 100) != $wr->direction) {
% @wagons = reverse @wagons;
% } % }
% }
<a href="https://dbf.finalrewind.org/_wr/<%= $journey->{train_no} %>/<%= $journey->{sched_departure}->strftime('%Y%m%d%H%M') %>?e=<%= $journey->{dep_direction} // q{} %>">
%= $direction %= $direction
% my $gi; % my $had_entry = 0;
% for my $wagon (@wagons) { % for my $group ($wr->groups) {
% if (not ($wagon->is_locomotive or $wagon->is_powercar)) { % if ($had_entry) {
% if (defined $gi and $gi != $wagon->group_index) { % $had_entry = 0;
% } % }
% for my $wagon ($group->carriages) {
% if (not ($wagon->is_locomotive or $wagon->is_powercar)) {
% $had_entry = 1;
% if ($wagon->is_closed) { % if ($wagon->is_closed) {
X X
% } % }
% elsif ( $wagon->number) {
%= $wagon->number
% }
% else { % else {
%= $wagon->number || ($wagon->type =~ m{AB} ? '½' : $wagon->type =~ m{A} ? '1.' : $wagon->type =~ m{B} ? '2.' : $wagon->type ) % if ( $wagon->has_first_class ) {
% if ( $wagon->has_second_class ) {
½
% }
% else {
1.
% }
% }
% elsif ( $wagon->has_second_class ) {
2.
% }
% else {
%= $wagon->type;
% }
% }
% } % }
% } % }
% $gi = $wagon->group_index;
% } % }
%= $direction %= $direction
</a> <!-- </a> -->
% } % }
</div> </div>
<div class="progress" style="height: 1ex;"> <div class="progress" style="height: 1ex;">

View file

@ -4,10 +4,16 @@
% if ($wagon_number and my $group_name = app->ice_name->{$wagon_number}) { % if ($wagon_number and my $group_name = app->ice_name->{$wagon_number}) {
„<%= $group_name %>“ „<%= $group_name %>“
% } % }
als <b><%= $journey->{type} %> <%= $wagongroup->{no} %></b> als <b><%= $wagongroup->{type} // $journey->{type} %> <%= $wagongroup->{no} %></b>
von <b><%= $wagongroup->{from} %></b> nach <b><%= $wagongroup->{to} %></b><br/> % if ($wagongroup->{from}) {
von <b><%= $wagongroup->{from} %></b>
% }
% if ($wagongroup->{to}) {
nach <b><%= $wagongroup->{to} %></b>
% }
<br/>
% for my $wagon (@{$wagongroup->{wagons}}) { % for my $wagon (@{$wagongroup->{wagons}}) {
% if (length($wagon->{id}) == 12) { % if (length($wagon->{id}) == 12 or length($wagon->{id}) == 14) {
<span><%= substr($wagon->{id}, 0, 2) %></span><span><%= substr($wagon->{id}, 2, 2) %></span><span><%= substr($wagon->{id}, 4, 1) %></span><span class="wagonclass"><%= substr($wagon->{id}, 5, 3) %></span><span class="wagonnum"><%= substr($wagon->{id}, 8, 3) %></span><span class="checksum"><%= substr($wagon->{id}, 11) %></span> <span><%= substr($wagon->{id}, 0, 2) %></span><span><%= substr($wagon->{id}, 2, 2) %></span><span><%= substr($wagon->{id}, 4, 1) %></span><span class="wagonclass"><%= substr($wagon->{id}, 5, 3) %></span><span class="wagonnum"><%= substr($wagon->{id}, 8, 3) %></span><span class="checksum"><%= substr($wagon->{id}, 11) %></span>
% } % }
% elsif ($wagon->{id}) { % elsif ($wagon->{id}) {