change route/stop layout to [name, eva, {data}]

This commit is contained in:
Daniel Friesel 2023-01-15 16:37:32 +01:00
parent f198c96e30
commit 4abc43b72e
No known key found for this signature in database
GPG key ID: 100D5BFB5166E005
7 changed files with 192 additions and 98 deletions

View file

@ -679,7 +679,7 @@ sub startup {
@{ $journey->{route} }
)
{
$station_data = $station_data->[1];
$station_data = $station_data->[2];
if ( $station_data->{sched_arr} ) {
my $sched_arr
= epoch_to_dt( $station_data->{sched_arr} );
@ -1040,10 +1040,19 @@ sub startup {
my $eva = $1;
if ( $route_data->{$eva} ) {
$station->[0] = $route_data->{$eva}{name};
$station->[1] = $route_data->{$eva}{eva};
}
}
$station->[1]
= $route_data->{ $station->[0] };
if ( my $sd = $route_data->{ $station->[0] } ) {
$station->[1] = $sd->{eva};
if ( $station->[2]{isAdditional} ) {
$sd->{isAdditional} = 1;
}
if ( $station->[2]{isCancelled} ) {
$sd->{isCancelled} = 1;
}
$station->[2] = $sd;
}
}
my @messages;
@ -1338,13 +1347,13 @@ sub startup {
for my $station ( @{ $journey->{route_after} } ) {
my $station_desc = $station->[0];
if ( $station->[1]{rt_arr} ) {
$station_desc .= $station->[1]{sched_arr}->strftime(';%s');
$station_desc .= $station->[1]{rt_arr}->strftime(';%s');
if ( $station->[1]{rt_dep} ) {
if ( $station->[2]{rt_arr} ) {
$station_desc .= $station->[2]{sched_arr}->strftime(';%s');
$station_desc .= $station->[2]{rt_arr}->strftime(';%s');
if ( $station->[2]{rt_dep} ) {
$station_desc
.= $station->[1]{sched_dep}->strftime(';%s');
$station_desc .= $station->[1]{rt_dep}->strftime(';%s');
.= $station->[2]{sched_dep}->strftime(';%s');
$station_desc .= $station->[2]{rt_dep}->strftime(';%s');
}
else {
$station_desc .= ';0;0';
@ -1414,7 +1423,7 @@ sub startup {
{
$is_after = 1;
if ( @{$station} > 1 and not $dep_info ) {
$dep_info = $station->[1];
$dep_info = $station->[2];
}
}
}
@ -1499,11 +1508,11 @@ sub startup {
for my $station (@route_after) {
if ( @{$station} > 1 ) {
# Note: $station->[1]{sched_arr} may already have been
# Note: $station->[2]{sched_arr} may already have been
# converted to a DateTime object. This can happen when a
# station is present several times in a train's route, e.g.
# for Frankfurt Flughafen in some nightly connections.
my $times = $station->[1];
my $times = $station->[2] // {};
if ( $times->{sched_arr}
and ref( $times->{sched_arr} ) ne 'DateTime' )
{
@ -1753,17 +1762,17 @@ sub startup {
@{ $ret->{intermediateStops} },
{
name => $stop->[0],
scheduledArrival => $stop->[1]{sched_arr}
? $stop->[1]{sched_arr}->epoch
scheduledArrival => $stop->[2]{sched_arr}
? $stop->[2]{sched_arr}->epoch
: undef,
realArrival => $stop->[1]{rt_arr}
? $stop->[1]{rt_arr}->epoch
realArrival => $stop->[2]{rt_arr}
? $stop->[2]{rt_arr}->epoch
: undef,
scheduledDeparture => $stop->[1]{sched_dep}
? $stop->[1]{sched_dep}->epoch
scheduledDeparture => $stop->[2]{sched_dep}
? $stop->[2]{sched_dep}->epoch
: undef,
realDeparture => $stop->[1]{rt_dep}
? $stop->[1]{rt_dep}->epoch
realDeparture => $stop->[2]{rt_dep}
? $stop->[2]{rt_dep}->epoch
: undef,
}
);

View file

@ -1212,6 +1212,82 @@ my @migrations = (
}
);
},
# v29 -> v30
# change layout of stops in in_transit and journeys "route" lists.
# Old layout: A mixture of [name, {data}, undef/"additional"/"cancelled"], [name, timestamp, timestamp], and [name]
# New layout: [name, eva, {data including isAdditional/isCancelled}]
# Combined with a maintenance task that adds eva IDs to past stops, this will allow for more resilience against station name changes.
# It will also help increase the performance of distance and map calculation
sub {
my ($db) = @_;
my $json = JSON->new;
say 'Adjusting route schema, this may take a while ...';
my $res = $db->select( 'in_transit_str', '*' );
while ( my $row = $res->expand->hash ) {
my @new_route;
for my $stop ( @{ $row->{route} } ) {
push( @new_route, [ $stop->[0], undef, {} ] );
}
$db->update(
'in_transit',
{ route => $json->encode( \@new_route ) },
{ user_id => $row->{user_id} }
);
}
my $total
= $db->select( 'journeys', 'count(*) as count' )->hash->{count};
my $count = 0;
$res = $db->select( 'journeys_str', '*' );
while ( my $row = $res->expand->hash ) {
my $id = $row->{journey_id};
my @new_route;
for my $stop ( @{ $row->{route} } ) {
if ( @{$stop} == 1 ) {
push( @new_route, [ $stop->[0], undef, {} ] );
}
elsif (
( not defined $stop->[1] or $stop->[1] =~ m{ ^ \d+ $ }x )
and
( not defined $stop->[2] or $stop->[2] =~ m{ ^ \d+ $ }x )
)
{
push( @new_route, [ $stop->[0], undef, {} ] );
}
else {
my $attr = $stop->[1] // {};
if ( $stop->[2] and $stop->[2] eq 'additional' ) {
$attr->{isAdditional} = 1;
}
elsif ( $stop->[2] and $stop->[2] eq 'cancelled' ) {
$attr->{isCancelled} = 1;
}
push( @new_route, [ $stop->[0], undef, $attr ] );
}
}
$db->update(
'journeys',
{ route => $json->encode( \@new_route ) },
{ id => $row->{journey_id} }
);
if ( $count++ % 10000 == 0 ) {
printf( " %2.0f%% complete\n", $count * 100 / $total );
}
}
say ' done';
$db->query(
qq{
update schema_version set version = 30;
}
);
},
);
sub sync_stations {

View file

@ -125,22 +125,22 @@ sub get_route_timestamps_p {
for my $stop ( $journey->route ) {
my $name = $stop->{name};
$ret->{$name} = $ret->{ $stop->{eva} } = {
name => $stop->{name},
eva => $stop->{eva},
sched_arr => _epoch( $stop->{sched_arr} ),
sched_dep => _epoch( $stop->{sched_dep} ),
rt_arr => _epoch( $stop->{rt_arr} ),
rt_dep => _epoch( $stop->{rt_dep} ),
arr_delay => $stop->{arr_delay},
dep_delay => $stop->{dep_delay},
eva => $stop->{eva},
load => $stop->{load},
isCancelled => (
( $stop->{arr_cancelled} or not $stop->{sched_arr} )
and
( $stop->{dep_cancelled} or not $stop->{sched_dep} )
),
name => $stop->{name},
eva => $stop->{eva},
sched_arr => _epoch( $stop->{sched_arr} ),
sched_dep => _epoch( $stop->{sched_dep} ),
rt_arr => _epoch( $stop->{rt_arr} ),
rt_dep => _epoch( $stop->{rt_dep} ),
arr_delay => $stop->{arr_delay},
dep_delay => $stop->{dep_delay},
eva => $stop->{eva},
load => $stop->{load}
};
if ( ( $stop->{arr_cancelled} or not $stop->{sched_arr} )
and ( $stop->{dep_cancelled} or not $stop->{sched_dep} ) )
{
$ret->{$name}{isCancelled} = 1;
}
if (
$station_is_past
and not $ret->{$name}{isCancelled}

View file

@ -179,27 +179,35 @@ sub route_diff {
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 ] );
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, [ $route[$route_idx], {}, 'additional' ], );
push( @json_route,
[ $route[$route_idx], undef, { isAdditional => 1 } ],
);
$route_idx++;
}
else {
push( @json_route, [ $sched_route[$sched_idx], {}, 'cancelled' ], );
push( @json_route,
[ $sched_route[$sched_idx], undef, { isCancelled => 1 } ],
);
$sched_idx++;
}
}
while ( $route_idx <= $#route ) {
push( @json_route, [ $route[$route_idx], {}, 'additional' ], );
push( @json_route,
[ $route[$route_idx], undef, { isAdditional => 1 } ],
);
$route_idx++;
}
while ( $sched_idx <= $#sched_route ) {
push( @json_route, [ $sched_route[$sched_idx], {}, 'cancelled' ], );
push( @json_route,
[ $sched_route[$sched_idx], undef, { isCancelled => 1 } ],
);
$sched_idx++;
}
return @json_route;

View file

@ -162,7 +162,7 @@ sub add {
my @route;
if ( not $route_has_start ) {
push( @route, [ $dep_station->{name}, {}, undef ] );
push( @route, [ $dep_station->{name}, $dep_station->{eva}, {} ] );
}
if ( $opt{route} ) {
@ -170,10 +170,11 @@ sub add {
for my $station ( @{ $opt{route} } ) {
my $station_info = $self->{stations}->search($station);
if ($station_info) {
push( @route, [ $station_info->{name}, {}, undef ] );
push( @route,
[ $station_info->{name}, $station_info->{eva}, {} ] );
}
else {
push( @route, [ $station, {}, undef ] );
push( @route, [ $station, undef, {} ] );
push( @unknown_stations, $station );
}
}
@ -192,7 +193,7 @@ sub add {
}
if ( not $route_has_stop ) {
push( @route, [ $arr_station->{name}, {}, undef ] );
push( @route, [ $arr_station->{name}, $arr_station->{eva}, {} ] );
}
my $entry = {
@ -358,7 +359,7 @@ sub update {
)->rows;
}
if ( exists $opt{route} ) {
my @new_route = map { [ $_, {}, undef ] } @{ $opt{route} };
my @new_route = map { [ $_, undef, {} ] } @{ $opt{route} };
$rows = $db->update(
'journeys',
{

View file

@ -124,19 +124,19 @@
% if ($station->[0] eq $journey->{arr_name}) {
% last;
% }
% if (($station->[1]{rt_arr_countdown} // 0) > 0 and $station->[1]{rt_arr}) {
<%= $station->[0] %><br/><%= $station->[1]{rt_arr}->strftime('%H:%M') %>
% if ($station->[1]{sched_arr} and $station->[1]{sched_arr}->epoch != $station->[1]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_arr}->epoch - $station->[1]{sched_arr}->epoch ) / 60);
% if (($station->[2]{rt_arr_countdown} // 0) > 0 and $station->[2]{rt_arr}) {
<%= $station->[0] %><br/><%= $station->[2]{rt_arr}->strftime('%H:%M') %>
% if ($station->[2]{sched_arr} and $station->[2]{sched_arr}->epoch != $station->[2]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_arr}->epoch - $station->[2]{sched_arr}->epoch ) / 60);
% }
% last;
% }
% if (($station->[1]{rt_dep_countdown} // 0) > 0 and $station->[1]{rt_arr} and $station->[1]{rt_dep}) {
% if (($station->[2]{rt_dep_countdown} // 0) > 0 and $station->[2]{rt_arr} and $station->[2]{rt_dep}) {
<%= $station->[0] %><br/>
<%= $station->[1]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[1]{rt_dep}->strftime('%H:%M') %>
% if ($station->[1]{sched_dep} and $station->[1]{sched_dep}->epoch != $station->[1]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_dep}->epoch - $station->[1]{sched_dep}->epoch ) / 60);
<%= $station->[2]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[2]{rt_dep}->strftime('%H:%M') %>
% if ($station->[2]{sched_dep} and $station->[2]{sched_dep}->epoch != $station->[2]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_dep}->epoch - $station->[2]{sched_dep}->epoch ) / 60);
% }
% last;
% }
@ -149,19 +149,19 @@
% if ($station->[0] eq $journey->{arr_name}) {
% last;
% }
% if (($station->[1]{rt_arr_countdown} // 0) > 0 and $station->[1]{rt_arr}) {
<%= $station->[0] %><br/><%= $station->[1]{rt_arr}->strftime('%H:%M') %>
% if ($station->[1]{sched_arr} and $station->[1]{sched_arr}->epoch != $station->[1]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_arr}->epoch - $station->[1]{sched_arr}->epoch ) / 60);
% if (($station->[2]{rt_arr_countdown} // 0) > 0 and $station->[2]{rt_arr}) {
<%= $station->[0] %><br/><%= $station->[2]{rt_arr}->strftime('%H:%M') %>
% if ($station->[2]{sched_arr} and $station->[2]{sched_arr}->epoch != $station->[2]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_arr}->epoch - $station->[2]{sched_arr}->epoch ) / 60);
% }
% last;
% }
% if (($station->[1]{rt_dep_countdown} // 0) > 0 and $station->[1]{rt_arr} and $station->[1]{rt_dep}) {
% if (($station->[2]{rt_dep_countdown} // 0) > 0 and $station->[2]{rt_arr} and $station->[2]{rt_dep}) {
<%= $station->[0] %><br/>
<%= $station->[1]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[1]{rt_dep}->strftime('%H:%M') %>
% if ($station->[1]{sched_dep} and $station->[1]{sched_dep}->epoch != $station->[1]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_dep}->epoch - $station->[1]{sched_dep}->epoch ) / 60);
<%= $station->[2]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[2]{rt_dep}->strftime('%H:%M') %>
% if ($station->[2]{sched_dep} and $station->[2]{sched_dep}->epoch != $station->[2]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_dep}->epoch - $station->[2]{sched_dep}->epoch ) / 60);
% }
% last;
% }
@ -220,20 +220,20 @@
<a class="tablerow action-checkout" data-station="<%= $station->[0] %>">
<span><%= $station->[0] %></span>
<span>
% if ($station->[1]{load}{SECOND}) {
% my ($first, $second) = load_icon($station->[1]{load});
% if ($station->[2]{load}{SECOND}) {
% my ($first, $second) = load_icon($station->[2]{load});
<i class="material-icons tiny" aria-hidden="true"><%= $first %></i> <i class="material-icons tiny" aria-hidden="true"><%= $second %></i>
% }
% if ($station->[2] and $station->[2] eq 'cancelled') {
% if ($station->[2]{isCancelled}) {
entfällt
% }
% elsif ($station->[1]{rt_arr} or $station->[1]{sched_arr}) {
%= ($station->[1]{rt_arr} || $station->[1]{sched_arr})->strftime('%H:%M')
% elsif ($station->[2]{rt_arr} or $station->[2]{sched_arr}) {
%= ($station->[2]{rt_arr} || $station->[2]{sched_arr})->strftime('%H:%M')
% }
% elsif ($station->[1]{rt_dep} or $station->[1]{sched_dep}) {
(<%= ($station->[1]{rt_dep} || $station->[1]{sched_dep})->strftime('%H:%M') %>)
% elsif ($station->[2]{rt_dep} or $station->[2]{sched_dep}) {
(<%= ($station->[2]{rt_dep} || $station->[2]{sched_dep})->strftime('%H:%M') %>)
% }
% elsif ($station->[2] and $station->[2] eq 'additional') {
% elsif ($station->[2]{isAdditional}) {
Zusatzhalt
% }
</span>
@ -335,26 +335,26 @@
<a class="action-checkout tablerow" style="<%= $is_dest? 'font-weight: bold;' : '' %>" data-station="<%= $station->[0] %>">
<span><%= $station->[0] %></span>
<span>
% if ($station->[1]{load}{SECOND}) {
% my ($first, $second) = load_icon($station->[1]{load});
% if ($station->[2]{load}{SECOND}) {
% my ($first, $second) = load_icon($station->[2]{load});
<i class="material-icons tiny" aria-hidden="true"><%= $first %></i> <i class="material-icons tiny" aria-hidden="true"><%= $second %></i>
% }
% if ($station->[2] and $station->[2] eq 'cancelled') {
% if ($station->[2]{isCancelled}) {
entfällt
% }
% elsif ($station->[1]{rt_arr} or $station->[1]{sched_arr}) {
%= ($station->[1]{rt_arr} || $station->[1]{sched_arr})->strftime('%H:%M')
% elsif ($station->[2]{rt_arr} or $station->[2]{sched_arr}) {
%= ($station->[2]{rt_arr} || $station->[2]{sched_arr})->strftime('%H:%M')
% }
% elsif ($station->[1]{rt_dep} or $station->[1]{sched_dep}) {
(<%= ($station->[1]{rt_dep} || $station->[1]{sched_dep})->strftime('%H:%M') %>)
% elsif ($station->[2]{rt_dep} or $station->[2]{sched_dep}) {
(<%= ($station->[2]{rt_dep} || $station->[2]{sched_dep})->strftime('%H:%M') %>)
% }
% elsif ($station->[2] and $station->[2] eq 'additional') {
% elsif ($station->[2]{isAdditional}) {
Zusatzhalt
% }
</span>
</a>
% if ($user->{sb_template}) {
<a class="nonflex" href="<%= resolve_sb_template($user->{sb_template}, name => $station->[0], eva => $station->[1]{eva}, tt => $journey->{train_type} // q{x}, tn => $journey->{train_no}, id => $journey->{train_id}) %>"><i class="material-icons tiny">train</i></a>
<a class="nonflex" href="<%= resolve_sb_template($user->{sb_template}, name => $station->[0], eva => $station->[1], tt => $journey->{train_type} // q{x}, tn => $journey->{train_no}, id => $journey->{train_id}) %>"><i class="material-icons tiny">train</i></a>
% }
% }
% if ($user->{sb_template}) {

View file

@ -79,19 +79,19 @@
% if ($journey->{arr_name} and $station->[0] eq $journey->{arr_name}) {
% last;
% }
% if (($station->[1]{rt_arr_countdown} // 0) > 0 and $station->[1]{rt_arr}) {
<%= $station->[0] %><br/><%= $station->[1]{rt_arr}->strftime('%H:%M') %>
% if ($station->[1]{sched_arr} and $station->[1]{sched_arr}->epoch != $station->[1]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_arr}->epoch - $station->[1]{sched_arr}->epoch ) / 60);
% if (($station->[2]{rt_arr_countdown} // 0) > 0 and $station->[2]{rt_arr}) {
<%= $station->[0] %><br/><%= $station->[2]{rt_arr}->strftime('%H:%M') %>
% if ($station->[2]{sched_arr} and $station->[2]{sched_arr}->epoch != $station->[2]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_arr}->epoch - $station->[2]{sched_arr}->epoch ) / 60);
% }
% last;
% }
% if (($station->[1]{rt_dep_countdown} // 0) > 0 and $station->[1]{rt_arr} and $station->[1]{rt_dep}) {
% if (($station->[2]{rt_dep_countdown} // 0) > 0 and $station->[2]{rt_arr} and $station->[2]{rt_dep}) {
<%= $station->[0] %><br/>
<%= $station->[1]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[1]{rt_dep}->strftime('%H:%M') %>
% if ($station->[1]{sched_dep} and $station->[1]{sched_dep}->epoch != $station->[1]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_dep}->epoch - $station->[1]{sched_dep}->epoch ) / 60);
<%= $station->[2]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[2]{rt_dep}->strftime('%H:%M') %>
% if ($station->[2]{sched_dep} and $station->[2]{sched_dep}->epoch != $station->[2]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_dep}->epoch - $station->[2]{sched_dep}->epoch ) / 60);
% }
% last;
% }
@ -104,21 +104,21 @@
% if ($journey->{arr_name} and $station->[0] eq $journey->{arr_name}) {
% last;
% }
% if (($station->[1]{rt_arr_countdown} // 0) > 0 and $station->[1]{rt_arr}) {
% if (($station->[2]{rt_arr_countdown} // 0) > 0 and $station->[2]{rt_arr}) {
Nächster Halt:<br/>
<%= $station->[0] %><br/><%= $station->[1]{rt_arr}->strftime('%H:%M') %>
% if ($station->[1]{sched_arr} and $station->[1]{sched_arr}->epoch != $station->[1]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_arr}->epoch - $station->[1]{sched_arr}->epoch ) / 60);
<%= $station->[0] %><br/><%= $station->[2]{rt_arr}->strftime('%H:%M') %>
% if ($station->[2]{sched_arr} and $station->[2]{sched_arr}->epoch != $station->[2]{rt_arr}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_arr}->epoch - $station->[2]{sched_arr}->epoch ) / 60);
% }
% last;
% }
% if (($station->[1]{rt_dep_countdown} // 0) > 0 and $station->[1]{rt_arr} and $station->[1]{rt_dep}) {
% if (($station->[2]{rt_dep_countdown} // 0) > 0 and $station->[2]{rt_arr} and $station->[2]{rt_dep}) {
Aktueller Halt:<br/>
<%= $station->[0] %><br/>
<%= $station->[1]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[1]{rt_dep}->strftime('%H:%M') %>
% if ($station->[1]{sched_dep} and $station->[1]{sched_dep}->epoch != $station->[1]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[1]{rt_dep}->epoch - $station->[1]{sched_dep}->epoch ) / 60);
<%= $station->[2]{rt_arr}->strftime('%H:%M') %> →
<%= $station->[2]{rt_dep}->strftime('%H:%M') %>
% if ($station->[2]{sched_dep} and $station->[2]{sched_dep}->epoch != $station->[2]{rt_dep}->epoch) {
%= sprintf('(%+d)', ($station->[2]{rt_dep}->epoch - $station->[2]{sched_dep}->epoch ) / 60);
% }
% last;
% }