summaryrefslogtreecommitdiff
path: root/templates
diff options
context:
space:
mode:
Diffstat (limited to 'templates')
-rw-r--r--templates/_intersection_infobox.html.ep22
-rw-r--r--templates/_map_infobox.html.ep10
-rw-r--r--templates/_train_attr.html.ep17
-rw-r--r--templates/_train_details.html.ep331
-rw-r--r--templates/_wagon.html.ep28
-rw-r--r--templates/about.html.ep72
-rw-r--r--templates/app.html.ep23
-rw-r--r--templates/exception.html.ep7
-rw-r--r--templates/geotrain.html.ep5
-rw-r--r--templates/landingpage.html.ep34
-rw-r--r--templates/layouts/app.html.ep157
-rw-r--r--templates/layouts/legacy.html.ep15
-rw-r--r--templates/route_map.html.ep3
-rw-r--r--templates/trainsearch.html.ep29
-rw-r--r--templates/wagenreihung.html.ep52
15 files changed, 446 insertions, 359 deletions
diff --git a/templates/_intersection_infobox.html.ep b/templates/_intersection_infobox.html.ep
deleted file mode 100644
index cb27d19..0000000
--- a/templates/_intersection_infobox.html.ep
+++ /dev/null
@@ -1,22 +0,0 @@
-<div class="container" id="infobox2" style="margin-top: 1ex; margin-bottom: 1ex;">
-<div class="journey" id="jdata"
-data-req="<%= stash('ajax_req') %>"
-data-route="<%= stash('ajax_route') %>"
-data-poly="<%= stash('ajax_polyline') %>"
->
- <strong><%= stash('train1_no') %></strong>
- und
- <strong><%= stash('train2_no') %></strong>
- werden sich wahrscheinlich
- % if (my $t = stash('time')) {
- gegen <strong><%= $t->strftime('%H:%M') %> Uhr</strong>
- % }
- % if (my $p = stash('likely_pair')) {
- zwischen <strong><%= $p->[0] %></strong> und <strong><%= $p->[1] %></strong>
- % }
- % if (not stash('time')) {
- nicht
- % }
- begegnen.
-</div>
-</div>
diff --git a/templates/_map_infobox.html.ep b/templates/_map_infobox.html.ep
index 42e121d..7372802 100644
--- a/templates/_map_infobox.html.ep
+++ b/templates/_map_infobox.html.ep
@@ -1,6 +1,6 @@
<div class="container" id="infobox" style="margin-top: 1ex; margin-bottom: 1ex;">
<div class="journey" id="jdata"
-data-req="<%= stash('ajax_req') %>"
+data-req="<%= stash('ajax_req') =~ s{#}{%23}gr %>"
data-route="<%= stash('ajax_route') %>"
data-poly="<%= stash('ajax_polyline') %>"
>
@@ -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}{name} %></strong>
+ Aufenthalt in <strong><%= $next->{station}->loc->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}{name} %></strong>
+ Abfahrt in <strong><%= $next->{station}->loc->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}{name} %></strong>
+ <strong><%= $next->{station}->loc->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}{name} %></strong>
+ <strong><%= $next->{station}->loc->name %></strong>
% if ($next->{station}{platform}) {
auf Gleis <strong><%= $next->{station}{platform} %></strong>
% }
diff --git a/templates/_train_attr.html.ep b/templates/_train_attr.html.ep
index 4f7e9ca..1b40d12 100644
--- a/templates/_train_attr.html.ep
+++ b/templates/_train_attr.html.ep
@@ -1,19 +1,18 @@
% if ($attr->{series}) {
- <span>BR <%= $attr->{series} %>
-% if ($attr->{series2}) {
- + <%= $attr->{series2} %>
-% }
- </span>
+ <span>BR <%= $attr->{series} %></span>
+% }
+% if ($attr->{vmax}) {
+ <span><%= $attr->{vmax} %> km/h</span>
% }
% if ($attr->{length}) {
<span>⇤ <%= $attr->{length} %>m ⇥</span>
% }
-% if ($attr->{vmax}) {
- <span><%= $attr->{vmax} %> km/h</span>
+% if ($attr->{weight}) {
+ <span><%= $attr->{weight} %>t</span>
% }
% if ($attr->{brakingPercentage}) {
<span>λ=<%= $attr->{brakingPercentage} %></span>
% }
-% if ($attr->{station} and $with_station) {
- <span>ab <%= $attr->{station} %></span>
+% if ($with_station and $attr->{range}[0]) {
+ <span>ab <%= $attr->{range}[0] %></span>
% }
diff --git a/templates/_train_details.html.ep b/templates/_train_details.html.ep
index 26c2eb4..f560950 100644
--- a/templates/_train_details.html.ep
+++ b/templates/_train_details.html.ep
@@ -2,9 +2,6 @@
<div>
% if ($departure->{train_no} or $departure->{train_line}) {
<span class="train-line <%= $linetype %>"><%= $departure->{train_type} %>
-% if ($linetype eq 'fern' and $icetype and $icetype->[1]) {
- <span class="trainsubtype" aria-hidden="true"><%= $icetype->[1] %></span>
-% }
<%= $departure->{train_line} // $departure->{train_no} %></span>
<span class="train-no"><%= $departure->{train_line} ? $departure->{train_no} : q{} %></span>
@@ -17,33 +14,11 @@
% }
<span class="train-dest"><%= $departure->{destination} // q{???} %></span>
</div>
-<!--
-% if ($departure->{is_cancelled}) {
- <div class="minfo">Fahrt fällt aus</div>
-% }
-% elsif (defined $departure->{delay} and $departure->{delay} > 0) {
- <div class="minfo">+<%= $departure->{delay} %>
-% if ($departure->{departure_is_cancelled}) {
- (endet hier)
-% }
- </div>
-% }
-% if (@{$departure->{replaced_by}}) {
-% for my $replacement (@{$departure->{replaced_by}}) {
- <span class="replaced">Ersatzzug: <%= $replacement %></span>
-% }
-% }
-% if (@{$departure->{replacement_for}}) {
-% for my $replacement (@{$departure->{replacement_for}}) {
- <span class="replacement">Ersatzzug für <%= $replacement %></span>
-% }
-% }
--->
</div> <!-- mheader -->
<div class="mfooter">
<div class="dataline">
<div>
- <div class="arrival">
+ <div class="arrival <%= $departure->{arrival_hidden} ? 'timehidden' : q{} %>">
% if ($departure->{is_cancelled} and $departure->{sched_arrival}) {
<span class="minfo">An: ––:––</span><br/>Plan: <%= $departure->{sched_arrival} %>
% }
@@ -52,7 +27,7 @@
% }
% elsif ($departure->{arrival}) {
% if ($departure->{arrival} ne $departure->{sched_arrival}) {
- % if ($departure->{delay} < 0) {
+ % if (($departure->{arrival_delay} // 0) < 0) {
An: <span class="undelay"><%= $departure->{arrival} %></span>
% }
% else {
@@ -64,20 +39,39 @@
An: <%= $departure->{arrival} %>
% }
% }
+% elsif ($departure->{sched_arrival}) {
+ An: <%= $departure->{sched_arrival} %>
+% }
+% elsif ($departure->{prep_time}) {
+ Ein: <%= $departure->{prep_time} %>
+% }
+% if ($departure->{tz_offset} and $departure->{local_sched_arr}) {
+ <br/>Lokal: <%= $departure->{local_sched_arr}->strftime('%H:%M') %>
+% }
</div>
</div>
<div>
<div class="platform">
+% if (@{$departure->{replaced_by}}) {
+% for my $replacement (@{$departure->{replaced_by}}) {
+ <span class="replaced">Ersatzfahrt: <a href="/z/<%= $replacement %>/<%= stash('station_name') // q{} %>"><%= $replacement %></a></span><br/>
+% }
+% }
+% if (@{$departure->{replacement_for}}) {
+% for my $replacement (@{$departure->{replacement_for}}) {
+ <span class="replacement">Ersatzfahrt für <a href="/z/<%= $replacement %>/<%= stash('station_name') // q{} %>"><%= $replacement %></a></span><br/>
+% }
+% }
% if ($departure->{arrival_is_cancelled} and $departure->{departure_is_cancelled}) {
<span class="minfo">Fahrt fällt aus</span>
% }
% else {
% my $left = '';
% my $right = '';
-% if ($departure->{direction} and $departure->{direction} eq 'l') {
+% if ($departure->{wr_direction} and $departure->{wr_direction} eq 'l') {
% $left = '◀ ';
% }
-% elsif ($departure->{direction} and $departure->{direction} eq 'r') {
+% elsif ($departure->{wr_direction} and $departure->{wr_direction} eq 'r') {
% $right = ' ▶';
% }
% if ($departure->{scheduled_platform} and $departure->{platform}
@@ -88,10 +82,16 @@
<%= $left %>Gleis <%= $departure->{platform} // $departure->{scheduled_platform} %><%= $right %>
% }
% }
+% if ($departure->{arrival_hidden} and not $departure->{prep_time}) {
+ <br/><span class="timehidden">Nur Einstieg</span>
+% }
+% if ($departure->{departure_hidden}) {
+ <br/><span class="timehidden">Nur Ausstieg</span>
+% }
</div>
</div>
<div>
- <div class="departure">
+ <div class="departure <%= $departure->{departure_hidden} ? 'timehidden' : q{} %>">
% if ($departure->{is_cancelled} and $departure->{sched_departure}) {
<span class="minfo">Ab: ––:––</span><br/>Plan: <%= $departure->{sched_departure} %>
% }
@@ -107,27 +107,56 @@
Ab: <%= $departure->{departure} %>
% }
% }
+% elsif ($departure->{sched_departure}) {
+ Ab: <%= $departure->{sched_departure} %>
+% }
+% if ($departure->{tz_offset} and $departure->{local_sched_dep}) {
+ <br/>Lokal: <%= $departure->{local_sched_dep}->strftime('%H:%M') %>
+% }
</div>
</div>
</div> <!-- dataline -->
+% if (my $wr = $departure->{wr}) {
+ <div class="wagonorder-preview">
+% 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} eq 'l') {
+% $left = '◀';
+% $right = q{};
+% }
+% elsif ($departure->{wr_direction} and $departure->{wr_direction} eq 'r') {
+% $left = q{};
+% $right = '▶';
+% }
+ <a href="/_wr/<%= $departure->{train_no} %>/<%= $departure->{wr_link} %>?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} %>/<%= $departure->{train_line} // 0 %>?from=<%= stash('station_name') %>"><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;hafas=<%= param('hafas') // q{} %>"><i class="material-icons" aria-hidden="true">map</i> Karte</a>
% }
% else {
- <a class="smallbutton" href="/map/<%= $departure->{trip_id} %>/<%= $departure->{train_line} // 0 %>"><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 %>?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> Wagenreihung
+ <a class="smallbutton" href="/_wr/<%= $departure->{train_no} %>/<%= $departure->{wr_link} %>?e=<%= $departure->{wr_direction} // '' %>"><i class="material-icons" aria-hidden="true">train</i> <%= $departure->{wr_text} || 'Wagen' %>
</a>
% }
-% elsif ($icetype and $icetype->[2] and ($linetype eq 'fern' or $departure->{train_type} =~ m{NJ})) {
- <a class="smallbutton" href="/wr/<%= $departure->{train_no} %>"><i class="material-icons" aria-hidden="true">train</i> Plan: <%= $icetype->[0] %></a>
-% }
-% elsif ($icetype and $icetype->[1] and $linetype eq 'fern') {
- <span class="disabledbutton"><i class="material-icons" aria-hidden="true">train</i> Plan: <%= $icetype->[0] %></span>
+% if ($departure->{train_type} and $departure->{train_no}) {
+ <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}}) {
<a class="smallbutton" href="<%= $link->[1] %>"><i class="material-icons" aria-hidden="true">warning</i> <%= $link->[0] %></a>
@@ -161,11 +190,11 @@
% }
% if ($departure->{moreinfo} and @{$departure->{moreinfo}}) {
- Meldungen:
- <ul>
+ Meldungen
+ <ul class="messages">
% for my $pair (@{$departure->{moreinfo}}) {
<li>
-% if ($pair->[0]->isa('DateTime')) {
+% if (ref($pair->[0]) eq 'DateTime') {
% if ($pair->[0]->day != $dt_now->day) {
% $pair->[0]->set_locale('de_DE');
%= $pair->[0]->strftime('%a %H:%M')
@@ -173,16 +202,22 @@
% else {
%= $pair->[0]->strftime('%H:%M')
% }
+ <span class="reason">
+%= $pair->[1]
+ </span>
% }
% else {
+% if ($pair->[1]{icon}) {
+ <i class="material-icons"><%= $pair->[1]{icon} %></i>
+% }
%= $pair->[0]
% if (length($pair->[0]) > 25) {
<br/>
% }
+ <span class="reason">
+%= $pair->[1]{text}
+ </span>
% }
- <span class="reason">
-%= $pair->[1]
- </span>
</li>
% }
% if ($departure->{route_info}) {
@@ -191,11 +226,33 @@
</ul>
% }
% if ($departure->{route_pre_diff} and $departure->{route_post_diff}) {
- Fahrtverlauf:
+% if ($departure->{date}) {
+ Fahrtverlauf am
+% if (stash('train') !~ m{[|]}) {
+ <a href="<%= url_for('train', train => stash('train'))->query({detailed => param('detailed'), past => param('past'), rt => param('rt'), hafas => param('hafas'), date => $departure->{date}->clone->subtract(days => 1)->strftime('%d.%m.%Y'), highlight => param('highlight') // stash('station')}) %>">◀</a>
+% }
+%= $departure->{date}->strftime('%d.%m.%Y')
+% if (stash('train') !~ m{[|]}) {
+ <a href="<%= url_for('train', train => stash('train'))->query({detailed => param('detailed'), past => param('past'), rt => param('rt'), hafas => param('hafas'), date => $departure->{date}->clone->add(days => 1)->strftime('%d.%m.%Y'), highlight => param('highlight') // stash('station')}) %>">▶</a>
+% }
+% }
<ul class="mroute">
% for my $stop (@{$departure->{route_pre_diff}}) {
+% if ($stop->{is_annotated} and $stop->{prod_name}) {
+ <li class="annotation">
+% if ($stop->{prod_name}) {
+%= $stop->{prod_name}
+% }
+% if ($stop->{direction}) {
+ → <%= $stop->{direction} %>
+% }
+% if ($stop->{operator}) {
+ (<%= $stop->{operator} %>)
+% }
+ </li>
+% }
<li class="<%= $stop->{isPast} ? 'past-stop' : 'future-stop' %>">
- <a href="<%= url_for('station', station => $stop->{name})->query({detailed => param('detailed'), past => param('past')}) %>#<%= ($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'), hafas => param('hafas')}) %>#<%= ($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x}) %>" class="
% if ($stop->{isAdditional}) {
additional-stop
% }
@@ -208,39 +265,85 @@
% else {
generic-stop
% }
-% if ($stop->{rt_dep}) {
- "><%= $stop->{sched_dep}->strftime('%H:%M') %> (heute <%= $stop->{rt_dep}->strftime('%H:%M') %>) <%= $stop->{name} %></a>
+% if (($stop->{rt_dep} and $stop->{dep_delay}) or (not $stop->{rt_dep} and $stop->{rt_arr} and $stop->{arr_delay})) {
+ "><span class="time-sched-only"><%= ($stop->{sched_dep} // $stop->{sched_arr})->strftime('%H:%M') %></span> <span class="time-delayed"><%= ($stop->{rt_dep} // $stop->{rt_arr})->strftime('%H:%M') %></span>
+% }
+% elsif (($stop->{rt_dep} and defined $stop->{dep_delay}) or (not $stop->{rt_dep} and $stop->{rt_arr} and defined $stop->{arr_delay})) {
+ "><span class="time-sched-ontime"><%= ($stop->{sched_dep} // $stop->{sched_arr}) ? ($stop->{sched_dep} // $stop->{sched_arr})->strftime('%H:%M') : q{} %></span>
% }
% else {
- "><%= $stop->{sched_dep} ? $stop->{sched_dep}->strftime('%H:%M') : q{} %>
-% if ($stop->{rt_bogus}) {
- <i class="material-icons" aria-label="Echtzeitdaten fehlen">gps_off</i>
-% }
- <%= $stop->{name} %></a>
+ "><span class="time-sched"><%= ($stop->{sched_dep} // $stop->{sched_arr}) ? ($stop->{sched_dep} // $stop->{sched_arr})->strftime('%H:%M') : q{} %></span>
+% }
+% if ($stop->{tz_offset} and $stop->{local_dt_da}) {
+ (lokal <%= $stop->{local_dt_da}->strftime('%H:%M') %>)
+% }
+ <%= $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>
+ <i class="material-icons" aria-hidden="true"><%= $icon2 %></i>
% }
</li>
% }
% if (stash('station_name')) {
- <li class="<%= $departure->{is_cancelled} ? 'cancelled-stop' : q{} %> <%= $departure->{isPast} ? 'past-stop' : 'future-stop' %>"><%= $departure->{sched_departure} // $departure->{sched_arrival} // q{} %>
-% if ($departure->{sched_departure}) {
-% if ($departure->{departure} ne $departure->{sched_departure}) {
- (heute <%= $departure->{departure} %>)
+% if ($departure->{is_annotated} and $departure->{prod_name}) {
+ <li class="annotation">
+% if ($departure->{prod_name}) {
+%= $departure->{prod_name}
% }
-% }
-% elsif ($departure->{arrival}) {
-% if ($departure->{arrival} ne $departure->{sched_arrival}) {
- (heute <%= $departure->{arrival} %>)
+% if ($departure->{direction}) {
+ → <%= $departure->{direction} %>
+% }
+% if ($departure->{operator}) {
+ (<%= $departure->{operator} %>)
% }
+ </li>
+% }
+ <li class="<%= $departure->{is_cancelled} ? 'cancelled-stop' : q{} %> <%= $departure->{isPast} ? 'past-stop' : 'future-stop' %>">
+% if ($departure->{departure} and $departure->{sched_departure} and $departure->{departure} ne $departure->{sched_departure}) {
+ <span class="time-sched-only"><%= $departure->{sched_departure} // $departure->{sched_arrival} // q{} %></span><span class="time-delayed">
+% }
+% elsif ($departure->{departure} and $departure->{sched_departure} and $departure->{departure} eq $departure->{sched_departure} and not $departure->{no_realtime_yet}) {
+ <span class="time-sched-ontime">
% }
-% if ($departure->{missing_realtime} or $departure->{no_realtime_yet}) {
- <i class="material-icons" aria-label="Echtzeitdaten fehlen">gps_off</i>
+% elsif ($departure->{arrival} and $departure->{sched_arrival} and $departure->{arrival} ne $departure->{sched_arrival}) {
+ <span class="time-sched-only"><%= $departure->{sched_departure} // $departure->{sched_arrival} // q{} %></span><span class="time-delayed">
+% }
+% elsif ($departure->{arrival} and $departure->{sched_arrival} and $departure->{arrival} eq $departure->{sched_arrival} and not $departure->{no_realtime_yet}) {
+ <span class="time-sched-ontime">
+% }
+% else {
+ <span class="time-sched">
+% }
+%= $departure->{departure} // $departure->{arrival} // $departure->{sched_departure} // $departure->{sched_arrival} // q{}
+ </span>
+% if ($departure->{tz_offset} and $departure->{local_dt_da}) {
+ (lokal <%= $departure->{local_dt_da}->strftime('%H:%M') %>)
% }
<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>
+ <i class="material-icons" aria-hidden="true"><%= $icon2 %></i>
+% }
</li>
% }
% for my $stop (@{$departure->{route_post_diff}}) {
+% if ($stop->{is_annotated} and $stop->{prod_name}) {
+ <li class="annotation">
+% if ($stop->{prod_name}) {
+%= $stop->{prod_name}
+% }
+% if ($stop->{direction}) {
+ → <%= $stop->{direction} %>
+% }
+% if ($stop->{operator}) {
+ (<%= $stop->{operator} %>)
+% }
+ </li>
+% }
<li class="<%= $stop->{isPast} ? 'past-stop' : 'future-stop' %>">
- <a href="<%= url_for('station', station => $stop->{name})->query({detailed => param('detailed'), past => param('past')}) %>#<%= ($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'), hafas => param('hafas')}) %>#<%= ($departure->{train_type} // q{x}) . ($departure->{train_no} // q{x}) %>" class="
% if ($stop->{isAdditional}) {
additional-stop
% }
@@ -253,84 +356,52 @@
% else {
generic-stop
% }
-% if ($stop->{rt_arr}) {
- "><%= $stop->{sched_arr}->strftime('%H:%M') %> (heute <%= $stop->{rt_arr}->strftime('%H:%M') %>) <%= $stop->{name} %></a>
+% if (($stop->{rt_arr} and $stop->{arr_delay}) or (not $stop->{rt_arr} and $stop->{rt_dep} and $stop->{dep_delay})) {
+ "><span class="time-sched-only"><%= ($stop->{sched_arr} // $stop->{sched_dep})->strftime('%H:%M') %></span> <span class="time-delayed"><%= ($stop->{rt_arr} // $stop->{rt_dep})->strftime('%H:%M') %></span>
+% }
+% elsif (($stop->{rt_arr} and defined $stop->{arr_delay}) or (not $stop->{rt_arr} and $stop->{rt_dep} and defined $stop->{dep_delay})) {
+ "><span class="time-sched-ontime"><%= ($stop->{sched_arr} // $stop->{sched_dep}) ? ($stop->{sched_arr} // $stop->{sched_dep})->strftime('%H:%M') : q{} %></span>
% }
% else {
- "><%= $stop->{sched_arr} ? $stop->{sched_arr}->strftime('%H:%M') : q{} %>
-% if ($stop->{rt_bogus}) {
- <i class="material-icons" aria-label="Echtzeitdaten fehlen">gps_off</i>
-% }
- <%= $stop->{name} %></a>
+ "><span class="time-sched"><%= ($stop->{sched_arr} // $stop->{sched_dep}) ? ($stop->{sched_arr} // $stop->{sched_dep})->strftime('%H:%M') : q{} %></span>
+% }
+% if ($stop->{tz_offset} and $stop->{local_dt_ad}) {
+ (lokal <%= $stop->{local_dt_ad}->strftime('%H:%M') %>)
+% }
+ <%= $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>
+ <i class="material-icons" aria-hidden="true"><%= $icon2 %></i>
% }
</li>
% }
</ul> <!-- mroute -->
% }
-% if ($departure->{has_cycle}) {
- <div class="db-attr"><a href="https://lib.finalrewind.org/dbdb/db_umlauf/<%= $departure->{train_no} %>.svg">Umlaufplan</a>
- (ggf. fehlerhaft)</div>
+% if ($departure->{operators} and @{$departure->{operators} // []}) {
+ <div class="details">Betrieb: <%= join(q{, }, @{ $departure->{operators} // [] } ) %></div>
% }
-% if ($details->{commonAttr}) {
-% if ($details->{attrVariants} and (not $details->{commonAttr}{vmax} or not $details->{commonAttr}{brakingPercentage})) {
- <div class="db-attr">
- Attribute:
- <ul>
-% for my $attr (@{$details->{attrVariants} // [] }) {
- <li><%= include '_train_attr', attr => $attr, with_station => 1 %></li>
-% }
- </ul>
- </div>
-% }
-% else {
- <div class="db-attr">
-%= include '_train_attr', attr => $details->{commonAttr}, with_station => 0
- </div>
-% }
-% }
-% if ($details and not $departure->{arrival}) {
-% if (my $s = $details->{route}{preStart}) {
- Zug wird voraussichtlich aus <%= $s %> eingesetzt.<br/><br/>
-% }
-% if (@{$departure->{cycle_from} // []}) {
- Bildung möglicherweise aus
+% if ($departure->{details} and @{$departure->{details}}) {
+ <div class="details">Details:
<ul>
-% for my $t (@{$departure->{cycle_from}}) {
-% my ($train_no, $train) = @{$t};
-% my $tt = $train->{type} // $train->{rawType} // 'Zug';
-% $tt =~ s{ .*|[0-9]}{};
- <li><%= $tt %> <%= $train_no %>
-% if ($train->{route}{start} and $train->{route}{end}) {
- <%= $train->{route}{start} %> → <%= $train->{route}{end} %>
-% }
- </li>
+% for my $pair (@{$departure->{details}}) {
+ <li>
+% if ($pair->[1]{icon}) {
+ <i class="material-icons"><%= $pair->[1]{icon} %></i>
% }
- </ul>
-% }
-% }
-% elsif ($details and not $departure->{departure}) {
-% if (my $e = $details->{route}{postEnd}) {
- Zug wird voraussichtlich in <%= $e %> abgestellt.<br/><br/>
-% }
-% if (@{$departure->{cycle_to} // []}) {
- Weiterfahrt möglicherweise als
- <ul>
-% for my $t (@{$departure->{cycle_to}}) {
-% my ($train_no, $train) = @{$t};
-% my $tt = $train->{type} // $train->{rawType} // 'Zug';
-% $tt =~ s{ .*|[0-9]}{};
- <li><%= $tt %> <%= $train_no %>
-% if ($train->{route}{start} and $train->{route}{end}) {
- <%= $train->{route}{start} %> → <%= $train->{route}{end} %>
-% }
- </li>
+%= $pair->[0]
+% if (length($pair->[0]) > 25) {
+ <br/>
% }
+ <span class="reason">
+%= $pair->[1]{text}
+ </span>
+ </li>
+% }
+% if ($departure->{route_info}) {
+ <li><%= $departure->{route_info} %></li>
+% }
</ul>
-% }
-% }
-% if ($icetype and not param('detailed')) {
- <div class="verbose">
- <a href="<%= url_for->query(detailed => 1) %>">Mehr Details</a>
</div>
% }
</div> <!-- mfooter -->
diff --git a/templates/_wagon.html.ep b/templates/_wagon.html.ep
index 94ef56a..59a2ca1 100644
--- a/templates/_wagon.html.ep
+++ b/templates/_wagon.html.ep
@@ -6,6 +6,9 @@
% if ($wagon->is_locomotive or $wagon->is_powercar) {
% $extra_class .= ' powercar';
% }
+% if ($wagon->is_closed) {
+% $extra_class .= ' closed';
+% }
% if ($wagon->train_no ne $train_no) {
% $extra_class .= ' nondestwagon';
% }
@@ -13,6 +16,9 @@
top: <%= $wagon->{position}{start_percent} %>%; bottom: <%= 100 - $wagon->{position}{end_percent} %>%; <%= $bg %>">
% if ($wagon->is_locomotive or $wagon->is_powercar) {
% }
+% elsif ($wagon->is_closed) {
+ X
+% }
% else {
%= $wagon->number // '?'
% if ($wagon->has_accessibility) {
@@ -38,9 +44,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 {
@@ -51,7 +57,7 @@
<div class="details" style="
top: <%= $wagon->{position}{start_percent} %>%; bottom: <%= 100 - $wagon->{position}{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($wagon->train_subtype // $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 {
@@ -71,7 +77,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($wagon->train_subtype // $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 {
@@ -80,4 +86,18 @@
</span>
% }
% }
+% if ($multi and $first) {
+ <br/>
+ <span class="groupno">
+% if (scalar $wr->train_nos > 1) {
+ <%= $wr->train_type %> <%= ($wr->groups)[$wagon->group_index]->train_no %>
+% }
+% if (scalar $wr->destinations > 1) {
+ → <%= $wr->{data}{istformation}{allFahrzeuggruppe}[$wagon->group_index]{zielbetriebsstellename} %>
+% }
+ </span>
+ % if ($multi and ($wr->groups)[$wagon->group_index]->desc_short) {
+ <span class="grouptype"><%= ($wr->groups)[$wagon->group_index]->desc_short %></span>
+% }
+% }
</div>
diff --git a/templates/about.html.ep b/templates/about.html.ep
index ae88a8d..b5af92b 100644
--- a/templates/about.html.ep
+++ b/templates/about.html.ep
@@ -1,13 +1,10 @@
<div class="container">
<p>
- DBF ist ein inoffizieller Abfahrtsmonitor für innerdeutsche Zugfahrten mit
- dem Ziel, Daten aus verschiedenen Quellen übersichtlich zusammenzutragen.
- 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. © 2021 <a
- href="https://finalrewind.org/me">Daniel Friesel</a> / <a href="https://twitter.com/derfnull">@derfnull</a>.
+ 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.
+ </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>.
% if (my $issue_url = app->config->{'issue_url'}) {
Fehlermeldungen bitte via
<a href="<%= $issue_url %>">Issue Tracker</a>.
@@ -20,40 +17,37 @@
und die Bezeichnung DBF wurde zum Eigennamen ohne weitere Bedeutung.
</p>
<p>
- Diese Installation verwendet die DBF-Version
- <b><%= stash('version') // '???' %></b> und greift auf die folgenden Backends
- zu:<br/>
- • Abfahrtstafel: DB IRIS via <a href="https://finalrewind.org/projects/Travel-Status-DE-IRIS/">Travel::Status::DE::IRIS</a>
- v<%= $Travel::Status::DE::IRIS::VERSION %><br/>
- • Meldungen und Ankunft/Abfahrt an Unterwegshalten: DB HAFAS via <a href="https://git.finalrewind.org/db-fakedisplay/tree/lib/DBInfoscreen/Helper/HAFAS.pm">Helper/HAFAS.pm</a><br/>
- • Wagenreihung: <a href="https://finalrewind.org/projects/Travel-Status-DE-DBWagenreihung/">Travel::Status::DE::DBWagenreihung</a>
- % if ($Travel::Status::DE::DBWagenreihung::VERSION) {
- v<%= $Travel::Status::DE::DBWagenreihung::VERSION %>
- % }
- <br/>
- % if (app->config->{hafas_rest_api} =~ m{v5.db.transport.rest}) {
- • Karte: DB HAFAS via <a href="https://v5.db.transport.rest/">v5.db.transport.rest</a><br/>
- % }
- % else {
- • Karte: DB HAFAS via <a href="https://github.com/public-transport/hafas-rest-api">hafas-rest-api</a><br/>
+ 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>
+ <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>
+ <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>
+ </ul>
+ </p>
+ <p>
+ Unterstützte HAFAS-Instanzen („hafas=…“):
+ <ul>
+ % for my $service (Travel::Status::DE::HAFAS::get_services()) {
+ <li><%= $service->{shortname} %> (<%= $service->{name} %>)</li>
% }
- • Zugauslastung Fernverkehr: DB HAFAS via <a href="https://docs.marudor.de/">marudor.de</a><br/>
- • Zugauslastung Regionalverkehr: VRR EFA via <a href="https://github.com/derf/eva-to-efa-gw">eva-to-efa-gw</a><br/>
- <br/>
- Sie nutzt zusätzlich die folgenden Open Data-Ressourcen:<br/>
- • <a href="https://data.deutschebahn.com/dataset/zugbildungsplanzugbildungsplan-zpar">Zugbildungsplan</a> © DB Fernverkehr AG, lizensiert unter CC-BY 4.0
- <br/>
- • <a href="http://data.deutschebahn.com/dataset/data-haltestellen">Haltestellenliste</a>
- © DB Station&amp;Service AG,
- Europaplatz 1,
- 10557 Berlin, lizensiert unter CC-BY 4.0<br/>
+ </ul>
</p>
-</div>
-
-<div class="container">
<p>
- <a href="https://finalrewind.org/me/">Kontakt</a>
- ·
+ Verwendete Open Data-Ressourcen:
+ <ul>
+ <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,
+ Europaplatz 1,
+ 10557 Berlin, lizensiert unter CC-BY 4.0</li>
+ <li><a href="https://data.deutschebahn.com/dataset/fahrzeuglexikon">Fahrzeuglexikon</a>
+ © 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>
</div>
diff --git a/templates/app.html.ep b/templates/app.html.ep
index 6baf0f4..50f8a5a 100644
--- a/templates/app.html.ep
+++ b/templates/app.html.ep
@@ -30,6 +30,9 @@
% $route_str .= $stop . ($via_cur < $via_max ? ' - ' : q{});
% }
<li
+% if (param('hafas')) {
+ data-jid="<%= $departure->{journey_id} =~ s{#}{%23}gr %>"
+% }
data-train="<%= ($departure->{train_type} // q{}) %> <%= ($departure->{train_no} // $departure->{train} // q{}) %>"
data-line="<%= $departure->{train_type} %> <%= $departure->{train_line} // $departure->{train_no} %>"
data-no="<%= $departure->{train_line} ? $departure->{train_no} : q{} %>"
@@ -40,7 +43,7 @@
data-platform="<%= $departure->{scheduled_platform} // $departure->{platform} // '' %>"
data-arrival="<%= $departure->{sched_arrival} // '' %>"
data-departure="<%= $departure->{sched_departure} // '' %>"
- data-moreinfo="<%= join(q{|}, map { ($_->[0]->isa('DateTime') ? $_->[0]->strftime('%H:%M') : $_->[0]) . ' ' . $_->[1] } @{ $departure->{moreinfo} // [] } ) %>"
+ data-moreinfo="<%= join(q{|}, map { ($_->[0]->isa('DateTime') ? $_->[0]->strftime('%H:%M') . ' ' . $_->[1] : $_->[0] . ' ' . $_->[1]{text}) } @{ $departure->{moreinfo} // [] } ) %>"
data-routeprev="<%= join(q{|}, @{ $departure->{route_pre} // [] } ) %>"
data-routenext="<%= join(q{|}, @{ $departure->{route_post} // [] } ) %>"
% if ($departure->{is_cancelled} or $departure->{departure_is_cancelled}) {
@@ -49,7 +52,12 @@
% else {
>
% }
- <a href="/z/<%= Mojo::Util::url_escape(($departure->{train_type} // q{}) . ' ' . ($departure->{train_no} // $departure->{train} // q{}) . '/' . ($departure->{station} // $station)) %>">
+% if (param('hafas')) {
+ <a href="/z/<%= Mojo::Util::url_escape($departure->{journey_id}) . '?hafas=1&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>
<div class="line <%= $departure->{linetype} %>">
% if ($departure->{train_type} and $departure->{train_no}) {
@@ -59,9 +67,6 @@
%= $departure->{train_line}
% }
% elsif ($departure->{train_no}) {
-% if (param('detailed') and $departure->{linetype} eq 'fern' and exists $ice_type->{$departure->{train_no}} and $ice_type->{$departure->{train_no}}[1]) {
- <span class="trainsubtype" aria-hidden="true"><%= $ice_type->{$departure->{train_no}}[1] %></span>
-% }
<span class="trainno"><%= $departure->{train_no} %></span>
% }
% else {
@@ -100,18 +105,18 @@
% if ($departure->{delay} and not $departure->{is_cancelled}) {
% if ($show_realtime) {
% if ($departure->{delay} > ($hide_low_delay ? 4 : 0)) {
- <span class="delaynorm" aria-hidden="true">(+<%= $departure->{delay} %>)</span>
+ <span class="delaynorm" aria-hidden="true">+<%= $departure->{delay} %> ⇒</span>
% }
% elsif ($departure->{delay} < 0) {
- <span class="undelaynorm" aria-hidden="true">(<%= $departure->{delay} %>)</span>
+ <span class="undelaynorm" aria-hidden="true"><%= $departure->{delay} %> ⇒</span>
% }
% }
% else {
% if ($departure->{delay} > ($hide_low_delay ? 4 : 0)) {
- <span class="delay" aria-hidden="true">(+<%= $departure->{delay} %>)</span>
+ <span class="delay" aria-hidden="true">+<%= $departure->{delay} %></span>
% }
% elsif ($departure->{delay} < 0) {
- <span class="undelay" aria-hidden="true">(<%= $departure->{delay} %>)</span>
+ <span class="undelay" aria-hidden="true"><%= $departure->{delay} %></span>
% }
% }
% }
diff --git a/templates/exception.html.ep b/templates/exception.html.ep
index 2f20bc6..7654c0b 100644
--- a/templates/exception.html.ep
+++ b/templates/exception.html.ep
@@ -4,9 +4,14 @@ Beim Bearbeiten der Anfrage ist ein Fehler aufgetreten.<br/>
<pre>
----------[Debug start]----------
-%= $exception->message
+% if ($exception) {
+%= ref($exception) ? $exception->message : $exception
Stash:
%= dumper $snapshot
+% }
+% else {
+%= stash('message')
+% }
----------[Debug end]----------
</pre>
</div>
diff --git a/templates/geotrain.html.ep b/templates/geotrain.html.ep
deleted file mode 100644
index 0193167..0000000
--- a/templates/geotrain.html.ep
+++ /dev/null
@@ -1,5 +0,0 @@
-<div class="geolocation">
-<div class="candidateheader"><a href="https://finalrewind.org/interblag/entry/dbf-zuglokalisierung/">Experimentelles Beta-Feature</a><br/><br/>Züge auf der Strecke:</div>
-<div class="candidatestatus">Bitte warten…</div>
-<div class="candidatelist"></div>
-</div> <!-- geolocation -->
diff --git a/templates/landingpage.html.ep b/templates/landingpage.html.ep
index ae72867..17bb2bb 100644
--- a/templates/landingpage.html.ep
+++ b/templates/landingpage.html.ep
@@ -1,19 +1,27 @@
% if (stash 'show_intro') {
<div class="container">
-<p>
- DBF ist ein inoffizieller Abfahrtsmonitor für innerdeutsche Zugfahrten mit
- dem Ziel, Daten aus verschiedenen Quellen übersichtlich zusammenzutragen.
-</p>
-<p>
- Diese Seite ist ein kostenfreies, privat betriebenes Projekt ohne
- Verfügbarkeitsgarantie. Alle Angaben ohne Gewähr.
-</p>
-<p class="geolink">
-<a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https') %>">Stationen in der Umgebung suchen</a>
-</p>
+% if (0) {
+ <p>
+ DBF is an unofficial departure monitor for regional and long-distance trains within Germany, aiming to combine multiple data sources in a useful manner.
+ It also has limited support for local transit and traffic outside of Germany.
+ </p>
+ <p>
+ This site is operated by a private entity in a not-for-profit manner.
+ There are no uptime or reliability guarantees whatsoever.
+ </p>
+% }
+% 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.
+ </p>
+ <p>
+ Diese Seite ist ein kostenfreies, privat betriebenes Projekt ohne Verfügbarkeitsgarantie.
+ Alle Angaben ohne Gewähr.
+ </p>
+% }
<p class="geolink">
-Oder
-<a href="<%= url_for('_autotrain')->to_abs->scheme('https') %>">Züge in der Umgebung suchen</a> (Beta-Feature)
+<a class="button" href="<%= url_for('_autostop')->to_abs->scheme('https')->query({hafas => param('hafas')}) %>">Stationen in der Umgebung suchen</a>
</p>
<p>
Oder hier angeben:
diff --git a/templates/layouts/app.html.ep b/templates/layouts/app.html.ep
index fa13f75..9c39019 100644
--- a/templates/layouts/app.html.ep
+++ b/templates/layouts/app.html.ep
@@ -5,7 +5,7 @@
<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="Inoffizieller Abfahrtsmonitor für innerdeutsche Zugfahrten">
+ <meta name="description" content="<%= stash('description') // 'Inoffizieller Abfahrtsmonitor für innerdeutsche Zugfahrten' %>">
<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 = 'v57'; # asset version
+ % my $av = 'v99'; # asset version
% if (session('theme') and session('theme') eq 'dark' or param('dark')) {
%= stylesheet "/static/${av}/css/dark.min.css", id => 'theme'
% }
@@ -27,14 +27,14 @@
% }
<script>
function addStyleSheet(name, id) {
- var path = '/static/<%=$av%>/css/' + name + '.min.css';
- var old = document.getElementById(id);
+ const path = '/static/<%=$av%>/css/' + name + '.min.css';
+ const old = document.getElementById(id);
if (old && (old.href != path)) {
old.href = path;
- document.cookie = 'theme=' + name;
+ document.cookie = 'theme=' + name + ';SameSite=None;Secure';
}
}
- var otherTheme = {
+ const otherTheme = {
'dark': 'light',
'light': 'dark',
};
@@ -43,24 +43,18 @@
currentTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
addStyleSheet(currentTheme, 'theme');
-
- function toggleTheme() {
- currentTheme = otherTheme[currentTheme] || 'light';
- localStorage.setItem('theme', currentTheme);
- addStyleSheet(currentTheme, 'theme');
- }
</script>
%= stylesheet "/static/${av}/css/material-icons.css"
%= stylesheet "/static/${av}/css/jquery-ui.min.css"
%= javascript '/static/js/jquery-3.4.1.min.js', defer => undef
%= javascript "/static/${av}/js/jquery-ui.min.js", defer => undef
%= javascript "/static/${av}/js/dbf.min.js", defer => undef
+ % if (not stash('hide_opts')) {
+ %= javascript "/dyn/${av}/autocomplete.js", defer => undef
+ % }
% if (stash('with_geostop')) {
%= javascript "/static/${av}/js/geostop.min.js", defer => undef
% }
- % if (stash('with_geotrain')) {
- %= javascript "/static/${av}/js/geotrain.min.js", defer => undef
- % }
% if (stash('with_map')) {
%= stylesheet "/static/${av}/leaflet/leaflet.css"
%= javascript "/static/${av}/leaflet/leaflet.js"
@@ -83,16 +77,17 @@
</span>
% }
<ul id="nav-mobile" style="float: right;">
- <li class="waves-effect waves-light">
- <a onClick="javascript:toggleTheme()"><span class="visually-hidden">Farbschema invertieren</span><i class="material-icons" aria-hidden="true">invert_colors</i></a>
- </li>
+ % if (stash('api_link')) {
+ <li class="waves-effect waves-light">
+ <a href="<%= stash('api_link') %>"><span class="visually-hidden"><%= stash('api_text') %></span><i class="material-icons" aria-hidden="true"><%= stash('api_icon') %></i></a>
+ </li>
+ % }
% if (stash('hide_opts')) {
<li><a href="/"><span class="visually-hidden">Hauptseite</span><i class="material-icons" aria-hidden="true">edit</i></a></li>
% }
% else {
<li><a href="#stationinput"><span class="visually-hidden">Menü</span><i class="material-icons" aria-hidden="true">edit</i></a></li>
% }
- <li><a href="/_autostop"><span class="visually-hidden">Stationen in der Umgebung suchen</span><i class="material-icons" aria-hidden="true">my_location</i></a></li>
</ul>
</div>
</nav>
@@ -122,6 +117,7 @@ Bitte eine Station aus der Liste auswählen</div>
%= form_for _redirect => begin
+%= hidden_field hafas => param('hafas')
<div>
<div class="field">
<div class="desc">Zug / Station</div>
@@ -130,22 +126,27 @@ Bitte eine Station aus der Liste auswählen</div>
%= select_field input => stash('stationlist')
% }
% elsif (stash('input')) {
- %= text_field 'input', class => 'station', placeholder => 'Zug, Stationsname oder DS100-Kürzel', id => 'stationinput'
+ %= text_field 'input', class => 'station', placeholder => 'Zug, Stationsname oder Ril100-Kürzel', id => 'stationinput'
% }
% else {
- %= text_field 'input', class => 'station', placeholder => 'Zug, Stationsname oder DS100-Kürzel', id => 'stationinput', autofocus => 'autofocus'
+ %= text_field 'input', class => 'station', placeholder => 'Zug, Stationsname oder Ril100-Kürzel', id => 'stationinput', autofocus => 'autofocus'
% }
</div>
</div>
<div class="field">
- %= submit_button 'Abfahrtsmonitor'
+ %= 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>
+ </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 'show_realtime' => 1, id => 'id_show_realtime'
+ %= check_box 'rt' => 1, id => 'id_show_realtime'
<label for="id_show_realtime">
Zeiten inkl. Verspätung angeben
</label>
@@ -163,7 +164,7 @@ Bitte eine Station aus der Liste auswählen</div>
<div class="desc">
%= check_box 'detailed' => 1, id => 'id_detailed'
<label for="id_detailed">
- Mehr Details (u.a. Zugnummern und Zugbildungsplan)
+ Mehr Details
</label>
</div>
</div>
@@ -171,7 +172,7 @@ Bitte eine Station aus der Liste auswählen</div>
<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)")
+ Betriebliche Bahnhofstrennungen berücksichtigen (z.B. "Hbf (Fern+Regio)" vs. "Hbf (S)")
</label>
</div>
</div>
@@ -179,7 +180,7 @@ Bitte eine Station aus der Liste auswählen</div>
<div class="desc">
%= check_box 'past' => 1, id => 'past'
<label for="past">
- Bereits abgefahrene Züge anzeigen
+ Bereits abgefahrene Züge anzeigen
</label>
</div>
</div>
@@ -187,7 +188,7 @@ Bitte eine Station aus der Liste auswählen</div>
<div class="desc">
%= check_box 'hide_opts' => 1, id => 'id_hide_opts'
<label for="id_hide_opts">
- Formular verstecken (für Infoscreens)
+ Formular verstecken
</label>
</div>
</div>
@@ -233,32 +234,65 @@ Bitte eine Station aus der Liste auswählen</div>
</div> <!-- input-field -->
<div class="notes">
- <div class="developers-header developers-header-collapsed button button-light">API- und Entwickler-Hinweise</div>
+ <div class="developers-header developers-header-collapsed button button-light">API</div>
<div class="developers developers-collapsed">
<ul>
- <li>DBF-Abfahrtstafeln können gerne als iframe eingebunden oder in
- fest installierten Vollbild-Browserfenstern verwendet werden.
- Für eine kleine Ansicht (z.B. iframe in einer normalen Website)
- empfiehlt sich das "App"-Frontend. Für eine große Ansicht
- (z.B. als alleinstehender Infoscreen) gibt es den "Infoscreen"-Modus.</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
- 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>
- <li>Dieser Dienst ist Open Source-Software und kann leicht auf eigenen Servern
- <a href="https://github.com/derf/db-fakedisplay/blob/master/README.md">installiert</a>
- werden. Automatisierte Crawler, die mehrere Dutzend Stationen pro Minute
- abfragen, bitte nur auf eigenen Instanzen betreiben.</li>
+ % if (0) {
+ <li>You're welcome to embed DBF departure boards as iframes or use them
+ in full-screen browser setups. The App frontend works best for
+ small screens, whereas the legacy Infoscreen mode is better suited
+ for large displays.</li>
+ <li>The departure board supports names, EVA IDs, and (in IRIS mode)
+ DS100/Ril100 codes as station identifiers.</li>
+ <li>Requests for train details can optionally be suffixed with the
+ DD.MM.[YYYY] date of the requested trip, e.g. "ICE 921 (1.1.)" or
+ "ICE 921 @ 1.1.". The date refers to the scheduled departure at the
+ train's origin station.</li>
+ <li>A JSON IRIS API is avaliable via
+ <span style="font-family: monospace;">mode=json&amp;version=3</span>
+ (or just <span style="font-family: monospace;">https://dbf.finalrewind.org/Station.json?version=3</span>).
+ Route elements may contain "isAdditional" and "isCancelled"; the rest
+ should be self-explanatory. Please do not send more than 30 requests
+ per minute and only one request per station per minute.</li>
+ <li>There is no JSON API for train details yet.</li>
+ <li>The optional <span style="font-family: monospace;">limit</span>
+ parameter limits the number of returnd departures; e.g.
+ <span style="font-family: monospace;">limit=10</span> will result in no more than ten.</li>
+ <li>DBF is available as Open Source software
+ (<a href="https://github.com/derf/db-fakedisplay/blob/master/README.md">installation instructions</a>).
+ Please use your own installation for automated crawlers that request dozens of stations per minute.</li>
+ % }
+ % else {
+ <li>DBF-Abfahrtstafeln können gerne als iframe eingebunden oder in
+ fest installierten Vollbild-Browserfenstern verwendet werden.
+ Für eine kleine Ansicht (z.B. iframe in einer normalen Website)
+ empfiehlt sich das "App"-Frontend. Für eine große Ansicht
+ (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
+ 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
+ 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>
+ <li>Dieser Dienst ist Open Source-Software und kann leicht auf eigenen Servern
+ <a href="https://github.com/derf/db-fakedisplay/blob/master/README.md">installiert</a>
+ werden. Automatisierte Crawler, die mehrere Dutzend Stationen pro Minute
+ abfragen, bitte nur auf eigenen Instanzen betreiben.</li>
+ % }
</ul>
</div> <!-- developers -->
</div> <!-- notes -->
@@ -266,13 +300,28 @@ Bitte eine Station aus der Liste auswählen</div>
</div> <!-- container -->
<div class="container">
+<div class="config">
+Farbschema:
+<a onClick="javascript:setTheme('light')">light</a>
+<a onClick="javascript:setTheme('dark')">dunkel</a>
+<a onClick="javascript:setTheme('default')">automatisch</a>
+<!--Language:
+<br/>
+<a onClick="javascript:setLang('de')">DE</a>
+<a onClick="javascript:setLang('en')">EN</a>
+<a onClick="javascript:setLang('default')">system language</a>
+-->
+</div>
<div class="about">
-<a href="_about">Über DBF</a>
+<a href="_about">DBF</a> v<%= stash('version') // '???' %>
·
<a href="_datenschutz" rel="nofollow">Datenschutz</a>
·
-<a href="_impressum" rel="nofollow">Impressum</a><br/>
-Version <%= stash('version') // '???' %>
+<a href="_impressum" rel="nofollow">Impressum</a>
</div> <!-- about -->
</div> <!-- container -->
% }
diff --git a/templates/layouts/legacy.html.ep b/templates/layouts/legacy.html.ep
index 6088009..5389c4b 100644
--- a/templates/layouts/legacy.html.ep
+++ b/templates/layouts/legacy.html.ep
@@ -17,18 +17,21 @@
<meta http-equiv="refresh" content="<%= $self->stash('refresh_interval') %>"/>
% }
- % my $av = 'v57'; # asset version
- %= stylesheet "/static/${av}/css/default.css"
+ % my $av = 'v99'; # asset version
+ %= stylesheet "/static/${av}/css/legacy.css"
%= stylesheet "/static/${av}/css/material-icons.css"
%= stylesheet "/static/${av}/css/jquery-ui.min.css"
% my $force_mobile = param('force_mobile') // stash('force_mobile');
% if ($force_mobile) {
- %= stylesheet "/static/${av}/css/mobile.css"
+ %= stylesheet "/static/${av}/css/legacy-mobile.css"
% }
%if (stash('load_marquee')) {
%= javascript '/static/js/jquery-3.4.1.min.js'
%= javascript "/static/${av}/js/jquery-ui.min.js"
%= javascript "/static/${av}/js/dbf.min.js"
+ % if (not stash('hide_opts')) {
+ %= javascript "/dyn/${av}/autocomplete.js", defer => undef
+ % }
%= javascript "/static/${av}/js/marquee.min.js"
%= javascript begin
$(function () { $('marquee').marquee() });
@@ -73,10 +76,10 @@ Bitte eine Station aus der Liste auswählen</div>
%= select_field input => stash('stationlist')
% }
% elsif (stash('input')) {
- %= text_field 'input', class => 'station', placeholder => 'Name oder DS100-Kürzel'
+ %= text_field 'input', class => 'station', placeholder => 'Name oder Ril100-Kürzel'
% }
% else {
- %= text_field 'input', class => 'station', placeholder => 'Name oder DS100-Kürzel', autofocus => 'autofocus'
+ %= text_field 'input', class => 'station', placeholder => 'Name oder Ril100-Kürzel', autofocus => 'autofocus'
% }
</div>
</div>
@@ -158,7 +161,7 @@ Bitte eine Station aus der Liste auswählen</div>
</div>
<div class="field">
<div class="desc">
- %= check_box 'show_realtime' => 1, id => 'id_show_realtime'
+ %= check_box 'rt' => 1, id => 'id_show_realtime'
<label for="id_show_realtime">
Echtzeitangaben statt Fahrplandaten anzeigen
</label>
diff --git a/templates/route_map.html.ep b/templates/route_map.html.ep
index 2f35b54..447960a 100644
--- a/templates/route_map.html.ep
+++ b/templates/route_map.html.ep
@@ -1,9 +1,6 @@
% if (stash('origin') and stash('destination')) {
%= include '_map_infobox'
% }
-% elsif (stash('intersection')) {
- %= include '_intersection_infobox'
-% }
<div class="container">
<div id="map" style="height: 500px;">
diff --git a/templates/trainsearch.html.ep b/templates/trainsearch.html.ep
deleted file mode 100644
index 5d6d3f9..0000000
--- a/templates/trainsearch.html.ep
+++ /dev/null
@@ -1,29 +0,0 @@
-<div class="container">
- <div class="input-field">
- %= form_for _trainsearch => begin
- <div>
- <div class="field">
- <div class="desc">Zug</div>
- <div>
- %= text_field 'train1', placeholder => 'RE 1234', id => 'train1_input', autofocus => 'autofocus'
- </div>
- </div>
- <div class="field">
- %= submit_button 'Strecke zeigen'
- </div>
- <div class="break"></div>
- <div class="field">
- <div class="desc">
- Zweiter Zug (optional)
- </div>
- <div>
- %= text_field 'train2', placeholder => 'S 5678', id => 'train2_input'
- </div>
- </div>
- <div class="field">
- %= submit_button 'Begegnungen suchen (beta)'
- </div>
- </div>
- % end
- </div>
-</div>
diff --git a/templates/wagenreihung.html.ep b/templates/wagenreihung.html.ep
index 493d9c6..6781dca 100644
--- a/templates/wagenreihung.html.ep
+++ b/templates/wagenreihung.html.ep
@@ -7,37 +7,10 @@
</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 )
+ <%= $wr->station->{name} %> 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'%>">
@@ -49,10 +22,29 @@
</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->wagons) {
+%= include '_wagon', wr => $wr, wagon => $wagon, first => $first, multi => (scalar $wr->destinations) - 1 + (scalar $wr->train_nos) - 1, wref => $wref, exit_dir => stash('exit_dir');
+% $first = 0;
+% }
% }
</div>
+ <div style="text-align: center;">
+%= join( ' / ', map { $_->{name} } $wr->origins )
+ →
+%= join( ' / ', map { $_->{name} } $wr->destinations )
+ </div>
+ % for my $group ($wr->groups) {
+ % if ($group->description) {
+ <div style="text-align: center;">
+ %= $group->description
+ % if (scalar $wr->groups > 1 and $group->has_sections) {
+ in Abschnitt <%= join(q{}, sort $group->sections) %>
+ % }
+ </div>
+ % }
+ % }
<!-- <div>
Legende: ♿ Behindertengerechte Ausstattung / 🍴 Bistro/Restaurant / 🚪 Abteile vorhanden
</div>