From ffaa0c44a78bb4bab632fcb76b668215da4c0a82 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Tue, 23 Apr 2019 21:30:31 +0200 Subject: [PATCH] Automatic checkout \o/ --- lib/Travelynx.pm | 44 +++++++++++--- lib/Travelynx/Command/work.pm | 111 ++++++++++++++++++++++++++++++++++ templates/landingpage.html.ep | 46 ++++++++------ 3 files changed, 171 insertions(+), 30 deletions(-) create mode 100644 lib/Travelynx/Command/work.pm diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index da10a9a..c11f175 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -474,10 +474,10 @@ sub startup { # called twice: once with the old and once with the new value. $self->helper( 'invalidate_stats_cache' => sub { - my ( $self, $ts, $db ) = @_; + my ( $self, $ts, $db, $uid ) = @_; - my $uid = $self->current_user->{id}; - $db //= $self->pg->db; + $uid //= $self->current_user->{id}; + $db //= $self->pg->db; $self->pg->db->delete( 'journey_stats', @@ -500,12 +500,12 @@ sub startup { $self->helper( 'checkout' => sub { - my ( $self, $station, $force ) = @_; + my ( $self, $station, $force, $uid ) = @_; - my $db = $self->pg->db; - my $uid = $self->current_user->{id}; - my $status = $self->get_departures( $station, 120, 120 ); - my $user = $self->get_user_status; + my $db = $self->pg->db; + my $status = $self->get_departures( $station, 120, 120 ); + $uid //= $self->current_user->{id}; + my $user = $self->get_user_status($uid); my $train_id = $user->{train_id}; if ( not $user->{checked_in} and not $user->{cancelled} ) { @@ -602,7 +602,7 @@ sub startup { month => $+{month} ); } - $self->invalidate_stats_cache( $cache_ts, $db ); + $self->invalidate_stats_cache( $cache_ts, $db, $uid ); } $tx->commit; @@ -1268,7 +1268,7 @@ sub startup { // $in_transit->{checkin_ts}; my $action_time = epoch_to_dt($ts); - return { + my $ret = { checked_in => !$in_transit->{cancelled}, cancelled => $in_transit->{cancelled}, timestamp => $action_time, @@ -1288,6 +1288,30 @@ sub startup { arr_name => $in_transit->{arr_name}, route_after => \@route_after, }; + + $ret->{departure_countdown} + = $ret->{real_departure}->epoch - $now->epoch; + if ( $in_transit->{real_arr_ts} ) { + $ret->{arrival_countdown} + = $ret->{real_arrival}->epoch - $now->epoch; + $ret->{journey_duration} = $ret->{real_arrival}->epoch + - $ret->{real_departure}->epoch; + $ret->{journey_completion} = 1 - ( + $ret->{arrival_countdown} / $ret->{journey_duration} ); + if ( $ret->{journey_completion} > 1 ) { + $ret->{journey_completion} = 1; + } + elsif ( $ret->{journey_completion} < 0 ) { + $ret->{journey_completion} = 0; + } + } + else { + $ret->{arrival_countdown} = undef; + $ret->{journey_duration} = undef; + $ret->{journey_completion} = undef; + } + + return $ret; } my $latest = $db->select( diff --git a/lib/Travelynx/Command/work.pm b/lib/Travelynx/Command/work.pm new file mode 100644 index 0000000..b8f8e52 --- /dev/null +++ b/lib/Travelynx/Command/work.pm @@ -0,0 +1,111 @@ +package Travelynx::Command::work; +use Mojo::Base 'Mojolicious::Command'; + +use DateTime; +use List::Util qw(first); + +has description => + 'Perform automatic checkout when users arrive at their destination'; + +has usage => sub { shift->extract_usage }; + +sub run { + my ($self) = @_; + + my $now = DateTime->now( time_zone => 'Europe/Berlin' ); + + my $db = $self->app->pg->db; + + for my $entry ( + $db->select( 'in_transit_str', '*', { cancelled => 0 } )->hashes->each ) + { + + my $uid = $entry->{user_id}; + my $dep = $entry->{dep_ds100}; + my $arr = $entry->{arr_ds100}; + my $train = $entry->{train_id}; + + $self->app->log->debug("Processing $uid"); + + eval { + if ( $now->epoch - $entry->{real_dep_ts} < 300 ) { + $self->app->log->debug(" - updating departure"); + my $status = $self->app->get_departures( $dep, 30, 30 ); + if ( $status->{errstr} ) { + die("get_departures($dep): $status->{errstr}\n"); + } + + my ($train) + = first { $_->train_id eq $train } @{ $status->{results} }; + + if ( not $train ) { + die("could not find train $train at $dep\n"); + } + + $db->update( + 'in_transit', + { real_departure => $train->departure }, + { user_id => $uid } + ); + } + }; + if ($@) { + $self->app->log->error("work($uid)/departure: $@"); + } + + eval { + if ( + $entry->{arr_name} + and ( not $entry->{real_arr_ts} + or $now->epoch - $entry->{real_arr_ts} < 60 ) + ) + { + $self->app->log->debug(" - updating arrival"); + my $status = $self->app->get_departures( $arr, 20, 220 ); + if ( $status->{errstr} ) { + die("get_departures($arr): $status->{errstr}\n"); + } + + my ($train) + = first { $_->train_id eq $train } @{ $status->{results} }; + + if ( not $train ) { + die("could not find train $train at $arr\n"); + } + + $db->update( + 'in_transit', + { + sched_arrival => $train->sched_arrival, + real_arrival => $train->arrival, + }, + { user_id => $uid } + ); + } + elsif ( $entry->{real_arr_ts} ) { + $self->app->log->debug(" - checking out"); + my ( undef, $error ) = $self->app->checkout( $arr, 1, $uid ); + if ($error) { + die("${error}\n"); + } + } + }; + if ($@) { + $self->app->log->error("work($uid)/arrival: $@"); + } + + eval { } + } +} + +1; + +__END__ + +=head1 SYNOPSIS + + Usage: index.pl work + + Work Work Work. + + Should be called from a cronjob every three minutes or so. diff --git a/templates/landingpage.html.ep b/templates/landingpage.html.ep index 26bae8d..84514c5 100644 --- a/templates/landingpage.html.ep +++ b/templates/landingpage.html.ep @@ -14,12 +14,6 @@
% my $status = get_user_status(); - % my $now = DateTime->now(time_zone => 'Europe/Berlin'); - % my $dep_wait = ($status->{real_departure}->epoch - $now->epoch)/60; - % my $arr_wait = undef; - % if ($status->{real_arrival}->epoch) { - % $arr_wait = ($status->{real_arrival}->epoch - $now->epoch)/60; - % } % if ($status->{checked_in}) {
@@ -34,30 +28,42 @@ % }

- Abfahrt - % if ($dep_wait > 0) { - in <%= int(($status->{real_departure}->epoch - $now->epoch)/60) %> Minute<%= $dep_wait == 1 ? '' : 'n' %> - % } - um <%= $status->{real_departure}->strftime('%H:%M') %> + <%= $status->{real_departure}->strftime('%H:%M') %> % if ($status->{real_departure}->epoch != $status->{sched_departure}->epoch) { - (+<%= int(($status->{real_departure}->epoch - $status->{sched_departure}->epoch)/60) %>) + (<%= sprintf('%+d', ($status->{real_departure}->epoch - $status->{sched_departure}->epoch)/60) %>) % } -

-

+ → % if ($status->{real_arrival}->epoch) { - Voraussichtliche Ankunft um <%= $status->{real_arrival}->strftime('%H:%M') %> + <%= $status->{real_arrival}->strftime('%H:%M') %> % if ($status->{real_arrival}->epoch != $status->{sched_arrival}->epoch) { - (+<%= int(($status->{real_arrival}->epoch - $status->{sched_arrival}->epoch)/60) %>) + (<%= sprintf('%+d', ($status->{real_arrival}->epoch - $status->{sched_arrival}->epoch)/60) %>) % } % } % else { - Ankunft: noch nicht bekannt + unbekannt % }

- Achtung: Automatischer Checkout ist noch nicht - implementiert. Bitte spätestens eine Stunde nach Ankunft - am Ziel manuell auschecken. +

+ % if ($status->{departure_countdown} > 120) { + Abfahrt in <%= int($status->{departure_countdown} / 60) %> Minuten + % } + % elsif ($status->{arrival_countdown}) { + % if ($status->{arrival_countdown} > 0) { + Ankunft in <%= int($status->{arrival_countdown} / 60) %> + Minute<%= int($status->{arrival_countdown} / 60) == 1 ? '' : 'n' %> + % } + % else { + Ziel erreicht + % } + % } + % elsif ($status->{arr_name}) { + Ankunft in mehr als zwei Stunden + % } +
+
+
+

% if ($status->{arr_name}) {

Zielstation ändern?