From 4abc43b72e597f7c441fc2c287ed38255a1f439b Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 15 Jan 2023 16:37:32 +0100 Subject: change route/stop layout to [name, eva, {data}] --- lib/Travelynx.pm | 49 +++++++++++++--------- lib/Travelynx/Command/database.pm | 76 +++++++++++++++++++++++++++++++++++ lib/Travelynx/Helper/HAFAS.pm | 30 +++++++------- lib/Travelynx/Helper/IRIS.pm | 18 ++++++--- lib/Travelynx/Model/Journeys.pm | 11 ++--- templates/_checked_in.html.ep | 70 ++++++++++++++++---------------- templates/_public_status_card.html.ep | 36 ++++++++--------- 7 files changed, 192 insertions(+), 98 deletions(-) diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index d9b4182..c5c937d 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -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, } ); diff --git a/lib/Travelynx/Command/database.pm b/lib/Travelynx/Command/database.pm index d6158bf..d8b04d2 100644 --- a/lib/Travelynx/Command/database.pm +++ b/lib/Travelynx/Command/database.pm @@ -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 { diff --git a/lib/Travelynx/Helper/HAFAS.pm b/lib/Travelynx/Helper/HAFAS.pm index 92cf1c2..803c10e 100644 --- a/lib/Travelynx/Helper/HAFAS.pm +++ b/lib/Travelynx/Helper/HAFAS.pm @@ -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} diff --git a/lib/Travelynx/Helper/IRIS.pm b/lib/Travelynx/Helper/IRIS.pm index 3222dad..eee7b58 100644 --- a/lib/Travelynx/Helper/IRIS.pm +++ b/lib/Travelynx/Helper/IRIS.pm @@ -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; diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm index f577236..0d47763 100755 --- a/lib/Travelynx/Model/Journeys.pm +++ b/lib/Travelynx/Model/Journeys.pm @@ -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', { diff --git a/templates/_checked_in.html.ep b/templates/_checked_in.html.ep index ec4e8ae..c994378 100644 --- a/templates/_checked_in.html.ep +++ b/templates/_checked_in.html.ep @@ -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] %>
<%= $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] %>
<%= $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] %>
- <%= $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] %>
<%= $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] %>
<%= $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] %>
- <%= $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 @@ <%= $station->[0] %> - % 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}); % } - % 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 % } @@ -335,26 +335,26 @@ <%= $station->[0] %> - % 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}); % } - % 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 % } % if ($user->{sb_template}) { - train + train % } % } % if ($user->{sb_template}) { diff --git a/templates/_public_status_card.html.ep b/templates/_public_status_card.html.ep index acc729a..43b9926 100644 --- a/templates/_public_status_card.html.ep +++ b/templates/_public_status_card.html.ep @@ -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] %>
<%= $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] %>
<%= $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] %>
- <%= $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:
- <%= $station->[0] %>
<%= $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] %>
<%= $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:
<%= $station->[0] %>
- <%= $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; % } -- cgit v1.2.3