diff options
Diffstat (limited to 'lib')
| -rwxr-xr-x | lib/Travelynx/Controller/Traveling.pm | 352 | 
1 files changed, 178 insertions, 174 deletions
| diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index 132b439..10f7278 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -14,6 +14,184 @@ use List::MoreUtils qw(first_index);  use Text::CSV;  use Travel::Status::DE::IRIS::Stations; +# Internal Helpers + +sub has_str_in_list { +	my ( $str, @strs ) = @_; +	if ( List::Util::any { $str eq $_ } @strs ) { +		return 1; +	} +	return; +} + +sub get_connecting_trains { +	my ( $self, %opt ) = @_; + +	my $uid         = $opt{uid} //= $self->current_user->{id}; +	my $use_history = $self->users->use_history( uid => $uid ); + +	my ( $eva, $exclude_via, $exclude_train_id, $exclude_before ); +	my $now = $self->now->epoch; +	my ( $stationinfo, $arr_epoch, $arr_platform ); + +	if ( $opt{eva} ) { +		if ( $use_history & 0x01 ) { +			$eva = $opt{eva}; +		} +		elsif ( $opt{destination_name} ) { +			$eva = $opt{eva}; +		} +	} +	else { +		if ( $use_history & 0x02 ) { +			my $status = $self->get_user_status; +			$eva              = $status->{arr_eva}; +			$exclude_via      = $status->{dep_name}; +			$exclude_train_id = $status->{train_id}; +			$arr_platform     = $status->{arr_platform}; +			$stationinfo      = $status->{extra_data}{stationinfo_arr}; +			if ( $status->{real_arrival} ) { +				$exclude_before = $arr_epoch = $status->{real_arrival}->epoch; +			} +		} +	} + +	$exclude_before //= $now - 300; + +	if ( not $eva ) { +		return; +	} + +	my @destinations = $self->journeys->get_connection_targets(%opt); + +	if ($exclude_via) { +		@destinations = grep { $_ ne $exclude_via } @destinations; +	} + +	if ( not @destinations ) { +		return; +	} + +	my $stationboard = $self->iris->get_departures( +		station      => $eva, +		lookbehind   => 10, +		lookahead    => 40, +		with_related => 1 +	); +	if ( $stationboard->{errstr} ) { +		return; +	} +	@{ $stationboard->{results} } = map { $_->[0] } +	  sort { $a->[1] <=> $b->[1] } +	  map  { [ $_, $_->departure ? $_->departure->epoch : 0 ] } +	  @{ $stationboard->{results} }; +	my @results; +	my @cancellations; +	my %via_count = map { $_ => 0 } @destinations; +	for my $train ( @{ $stationboard->{results} } ) { +		if ( not $train->departure ) { +			next; +		} +		if (    $exclude_before +			and $train->departure +			and $train->departure->epoch < $exclude_before ) +		{ +			next; +		} +		if (    $exclude_train_id +			and $train->train_id eq $exclude_train_id ) +		{ +			next; +		} + +		# In general, this function is meant to return feasible +		# connections. However, cancelled connections may also be of +		# interest and are also useful for logging cancellations. +		# To satisfy both demands with (hopefully) little confusion and +		# UI clutter, this function returns two concatenated arrays: +		# actual connections (ordered by actual departure time) followed +		# by cancelled connections (ordered by scheduled departure time). +		# This is easiest to achieve in two separate loops. +		# +		# Note that a cancelled train may still have a matching destination +		# in its route_post, e.g. if it leaves out $eva due to +		# unscheduled route changes but continues on schedule afterwards +		# -- so it is only cancelled at $eva, not on the remainder of +		# the route. Also note that this specific case is not yet handled +		# properly by the cancellation logic etc. + +		if ( $train->departure_is_cancelled ) { +			my @via = ( $train->sched_route_post, $train->sched_route_end ); +			for my $dest (@destinations) { +				if ( List::Util::any { $_ eq $dest } @via ) { +					push( @cancellations, [ $train, $dest ] ); +					next; +				} +			} +		} +		else { +			my @via = ( $train->route_post, $train->route_end ); +			for my $dest (@destinations) { +				if ( $via_count{$dest} < 2 +					and List::Util::any { $_ eq $dest } @via ) +				{ +					push( @results, [ $train, $dest ] ); + +                 # Show all past and up to two future departures per destination +					if ( not $train->departure +						or $train->departure->epoch >= $now ) +					{ +						$via_count{$dest}++; +					} +					next; +				} +			} +		} +	} + +	@results = map { $_->[0] } +	  sort { $a->[1] <=> $b->[1] } +	  map { +		[ $_, $_->[0]->departure->epoch // $_->[0]->sched_departure->epoch ] +	  } @results; +	@cancellations = map { $_->[0] } +	  sort { $a->[1] <=> $b->[1] } +	  map { [ $_, $_->[0]->sched_departure->epoch ] } @cancellations; + +	for my $result (@results) { +		my $train       = $result->[0]; +		my @message_ids = List::Util::uniq map { $_->[1] } $train->raw_messages; +		$train->{message_id} = { map { $_ => 1 } @message_ids }; +		my $interchange_duration; +		if ( exists $stationinfo->{i} ) { +			$interchange_duration +			  = $stationinfo->{i}{$arr_platform}{ $train->platform }; +			$interchange_duration //= $stationinfo->{i}{"*"}; +		} +		if ( defined $interchange_duration ) { +			my $interchange_time +			  = ( $train->departure->epoch - $arr_epoch ) / 60; +			if ( $interchange_time < $interchange_duration ) { +				$train->{interchange_text} = 'Anschluss knapp'; +				$train->{interchange_icon} = 'warning'; +			} +			elsif ( $interchange_time == $interchange_duration ) { +				$train->{interchange_text} = 'Anschluss könnte knapp werden'; +				$train->{interchange_icon} = 'directions_run'; +			} + +       #else { +       #	$train->{interchange_text} = 'Anschluss wird voraussichtlich erreicht'; +       #	$train->{interchange_icon} = 'check'; +       #} +		} +	} + +	return ( @results, @cancellations ); +} + +# Controllers +  sub homepage {  	my ($self) = @_;  	if ( $self->is_user_authenticated ) { @@ -852,14 +1030,6 @@ sub commute {  	);  } -sub has_str_in_list { -	my ( $str, @strs ) = @_; -	if ( List::Util::any { $str eq $_ } @strs ) { -		return 1; -	} -	return; -} -  sub map_history {  	my ($self) = @_; @@ -1476,170 +1646,4 @@ sub add_journey_form {  	}  } -sub get_connecting_trains { -	my ( $self, %opt ) = @_; - -	my $uid         = $opt{uid} //= $self->current_user->{id}; -	my $use_history = $self->users->use_history( uid => $uid ); - -	my ( $eva, $exclude_via, $exclude_train_id, $exclude_before ); -	my $now = $self->now->epoch; -	my ( $stationinfo, $arr_epoch, $arr_platform ); - -	if ( $opt{eva} ) { -		if ( $use_history & 0x01 ) { -			$eva = $opt{eva}; -		} -		elsif ( $opt{destination_name} ) { -			$eva = $opt{eva}; -		} -	} -	else { -		if ( $use_history & 0x02 ) { -			my $status = $self->get_user_status; -			$eva              = $status->{arr_eva}; -			$exclude_via      = $status->{dep_name}; -			$exclude_train_id = $status->{train_id}; -			$arr_platform     = $status->{arr_platform}; -			$stationinfo      = $status->{extra_data}{stationinfo_arr}; -			if ( $status->{real_arrival} ) { -				$exclude_before = $arr_epoch = $status->{real_arrival}->epoch; -			} -		} -	} - -	$exclude_before //= $now - 300; - -	if ( not $eva ) { -		return; -	} - -	my @destinations = $self->journeys->get_connection_targets(%opt); - -	if ($exclude_via) { -		@destinations = grep { $_ ne $exclude_via } @destinations; -	} - -	if ( not @destinations ) { -		return; -	} - -	my $stationboard = $self->iris->get_departures( -		station      => $eva, -		lookbehind   => 10, -		lookahead    => 40, -		with_related => 1 -	); -	if ( $stationboard->{errstr} ) { -		return; -	} -	@{ $stationboard->{results} } = map { $_->[0] } -	  sort { $a->[1] <=> $b->[1] } -	  map  { [ $_, $_->departure ? $_->departure->epoch : 0 ] } -	  @{ $stationboard->{results} }; -	my @results; -	my @cancellations; -	my %via_count = map { $_ => 0 } @destinations; -	for my $train ( @{ $stationboard->{results} } ) { -		if ( not $train->departure ) { -			next; -		} -		if (    $exclude_before -			and $train->departure -			and $train->departure->epoch < $exclude_before ) -		{ -			next; -		} -		if (    $exclude_train_id -			and $train->train_id eq $exclude_train_id ) -		{ -			next; -		} - -		# In general, this function is meant to return feasible -		# connections. However, cancelled connections may also be of -		# interest and are also useful for logging cancellations. -		# To satisfy both demands with (hopefully) little confusion and -		# UI clutter, this function returns two concatenated arrays: -		# actual connections (ordered by actual departure time) followed -		# by cancelled connections (ordered by scheduled departure time). -		# This is easiest to achieve in two separate loops. -		# -		# Note that a cancelled train may still have a matching destination -		# in its route_post, e.g. if it leaves out $eva due to -		# unscheduled route changes but continues on schedule afterwards -		# -- so it is only cancelled at $eva, not on the remainder of -		# the route. Also note that this specific case is not yet handled -		# properly by the cancellation logic etc. - -		if ( $train->departure_is_cancelled ) { -			my @via = ( $train->sched_route_post, $train->sched_route_end ); -			for my $dest (@destinations) { -				if ( List::Util::any { $_ eq $dest } @via ) { -					push( @cancellations, [ $train, $dest ] ); -					next; -				} -			} -		} -		else { -			my @via = ( $train->route_post, $train->route_end ); -			for my $dest (@destinations) { -				if ( $via_count{$dest} < 2 -					and List::Util::any { $_ eq $dest } @via ) -				{ -					push( @results, [ $train, $dest ] ); - -                 # Show all past and up to two future departures per destination -					if ( not $train->departure -						or $train->departure->epoch >= $now ) -					{ -						$via_count{$dest}++; -					} -					next; -				} -			} -		} -	} - -	@results = map { $_->[0] } -	  sort { $a->[1] <=> $b->[1] } -	  map { -		[ $_, $_->[0]->departure->epoch // $_->[0]->sched_departure->epoch ] -	  } @results; -	@cancellations = map { $_->[0] } -	  sort { $a->[1] <=> $b->[1] } -	  map { [ $_, $_->[0]->sched_departure->epoch ] } @cancellations; - -	for my $result (@results) { -		my $train       = $result->[0]; -		my @message_ids = List::Util::uniq map { $_->[1] } $train->raw_messages; -		$train->{message_id} = { map { $_ => 1 } @message_ids }; -		my $interchange_duration; -		if ( exists $stationinfo->{i} ) { -			$interchange_duration -			  = $stationinfo->{i}{$arr_platform}{ $train->platform }; -			$interchange_duration //= $stationinfo->{i}{"*"}; -		} -		if ( defined $interchange_duration ) { -			my $interchange_time -			  = ( $train->departure->epoch - $arr_epoch ) / 60; -			if ( $interchange_time < $interchange_duration ) { -				$train->{interchange_text} = 'Anschluss knapp'; -				$train->{interchange_icon} = 'warning'; -			} -			elsif ( $interchange_time == $interchange_duration ) { -				$train->{interchange_text} = 'Anschluss könnte knapp werden'; -				$train->{interchange_icon} = 'directions_run'; -			} - -       #else { -       #	$train->{interchange_text} = 'Anschluss wird voraussichtlich erreicht'; -       #	$train->{interchange_icon} = 'check'; -       #} -		} -	} - -	return ( @results, @cancellations ); -} -  1; | 
