Commit c8383c69 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

Merge branch 'master' of git.finalrewind.org:var/git_root/db-fakedisplay into master

parents 8bf1dd35 37c510b2
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -142,8 +142,9 @@ sub startup {

	$self->helper(
		'handle_no_results_json' => sub {
			my ( $self, $backend, $station, $errstr, $api_version, $callback )
			  = @_;
			my ( $self, $backend, $station, $errstr, $api_version ) = @_;

			my $callback = $self->param('callback');

			$self->res->headers->access_control_allow_origin(q{*});
			my $json;
@@ -315,7 +316,9 @@ sub startup {

	$r->get('/_wr/:train/:departure')->to('wagenreihung#wagenreihung');

	$r->get('/_ajax_mapinfo/:tripid/:lineno')->to('map#ajax_route');
	$r->get('/map/:tripid/:lineno')->to('map#route');
	$r->get('/intersection/:trips')->to('map#intersection');

	$self->defaults( layout => 'app' );

+764 −224

File changed.

Preview size limit exceeded, changes collapsed.

+313 −311
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ use File::Slurp qw(read_file write_file);
use List::Util qw(max);
use List::MoreUtils qw();
use Mojo::JSON qw(decode_json);
use Mojo::Promise;
use Travel::Status::DE::HAFAS;
use Travel::Status::DE::IRIS;
use Travel::Status::DE::IRIS::Stations;
@@ -506,22 +507,10 @@ sub get_results_for {
sub handle_request {
	my ($self) = @_;
	my $station = $self->stash('station');
	my $via     = $self->param('via');

	my @platforms = split( /,/, $self->param('platforms') // q{} );
	my @lines     = split( /,/, $self->param('lines')     // q{} );
	my $template = $self->param('mode')    // 'app';
	my $hide_low_delay = $self->param('hidelowdelay')  // 0;
	my $hide_opts      = $self->param('hide_opts')     // 0;
	my $show_realtime  = $self->param('show_realtime') // 0;
	my $show_details   = $self->param('detailed')      // 0;
	my $backend  = $self->param('backend') // 'iris';
	my $admode         = $self->param('admode')        // 'deparr';
	my $apiver         = $self->param('version')       // 0;
	my $callback       = $self->param('callback');
	my $with_related = !$self->param('no_related');
	my $limit       = $self->param('limit') // 0;
	my @train_types = split( /,/, $self->param('train_types') // q{} );
	my %opt          = (
		cache_hafas     => $self->app->cache_hafas,
		cache_iris_main => $self->app->cache_iris_main,
@@ -568,6 +557,8 @@ sub handle_request {
		$template = 'app';
	}

	$self->param( mode => $template );

	if ( not $station ) {
		$self->render( 'landingpage', show_intro => 1 );
		return;
@@ -582,113 +573,60 @@ sub handle_request {
		$opt{with_related} = 1;
	}

	my @departures;
	my $data   = get_results_for( $backend, $station, %opt );
	my $results_ref = $data->{results};
	my $errstr = $data->{errstr};
	my @results     = @{$results_ref};

	if ( not @results and $template eq 'json' ) {
	if ( not @{ $data->{results} } and $template eq 'json' ) {
		$self->handle_no_results_json( $backend, $station, $errstr,
			$api_version, $callback );
			$api_version );
		return;
	}

	# foo/bar used to mean "departures for foo via bar". This is now
	# deprecated, but most of these cases are handled here.
	if ( not @results and $station =~ m{/} ) {
		( $station, $via ) = split( qr{/}, $station );
		$self->param( station => $station );
		$self->param( via     => $via );
		$data        = get_results_for( $backend, $station, %opt );
		$results_ref = $data->{results};
		$errstr      = $data->{errstr};
		@results     = @{$results_ref};
	}

	if ( not @results ) {
	if ( not @{ $data->{results} } ) {
		$self->handle_no_results( $backend, $station, $errstr );
		return;
	}

	if ( $template eq 'single' ) {
		if ( not @platforms ) {
			for my $result (@results) {
				if (
					not( $self->numeric_platform_part( $result->platform ) ~~
						\@platforms )
				  )
				{
					push( @platforms,
						$self->numeric_platform_part( $result->platform ) );
				}
			}
			@platforms = sort { $a <=> $b } @platforms;
		}
		my %pcnt;
		@results
		  = grep { $pcnt{ $self->numeric_platform_part( $_->platform ) }++ < 1 }
		  @results;
		@results = map { $_->[1] }
		  sort { $a->[0] <=> $b->[0] }
		  map { [ $self->numeric_platform_part( $_->platform ), $_ ] } @results;
	$self->handle_result($data);
}

	if ( $backend eq 'iris' and $show_realtime ) {
		if ( $admode eq 'arr' ) {
			@results = sort {
				( $a->arrival // $a->departure )
				  <=> ( $b->arrival // $b->departure )
			} @results;
		}
		else {
			@results = sort {
				( $a->departure // $a->arrival )
				  <=> ( $b->departure // $b->arrival )
			} @results;
		}
	}
sub filter_results {
	my ( $self, @results ) = @_;

	if ( my $train = $self->param('train') ) {
		@results = grep { result_is_train( $_, $train ) } @results;
	}

	if (@lines) {
	if ( my @lines = split( /,/, $self->param('lines') // q{} ) ) {
		@results = grep { result_has_line( $_, @lines ) } @results;
	}

	if (@platforms) {
	if ( my @platforms = split( /,/, $self->param('platforms') // q{} ) ) {
		@results = grep { result_has_platform( $_, @platforms ) } @results;
	}

	if ($via) {
	if ( my $via = $self->param('via') ) {
		$via =~ s{ , \s* }{|}gx;
		@results = grep { result_has_via( $_, $via ) } @results;
	}

	if (@train_types) {
	if ( my @train_types = split( /,/, $self->param('train_types') // q{} ) ) {
		@results = grep { result_has_train_type( $_, @train_types ) } @results;
	}

	if ( $limit and $limit =~ m{ ^ \d+ $ }x ) {
	if ( my $limit = $self->param('limit') ) {
		if ( $limit =~ m{ ^ \d+ $ }x ) {
			splice( @results, $limit );
		}

	for my $result (@results) {
		my $platform = ( split( qr{ }, $result->platform // '' ) )[0];
		my $delay    = $result->delay;
		if ( $backend eq 'iris' and $admode eq 'arr' and not $result->arrival )
		{
			next;
	}
		if (    $backend eq 'iris'
			and $admode eq 'dep'
			and not $result->departure )
		{
			next;

	return @results;
}

sub format_iris_result_info {
	my ( $self, $template, $result ) = @_;
	my ( $info, $moreinfo );
		if ( $backend eq 'iris' ) {

	my $delaymsg
	  = join( ', ', map { $_->[1] } $result->delay_messages );
	my $qosmsg = join( ' +++ ', map { $_->[1] } $result->qos_messages );
@@ -732,28 +670,28 @@ sub handle_request {
		  . ( $info ? ' +++ ' : q{} )
		  . $info;
		if ( $template ne 'json' ) {
					push(
						@{$moreinfo},
						[ 'Zusätzliche Halte', $additional_line ]
					);
			push( @{$moreinfo}, [ 'Zusätzliche Halte', $additional_line ] );
		}
	}

	if ( $result->canceled_stops and not $result->is_cancelled ) {
		my $cancel_line = join( q{, }, $result->canceled_stops );
		$info
				  = 'Ohne Halt in: '
				  . $cancel_line
				  . ( $info ? ' +++ ' : q{} )
				  . $info;
		  = 'Ohne Halt in: ' . $cancel_line . ( $info ? ' +++ ' : q{} ) . $info;
		if ( $template ne 'json' ) {
			push( @{$moreinfo}, [ 'Ohne Halt in', $cancel_line ] );
		}
	}

	push( @{$moreinfo}, $result->messages );

	return ( $info, $moreinfo );
}
		else {

sub format_hafas_result_info {
	my ( $self, $result ) = @_;
	my ( $info, $moreinfo );

	$info = $result->info;
	if ($info) {
		$moreinfo = [ [ 'HAFAS', $info ] ];
@@ -767,6 +705,240 @@ sub handle_request {
		}
	}
	push( @{$moreinfo}, map { [ 'HAFAS', $_ ] } $result->messages );

	return ( $info, $moreinfo );
}

sub render_train {
	my ( $self, $result, $departure, $station_name ) = @_;

	$departure->{route_pre_diff} = [
		$self->json_route_diff(
			[ $result->route_pre ],
			[ $result->sched_route_pre ]
		)
	];
	$departure->{route_post_diff} = [
		$self->json_route_diff(
			[ $result->route_post ],
			[ $result->sched_route_post ]
		)
	];

	$departure->{trip_id}
	  = get_hafas_trip_id( $self->ua, $self->app->cache_iris_main, $result );

	if (
		$departure->{wr_link}
		and not check_wagonorder_with_wings(
			$self->ua, $self->app->cache_iris_main,
			$result,   $departure->{wr_link}
		)
	  )
	{
		$departure->{wr_link} = undef;
	}

	my ( $route_ts, $route_info ) = get_route_timestamps(
		$self->ua,
		$self->app->cache_iris_main,
		$self->app->cache_iris_rt,
		{ train => $result }
	);

	# If a train number changes on the way, IRIS routes are incomplete,
	# whereas HAFAS data has all stops -> merge HAFAS stops into IRIS
	# stops. This is a rare case, one point where it can be observed is
	# the TGV service at Frankfurt/Karlsruhe/Mannheim.
	if ( $route_info
		and my @hafas_stations = @{ $route_info->{stations} // [] } )
	{
		if ( my @iris_stations = @{ $departure->{route_pre_diff} } ) {
			my @missing_pre;
			for my $station (@hafas_stations) {
				if (
					List::MoreUtils::any { $_->{name} eq $station }
					@iris_stations
				  )
				{
					unshift( @{ $departure->{route_pre_diff} }, @missing_pre );
					last;
				}
				push(
					@missing_pre,
					{
						name  => $station,
						hafas => 1
					}
				);
			}
		}
		if ( my @iris_stations = @{ $departure->{route_post_diff} } ) {
			my @missing_post;
			for my $station ( reverse @hafas_stations ) {
				if (
					List::MoreUtils::any { $_->{name} eq $station }
					@iris_stations
				  )
				{
					push( @{ $departure->{route_post_diff} }, @missing_post );
					last;
				}
				unshift(
					@missing_post,
					{
						name  => $station,
						hafas => 1
					}
				);
			}
		}
	}
	if ($route_ts) {
		for my $elem (
			@{ $departure->{route_pre_diff} },
			@{ $departure->{route_post_diff} }
		  )
		{
			for my $key ( keys %{ $route_ts->{ $elem->{name} } // {} } ) {
				$elem->{$key} = $route_ts->{ $elem->{name} }{$key};
			}
		}
	}
	if ( $route_info and @{ $route_info->{messages} // [] } ) {
		my $him = $route_info->{messages};
		my @him_messages;
		$departure->{messages}{him} = $him;
		for my $message ( @{$him} ) {
			if ( $message->{display} ) {
				push( @him_messages, [ $message->{header}, $message->{lead} ] );
			}
		}
		for my $message ( @{ $departure->{moreinfo} // [] } ) {
			my $m = $message->[1];
			@him_messages
			  = grep { $_->[0] !~ m{Information\. $m\.$} } @him_messages;
		}
		unshift( @{ $departure->{moreinfo} }, @him_messages );
	}

	my $linetype = 'bahn';
	if ( $departure->{train_type} eq 'S' ) {
		$linetype = 'sbahn';
	}
	elsif ($departure->{train_type} eq 'IC'
		or $departure->{train_type} eq 'ICE'
		or $departure->{train_type} eq 'EC'
		or $departure->{train_type} eq 'ECE'
		or $departure->{train_type} eq 'EN' )
	{
		$linetype = 'fern';
	}
	elsif ($departure->{train_type} eq 'THA'
		or $departure->{train_type} eq 'TGV'
		or $departure->{train_type} eq 'FLX'
		or $departure->{train_type} eq 'NJ' )
	{
		$linetype = 'ext';
	}
	elsif ( $departure->{train_line}
		and $departure->{train_line} =~ m{^S\d} )
	{
		$linetype = 'sbahn';
	}

	$self->render(
		'_train_details',
		departure    => $departure,
		linetype     => $linetype,
		icetype      => $self->app->ice_type_map->{ $departure->{train_no} },
		dt_now       => DateTime->now( time_zone => 'Europe/Berlin' ),
		station_name => $station_name,
	);
}

sub handle_result {
	my ( $self, $data ) = @_;

	my @results = @{ $data->{results} };
	my @departures;

	my @platforms      = split( /,/, $self->param('platforms') // q{} );
	my $template       = $self->param('mode') // 'app';
	my $hide_low_delay = $self->param('hidelowdelay') // 0;
	my $hide_opts      = $self->param('hide_opts') // 0;
	my $show_realtime  = $self->param('show_realtime') // 0;
	my $show_details   = $self->param('detailed') // 0;
	my $backend        = $self->param('backend') // 'iris';
	my $admode         = $self->param('admode') // 'deparr';
	my $apiver         = $self->param('version') // 0;
	my $callback       = $self->param('callback');
	my $via            = $self->param('via');

	if ( $self->param('ajax') ) {
		delete $self->stash->{layout};
	}

	if ( $template eq 'single' ) {
		if ( not @platforms ) {
			for my $result (@results) {
				if (
					not( $self->numeric_platform_part( $result->platform ) ~~
						\@platforms )
				  )
				{
					push( @platforms,
						$self->numeric_platform_part( $result->platform ) );
				}
			}
			@platforms = sort { $a <=> $b } @platforms;
		}
		my %pcnt;
		@results
		  = grep { $pcnt{ $self->numeric_platform_part( $_->platform ) }++ < 1 }
		  @results;
		@results = map { $_->[1] }
		  sort { $a->[0] <=> $b->[0] }
		  map { [ $self->numeric_platform_part( $_->platform ), $_ ] } @results;
	}

	if ( $backend eq 'iris' and $show_realtime ) {
		if ( $admode eq 'arr' ) {
			@results = sort {
				( $a->arrival // $a->departure )
				  <=> ( $b->arrival // $b->departure )
			} @results;
		}
		else {
			@results = sort {
				( $a->departure // $a->arrival )
				  <=> ( $b->departure // $b->arrival )
			} @results;
		}
	}

	@results = $self->filter_results(@results);

	for my $result (@results) {
		my $platform = ( split( qr{ }, $result->platform // '' ) )[0];
		my $delay    = $result->delay;
		if ( $backend eq 'iris' and $admode eq 'arr' and not $result->arrival )
		{
			next;
		}
		if (    $backend eq 'iris'
			and $admode eq 'dep'
			and not $result->departure )
		{
			next;
		}
		my ( $info, $moreinfo );
		if ( $backend eq 'iris' ) {
			( $info, $moreinfo )
			  = $self->format_iris_result_info( $template, $result );
		}
		else {
			( $info, $moreinfo ) = $self->format_hafas_result_info($result);
		}

		my $time = $result->time;
@@ -1026,131 +1198,9 @@ sub handle_request {
				}
			);
			if ( $self->param('train') ) {
				$departures[-1]{route_pre_diff} = [
					$self->json_route_diff(
						[ $result->route_pre ],
						[ $result->sched_route_pre ]
					)
				];
				$departures[-1]{route_post_diff} = [
					$self->json_route_diff(
						[ $result->route_post ],
						[ $result->sched_route_post ]
					)
				];

				$departures[-1]{trip_id}
				  = get_hafas_trip_id( $self->ua, $self->app->cache_iris_main,
					$result );

				if (
					$departures[-1]{wr_link}
					and not check_wagonorder_with_wings(
						$self->ua, $self->app->cache_iris_main,
						$result,   $departures[-1]{wr_link}
					)
				  )
				{
					$departures[-1]{wr_link} = undef;
				}

				my ( $route_ts, $route_info ) = get_route_timestamps(
					$self->ua,
					$self->app->cache_iris_main,
					$self->app->cache_iris_rt,
					{ train => $result }
				);

             # If a train number changes on the way, IRIS routes are incomplete,
             # whereas HAFAS data has all stops -> merge HAFAS stops into IRIS
             # stops. This is a rare case, one point where it can be observed is
             # the TGV service at Frankfurt/Karlsruhe/Mannheim.
				if ( $route_info
					and my @hafas_stations
					= @{ $route_info->{stations} // [] } )
				{
					if ( my @iris_stations
						= @{ $departures[-1]{route_pre_diff} } )
					{
						my @missing_pre;
						for my $station (@hafas_stations) {
							if (
								List::MoreUtils::any { $_->{name} eq $station }
								@iris_stations
							  )
							{
								unshift(
									@{ $departures[-1]{route_pre_diff} },
									@missing_pre
								);
								last;
							}
							push(
								@missing_pre,
								{
									name  => $station,
									hafas => 1
								}
							);
						}
					}
					if ( my @iris_stations
						= @{ $departures[-1]{route_post_diff} } )
					{
						my @missing_post;
						for my $station ( reverse @hafas_stations ) {
							if (
								List::MoreUtils::any { $_->{name} eq $station }
								@iris_stations
							  )
							{
								push(
									@{ $departures[-1]{route_post_diff} },
									@missing_post
								);
								last;
							}
							unshift(
								@missing_post,
								{
									name  => $station,
									hafas => 1
								}
							);
						}
					}
				}
				if ($route_ts) {
					for my $elem (
						@{ $departures[-1]{route_pre_diff} },
						@{ $departures[-1]{route_post_diff} }
					  )
					{
						for my $key (
							keys %{ $route_ts->{ $elem->{name} } // {} } )
						{
							$elem->{$key} = $route_ts->{ $elem->{name} }{$key};
						}
					}
				}
				if ( $route_info and @{ $route_info->{messages} // [] } ) {
					my $him = $route_info->{messages};
					my @him_messages;
					$departures[-1]{messages}{him} = $him;
					for my $message ( @{$him} ) {
						if ( $message->{display} ) {
							push( @him_messages,
								[ $message->{header}, $message->{lead} ] );
						}
					}
					for my $message ( @{ $departures[-1]{moreinfo} // [] } ) {
						my $m = $message->[1];
						@him_messages
						  = grep { $_->[0] !~ m{Information\. $m\.$} }
						  @him_messages;
					}
					unshift( @{ $departures[-1]{moreinfo} }, @him_messages );
				}
				$self->render_train( $result, $departures[-1],
					$data->{station_name} // $self->stash('station') );
				return;
			}
		}
		else {
@@ -1182,10 +1232,6 @@ sub handle_request {
		}
	}

	if ( $self->param('ajax') ) {
		delete $self->stash->{layout};
	}

	if ( $template eq 'json' ) {
		$self->res->headers->access_control_allow_origin(q{*});
		my $json = $self->render_to_string(
@@ -1223,52 +1269,8 @@ sub handle_request {
			format => 'text',
		);
	}
	elsif ( my $train = $self->param('train') ) {

		my ($departure) = @departures;

		if ($departure) {

			my $linetype = 'bahn';
			if ( $departure->{train_type} eq 'S' ) {
				$linetype = 'sbahn';
			}
			elsif ($departure->{train_type} eq 'IC'
				or $departure->{train_type} eq 'ICE'
				or $departure->{train_type} eq 'EC'
				or $departure->{train_type} eq 'ECE'
				or $departure->{train_type} eq 'EN' )
			{
				$linetype = 'fern';
			}
			elsif ($departure->{train_type} eq 'THA'
				or $departure->{train_type} eq 'TGV'
				or $departure->{train_type} eq 'FLX'
				or $departure->{train_type} eq 'NJ' )
			{
				$linetype = 'ext';
			}
			elsif ( $departure->{train_line}
				and $departure->{train_line} =~ m{^S\d} )
			{
				$linetype = 'sbahn';
			}

			$self->render(
				'_train_details',
				departure => $departure,
				linetype  => $linetype,
				icetype => $self->app->ice_type_map->{ $departure->{train_no} },
				dt_now  => DateTime->now( time_zone => 'Europe/Berlin' ),
				station_name => $data->{station_name} // $station,
			);
		}
		else {
			$self->render('not_found');
		}
	}
	else {
		my $station_name = $data->{station_name} // $station;
		my $station_name = $data->{station_name} // $self->stash('station');
		$self->render(
			$template,
			departures       => \@departures,
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ sub get_wagenreihung_p {

	if ( my $content = $cache->thaw($url) ) {
		$promise->resolve($content);
		$self->app->log->debug("GET $url (cached)");
		return $promise;
	}

@@ -33,6 +34,7 @@ sub get_wagenreihung_p {
	  ->then(
		sub {
			my ($tx) = @_;
			$self->app->log->debug("GET $url (OK)");
			my $body = decode( 'utf-8', $tx->res->body );
			my $json = JSON->new->decode($body);

@@ -42,6 +44,7 @@ sub get_wagenreihung_p {
	)->catch(
		sub {
			my ($err) = @_;
			$self->app->log->debug("GET $url (error: $err)");
			$promise->reject($err);
		}
	)->wait;
+81 −0
Original line number Diff line number Diff line
var j_reqid;
//var j_stops = [];
var j_positions = [];
var j_frame = [];
var j_frame_i = [];

function dbf_map_parse() {
	$('#jdata').each(function() {
		j_reqid = $(this).data('req');
		/*var route_data = $(this).data('route');
		if (route_data) {
			route_data = route_data.split('|');
			j_stops = [];
			for (var stop_id in route_data) {
				var stopdata = route_data[stop_id].split(';');
				for (var i = 1; i < 5; i++) {
					stopdata[i] = parseInt(stopdata[i]);
				}
				j_stops.push(stopdata);
			}
		}*/
		var positions = $(this).data('poly');
		if (positions) {
			positions = positions.split('|');
			j_positions = [];
			for (var pos_id in positions) {
				var posdata = positions[pos_id].split(';');
				posdata[0] = parseFloat(posdata[0]);
				posdata[1] = parseFloat(posdata[1]);
				j_positions.push(posdata);
			}
		}
	});
}

function dbf_anim_coarse() {
	if (j_positions.length) {
		var pos1 = marker.getLatLng();
		var pos1lat = pos1.lat;
		var pos1lon = pos1.lng;
		var pos2 = j_positions.shift();
		var pos2lat = pos2[0];
		var pos2lon = pos2[1];

		j_frame_i = 200;
		j_frame = [];

		// approx 30 Hz -> 60 frames per 2 seconds
		for (var i = 1; i <= 60; i++) {
			var ratio = i / 60;
			j_frame.push([pos1lat + ((pos2lat - pos1lat) * ratio), pos1lon + ((pos2lon - pos1lon) * ratio)]);
		}

		j_frame_i = 0;
	}
}

function dbf_anim_fine() {
	if (j_frame[j_frame_i]) {
		marker.setLatLng(j_frame[j_frame_i++]);
	}
}

function dbf_map_reload() {
	$.get('/_ajax_mapinfo/' + j_reqid, function(data) {
		$('#infobox').html(data);
		dbf_map_parse();
		setTimeout(dbf_map_reload, 61000);
	}).fail(function() {
		setTimeout(dbf_map_reload, 5000);
	});
}

$(document).ready(function() {
	if ($('#infobox').length) {
		dbf_map_parse();
		setInterval(dbf_anim_coarse, 2000);
		setInterval(dbf_anim_fine, 33);
		setTimeout(dbf_map_reload, 61000);
	}
});
Loading