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