diff options
author | Birte Kristina Friesel <derf@finalrewind.org> | 2024-10-18 19:17:10 +0200 |
---|---|---|
committer | Birte Kristina Friesel <derf@finalrewind.org> | 2024-10-18 19:17:10 +0200 |
commit | 4dda0fd251e6c82c73cf7ae280caf1ae94d3012e (patch) | |
tree | f0301daaac4af07af8e5507d08cce8f1f05c0397 | |
parent | d8ffb5163a0f4bf543e5b026879cfff8ada0ab52 (diff) |
Add preliminary EFA support
-rw-r--r-- | lib/DBInfoscreen/Controller/Map.pm | 8 | ||||
-rw-r--r-- | lib/DBInfoscreen/Controller/Stationboard.pm | 260 | ||||
-rw-r--r-- | lib/DBInfoscreen/Helper/EFA.pm | 13 | ||||
-rw-r--r-- | public/static/js/geostop.js | 9 | ||||
-rw-r--r-- | public/static/js/map-refresh.js | 2 | ||||
-rw-r--r-- | templates/_train_details.html.ep | 8 | ||||
-rw-r--r-- | templates/layouts/app.html.ep | 3 | ||||
-rw-r--r-- | templates/select_backend.html.ep | 11 |
8 files changed, 299 insertions, 15 deletions
diff --git a/lib/DBInfoscreen/Controller/Map.pm b/lib/DBInfoscreen/Controller/Map.pm index f3f3f16..ba63d92 100644 --- a/lib/DBInfoscreen/Controller/Map.pm +++ b/lib/DBInfoscreen/Controller/Map.pm @@ -12,6 +12,7 @@ use DateTime; use DateTime::Format::Strptime; use GIS::Distance; use List::Util qw(); +use Travel::Status::DE::EFA; my $strp = DateTime::Format::Strptime->new( pattern => '%Y-%m-%dT%H:%M:%S%z', @@ -537,12 +538,15 @@ sub ajax_route { sub coverage { my ($self) = @_; - my $backend = $self->stash('backend'); + my $backend = lc( $self->stash('backend') ); my $service = $self->stash('service'); my $coverage = {}; - if ( $backend eq 'HAFAS' ) { + if ( $backend eq 'efa' ) { + $coverage = $self->efa->get_coverage($service); + } + elsif ( $backend eq 'hafas' ) { $coverage = $self->hafas->get_coverage($service); } diff --git a/lib/DBInfoscreen/Controller/Stationboard.pm b/lib/DBInfoscreen/Controller/Stationboard.pm index 34a9efd..653c914 100644 --- a/lib/DBInfoscreen/Controller/Stationboard.pm +++ b/lib/DBInfoscreen/Controller/Stationboard.pm @@ -1220,11 +1220,202 @@ sub station_train_details { )->wait; } +sub train_details_efa { + my ($self) = @_; + my $trip_id = $self->stash('train'); + + my $stopseq; + if ( $trip_id =~ m{ ^ ([^@]*) @ ([^@]*) [(] ([^)]*) [)] (.*) $ }x ) { + $stopseq = { + stateless => $1, + stop_id => $2, + date => $3, + key => $4 + }; + } + else { + $self->render( 'not_found', status => 404 ); + return; + } + + $self->render_later; + + Travel::Status::DE::EFA->new_p( + service => $self->param('efa'), + stopseq => $stopseq, + cache => $self->app->cache_iris_rt, + lwp_options => { + timeout => 10, + agent => 'dbf.finalrewind.org/2' + }, + promise => 'Mojo::Promise', + user_agent => Mojo::UserAgent->new, + )->then( + sub { + my ($efa) = @_; + my $trip = $efa->result; + + my $now = DateTime->now( time_zone => 'Europe/Berlin' ); + my $res = { + trip_id => $trip_id, + train_type => $trip->type, + train_line => $trip->line, + train_no => $trip->number, + origin => ( $trip->route )[0]->full_name, + destination => ( $trip->route )[-1]->full_name, + operators => [ $trip->operator ], + linetype => lc( $trip->product ) =~ tr{a-z}{}cdr, + route_pre_diff => [], + route_post_diff => [], + moreinfo => [], + replaced_by => [], + replacement_for => [], + }; + + if ( $res->{linetype} =~ m{strab|stra.?enbahn} ) { + $res->{linetype} = 'tram'; + } + elsif ( $res->{linetype} =~ m{bus} ) { + $res->{linetype} = 'bus'; + } + + my $station_is_past = 1; + for my $stop ( $trip->route ) { + + push( + @{ $res->{route_post_diff} }, + { + name => $stop->full_name, + id => $stop->stop_id, + sched_arr => $stop->sched_arr, + sched_dep => $stop->sched_dep, + rt_arr => $stop->rt_arr, + rt_dep => $stop->rt_dep, + platform => $stop->platform, + } + ); + if ( + $station_is_past + and $now->epoch < ( + $res->{route_post_diff}[-1]{rt_arr} + // $res->{route_post_diff}[-1]{rt_dep} + // $res->{route_post_diff}[-1]{sched_arr} + // $res->{route_post_diff}[-1]{sched_dep} // $now + )->epoch + ) + { + $station_is_past = 0; + } + $res->{route_post_diff}[-1]{isPast} = $station_is_past; + } + + if ( my $req_id = $self->param('highlight') ) { + my $split; + for my $i ( 0 .. $#{ $res->{route_post_diff} } ) { + if ( $res->{route_post_diff}[$i]{id} eq $req_id ) { + $split = $i; + last; + } + } + if ( defined $split ) { + $self->stash( + station_name => $res->{route_post_diff}[$split]{name} ); + for my $i ( 0 .. $split - 1 ) { + push( + @{ $res->{route_pre_diff} }, + shift( @{ $res->{route_post_diff} } ) + ); + } + my $station_info = shift( @{ $res->{route_post_diff} } ); + $res->{eva} = $station_info->{eva}; + if ( $station_info->{sched_arr} ) { + $res->{sched_arrival} + = $station_info->{sched_arr}->strftime('%H:%M'); + } + if ( $station_info->{rt_arr} ) { + $res->{arrival} + = $station_info->{rt_arr}->strftime('%H:%M'); + } + if ( $station_info->{sched_dep} ) { + $res->{sched_departure} + = $station_info->{sched_dep}->strftime('%H:%M'); + } + if ( $station_info->{rt_dep} ) { + $res->{departure} + = $station_info->{rt_dep}->strftime('%H:%M'); + } + $res->{arrival_is_cancelled} + = $station_info->{arr_cancelled}; + $res->{departure_is_cancelled} + = $station_info->{dep_cancelled}; + $res->{is_cancelled} = $res->{arrival_is_cancelled} + || $res->{arrival_is_cancelled}; + $res->{tz_offset} = $station_info->{tz_offset}; + $res->{local_dt_da} = $station_info->{local_dt_da}; + $res->{local_sched_arr} = $station_info->{local_sched_arr}; + $res->{local_sched_dep} = $station_info->{local_sched_dep}; + $res->{is_annotated} = $station_info->{is_annotated}; + $res->{prod_name} = $station_info->{prod_name}; + $res->{direction} = $station_info->{direction}; + $res->{operator} = $station_info->{operator}; + $res->{platform} = $station_info->{platform}; + $res->{scheduled_platform} + = $station_info->{sched_platform}; + } + } + + $self->respond_to( + json => { + json => { + journey => $trip, + }, + }, + any => { + template => $self->param('ajax') + ? '_train_details' + : 'train_details', + description => sprintf( + '%s %s%s%s nach %s', + $res->{train_type}, + $res->{train_line} // $res->{train_no}, + $res->{origin} ? ' von ' : q{}, + $res->{origin} // q{}, + $res->{destination} // 'unbekannt' + ), + departure => $res, + linetype => $res->{linetype}, + dt_now => DateTime->now( time_zone => 'Europe/Berlin' ), + }, + ); + } + )->catch( + sub { + my ($e) = @_; + $self->respond_to( + json => { + json => { + error => $e, + }, + status => 500, + }, + any => { + template => 'exception', + message => $e, + exception => undef, + snapshot => {}, + status => 500, + }, + ); + } + )->wait; +} + # /z/:train sub train_details { my ($self) = @_; my $train = $self->stash('train'); my $hafas = $self->param('hafas'); + my $efa = $self->param('efa'); # TODO error handling @@ -1235,6 +1426,10 @@ sub train_details { $self->stash( departures => [] ); $self->stash( title => 'DBF' ); + if ($efa) { + return $self->train_details_efa; + } + my $res = { train_type => undef, train_line => undef, @@ -1570,7 +1765,7 @@ sub handle_efa { $template, description => "Abfahrtstafel $station_name", departures => \@departures, - station => $efa->stop->name,, + station => $efa->stop->name, version => $self->config->{version}, title => $efa->stop->name // $station_name, refresh_interval => $template eq 'app' ? 0 : 120, @@ -2103,6 +2298,7 @@ sub stations_by_coordinates { my $lon = $self->param('lon'); my $lat = $self->param('lat'); + my $efa = $self->param('efa'); my $hafas = $self->param('hafas'); if ( not $lon or not $lat ) { @@ -2120,6 +2316,46 @@ sub stations_by_coordinates { $self->render_later; + if ($efa) { + Travel::Status::DE::EFA->new_p( + promise => 'Mojo::Promise', + user_agent => $self->ua, + service => $efa, + coord => { + lat => $lat, + lon => $lon + } + )->then( + sub { + my ($efa) = @_; + my @efa = map { + { + name => $_->full_name, + eva => $_->id, + distance => $_->distance_m / 1000, + efa => $efa, + } + } $efa->results; + $self->render( + json => { + candidates => [@efa], + } + ); + } + )->catch( + sub { + my ($err) = @_; + $self->render( + json => { + candidates => [], + warning => $err, + } + ); + } + )->wait; + return; + } + my @iris = map { { ds100 => $_->[0][0], @@ -2219,6 +2455,24 @@ sub backend_list { } ); + for my $backend ( Travel::Status::DE::EFA::get_services() ) { + push( + @backends, + { + name => $backend->{name}, + shortname => $backend->{shortname}, + homepage => $backend->{homepage}, + regions => [ + map { $place_map{$_} // $_ } + @{ $backend->{coverage}{regions} } + ], + has_area => $backend->{coverage}{area} ? 1 : 0, + type => 'EFA', + efa => 1, + } + ); + } + for my $backend ( Travel::Status::DE::HAFAS::get_services() ) { push( @backends, @@ -2292,6 +2546,10 @@ sub redirect_to_station { $params = $params->to_string; $self->redirect_to("/z/${input}?${params}"); } + elsif ( $params->param('efa') ) { + $params = $params->to_string; + $self->redirect_to("/${input}?${params}"); + } elsif ( $params->param('hafas') and $params->param('hafas') ne '1' ) { $params = $params->to_string; $self->redirect_to("/${input}?${params}"); diff --git a/lib/DBInfoscreen/Helper/EFA.pm b/lib/DBInfoscreen/Helper/EFA.pm index 4e81bc3..13944cd 100644 --- a/lib/DBInfoscreen/Helper/EFA.pm +++ b/lib/DBInfoscreen/Helper/EFA.pm @@ -13,6 +13,7 @@ use Encode qw(decode encode); use Mojo::JSON qw(decode_json); use Mojo::Promise; use Mojo::Util qw(url_escape); +use Travel::Status::DE::EFA; sub new { my ( $class, %opt ) = @_; @@ -28,6 +29,18 @@ sub new { } +sub get_coverage { + my ( $self, $service ) = @_; + + my $service_definition = Travel::Status::DE::EFA::get_service($service); + + if ( not $service_definition ) { + return {}; + } + + return $service_definition->{coverage}{area} // {}; +} + sub get_json_p { my ( $self, $cache, $url ) = @_; diff --git a/public/static/js/geostop.js b/public/static/js/geostop.js index fa2d6f1..69bb607 100644 --- a/public/static/js/geostop.js +++ b/public/static/js/geostop.js @@ -39,10 +39,13 @@ $(function() { const eva = candidate.eva, name = candidate.name, distance = candidate.distance.toFixed(1), + efa = candidate.efa, hafas = candidate.hafas; const stationlink = $(document.createElement('a')); - if (hafas) { + if (efa) { + stationlink.attr('href', eva + '?efa=' + efa); + } else if (hafas) { stationlink.attr('href', eva + '?hafas=' + hafas); } else { stationlink.attr('href', eva); @@ -55,7 +58,7 @@ $(function() { const icon = $(document.createElement('i')); icon.attr('class', 'material-icons'); - icon.text(hafas ? 'directions' : 'train'); + icon.text((hafas || efa) ? 'directions' : 'train'); stationlink.append(icon); stationlink.append(distancenode); @@ -66,7 +69,7 @@ $(function() { const processLocation = function(loc) { const param = new URLSearchParams(window.location.search); - $.post('/_geolocation', {lon: loc.coords.longitude, lat: loc.coords.latitude, hafas: param.get('hafas')}, processResult).fail(function(jqXHR, textStatus, errorThrown) { + $.post('/_geolocation', {lon: loc.coords.longitude, lat: loc.coords.latitude, efa: param.get('efa'), hafas: param.get('hafas')}, processResult).fail(function(jqXHR, textStatus, errorThrown) { removeStatus(); showError("Netzwerkfehler: ", textStatus, errorThrown); }); diff --git a/public/static/js/map-refresh.js b/public/static/js/map-refresh.js index 0389323..1d8453a 100644 --- a/public/static/js/map-refresh.js +++ b/public/static/js/map-refresh.js @@ -69,7 +69,7 @@ function dbf_anim_fine() { function dbf_map_reload() { const param = new URLSearchParams(window.location.search); - $.get('/_ajax_mapinfo/' + j_reqid + '?hafas=' + param.get('hafas'), function(data) { + $.get('/_ajax_mapinfo/' + j_reqid + '?efa=' + param.get('efa') + '&hafas=' + param.get('hafas'), function(data) { $('#infobox').html(data); dbf_map_parse(); setTimeout(dbf_map_reload, 61000); diff --git a/templates/_train_details.html.ep b/templates/_train_details.html.ep index a02336b..dab05d0 100644 --- a/templates/_train_details.html.ep +++ b/templates/_train_details.html.ep @@ -2,8 +2,8 @@ <div> % if ($departure->{train_no} or $departure->{train_line}) { <span class="train-line <%= $linetype %>"><%= $departure->{train_type} %> - - <%= $departure->{train_line} // $departure->{train_no} %></span> + %= $departure->{train_line} // $departure->{train_no} + </span> <span class="train-no"><%= $departure->{train_line} ? $departure->{train_no} : q{} %></span> % } </div> @@ -145,10 +145,10 @@ <div class="verbose"> % if ($departure->{trip_id}) { % if (stash('station_name')) { - <a class="smallbutton" href="/map/<%= $departure->{trip_id} =~ s{#}{%23}gr %>/<%= $departure->{train_line} || 0 %>?from=<%= stash('station_name') %>&hafas=<%= param('hafas') // q{} %>"><i class="material-icons" aria-hidden="true">map</i> Karte</a> + <a class="smallbutton" href="/map/<%= $departure->{trip_id} =~ s{#}{%23}gr %>/<%= $departure->{train_line} || 0 %>?from=<%= stash('station_name') %>&efa=<%= param('efa') // q{} %>&hafas=<%= param('hafas') // q{} %>"><i class="material-icons" aria-hidden="true">map</i> Karte</a> % } % else { - <a class="smallbutton" href="/map/<%= $departure->{trip_id} =~ s{#}{%23}gr %>/<%= $departure->{train_line} || 0 %>?hafas=<%= param('hafas') // q{} %>"><i class="material-icons" aria-hidden="true">map</i> Karte</a> + <a class="smallbutton" href="/map/<%= $departure->{trip_id} =~ s{#}{%23}gr %>/<%= $departure->{train_line} || 0 %>?efa=<%= param('efa') // q{} %>&hafas=<%= param('hafas') // q{} %>"><i class="material-icons" aria-hidden="true">map</i> Karte</a> % } % } % if ($departure->{wr_link}) { diff --git a/templates/layouts/app.html.ep b/templates/layouts/app.html.ep index 685f31a..cc13143 100644 --- a/templates/layouts/app.html.ep +++ b/templates/layouts/app.html.ep @@ -117,6 +117,7 @@ Bitte eine Station aus der Liste auswählen</div> %= form_for _redirect => begin +%= hidden_field efa => param('efa') %= hidden_field hafas => param('hafas') <div> <div class="field"> @@ -142,7 +143,7 @@ Bitte eine Station aus der Liste auswählen</div> </div> % } <div class="backendlink"> - <a class="button button-light" href="<%= url_for('_backend')->query({hafas => param('hafas')}) %>">Backend: <%= param('hafas') ? param('hafas') . ' (HAFAS)' : 'DB (IRIS-TTS)' %></a> + <a class="button button-light" href="<%= url_for('_backend')->query({efa => param('efa'), hafas => param('hafas')}) %>">Backend: <%= param('efa') ? param('efa') . ' (EFA)' : param('hafas') ? param('hafas') . ' (HAFAS)' : 'DB (IRIS-TTS)' %></a> </div> <div class="break"></div> <div class="moresettings-header moresettings-header-collapsed button button-light">Weitere Einstellungen</div> diff --git a/templates/select_backend.html.ep b/templates/select_backend.html.ep index 836e5c7..2603800 100644 --- a/templates/select_backend.html.ep +++ b/templates/select_backend.html.ep @@ -14,17 +14,22 @@ <%= $prev_type %>:<br/> % } % my $class = 'button'; - % if (param('hafas')) { + % if (param('efa')) { + % if ($backend->{efa} and $backend->{shortname} eq param('efa')) { + % $class .= ' button-active'; + % } + % } + % elsif (param('hafas')) { % if ($backend->{hafas} and $backend->{shortname} eq param('hafas')) { % $class .= ' button-active'; % } % } % else { - % if (not $backend->{hafas}) { + % if (not ($backend->{efa} or $backend->{hafas})) { % $class .= ' button-active'; % } % } - <a class="<%= $class %>" href="<%= url_for(q{/})->query({ hafas => $backend->{hafas} ? $backend->{shortname} : q{} }) %>"><%= $backend->{shortname} // 'IRIS-TTS' %> – <%= $backend->{name} %></a> + <a class="<%= $class %>" href="<%= url_for(q{/})->query({ efa => $backend->{efa} ? $backend->{shortname} : q{}, hafas => $backend->{hafas} ? $backend->{shortname} : q{} }) %>"><%= $backend->{shortname} // 'IRIS-TTS' %> – <%= $backend->{name} %></a> % if ($backend->{has_area}) { <a href="/coverage/<%= $backend->{type} %>/<%= $backend->{shortname} %>"><%= join(q{, }, @{$backend->{regions}}) || '[Karte]' %></a> % } |