Traveling: sort helpers <-> controllers
This commit is contained in:
parent
de73024f1b
commit
c06d653195
1 changed files with 178 additions and 174 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue