diff options
author | Daniel Friesel <derf@finalrewind.org> | 2022-12-27 11:07:16 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2022-12-27 11:07:16 +0100 |
commit | 3abe6aed5cf4ddb37fcfc1c03df59c57e5867c9c (patch) | |
tree | c40d20051de4a0ad33239154ada64196524eac55 /lib/Travelynx/Model/Journeys.pm | |
parent | 73fa1a960c6affad0d3131ac62aa961267cdfe7f (diff) |
it's a secret to everybody.
Diffstat (limited to 'lib/Travelynx/Model/Journeys.pm')
-rwxr-xr-x | lib/Travelynx/Model/Journeys.pm | 213 |
1 files changed, 212 insertions, 1 deletions
diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm index b6647d2..1ab179a 100755 --- a/lib/Travelynx/Model/Journeys.pm +++ b/lib/Travelynx/Model/Journeys.pm @@ -34,6 +34,53 @@ sub epoch_to_dt { ); } +sub min_to_human { + my ($minutes) = @_; + + my @ret; + + if ( $minutes >= 14 * 24 * 60 ) { + push( @ret, int( $minutes / ( 7 * 24 * 60 ) ) . ' Wochen' ); + } + elsif ( $minutes >= 7 * 24 * 60 ) { + push( @ret, '1 Woche' ); + } + $minutes %= 7 * 24 * 60; + + if ( $minutes >= 2 * 24 * 60 ) { + push( @ret, int( $minutes / ( 24 * 60 ) ) . ' Tage' ); + } + elsif ( $minutes >= 24 * 60 ) { + push( @ret, '1 Tag' ); + } + $minutes %= 24 * 60; + + if ( $minutes >= 2 * 60 ) { + push( @ret, int( $minutes / 60 ) . ' Stunden' ); + } + elsif ( $minutes >= 60 ) { + push( @ret, '1 Stunde' ); + } + $minutes %= 60; + + if ( $minutes >= 2 ) { + push( @ret, "$minutes Minuten" ); + } + elsif ($minutes) { + push( @ret, "1 Minute" ); + } + + if ( @ret == 1 ) { + return $ret[0]; + } + + if ( @ret > 2 ) { + my $last = pop(@ret); + return join( ', ', @ret ) . " und $last"; + } + return "$ret[0] und $ret[1]"; +} + sub new { my ( $class, %opt ) = @_; @@ -991,6 +1038,165 @@ sub get_travel_distance { $distance_beeline, $skipped ); } +sub compute_review { + my ( $self, $stats, @journeys ) = @_; + my $longest_km; + my $longest_t; + my $shortest_km; + my $shortest_t; + my $message_count + ; # anzahl fahrten bei denen irgendeine nachricht vermerkt war -> irgendwas war anders als geplant + my %num_by_message; # für jede nachricht + my %num_by_wrtype + ; # zugtyp, sofern wagenreihung verfügbar. 'none' für nicht verfügbar. + my %num_by_linetype; # zugtyp nach "ICE 123" / "RE 127". + my %num_by_stop; # arr/dep name + + if ( not $stats or not @journeys or $stats->{num_trains} == 0 ) { + return; + } + + my %review; + + my $trains_per_journey = $stats->{num_trains} / $stats->{num_journeys}; + my $avg_change_count = sprintf( '%.1f', $trains_per_journey - 1 ); + my $min_total = $stats->{min_travel_real} + $stats->{min_interchange_real}; + + for my $journey (@journeys) { + if ( $journey->{rt_duration} ) { + if ( not $longest_t + or $journey->{rt_duration} > $longest_t->{rt_duration} ) + { + $longest_t = $journey; + } + if ( not $shortest_t + or $journey->{rt_duration} < $shortest_t->{rt_duration} ) + { + $shortest_t = $journey; + } + } + if ( $journey->{km_route} ) { + if ( not $longest_km + or $journey->{km_route} > $longest_km->{km_route} ) + { + $longest_km = $journey; + } + if ( not $shortest_km + or $journey->{km_route} < $shortest_km->{km_route} ) + { + $shortest_km = $journey; + } + } + if ( $journey->{messages} and @{ $journey->{messages} } ) { + $message_count += 1; + for my $message ( @{ $journey->{messages} } ) { + $num_by_message{ $message->[1] } += 1; + } + } + if ( $journey->{type} ) { + $num_by_linetype{ $journey->{type} } += 1; + } + if ( $journey->{from_name} ) { + $num_by_stop{ $journey->{from_name} } += 1; + } + if ( $journey->{to_name} ) { + $num_by_stop{ $journey->{to_name} } += 1; + } + } + + my @linetypes = sort { $b->[1] <=> $a->[1] } + map { [ $_, $num_by_linetype{$_} ] } keys %num_by_linetype; + my @stops = sort { $b->[1] <=> $a->[1] } + map { [ $_, $num_by_stop{$_} ] } keys %num_by_stop; + + my @reasons = sort { $b->[1] <=> $a->[1] } + map { [ $_, $num_by_message{$_} ] } keys %num_by_message; + + $review{num_stops} = scalar @stops; + $review{trains_per_day} = sprintf( '%.1f', $stats->{num_trains} / 365 ); + $review{km_route} = sprintf( '%.0f', $stats->{km_route} ); + $review{km_beeline} = sprintf( '%.0f', $stats->{km_beeline} ); + $review{km_circle} = sprintf( '%.1f', $stats->{km_route} / 40030 ); + $review{km_diag} = sprintf( '%.1f', $stats->{km_route} / 12742 ); + + $review{traveling_min_total} = $min_total; + $review{traveling_percentage_year} + = sprintf( "%.1f%%", $min_total * 100 / 525948.77 ); + $review{traveling_time_year} = min_to_human($min_total); + + if (@linetypes) { + $review{typical_type} = $linetypes[0][0]; + } + if ( @stops >= 3 ) { + my $desc = q{}; + $review{typical_stops_3} = [ $stops[0][0], $stops[1][0], $stops[2][0] ]; + } + elsif ( @stops == 2 ) { + $review{typical_stops_2} = [ $stops[0][0], $stops[1][0] ]; + } + $review{typical_time} + = min_to_human( $stats->{min_travel_real} / $stats->{num_trains} ); + $review{typical_km} + = sprintf( '%.0f', $stats->{km_route} / $stats->{num_trains} ); + $review{typical_kmh} = sprintf( '%.0f', + $stats->{km_route} / ( $stats->{min_travel_real} / 60 ) ); + $review{typical_delay_dep} + = sprintf( '%.0f', $stats->{delay_dep} / $stats->{num_trains} ); + $review{typical_delay_dep_h} = min_to_human( $review{typical_delay_dep} ); + $review{typical_delay_arr} + = sprintf( '%.0f', $stats->{delay_arr} / $stats->{num_trains} ); + $review{typical_delay_arr_h} = min_to_human( $review{typical_delay_arr} ); + + $review{longest_t_time} = min_to_human( $longest_t->{rt_duration} / 60 ); + $review{longest_t_type} = $longest_t->{type}; + $review{longest_t_lineno} = $longest_t->{line} // $longest_t->{no}; + $review{longest_t_from} = $longest_t->{from_name}; + $review{longest_t_to} = $longest_t->{to_name}; + $review{longest_t_id} = $longest_t->{id}; + + $review{longest_km_km} = sprintf( '%.0f', $longest_km->{km_route} ); + $review{longest_km_type} = $longest_km->{type}; + $review{longest_km_lineno} = $longest_km->{line} // $longest_km->{no}; + $review{longest_km_from} = $longest_km->{from_name}; + $review{longest_km_to} = $longest_km->{to_name}; + $review{longest_km_id} = $longest_km->{id}; + + $review{shortest_t_time} = min_to_human( $shortest_t->{rt_duration} / 60 ); + $review{shortest_t_type} = $shortest_t->{type}; + $review{shortest_t_lineno} = $shortest_t->{line} // $shortest_t->{no}; + $review{shortest_t_from} = $shortest_t->{from_name}; + $review{shortest_t_to} = $shortest_t->{to_name}; + $review{shortest_t_id} = $shortest_t->{id}; + + $review{shortest_km_m} = sprintf( '%.0f', $shortest_km->{km_route} * 1000 ); + $review{shortest_km_type} = $shortest_km->{type}; + $review{shortest_km_lineno} = $shortest_km->{line} // $shortest_km->{no}; + $review{shortest_km_from} = $shortest_km->{from_name}; + $review{shortest_km_to} = $shortest_km->{to_name}; + $review{shortest_km_id} = $shortest_km->{id}; + + $review{issue_percent} + = sprintf( '%.0f%%', $message_count * 100 / $stats->{num_trains} ); + for my $i ( 0 .. 2 ) { + if ( $reasons[$i] ) { + my $p = 'issue' . ( $i + 1 ); + $review{"${p}_count"} = $reasons[$i][1]; + $review{"${p}_text"} = $reasons[$i][0]; + } + } + + printf( "In %.0f%% der Fahrten war irgendetwas nicht wie vorgesehen\n", + $message_count * 100 / $stats->{num_trains} ); + say "Die drei häufigsten Anmerkungen waren:"; + for my $i ( 0 .. 2 ) { + if ( $reasons[$i] ) { + printf( "%d× %s\n", $reasons[$i][1], $reasons[$i][0] ); + } + } + + return \%review; +} + sub compute_stats { my ( $self, @journeys ) = @_; my $km_route = 0; @@ -1093,7 +1299,8 @@ sub get_stats { # checks out of a train or manually edits/adds a journey. if ( - not $opt{write_only} + not $opt{write_only} + and not $opt{review} and my $stats = $self->stats_cache->get( uid => $uid, db => $db, @@ -1148,6 +1355,10 @@ sub get_stats { stats => $stats ); + if ( $opt{review} ) { + return ( $stats, $self->compute_review( $stats, @journeys ) ); + } + return $stats; } |