summaryrefslogtreecommitdiff
path: root/templates
diff options
context:
space:
mode:
Diffstat (limited to 'templates')
-rw-r--r--templates/_map_infobox.html.ep8
-rw-r--r--templates/_train_details.html.ep77
-rw-r--r--templates/_wagon.html.ep46
-rw-r--r--templates/about.html.ep42
-rw-r--r--templates/app.html.ep47
-rw-r--r--templates/coverage_map.html.ep22
-rw-r--r--templates/exception.html.ep2
-rw-r--r--templates/landingpage.html.ep9
-rw-r--r--templates/layouts/app.html.ep82
-rw-r--r--templates/layouts/legacy.html.ep166
-rw-r--r--templates/route_map.html.ep14
-rw-r--r--templates/select_backend.html.ep46
-rw-r--r--templates/wagenreihung.html.ep72
13 files changed, 279 insertions, 354 deletions
diff --git a/templates/_map_infobox.html.ep b/templates/_map_infobox.html.ep
index 7372802..16625f5 100644
--- a/templates/_map_infobox.html.ep
+++ b/templates/_map_infobox.html.ep
@@ -14,7 +14,7 @@ data-poly="<%= stash('ajax_polyline') %>"
% if (my $next = stash('next_stop')) {
<div class="nextstop">
% if ($next->{type} eq 'present' and $next->{station}{dep} and $next->{station}{arr}) {
- Aufenthalt in <strong><%= $next->{station}->loc->name %></strong>
+ Aufenthalt in <strong><%= $next->{station}{name} %></strong>
% if ($next->{station}{platform}) {
an Gleis <strong><%= $next->{station}{platform} %></strong>
% }
@@ -24,7 +24,7 @@ data-poly="<%= stash('ajax_polyline') %>"
% }
% }
% elsif ($next->{type} eq 'present' and $next->{station}{dep}) {
- Abfahrt in <strong><%= $next->{station}->loc->name %></strong>
+ Abfahrt in <strong><%= $next->{station}{name} %></strong>
% if ($next->{station}{platform}) {
von Gleis <strong><%= $next->{station}{platform} %></strong>
% }
@@ -52,7 +52,7 @@ data-poly="<%= stash('ajax_polyline') %>"
% }
% elsif ($next->{type} eq 'next' and $next->{station}{arr}) {
Nächster Halt:
- <strong><%= $next->{station}->loc->name %></strong>
+ <strong><%= $next->{station}{name} %></strong>
um <strong><%= $next->{station}{arr}->strftime('%H:%M') %></strong>
% if ($next->{station}{arr_delay}) {
%= sprintf('(%+d)', $next->{station}{arr_delay})
@@ -63,7 +63,7 @@ data-poly="<%= stash('ajax_polyline') %>"
% }
% elsif ($next->{type} eq 'next') {
Nächster Halt:
- <strong><%= $next->{station}->loc->name %></strong>
+ <strong><%= $next->{station}{name} %></strong>
% if ($next->{station}{platform}) {
auf Gleis <strong><%= $next->{station}{platform} %></strong>
% }
diff --git a/templates/_train_details.html.ep b/templates/_train_details.html.ep
index 709a1ac..2c18da2 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>
@@ -68,10 +68,10 @@
% else {
% my $left = '';
% my $right = '';
-% if ($departure->{direction} and $departure->{direction} eq 'l') {
+% if ($departure->{wr_direction} and $departure->{wr_direction} =~ m{l}) {
% $left = '◀ ';
% }
-% elsif ($departure->{direction} and $departure->{direction} eq 'r') {
+% elsif ($departure->{wr_direction} and $departure->{wr_direction} =~ m{r}) {
% $right = ' ▶';
% }
% if ($departure->{scheduled_platform} and $departure->{platform}
@@ -118,49 +118,46 @@
</div> <!-- dataline -->
% if (my $wr = $departure->{wr}) {
<div class="wagonorder-preview">
-% my @wagons = $wr->wagons;
-% my $direction = $wr->direction ? $wr->direction == 100 ? '→' : '←' : q{};
-% if ($departure->{direction}) {
-% $direction = $departure->{direction} eq 'l' ? '◀' : '▶';
-% if (($departure->{direction} eq 'l' ? 0 : 100) != $wr->direction) {
-% @wagons = reverse @wagons;
-% }
+% my $left = defined $wr->direction ? $wr->direction == 100 ? q{} : '←' : q{};
+% my $right = defined $wr->direction ? $wr->direction == 100 ? '→' : q{} : q{};
+% if ($departure->{wr_direction} and $departure->{wr_direction} =~ m{l}) {
+% $left = '◀';
+% $right = q{};
% }
- <a href="/_wr/<%= $departure->{train_no} %>/<%= $departure->{wr_link} %>?e=<%= $departure->{direction} // '' %>">
- %= $direction
-% my $gi;
-% for my $wagon (@wagons) {
-% if (not ($wagon->is_locomotive or $wagon->is_powercar)) {
-% if (defined $gi and $gi != $wagon->group_index) {
- •
-% }
-% if ($wagon->is_closed) {
- X
-% }
-% else {
-%= $wagon->number || ($wagon->type =~ m{AB} ? '½' : $wagon->type =~ m{A} ? '1.' : $wagon->type =~ m{B} ? '2.' : $wagon->type )
-% }
-% }
-% $gi = $wagon->group_index;
+% elsif ($departure->{wr_direction} and $departure->{wr_direction} =~ m{r}) {
+% $left = q{};
+% $right = '▶';
% }
- %= $direction
+ <a href="/carriage-formation?<%= $departure->{wr_link} %>&amp;e=<%= $departure->{wr_direction} // '' %>">
+ %= $left
+ % for my $entry ((defined $departure->{wr_direction_num} and $departure->{wr_direction_num} != $wr->direction) ? reverse @{$departure->{wr_preview} // []} : @{$departure->{wr_preview} // []}) {
+ % if ($entry->[1]) {
+ <span class="<%= $entry->[1] %>"><%= $entry->[0] %></span>
+ % }
+ % else {
+ %= $entry->[0]
+ % }
+ % }
+ %= $right
</a>
</div>
% }
<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') %>&amp;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') %>&amp;dbris=<%= param('dbris') %>&amp;efa=<%= param('efa') // q{} %>&amp;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 %>?dbris=<%= param('dbris') %>&amp;efa=<%= param('efa') // q{} %>&amp;hafas=<%= param('hafas') // q{} %>"><i class="material-icons" aria-hidden="true">map</i> Karte</a>
% }
% }
% if ($departure->{wr_link}) {
- <a class="smallbutton" href="/_wr/<%= $departure->{train_no} %>/<%= $departure->{wr_link} %>?e=<%= $departure->{direction} // '' %>"><i class="material-icons" aria-hidden="true">train</i> <%= $departure->{wr_text} || 'Wagen' %>
+ <a class="smallbutton" href="/carriage-formation?<%= $departure->{wr_link} %>&amp;e=<%= $departure->{wr_direction} // '' %>"><i class="material-icons" aria-hidden="true">train</i> <%= $departure->{wr_text} || 'Wagen' %>
</a>
% }
-% if ($departure->{train_type} and $departure->{train_no}) {
+% if ($departure->{trip_id} and param('dbris') and param('dbris') eq 'bahn.de') {
+ <a class="smallbutton" href="https://bahn.expert/details/x/h/<%= Mojo::Util::url_escape( $departure->{trip_id} ) %>"><img src="/static/icons/bahn-expert.svg">Details</a>
+% } elsif ($departure->{train_type} and $departure->{train_no} and (not param('hafas') or param('hafas') eq 'DB')) {
<a class="smallbutton" href="https://bahn.expert/details/<%= $departure->{train_type} %>%20<%= $departure->{train_no} %>/<%= ($departure->{date} // DateTime->now(time_zone => 'Europe/Berlin'))->iso8601 %>?evaNumberAlongRoute=<%= $departure->{eva} %>"><img src="/static/icons/bahn-expert.svg">Details</a>
% }
% for my $link (@{$departure->{links}}) {
@@ -257,7 +254,7 @@
</li>
% }
<li class="<%= $stop->{isPast} ? 'past-stop' : 'future-stop' %>">
- <a href="<%= url_for('station', station => $stop->{eva} // $stop->{name})->query({detailed => param('detailed'), past => param('past'), rt => param('rt'), hafas => param('hafas')}) %>#<%= ($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x}) %>" class="
+ <a href="<%= url_for('station', station => $stop->{eva} // $stop->{name})->query({detailed => param('detailed'), past => param('past'), rt => param('rt'), dbris => param('dbris'), efa => param('efa'), hafas => param('hafas')}) %>#<%= ((param('dbris') or param('hafas')) and $departure->{trip_id}) ? ($departure->{trip_id} =~ s{[ #|]}{x}gr) : (($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x})) %>" class="
% if ($stop->{isAdditional}) {
additional-stop
% }
@@ -285,7 +282,9 @@
<%= $stop->{name} %></a>
% if ($stop->{load}{FIRST} or $stop->{load}{SECOND}) {
% my ($text, $icon1, $icon2) = utilization_icon([$stop->{load}{FIRST}, $stop->{load}{SECOND}]);
- <i class="material-icons" aria-hidden="true"><%= $icon1 %></i>
+ % if ($icon1 ne 'help_outline') {
+ <i class="material-icons" aria-hidden="true"><%= $icon1 %></i>
+ % }
<i class="material-icons" aria-hidden="true"><%= $icon2 %></i>
% }
</li>
@@ -328,7 +327,9 @@
<strong><%= stash('station_name') %></strong>
% if (my $u = $departure->{utilization}) {
% my ($text, $icon1, $icon2) = utilization_icon($u);
- <i class="material-icons" aria-hidden="true"><%= $icon1 %></i>
+ % if ($icon1 ne 'help_outline') {
+ <i class="material-icons" aria-hidden="true"><%= $icon1 %></i>
+ % }
<i class="material-icons" aria-hidden="true"><%= $icon2 %></i>
% }
</li>
@@ -348,7 +349,7 @@
</li>
% }
<li class="<%= $stop->{isPast} ? 'past-stop' : 'future-stop' %>">
- <a href="<%= url_for('station', station => $stop->{eva} // $stop->{name})->query({detailed => param('detailed'), past => param('past'), rt => param('rt'), hafas => param('hafas')}) %>#<%= ($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x}) %>" class="
+ <a href="<%= url_for('station', station => $stop->{eva} // $stop->{name})->query({detailed => param('detailed'), past => param('past'), rt => param('rt'), dbris => param('dbris'), efa => param('efa'), hafas => param('hafas')}) %>#<%= ((param('dbris') or param('hafas')) and $departure->{trip_id}) ? ($departure->{trip_id} =~ s{[ #|]}{x}gr) : (($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x})) %>" class="
% if ($stop->{isAdditional}) {
additional-stop
% }
@@ -376,7 +377,9 @@
<%= $stop->{name} %></a>
% if ($stop->{load}{FIRST} or $stop->{load}{SECOND}) {
% my ($text, $icon1, $icon2) = utilization_icon([$stop->{load}{FIRST}, $stop->{load}{SECOND}]);
- <i class="material-icons" aria-hidden="true"><%= $icon1 %></i>
+ % if ($icon1 ne 'help_outline') {
+ <i class="material-icons" aria-hidden="true"><%= $icon1 %></i>
+ % }
<i class="material-icons" aria-hidden="true"><%= $icon2 %></i>
% }
</li>
diff --git a/templates/_wagon.html.ep b/templates/_wagon.html.ep
index 2f5a0df..dccecc0 100644
--- a/templates/_wagon.html.ep
+++ b/templates/_wagon.html.ep
@@ -1,6 +1,6 @@
% my $bg = '';
% my $extra_class = '';
-% if ($wagon->is_first_class) {
+% if ($wagon->has_first_class) {
% $extra_class .= ' firstclass';
% }
% if ($wagon->is_locomotive or $wagon->is_powercar) {
@@ -9,34 +9,28 @@
% if ($wagon->is_closed) {
% $extra_class .= ' closed';
% }
-% if ($wagon->train_no ne $train_no) {
+% if ($group->train_no ne $train_no) {
% $extra_class .= ' nondestwagon';
% }
<div class="wagon <%= $extra_class %>" style="
- top: <%= $wagon->{position}{start_percent} %>%; bottom: <%= 100 - $wagon->{position}{end_percent} %>%; <%= $bg %>">
+ top: <%= $wagon->start_percent %>%; bottom: <%= 100 - $wagon->end_percent %>%; <%= $bg %>">
% if ($wagon->is_locomotive or $wagon->is_powercar) {
% }
% elsif ($wagon->is_closed) {
X
% }
% else {
-%= $wagon->number // '?'
-% if ($wagon->has_accessibility) {
+%= $wagon->number // q{}
+% if ($wagon->has_wheelchair_space) {
<i class="material-icons" style="font-size: 20px;">accessible</i>
% }
% if ($wagon->has_bistro) {
<i class="material-icons">restaurant</i>
% }
-% if ($wagon->has_compartments) {
- <!--<i class="material-icons">folder</i>-->
-% }
-% if ($wagon->has_quiet_area) {
+% if ($wagon->has_quiet_zone) {
<i class="tiny material-icons">volume_off</i>
% }
-% if ($wagon->has_phone_area) {
- <i class="material-icons">smartphone</i>
-% }
-% if ($wagon->has_family_area) {
+% if ($wagon->has_family_zone) {
<i class="material-icons">people</i>
% }
% if ($wagon->has_bahn_comfort) {
@@ -44,9 +38,9 @@
% }
% }
<div class="direction">
-% if (not defined $direction) {
+% if (not defined $wr->direction) {
% }
-% elsif ($direction == 100) {
+% elsif ($wr->direction == 100) {
<i class="material-icons">arrow_downward</i>
% }
% else {
@@ -55,9 +49,9 @@
</div>
</div>
<div class="details" style="
- top: <%= $wagon->{position}{start_percent} %>%; bottom: <%= 100 - $wagon->{position}{end_percent} %>%;">
+ top: <%= $wagon->start_percent %>%; bottom: <%= 100 - $wagon->end_percent %>%;">
% if ($exit_dir ne 'right') {
-% if (my $img = wagon_image($wagon->train_subtype // $type // '?', $wagon->type, $wagon->uic_id)) {
+% if (my $img = wagon_image($wr->train_type // '?', $wagon->type, $wagon->uic_id)) {
<a class="type" href="/w/<%= $img %>?n=<%= $wagon->number // '' %>&amp;s=<%= $wagon->section %>&amp;r=<%= $wref %>"><%= $wagon->type %></a>
% }
% else {
@@ -67,7 +61,7 @@
% }
% }
% my $uic_id = $wagon->uic_id;
-% if (length($uic_id) != 12) {
+% if (length($uic_id) != 12 and length($uic_id) != 14) {
<span class="uicunknown"><%= $uic_id %></span>
% }
% elsif (substr($uic_id, 0, 2) >= 90) {
@@ -77,7 +71,7 @@
<span class="uicexchange"><%= substr($uic_id, 0, 2) %></span><span class="uiccountry"><%= substr($uic_id, 2, 2) %></span><span class="uic56"><%= substr($uic_id, 4, 2) %></span><span class="uic78"><%= substr($uic_id, 6, 2) %></span><span class="uicno"><%= substr($uic_id, 8, 3) %></span><span class="uiccheck"><%= substr($uic_id, 11) %></span>
% }
% if ($exit_dir eq 'right') {
-% if (my $img = wagon_image($wagon->train_subtype // $type // '?', $wagon->type, $wagon->uic_id)) {
+% if (my $img = wagon_image($wr->train_type // '?', $wagon->type, $wagon->uic_id)) {
<a class="type" href="/w/<%= $img %>?n=<%= $wagon->number // '' %>&amp;s=<%= $wagon->section %>&amp;r=<%= $wref %>"><%= $wagon->type %></a>
% }
% else {
@@ -86,4 +80,18 @@
</span>
% }
% }
+% if ($multi and $first) {
+ <br/>
+ <span class="groupno">
+% if (scalar $wr->train_numbers > 1) {
+ <%= $group->train_type %> <%= $group->train_no %>
+% }
+% if (scalar $wr->destinations > 1) {
+ → <%= $group->destination %>
+% }
+ </span>
+ % if ($multi and $group->desc_short) {
+ <span class="grouptype"><%= $group->desc_short %></span>
+% }
+% }
</div>
diff --git a/templates/about.html.ep b/templates/about.html.ep
index b5af92b..3bf8295 100644
--- a/templates/about.html.ep
+++ b/templates/about.html.ep
@@ -1,7 +1,8 @@
<div class="container">
<p>
- DBF ist ein inoffizieller Abfahrtsmonitor für den Regional- und Fernverkehr mit dem Ziel, Daten aus verschiedenen Quellen übersichtlich zusammenzutragen.
- Der Fokus liegt auf Zügen im Netz der Deutschen Bahn; eingeschränkte Unterstützung für Nahverkehr und Züge in anderen Netzen lässt sich optional zuschalten.
+ DBF ist ein inoffizieller Abfahrtsmonitor für Nah-, Regional- und Fernverkehr in Deutschland und Umgebung.
+ Die Fahrten in der Übersicht verlinken je eine Detailseite mit Unterwegshalten, Meldungen und Kartendarstellung.
+ Bei HAFAS-Backends ist zusätzlich die Suche nach spezifischen Fahrten möglich.
</p>
<p>
Der <a href="<%= app->config->{'source_url'} %>">Quelltext</a> steht unter der <a href="https://git.finalrewind.org/db-fakedisplay/tree/COPYING">GNU AGPL v3</a> als Open Source zur Verfügung. © 2011 – 2024 <a href="https://finalrewind.org">derf</a>.
@@ -9,37 +10,28 @@
Fehlermeldungen bitte via
<a href="<%= $issue_url %>">Issue Tracker</a>.
% }
- </p>
- <p>
- Das Projekt begann als „db-fakedisplay“ (kurz dbf) zur <a href="/Dortmund
- Hbf?mode=multi">Nachahmung von Bahnhofs-Abfahrtstafeln</a>. Inzwischen
- liegt der Fokus auf dem <a href="/Dortmund Hbf">App/Infoscreen-Modus</a>
- und die Bezeichnung DBF wurde zum Eigennamen ohne weitere Bedeutung.
+ Alle von DBF referenzierten Informationen können auch direkt per CLI im Text- oder JSON-Format abgerufen werden – die unten verlinkten Backends beinhalten entsprechende Anwendungen.
</p>
<p>
Diese Installation nutzt
<strong>DBF v<%= stash('version') // '???' %></strong> mit folgenden Backends:
<ul>
- <li> Innerdeutscher Regional- und Fernverkehr: DB IRIS via <a href="https://finalrewind.org/projects/Travel-Status-DE-IRIS/">Travel::Status::DE::IRIS</a>
+ <li>Innerdeutscher Regional- und Fernverkehr: DB IRIS via <a href="https://finalrewind.org/projects/Travel-Status-DE-IRIS/">Travel::Status::DE::IRIS</a>
<strong>v<%= $Travel::Status::DE::IRIS::VERSION %></strong></li>
- <li> Außerdeutsche Fahrten, Nahverkehr, Details, Karten: HAFAS via <a href="https://finalrewind.org/projects/Travel-Status-DE-DeutscheBahn/">Travel::Status::DE::HAFAS</a>
+ <li>Nah-, Regional- und Fernverkehr im In- und Ausland: bahn.de via <a href="https://finalrewind.org/projects/Travel-Status-DE-DBRIS/">Travel::Status::DE::DBRIS</a>
+ <strong>v<%= $Travel::Status::DE::DBRIS::VERSION %></strong></li>
+ <li>Nah-, Regional- und Fernverkehr im In- und Ausland: EFA via <a href="https://finalrewind.org/projects/Travel-Status-DE-VRR/">Travel::Status::DE::EFA</a>
+ <strong>v<%= $Travel::Status::DE::EFA::VERSION %></strong></li>
+ <li>Nah-, Regional- und Fernverkehr im In- und Ausland: HAFAS via <a href="https://finalrewind.org/projects/Travel-Status-DE-DeutscheBahn/">Travel::Status::DE::HAFAS</a>
<strong>v<%= $Travel::Status::DE::HAFAS::VERSION %></strong></li>
- <li>Wagenreihung: <a href="https://finalrewind.org/projects/Travel-Status-DE-DBWagenreihung/">Travel::Status::DE::DBWagenreihung</a>
- <strong>v<%= $Travel::Status::DE::DBWagenreihung::VERSION %></strong></li>
- <li>Zugauslastung Regionalverkehr: VRR EFA via <a href="https://github.com/derf/eva-to-efa-gw">eva-to-efa-gw</a></li>
+ <li>Nah-, Regional- und Fernverkehr im In- und Ausland: MOTIS via <a href="https://finalrewind.org/projects/Travel-Status-MOTIS/">Travel::Status::MOTIS</a>
+ <strong>v<%= $Travel::Status::MOTIS::VERSION %></strong></li>
</ul>
</p>
<p>
- Unterstützte HAFAS-Instanzen („hafas=…“):
- <ul>
- % for my $service (Travel::Status::DE::HAFAS::get_services()) {
- <li><%= $service->{shortname} %> (<%= $service->{name} %>)</li>
- % }
- </ul>
- </p>
- <p>
- Verwendete Open Data-Ressourcen:
+ Verwendete Ressourcen:
<ul>
+ <li><a href="/_backend">HAFAS-Backends</a> via <a href="https://github.com/public-transport/transport-apis">transport-apis</a>, CC0</li>
<li><a href="https://data.deutschebahn.com/dataset/zugbildungsplanzugbildungsplan-zpar">Zugbildungsplan</a> © DB Fernverkehr AG, lizensiert unter CC-BY 4.0</li>
<li><a href="http://data.deutschebahn.com/dataset/data-haltestellen">Haltestellenliste</a>
© DB Station&amp;Service AG,
@@ -49,6 +41,12 @@
© DB Fernverkehr AG, lizensiert unter CC-BY 4.0; Abbildungen © Seemanngrafik d.i.p. im Auftrag der Deutschen Bahn AG, lizensiert unter CC-BY-SA 4.0</li>
</ul>
</p>
+ <p>
+ Trivia: Das Projekt begann als „db-fakedisplay“ (kurz dbf) zur
+ Nachahmung von Bahnhofs-Abfahrtstafeln. Inzwischen liegt der Fokus auf
+ der Bereitstellung von Informationen für mobile und Desktop-Anwendungen
+ und die Bezeichnung DBF wurde zum Eigennamen ohne weitere Bedeutung.
+ </p>
</div>
% if (-e 'templates/imprint.html.ep') {
diff --git a/templates/app.html.ep b/templates/app.html.ep
index 50f8a5a..8b52c61 100644
--- a/templates/app.html.ep
+++ b/templates/app.html.ep
@@ -30,7 +30,7 @@
% $route_str .= $stop . ($via_cur < $via_max ? ' - ' : q{});
% }
<li
-% if (param('hafas')) {
+% if (param('dbris') or param('hafas') or param('efa')) {
data-jid="<%= $departure->{journey_id} =~ s{#}{%23}gr %>"
% }
data-train="<%= ($departure->{train_type} // q{}) %> <%= ($departure->{train_no} // $departure->{train} // q{}) %>"
@@ -53,12 +53,23 @@
>
% }
% if (param('hafas')) {
- <a href="/z/<%= Mojo::Util::url_escape($departure->{journey_id}) . '?hafas=1&highlight=' . Mojo::Util::url_escape($departure->{station} // $station) %>">
+ <a href="/z/<%= Mojo::Util::url_escape($departure->{journey_id}) . '?hafas=' . Mojo::Util::url_escape(param('hafas')) . '&amp;highlight=' . Mojo::Util::url_escape($departure->{station} // $station) %>">
+% }
+% elsif (param('efa')) {
+ <a href="/z/<%= Mojo::Util::url_escape($departure->{journey_id}) . '?efa=' . Mojo::Util::url_escape(param('efa')) . '&amp;highlight=' . Mojo::Util::url_escape($departure->{station} // $station) %>">
+% }
+% elsif (param('dbris')) {
+ <a href="/z/<%= Mojo::Util::url_escape($departure->{journey_id}) . '?dbris=' . Mojo::Util::url_escape(param('dbris')) . '&amp;highlight=' . Mojo::Util::url_escape($departure->{station} // $station) %>">
% }
% else {
<a href="/z/<%= Mojo::Util::url_escape(($departure->{train_type} // q{}) . ' ' . ($departure->{train_no} // $departure->{train} // q{})) . '/' . Mojo::Util::url_escape($departure->{station} // $station) %>">
% }
- <div class="anchor" id="<%= ($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x}) %>"></div>
+% if (param('dbris') or param('hafas')) {
+ <div class="anchor" id="<%= $departure->{journey_id} =~ s{[ #|]}{x}gr %>"></div>
+% }
+% else {
+ <div class="anchor" id="<%= ($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x}) %>"></div>
+% }
<div class="line <%= $departure->{linetype} %>">
% if ($departure->{train_type} and $departure->{train_no}) {
%= $departure->{train_type}
@@ -100,15 +111,14 @@
%= $departure->{origin}
</span>
% }
- <span class="time <%= ($show_realtime and $departure->{delay} and not
- $departure->{is_cancelled}) ? 'delayed' : q{} %>">
-% if ($departure->{delay} and not $departure->{is_cancelled}) {
-% if ($show_realtime) {
+ <span class="time <%= $show_realtime ? get_rt_time_class($departure) : q{} %>">
+% if ($departure->{delay} and not $departure->{is_cancelled} and not $departure->{departure_is_cancelled}) {
+% if ($show_realtime and ($departure->{sched_arrival} or $departure->{sched_departure})) {
% if ($departure->{delay} > ($hide_low_delay ? 4 : 0)) {
- <span class="delaynorm" aria-hidden="true">+<%= $departure->{delay} %> ⇒</span>
+ <span class="delaynorm" aria-hidden="true"><%= $departure->{sched_departure} // $departure->{sched_arrival} %> ⇒</span>
% }
% elsif ($departure->{delay} < 0) {
- <span class="undelaynorm" aria-hidden="true"><%= $departure->{delay} %> ⇒</span>
+ <span class="undelaynorm" aria-hidden="true"><%= $departure->{sched_departure} // $departure->{sched_arrival} %> ⇒</span>
% }
% }
% else {
@@ -140,7 +150,12 @@
% }
% }
% else {
-%= $departure->{time}
+% if ($departure->{is_cancelled} or $departure->{departure_is_cancelled}) {
+%= $departure->{sched_departure} // $departure->{sched_arrival} // $departure->{time}
+% }
+% else {
+%= $departure->{time}
+% }
% }
</span>
% if (($departure->{scheduled_platform} and $departure->{platform} and
@@ -151,6 +166,18 @@
% else {
<span class="platform">
% }
+% if ($departure->{load}{FIRST} or $departure->{load}{SECOND}) {
+% my ($text, $icon1, $icon2) = utilization_icon([$departure->{load}{FIRST}, $departure->{load}{SECOND}]);
+ <span class="load">
+ <i class="material-icons" style="vertical-align: bottom;" aria-hidden="true"><%= $icon2 %></i>
+ </span>
+% }
+% elsif (my $o = $departure->{occupancy}) {
+ <span class="load">
+% my ($text, $icon) = occupancy_icon($o);
+ <i class="material-icons" style="vertical-align: bottom;" aria-hidden="true"><%= $icon %></i>
+ </span>
+% }
<span class="visually-hidden">Gleis</span>
%= $departure->{platform}
</span>
diff --git a/templates/coverage_map.html.ep b/templates/coverage_map.html.ep
new file mode 100644
index 0000000..bd3d94c
--- /dev/null
+++ b/templates/coverage_map.html.ep
@@ -0,0 +1,22 @@
+<div class="container">
+ Das <%= $backend %>-Backend „<%= $service %>“ liefert ungefähr innerhalb
+ der folgenden grob umrissenen Region voraussichtlich nützliche Echtzeitdaten.
+</div>
+
+<div class="container">
+ <div id="map" style="height: 70vh;">
+ </div>
+</div>
+
+<script>
+const map = L.map('map').setView([51.306, 9.712], 6);
+
+L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
+}).addTo(map);
+
+const coverage = L.geoJSON(<%== $coverage %>);
+
+coverage.addTo(map);
+map.fitBounds(coverage.getBounds());
+</script>
diff --git a/templates/exception.html.ep b/templates/exception.html.ep
index 65ec7ff..7654c0b 100644
--- a/templates/exception.html.ep
+++ b/templates/exception.html.ep
@@ -5,7 +5,7 @@ Beim Bearbeiten der Anfrage ist ein Fehler aufgetreten.<br/>
<pre>
----------[Debug start]----------
% if ($exception) {
-%= $exception->message
+%= ref($exception) ? $exception->message : $exception
Stash:
%= dumper $snapshot
% }
diff --git a/templates/landingpage.html.ep b/templates/landingpage.html.ep
index 17bb2bb..80fd34f 100644
--- a/templates/landingpage.html.ep
+++ b/templates/landingpage.html.ep
@@ -12,8 +12,9 @@
% }
% else {
<p>
- DBF ist ein inoffizieller Abfahrtsmonitor für den Regional- und Fernverkehr mit dem Ziel, Daten aus verschiedenen Quellen übersichtlich zusammenzutragen.
- Der Fokus liegt auf Zügen im Netz der Deutschen Bahn; eingeschränkte Unterstützung für Nahverkehr und Züge in anderen Netzen lässt sich optional zuschalten.
+ DBF ist ein inoffizieller Abfahrtsmonitor für Nah-, Regional- und Fernverkehr in Deutschland und Umgebung mit dem Ziel, Daten aus verschiedenen Quellen zusammenzutragen.
+ Es unterstützt neben Fahrten im Netz der DB InfraGO diverse Nah- und Fernverkehrsunternehmen mit EFA- und HAFAS-Backends.
+ Die Fahrten in der Übersicht verlinken je eine Detailseite mit Unterwegshalten, Meldungen und Kartendarstellung.
</p>
<p>
Diese Seite ist ein kostenfreies, privat betriebenes Projekt ohne Verfügbarkeitsgarantie.
@@ -21,10 +22,10 @@
</p>
% }
<p class="geolink">
-<a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https')->query({hafas => param('hafas')}) %>">Stationen in der Umgebung suchen</a>
+<a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https')->query({efa => param('efa'), hafas => param('hafas')}) %>">Stationen in der Umgebung suchen</a>
</p>
<p>
-Oder hier angeben:
+Oder hier eine Station angeben:
</p>
</div>
% }
diff --git a/templates/layouts/app.html.ep b/templates/layouts/app.html.ep
index 1578298..c557bee 100644
--- a/templates/layouts/app.html.ep
+++ b/templates/layouts/app.html.ep
@@ -4,8 +4,8 @@
<title><%= stash('title') // 'DBF' %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="keywords" content="Abfahrtsmonitor, Bahnhofstafel, Abfahrten, Abfahrtstafel, ICE, IC, RE, RB, S-Bahn">
- <meta name="description" content="<%= stash('description') // 'Inoffizieller Abfahrtsmonitor für innerdeutsche Zugfahrten' %>">
+ <meta name="keywords" content="Abfahrtsmonitor, Bahnhofstafel, Abfahrten, Abfahrtstafel, Nahverkehr, Regionalverkehr, Fernverkehr, ICE, IC, RE, RB, S-Bahn">
+ <meta name="description" content="<%= stash('description') // 'Inoffizieller Abfahrtsmonitor für Nah-, Reginol- und Fernverkehr' %>">
<meta name="theme-color" content="#00838f">
<link rel="icon" type="image/png" href="/static/icons/icon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="/static/icons/icon-32x32.png" sizes="32x32">
@@ -18,7 +18,7 @@
<meta http-equiv="refresh" content="<%= $self->stash('refresh_interval') %>"/>
% }
- % my $av = 'v96'; # asset version
+ % my $av = 'v110'; # asset version
% if (session('theme') and session('theme') eq 'dark' or param('dark')) {
%= stylesheet "/static/${av}/css/dark.min.css", id => 'theme'
% }
@@ -117,43 +117,36 @@ 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">
- <div class="desc">Zug / Station</div>
- <div>
-% if (stash('stationlist')) {
+% if (stash('stationlist')) {
%= select_field input => stash('stationlist')
-% }
-% elsif (stash('input')) {
- %= text_field 'input', class => 'station', placeholder => 'Zug, Stationsname oder Ril100-Kürzel', id => 'stationinput'
-% }
-% else {
- %= text_field 'input', class => 'station', placeholder => 'Zug, Stationsname oder Ril100-Kürzel', id => 'stationinput', autofocus => 'autofocus'
-% }
- </div>
+% }
+% elsif (stash('input')) {
+ %= text_field 'input', class => 'station', placeholder => 'Stationsname oder Fahrtnummer', id => 'stationinput'
+% }
+% else {
+ %= text_field 'input', class => 'station', placeholder => 'Stationsname oder Fahrtnummer', id => 'stationinput', autofocus => 'autofocus'
+% }
</div>
<div class="field">
%= submit_button 'Abfahrtstafel'
</div>
% if (stash('input')) {
<div class="geolink">
- <a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https')->query({hafas => param('hafas')}) %>">Stationen in der Umgebung suchen</a>
+ <a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https')->query({efa => param('efa'), hafas => param('hafas')}) %>">Stationen in der Umgebung suchen</a>
</div>
% }
+ <div class="backendlink">
+ <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>
<div class="moresettings moresettings-collapsed">
<div class="field">
<div class="desc">
- %= check_box 'rt' => 1, id => 'id_show_realtime'
- <label for="id_show_realtime">
- Zeiten inkl. Verspätung angeben
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
%= check_box 'hidelowdelay' => 1, id => 'id_hidelowdelay'
<label for="id_hidelowdelay">
Verspätungen erst ab 5 Minuten anzeigen
@@ -170,17 +163,9 @@ Bitte eine Station aus der Liste auswählen</div>
</div>
<div class="field">
<div class="desc">
- %= check_box 'no_related' => 1, id => 'id_no_related'
- <label for="id_no_related">
- Betriebliche Bahnhofstrennungen berücksichtigen (z.B. "Hbf (Fern+Regio)" vs. "Hbf (S)")
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
%= check_box 'past' => 1, id => 'past'
<label for="past">
- Bereits abgefahrene Züge anzeigen
+ Fahrten der vergangenen 60 Minuten zeigen
</label>
</div>
</div>
@@ -194,7 +179,7 @@ Bitte eine Station aus der Liste auswählen</div>
</div>
<div class="field">
<div class="desc">
- Nur Züge über
+ Nur Fahrten über
</div>
<div>
%= text_field 'via', placeholder => 'Bahnhof 1, Bhf2, ... (oder regulärer Ausdruck)', class => 'station'
@@ -270,21 +255,22 @@ Bitte eine Station aus der Liste auswählen</div>
(z.B. als alleinstehender Infoscreen) gibt es den "Infoscreen"-Modus.</li>
<li>Die Abfahrtstafel unterstützt Namen, EVA-IDs, und (im IRIS-Backend)
DS100/Ril100-Codes zur Identifikation von Stationen.</li>
- <li>Zugdetails können optional für spezifische Abfahrtsdaten im
+ <li>Abfahrten werden mit Echtzeitdaten bzw. Prognosen angegeben und
+ danach sortiert. Mit dem Parameter
+ <span style="font-family: monospace;">rt=0</span> wwerden stattdessen
+ Plandaten angegeben und zur Sortierung genutzt.</li>
+ <li>Bei HAFAS-Backends können optional Details für spezifische Fahrten im
DD.MM.[YYYY]-Format abgefragt werden, z.B. "ICE 921 (1.1.)" oder
"ICE 921 @ 1.1.". Das Datum bezieht sich auf die geplante
- Abfahrtszeit am Startbahnhof der Zugfahrt.</li>
- <li>Die Parameter <span style="font-family: monospace;">mode=json&amp;version=3</span>
- (alternativ <span style="font-family:
- monospace;">https://dbf.finalrewind.org/Bahnhofsname.json?version=3</span>)
- bieten ein JSON-IRIS-Interface. Die route-Elemente können zusätzlich
- die Felder "isAdditional" oder "isCancelled" enthalten, der Rest sollte
- selbsterklärend sein. Im Fehlerfall fehlt das "departures"-Element,
- stattdessen wird ein "error"-Element mit Fehlermeldung zurückgegeben.
- Bitte maximal 30 Anfragen pro Minute und insbesondere nur eine Anfrage
+ Abfahrtszeit am Startbahnhof der Fahrt.</li>
+ <li>Viele Seiten sind auch als JSON verfügbar, wahlweise mittels
+ <span style="font-family: monospace;">Accept: application/json</span> oder
+ durch <span style="font-family: monospace;">.json</span> in der URL.
+ HAFAS- und IRIS-Abfahrtstafeln liefern mit dem GET-Parameter <span style="font-family: monospace;">version=3</span> eine stabile JSON-API.
+ Alle anderen Endpunkte (sowie Abfahrtstafeln mit <span style="font-family: monospace;">version=raw</span>) erlauben direkten Zugriff auf die serialisierten Travel::Status::DE::{EFA,HAFAS,IRIS}-Objekte ohne stabile API.</li>
+ <li>Bitte maximal 30 Anfragen pro Minute und insbesondere nur eine Anfrage
pro Station und Minute – eine höhere Auflösung haben die Backenddaten
ohnehin nicht.</li>
- <li>Ein JSON-Interface für Zugdetails ist in Arbeit.</li>
<li>Mit <span style="font-family: monospace;">limit</span> kann die Anzahl der
angezeigten / im JSON enthaltenen Abfahrten eingeschränkt werden, z.B.
<span style="font-family: monospace;">limit=10</span> für die ersten zehn.</li>
@@ -302,7 +288,7 @@ Bitte eine Station aus der Liste auswählen</div>
<div class="container">
<div class="config">
Farbschema:
-<a onClick="javascript:setTheme('light')">light</a>
+<a onClick="javascript:setTheme('light')">hell</a>
·
<a onClick="javascript:setTheme('dark')">dunkel</a>
·
@@ -315,7 +301,11 @@ Farbschema:
·
<a onClick="javascript:setLang('default')">system language</a>
-->
-</div>
+</div> <!-- config -->
+</div> <!-- container -->
+% }
+% if (not stash('hide_footer')) {
+<div class="container">
<div class="about">
<a href="_about">DBF</a> v<%= stash('version') // '???' %>
·
diff --git a/templates/layouts/legacy.html.ep b/templates/layouts/legacy.html.ep
index 43a3cc5..e7e59ec 100644
--- a/templates/layouts/legacy.html.ep
+++ b/templates/layouts/legacy.html.ep
@@ -17,7 +17,7 @@
<meta http-equiv="refresh" content="<%= $self->stash('refresh_interval') %>"/>
% }
- % my $av = 'v96'; # asset version
+ % my $av = 'v110'; # asset version
%= stylesheet "/static/${av}/css/legacy.css"
%= stylesheet "/static/${av}/css/material-icons.css"
%= stylesheet "/static/${av}/css/jquery-ui.min.css"
@@ -62,169 +62,5 @@ Bitte eine Station aus der Liste auswählen</div>
%= content
</div>
-% if (not stash('hide_opts')) {
-<div class="container">
-<div class="input-field">
-
-
-%= form_for _redirect => begin
-<div>
- <div class="field">
- <div class="desc">Bahnhof / Haltestelle</div>
- <div>
-% if (stash('stationlist')) {
- %= select_field input => stash('stationlist')
-% }
-% elsif (stash('input')) {
- %= text_field 'input', class => 'station', placeholder => 'Name oder Ril100-Kürzel'
-% }
-% else {
- %= text_field 'input', class => 'station', placeholder => 'Name oder Ril100-Kürzel', autofocus => 'autofocus'
-% }
- </div>
- </div>
- <div class="field">
- %= submit_button 'Abfahrtsmonitor'
- </div>
- % if (not stash('show_intro')) {
- <div class="break"></div>
- <div class="field">
- <a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https') %>">Bahnhöfe im Umfeld suchen</a>
- </div>
- % }
- <div class="break"></div>
- <div class="moresettings-header moresettings-header-collapsed button button-light">Weitere Einstellungen</div>
- <div class="moresettings moresettings-collapsed">
- <div class="field">
- <div class="desc">
- Frontend
- </div>
- <div>
- %= select_field mode => [ ['App' => 'app'], ['Infoscreen' => 'infoscreen'], ['Bahnhofstafel' => 'multi'], ['Gleisanzeiger' => 'single'] ]
- </div>
- </div>
- <div class="field">
- <div class="desc">
- Nur Züge über
- </div>
- <div>
- %= text_field 'via', placeholder => 'Bahnhof 1, Bhf2, ... (oder regulärer Ausdruck)', class => 'station'
- </div>
- </div>
- <div class="field">
- <div class="desc">
- Gleise
- </div>
- <div>
- %= text_field 'platforms', placeholder => '1, 2, 5, ...'
- </div>
- </div>
- <div class="field">
- <div class="desc">
- %= check_box 'hidelowdelay' => 1, id => 'id_hidelowdelay'
- <label for="id_hidelowdelay">
- Nur Verspätungen &gt;5 Min. anzeigen
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
- %= check_box 'dark' => 1, id => 'id_dark'
- <label for="id_dark">
- Dunkles Layout (experimentell)
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
- %= check_box 'hide_opts' => 1, id => 'id_hide_opts'
- <label for="id_hide_opts">
- Formular verstecken (für Infoscreens)
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
- Ankunfts- oder Abfahrtszeit anzeigen?
- </div>
- <div>
- %= select_field admode => [['Abfahrt bevorzugen' => 'deparr'], ['Nur Abfahrt' => 'dep'], ['Nur Ankunft' => 'arr']]
- </div>
- </div>
- <div class="field">
- <div class="desc">
- %= check_box 'detailed' => 1, id => 'id_detailed'
- <label for="id_detailed">
- Mehr Details (Zugnummern und Ankunftszeiten) anzeigen
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
- %= check_box 'rt' => 1, id => 'id_show_realtime'
- <label for="id_show_realtime">
- Echtzeitangaben statt Fahrplandaten anzeigen
- </label>
- </div>
- </div>
- <div class="field">
- <div class="desc">
- %= check_box 'no_related' => 1, id => 'id_no_related'
- <label for="id_no_related">
- Betriebliche Bahnhofstrennungen berücksichtigen (z.B. "Hbf (Fern+Regio)" vs. "Hbf (S)")
- </label>
- </div>
- </div>
- <div class="field">
- %= submit_button 'Anzeigen'
- </div>
- </div> <!-- moresettings -->
-</div>
-% end
-
-</div> <!-- input-field -->
-
-<div class="notes">
- <div class="developers-header developers-header-collapsed button button-light">API- und Entwickler-Hinweise</div>
- <div class="developers developers-collapsed">
- <ul>
- <li>Diese Seite kann gerne als iframe in eigene Infoscreens o.ä. eingebunden werden.
- Für eine kleine Ansicht (z.B. iframe in einer normalen Website) bitte das
- "App"-Frontend verwenden. Für eine große Ansicht
- (z.B. als alleinstehender Infoscreen) gibt es das "Infoscreen"-Frontend.</li>
- <li>Die Parameter <span style="font-family: monospace;">mode=json&amp;version=3</span>
- (alternativ auch <span style="font-family:
- monospace;">https://dbf.finalrewind.org/Bahnhofsname.json?version=3</span>)
- bieten ein JSON-IRIS-Interface. Die route-Elemente können zusätzlich
- die Felder "isAdditional" oder "isCancelled" enthalten, der Rest sollte
- selbsterklärend sein. Im Fehlerfall fehlt das "departures"-Element,
- stattdessen wird ein "error"-Element mit Fehlermeldung zurückgegeben.
- Bitte nur eine Anfrage pro Station und Minute
- – eine höhere Auflösung haben die Backenddaten ohnehin nicht.</li>
- <li>Mit <span style="font-family: monospace;">limit</span> kann die Anzahl der
- angezeigten / im JSON enthaltenen Abfahrten eingeschränkt werden, z.B.
- <span style="font-family: monospace;">limit=10</span> für die ersten zehn.</li>
- <li>Dieser Dienst ist Open Source-Software (Links siehe unten) und kann auch
- auf eigenen Servern installiert werden. Automatisierte Crawler, die mehrere
- Dutzend Stationen pro Minute abfragen, bitte nur auf eigenen Instanzen
- betreiben.</li>
- </ul>
- </div> <!-- developers -->
-</div> <!-- notes -->
-
-</div> <!-- container -->
-
-<div class="container">
-<div class="about">
-<a href="_about">Über DBF</a>
-<a href="_datenschutz" rel="nofollow">Datenschutz</a>
-<a href="_impressum" rel="nofollow">Impressum</a><br/>
-Version <%= stash('version') // '???' %>
-</div> <!-- about -->
-</div> <!-- container -->
-% }
-
</body>
</html>
diff --git a/templates/route_map.html.ep b/templates/route_map.html.ep
index 447960a..e1c4642 100644
--- a/templates/route_map.html.ep
+++ b/templates/route_map.html.ep
@@ -3,7 +3,7 @@
% }
<div class="container">
- <div id="map" style="height: 500px;">
+ <div id="map" style="height: 70vh;">
</div>
</div>
@@ -79,18 +79,20 @@ var marker;
</script>
<div class="container" style="margin-top: 1ex; margin-bottom: 1ex; color: #555;">
-Die eingezeichnete Route stammt aus dem HAFAS und ist im Detail oft
-fehlerbehaftet.<br/>
-Die Zugposition auf der Karte ist eine DBF-eigene Schätzung und kann erheblich
-von den tatsächlichen Gegebenheiten abweichen.
+<p>
+Die eingezeichnete Route stammt aus dem angefragten Backend und stimmt nicht
+notwendigerweise mit der Realität überein.
+Die Fahrzeugposition auf der Karte ist eine DBF-eigene Schätzung und kann
+erheblich von den tatsächlichen Gegebenheiten abweichen.
% if (stash('intersection')) {
<br/>In dieser Ansicht sind Live-Updates der Zug- und Begegnungspositionen noch
nicht implementiert.
% }
+</p>
</div>
% if (my $op = stash('operator')) {
<div class="container" style="margin-top: 1ex; margin-bottom: 1ex; color: #555;">
-Betrieb: <%= $op %>
+<p>Betrieb: <%= $op %></p>
</div>
% }
diff --git a/templates/select_backend.html.ep b/templates/select_backend.html.ep
new file mode 100644
index 0000000..c6d2a4c
--- /dev/null
+++ b/templates/select_backend.html.ep
@@ -0,0 +1,46 @@
+<div class="container">
+ <p>
+ Das Backend bestimmt die Datenquelle für Stations- und Zuginformationen.
+ Innerhalb Deutschlands ist <strong>Deutsche Bahn</strong> via IRIS-TTS eine gute Wahl für Schienenverkehr im Bahnnetz.
+ Die anderen Backends bieten sich für Fahrten im zugehörigen Verkehrsverbund (inklusive Nahverkehr) sowie im Ausland an.
+ Sofern bekannt sind unterhalb der Backend-Namen Karten verlinkt, die die ungefähre Abdeckung aufzeigen.
+ Ein Backend, welches Nah- und Fernverkehr in ganz Deutschland abdeckt, ist aktuell leider nicht verfügbar.
+ </p>
+ <p>
+ % my $prev_type = 'IRIS-TTS';
+ % for my $backend (@{$backends}) {
+ <p>
+ % if ($backend->{type} ne $prev_type) {
+ % $prev_type = $backend->{type};
+ <%= $prev_type %>:<br/>
+ % }
+ % my $class = 'button';
+ % 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->{efa} or $backend->{hafas})) {
+ % $class .= ' button-active';
+ % }
+ % }
+ <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>
+ % }
+ % else {
+ %= join(q{, }, @{$backend->{regions} // []})
+ % }
+ % if ($backend->{homepage}) {
+ (<a href="<%= $backend->{homepage} %>"><%= $backend->{homepage} =~ s{ ^ http s? :// (?: www[.] )? (.*?) (?: / )? $ }{$1}xr %></a>)
+ % }
+ </p>
+ % }
+ </p>
+</div>
diff --git a/templates/wagenreihung.html.ep b/templates/wagenreihung.html.ep
index 493d9c6..19c49ab 100644
--- a/templates/wagenreihung.html.ep
+++ b/templates/wagenreihung.html.ep
@@ -1,64 +1,56 @@
-% if (not $wr or $wr->errstr) {
+% if (not $wr or $wr_error) {
<div class="container">
<div class="error">
<strong>Fehler bei der Abfrage der Wagenreihung:</strong>
- <%= $wr ? $wr->errstr : $wr_error %>
+ <%= $wr_error // 'Unbekannter Fehler' %>
</div>
</div>
% }
% else {
- % my $has_multi_dest = 0;
- % my $has_multi_desc = 0;
- % if (scalar $wr->destinations > 1) {
- % $has_multi_dest = 1;
- % }
- % if (scalar $wr->train_descriptions > 1) {
- % $has_multi_desc = 1;
- % }
<div class="container">
<div style="text-align: center;">
-%= join( ' / ', $wr->origins )
- →
-%= join( ' / ', map { $_->{name} } $wr->destinations )
+ Gleis <%= $wr->platform %><br/>
</div>
- % if ($has_multi_dest) {
- <div style="text-align: center;">
- % for my $destination ($wr->destinations) {
- Nach <%= $destination->{name} %> in Abschnitt <%= join(q{}, sort @{$destination->{sections} // []}) %><br/>
- % }
- </div>
- % }
- <%= $wr->station_name %> Gleis <%= $wr->platform %><br/>
- % for my $desc ($wr->train_descriptions) {
- % if ($desc->{text}) {
- %= $desc->{text}
- % if ($has_multi_desc and length(join(q{}, sort @{$desc->{sections}}))) {
- in Abschnitt <%= join(q{}, sort @{$desc->{sections}}) %>
- % }
- <br/>
- % }
- % }
</div>
<div class="container">
<div class="wagonorder exit-<%= stash('exit_dir') // 'unknown'%>">
-% if (not $wr->has_bad_wagons) {
-% for my $section ($wr->sections) {
- <div class="section" style="
- top: <%= $section->{start_percent} %>%; bottom: <%= 100 - $section->{end_percent} %>%;">
-%= $section->{name}
- </div>
-% }
+% for my $sector ($wr->sectors) {
+ <div class="section" style="
+ top: <%= $sector->start_percent %>%; bottom: <%= 100 - $sector->end_percent %>%;">
+%= $sector->name
+ </div>
% }
-% for my $wagon ($wr->wagons) {
-%= include '_wagon', direction => $wr->direction, wagon => $wagon, type => $wr->train_type, wref => $wref, exit_dir => stash('exit_dir');
+% for my $group ($wr->groups) {
+% my $first = 1;
+% for my $wagon ($group->carriages) {
+%= include '_wagon', wr => $wr, group => $group, wagon => $wagon, first => $first, multi => (scalar $wr->destinations) - 1 + (scalar $wr->train_numbers) - 1, wref => $wref, exit_dir => stash('exit_dir'), train_no => param('number');
+% $first = 0;
+% }
% }
</div>
+ % for my $group ($wr->groups) {
+ % if ($group->description) {
+ <div style="text-align: center;">
+ %= $group->description
+ % if ($group->designation) {
+ „<%= $group->designation %>“
+ % }
+ % if (scalar $wr->groups > 1 and $group->has_sectors) {
+ in Abschnitt <%= join(q{}, sort $group->sectors) %>
+ % }
+ </div>
+ % }
+ % }
+ <div style="text-align: center;">
+ nach
+%= join( ' / ', map { $_->{name} } $wr->destinations )
+ </div>
<!-- <div>
Legende: ♿ Behindertengerechte Ausstattung / 🍴 Bistro/Restaurant / 🚪 Abteile vorhanden
</div>
-->
<p class="copyright">
- Quelle: DB Wagenreihungs-API. Angaben ohne Gewähr.
+ Quelle: DB Wagenreihungs-API (<%= stash('ts') // q{} %>). Angaben ohne Gewähr.
</p>
</div>