summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2022-07-30 10:47:18 +0200
committerDaniel Friesel <derf@finalrewind.org>2022-07-30 10:47:18 +0200
commitc06d653195edde4337971d441b48d14316858857 (patch)
treee34e9e4e4c4b46c16b852d49b2d3c56c36b0a6a7 /lib
parentde73024f1bac7cfce5f4b0882a04a27923dcb158 (diff)
Traveling: sort helpers <-> controllers
Diffstat (limited to 'lib')
-rwxr-xr-xlib/Travelynx/Controller/Traveling.pm352
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;