From b1348c7d4a4f8432859c36217d87b20fdc359cb2 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 11 Oct 2020 19:38:01 +0200 Subject: [PATCH] move in_transit queries to an InTransit model class --- lib/Travelynx.pm | 417 +++++++++----------------- lib/Travelynx/Command/maintenance.pm | 2 + lib/Travelynx/Command/work.pm | 10 +- lib/Travelynx/Controller/Api.pm | 12 +- lib/Travelynx/Controller/Traveling.pm | 5 +- lib/Travelynx/Helper/IRIS.pm | 37 +++ lib/Travelynx/Model/InTransit.pm | 298 ++++++++++++++++++ 7 files changed, 503 insertions(+), 278 deletions(-) create mode 100644 lib/Travelynx/Model/InTransit.pm diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 7c7bb75..f446cda 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -21,6 +21,7 @@ use Travelynx::Helper::HAFAS; use Travelynx::Helper::IRIS; use Travelynx::Helper::Sendmail; use Travelynx::Helper::Traewelling; +use Travelynx::Model::InTransit; use Travelynx::Model::Journeys; use Travelynx::Model::Traewelling; use Travelynx::Model::Users; @@ -314,6 +315,16 @@ sub startup { } ); + $self->helper( + in_transit => sub { + my ($self) = @_; + state $in_transit = Travelynx::Model::InTransit->new( + log => $self->app->log, + pg => $self->pg, + ); + } + ); + $self->helper( journeys => sub { my ($self) = @_; @@ -454,34 +465,12 @@ sub startup { } eval { - my $json = JSON->new; - $db->insert( - 'in_transit', - { - user_id => $uid, - cancelled => $train->departure_is_cancelled - ? 1 - : 0, - checkin_station_id => $status->{station_eva}, - checkin_time => - DateTime->now( time_zone => 'Europe/Berlin' ), - dep_platform => $train->platform, - train_type => $train->type, - train_line => $train->line_no, - train_no => $train->train_no, - train_id => $train->train_id, - sched_departure => $train->sched_departure, - real_departure => $train->departure, - route => $json->encode( - [ $self->route_diff($train) ] - ), - messages => $json->encode( - [ - map { [ $_->[0]->epoch, $_->[1] ] } - $train->messages - ] - ) - } + $self->in_transit->add( + uid => $uid, + db => $db, + departure_eva => $status->{station_eva}, + train => $train, + route => [ $self->iris->route_diff($train) ], ); }; if ($@) { @@ -507,9 +496,7 @@ sub startup { $uid //= $self->current_user->{id}; if ( $journey_id eq 'in_transit' ) { - eval { - $self->pg->db->delete( 'in_transit', { user_id => $uid } ); - }; + eval { $self->in_transit->delete( uid => $uid ); }; if ($@) { $self->app->log->error("Undo($uid, $journey_id): $@"); return "Undo($journey_id): $@"; @@ -550,7 +537,10 @@ sub startup { delete $journey->{edited}; delete $journey->{id}; - $db->insert( 'in_transit', $journey ); + $self->in_transit->add_from_journey( + db => $db, + journey => $journey + ); my $cache_ts = DateTime->now( time_zone => 'Europe/Berlin' ); if ( $journey->{real_departure} @@ -603,10 +593,11 @@ sub startup { return ( 1, $status->{errstr} ); } - my $now = DateTime->now( time_zone => 'Europe/Berlin' ); - my $journey - = $db->select( 'in_transit', '*', { user_id => $uid } ) - ->expand->hash; + my $now = DateTime->now( time_zone => 'Europe/Berlin' ); + my $journey = $self->in_transit->get( + uid => $uid, + with_data => 1 + ); # Note that a train may pass the same station several times. # Notable example: S41 / S42 ("Ringbahn") both starts and @@ -650,12 +641,10 @@ sub startup { # Store the intended checkout station regardless of this operation's # success. - $db->update( - 'in_transit', - { - checkout_station_id => $new_checkout_station_id, - }, - { user_id => $uid } + $self->in_transit->set_arrival_eva( + uid => $uid, + db => $db, + arrival_eva => $new_checkout_station_id ); # If in_transit already contains arrival data for another estimated @@ -664,15 +653,9 @@ sub startup { and $journey->{checkout_station_id} != $new_checkout_station_id ) { - $db->update( - 'in_transit', - { - checkout_time => undef, - arr_platform => undef, - sched_arrival => undef, - real_arrival => undef, - }, - { user_id => $uid } + $self->in_transit->unset_arrival_data( + uid => $uid, + db => $db ); } @@ -697,13 +680,11 @@ sub startup { { $rt_arr->add( minutes => $station_data->{adelay} ); } - $db->update( - 'in_transit', - { - sched_arrival => $sched_arr, - real_arrival => $rt_arr - }, - { user_id => $uid } + $self->in_transit->set_arrival_times( + uid => $uid, + db => $db, + sched_arrival => $sched_arr, + rt_arrival => $rt_arr ); } } @@ -731,27 +712,14 @@ sub startup { die("Train ${train_no} has no arrival timestamp\n"); } elsif ( defined $train and $train->arrival ) { + $self->in_transit->set_arrival( + uid => $uid, + db => $db, + train => $train, + route => [ $self->iris->route_diff($train) ] + ); $has_arrived = $train->arrival->epoch < $now->epoch ? 1 : 0; - my $json = JSON->new; - $db->update( - 'in_transit', - { - checkout_time => $now, - arr_platform => $train->platform, - sched_arrival => $train->sched_arrival, - real_arrival => $train->arrival, - route => - $json->encode( [ $self->route_diff($train) ] ), - messages => $json->encode( - [ - map { [ $_->[0]->epoch, $_->[1] ] } - $train->messages - ] - ) - }, - { user_id => $uid } - ); if ($has_arrived) { my @unknown_stations = $self->grep_unknown_stations( $train->route ); @@ -770,15 +738,20 @@ sub startup { } } - $journey - = $db->select( 'in_transit', '*', { user_id => $uid } )->hash; + $journey = $self->in_transit->get( + uid => $uid, + db => $db + ); if ( $has_arrived or $force ) { delete $journey->{data}; $journey->{edited} = 0; $journey->{checkout_time} = $now; $db->insert( 'journeys', $journey ); - $db->delete( 'in_transit', { user_id => $uid } ); + $self->in_transit->delete( + uid => $uid, + db => $db + ); my $cache_ts = $now->clone; if ( $journey->{real_departure} @@ -810,22 +783,10 @@ sub startup { delete $journey->{data}; $db->insert( 'journeys', $journey ); - $journey - = $db->select( 'in_transit', ['data'], - { user_id => $uid } )->expand->hash; - $journey->{data}{cancelled_destination} = $train->station; - - $db->update( - 'in_transit', - { - checkout_station_id => undef, - checkout_time => undef, - arr_platform => undef, - sched_arrival => undef, - real_arrival => undef, - data => JSON->new->encode( $journey->{data} ), - }, - { user_id => $uid } + $self->in_transit->set_cancelled_destination( + uid => $uid, + db => $db, + cancelled_destination => $train->station, ); } @@ -853,27 +814,6 @@ sub startup { } ); - $self->helper( - 'update_in_transit_comment' => sub { - my ( $self, $comment, $uid, $db ) = @_; - $uid //= $self->current_user->{id}; - $db //= $self->pg->db; - - my $status - = $db->select( 'in_transit', ['user_data'], { user_id => $uid } ) - ->expand->hash; - if ( not $status ) { - return; - } - $status->{user_data}{comment} = $comment; - $db->update( - 'in_transit', - { user_data => JSON->new->encode( $status->{user_data} ) }, - { user_id => $uid } - ); - } - ); - # This helper should only be called directly when also providing a user ID. # If you don't have one, use current_user() instead (get_user_data will # delegate to it anyways). @@ -1180,52 +1120,6 @@ sub startup { } ); - $self->helper( - 'route_diff' => sub { - my ( $self, $train ) = @_; - my @json_route; - my @route = $train->route; - my @sched_route = $train->sched_route; - - my $route_idx = 0; - my $sched_idx = 0; - - while ( $route_idx <= $#route and $sched_idx <= $#sched_route ) { - if ( $route[$route_idx] eq $sched_route[$sched_idx] ) { - push( @json_route, [ $route[$route_idx], {}, undef ] ); - $route_idx++; - $sched_idx++; - } - - # this branch is inefficient, but won't be taken frequently - elsif ( not( grep { $_ eq $route[$route_idx] } @sched_route ) ) - { - push( @json_route, - [ $route[$route_idx], {}, 'additional' ], - ); - $route_idx++; - } - else { - push( @json_route, - [ $sched_route[$sched_idx], {}, 'cancelled' ], - ); - $sched_idx++; - } - } - while ( $route_idx <= $#route ) { - push( @json_route, [ $route[$route_idx], {}, 'additional' ], ); - $route_idx++; - } - while ( $sched_idx <= $#sched_route ) { - push( @json_route, - [ $sched_route[$sched_idx], {}, 'cancelled' ], - ); - $sched_idx++; - } - return @json_route; - } - ); - $self->helper( 'add_route_timestamps' => sub { my ( $self, $uid, $train, $is_departure ) = @_; @@ -1234,18 +1128,21 @@ sub startup { my $db = $self->pg->db; - my $journey = $db->select( - 'in_transit_str', - [ 'arr_eva', 'dep_eva', 'route', 'data' ], - { user_id => $uid } - )->expand->hash; +# TODO "with_timestamps" is misleading, there are more differences between in_transit and in_transit_str +# Here it's only needed because of dep_eva / arr_eva names + my $journey = $self->in_transit->get( + db => $db, + uid => $uid, + with_data => 1, + with_timestamps => 1 + ); if ( not $journey ) { return; } if ( $journey->{data}{trip_id} - and not $journey->{data}{polyline_id} ) + and not $journey->{polyline} ) { my ( $origin_eva, $destination_eva, $polyline_str ); $self->hafas->get_polyline_p( $train, @@ -1297,10 +1194,10 @@ sub startup { } } if ($polyline_id) { - $db->update( - 'in_transit', - { polyline_id => $polyline_id }, - { user_id => $uid } + $self->in_transit->set_polyline_id( + uid => $uid, + db => $db, + polyline_id => $polyline_id ); } return; @@ -1371,22 +1268,16 @@ sub startup { # HAFAS is happy as long as the date part starts with a number. # HAFAS-internal tripIDs use this format (withouth leading zero # for day of month < 10) though, so let's stick with it. - - my $res = $db->select( 'in_transit', ['data'], - { user_id => $uid } ); - my $res_h = $res->expand->hash; - my $data = $res_h->{data} // {}; - my $date_map = $date_yyyy; $date_map =~ tr{.}{}d; - $data->{trip_id} = sprintf( '1|%d|%d|%d|%s', + my $trip_id = sprintf( '1|%d|%d|%d|%s', $result->{id}, $result->{cycle}, $result->{pool}, $date_map ); - $db->update( - 'in_transit', - { data => JSON->new->encode($data) }, - { user_id => $uid } + $self->in_transit->update_data( + uid => $uid, + db => $db, + data => { trip_id => $trip_id } ); my $base2 @@ -1449,25 +1340,19 @@ sub startup { = $route_data->{ $station->[0] }; } - my $res = $db->select( 'in_transit', ['data'], - { user_id => $uid } ); - my $res_h = $res->expand->hash; - my $data = $res_h->{data} // {}; - - $data->{delay_msg} = [ map { [ $_->[0]->epoch, $_->[1] ] } - $train->delay_messages ]; - $data->{qos_msg} = [ map { [ $_->[0]->epoch, $_->[1] ] } - $train->qos_messages ]; - - $data->{him_msg} = $traininfo2->{messages}; - - $db->update( - 'in_transit', - { - route => JSON->new->encode($route), - data => JSON->new->encode($data) - }, - { user_id => $uid } + $self->in_transit->set_route_data( + uid => $uid, + db => $db, + route => $route, + delay_messages => [ + map { [ $_->[0]->epoch, $_->[1] ] } + $train->delay_messages + ], + qos_messages => [ + map { [ $_->[0]->epoch, $_->[1] ] } + $train->qos_messages + ], + him_messages => $traininfo2->{messages}, ); return; } @@ -1490,21 +1375,13 @@ sub startup { sub { my ($wagonorder) = @_; - my $res = $db->select( - 'in_transit', - [ 'data', 'user_data' ], - { user_id => $uid } - ); - my $res_h = $res->expand->hash; - my $data = $res_h->{data} // {}; - my $user_data = $res_h->{user_data} // {}; + my $data = {}; + my $user_data = {}; if ( $is_departure and not exists $wagonorder->{error} ) { - $data->{wagonorder_dep} = $wagonorder; - if ( exists $user_data->{wagongroups} ) { - $user_data->{wagongroups} = []; - } + $data->{wagonorder_dep} = $wagonorder; + $user_data->{wagongroups} = []; for my $group ( @{ $wagonorder->{data}{istformation} @@ -1539,23 +1416,25 @@ sub startup { } ); } - $db->update( - 'in_transit', - { - data => JSON->new->encode($data), - user_data => JSON->new->encode($user_data) - }, - { user_id => $uid } + $self->in_transit->update_data( + uid => $uid, + db => $db, + data => $data + ); + $self->in_transit->update_user_data( + uid => $uid, + db => $db, + user_data => $user_data ); } elsif ( not $is_departure and not exists $wagonorder->{error} ) { $data->{wagonorder_arr} = $wagonorder; - $db->update( - 'in_transit', - { data => JSON->new->encode($data) }, - { user_id => $uid } + $self->in_transit->update_data( + uid => $uid, + db => $db, + data => $data ); } return; @@ -1572,18 +1451,12 @@ sub startup { $self->dbdb->get_stationinfo_p( $journey->{dep_eva} )->then( sub { my ($station_info) = @_; + my $data = { stationinfo_dep => $station_info }; - my $res = $db->select( 'in_transit', ['data'], - { user_id => $uid } ); - my $res_h = $res->expand->hash; - my $data = $res_h->{data} // {}; - - $data->{stationinfo_dep} = $station_info; - - $db->update( - 'in_transit', - { data => JSON->new->encode($data) }, - { user_id => $uid } + $self->in_transit->update_data( + uid => $uid, + db => $db, + data => $data ); return; } @@ -1599,18 +1472,12 @@ sub startup { $self->dbdb->get_stationinfo_p( $journey->{arr_eva} )->then( sub { my ($station_info) = @_; + my $data = { stationinfo_arr => $station_info }; - my $res = $db->select( 'in_transit', ['data'], - { user_id => $uid } ); - my $res_h = $res->expand->hash; - my $data = $res_h->{data} // {}; - - $data->{stationinfo_arr} = $station_info; - - $db->update( - 'in_transit', - { data => JSON->new->encode($data) }, - { user_id => $uid } + $self->in_transit->update_data( + uid => $uid, + db => $db, + data => $data ); return; } @@ -1631,23 +1498,29 @@ sub startup { my $uid = $opt{uid} // $self->current_user->{id}; my $db = $opt{db} // $self->pg->db; - my $journey = $db->select( 'in_transit', ['checkout_station_id'], - { user_id => $uid } )->hash; - if ( not $journey ) { - $journey = $db->select( - 'journeys', - ['checkout_station_id'], - { - user_id => $uid, - cancelled => 0 - }, - { - limit => 1, - order_by => { -desc => 'real_departure' } - } - )->hash; + if ( + my $id = $self->in_transit->get_checkout_station_id( + uid => $uid, + db => $db + ) + ) + { + return $id; } + my $journey = $db->select( + 'journeys', + ['checkout_station_id'], + { + user_id => $uid, + cancelled => 0 + }, + { + limit => 1, + order_by => { -desc => 'real_departure' } + } + )->hash; + if ( not $journey ) { return; } @@ -1947,9 +1820,12 @@ sub startup { my $now = DateTime->now( time_zone => 'Europe/Berlin' ); my $epoch = $now->epoch; - my $in_transit - = $db->select( 'in_transit_str', '*', { user_id => $uid } ) - ->expand->hash; + my $in_transit = $self->in_transit->get( + uid => $uid, + db => $db, + with_data => 1, + with_timestamps => 1 + ); if ($in_transit) { @@ -2491,9 +2367,12 @@ sub startup { if ( not $err ) { $self->log->debug("... success!"); if ( $traewelling->{message} ) { - $self->update_in_transit_comment( - $traewelling->{message}, - $uid, $db ); + $self->in_transit->update_user_data( + uid => $uid, + db => $db, + user_data => + { comment => $traewelling->{message} } + ); } $self->traewelling->log( uid => $uid, diff --git a/lib/Travelynx/Command/maintenance.pm b/lib/Travelynx/Command/maintenance.pm index e92018e..d9ce55a 100644 --- a/lib/Travelynx/Command/maintenance.pm +++ b/lib/Travelynx/Command/maintenance.pm @@ -111,6 +111,8 @@ sub run { my $stats_res = $db->delete( 'journey_stats', { user_id => $uid } ); my $journeys_res = $db->delete( 'journeys', { user_id => $uid } ); my $transit_res = $db->delete( 'in_transit', { user_id => $uid } ); + + # TODO + traewelling, webhooks my $password_res = $db->delete( 'pending_passwords', { user_id => $uid } ); my $user_res = $db->delete( 'users', { id => $uid } ); diff --git a/lib/Travelynx/Command/work.pm b/lib/Travelynx/Command/work.pm index a97dc62..a43a5b9 100644 --- a/lib/Travelynx/Command/work.pm +++ b/lib/Travelynx/Command/work.pm @@ -60,8 +60,9 @@ sub run { { dep_platform => $train->platform, real_departure => $train->departure, - route => - $json->encode( [ $self->app->route_diff($train) ] ), + route => $json->encode( + [ $self->app->iris->route_diff($train) ] + ), messages => $json->encode( [ map { [ $_->[0]->epoch, $_->[1] ] } @@ -170,8 +171,9 @@ sub run { arr_platform => $train->platform, sched_arrival => $train->sched_arrival, real_arrival => $train->arrival, - route => - $json->encode( [ $self->app->route_diff($train) ] ), + route => $json->encode( + [ $self->app->iris->route_diff($train) ] + ), messages => $json->encode( [ map { [ $_->[0]->epoch, $_->[1] ] } diff --git a/lib/Travelynx/Controller/Api.pm b/lib/Travelynx/Controller/Api.pm index 8d2d2a7..74260c4 100755 --- a/lib/Travelynx/Controller/Api.pm +++ b/lib/Travelynx/Controller/Api.pm @@ -264,8 +264,10 @@ sub travel_v1 { uid => $uid ); if ( $payload->{comment} and not $error ) { - $self->update_in_transit_comment( - sanitize( q{}, $payload->{comment} ), $uid ); + $self->in_transit->update_user_data( + uid => $uid, + user_data => { comment => sanitize( q{}, $payload->{comment} ) } + ); } if ( $to_station and not $error ) { ( $train, $error ) = $self->checkout( @@ -310,8 +312,10 @@ sub travel_v1 { } if ( $payload->{comment} ) { - $self->update_in_transit_comment( - sanitize( q{}, $payload->{comment} ), $uid ); + $self->in_transit->update_user_data( + uid => $uid, + user_data => { comment => sanitize( q{}, $payload->{comment} ) } + ); } my ( $train, $error ) = $self->checkout( diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index 4df1558..6a1d1e1 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -1091,7 +1091,10 @@ sub comment_form { } else { $self->app->log->debug("set comment"); - $self->update_in_transit_comment( $self->param('comment') ); + $self->in_transit->update_user_data( + uid => $self->current_user->{id}, + user_data => { comment => $self->param('comment') } + ); $self->redirect_to('/'); } } diff --git a/lib/Travelynx/Helper/IRIS.pm b/lib/Travelynx/Helper/IRIS.pm index 3b98a51..a8ca6c3 100644 --- a/lib/Travelynx/Helper/IRIS.pm +++ b/lib/Travelynx/Helper/IRIS.pm @@ -68,4 +68,41 @@ sub get_departures { } } +sub route_diff { + my ( $self, $train ) = @_; + my @json_route; + my @route = $train->route; + my @sched_route = $train->sched_route; + + my $route_idx = 0; + my $sched_idx = 0; + + while ( $route_idx <= $#route and $sched_idx <= $#sched_route ) { + if ( $route[$route_idx] eq $sched_route[$sched_idx] ) { + push( @json_route, [ $route[$route_idx], {}, undef ] ); + $route_idx++; + $sched_idx++; + } + + # this branch is inefficient, but won't be taken frequently + elsif ( not( grep { $_ eq $route[$route_idx] } @sched_route ) ) { + push( @json_route, [ $route[$route_idx], {}, 'additional' ], ); + $route_idx++; + } + else { + push( @json_route, [ $sched_route[$sched_idx], {}, 'cancelled' ], ); + $sched_idx++; + } + } + while ( $route_idx <= $#route ) { + push( @json_route, [ $route[$route_idx], {}, 'additional' ], ); + $route_idx++; + } + while ( $sched_idx <= $#sched_route ) { + push( @json_route, [ $sched_route[$sched_idx], {}, 'cancelled' ], ); + $sched_idx++; + } + return @json_route; +} + 1; diff --git a/lib/Travelynx/Model/InTransit.pm b/lib/Travelynx/Model/InTransit.pm new file mode 100644 index 0000000..6aeab5f --- /dev/null +++ b/lib/Travelynx/Model/InTransit.pm @@ -0,0 +1,298 @@ +package Travelynx::Model::InTransit; + +use strict; +use warnings; +use 5.020; + +use DateTime; +use JSON; + +sub new { + my ( $class, %opt ) = @_; + + return bless( \%opt, $class ); +} + +sub add { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $train = $opt{train}; + my $checkin_station_id = $opt{departure_eva}; + my $route = $opt{route}; + + my $json = JSON->new; + + $db->insert( + 'in_transit', + { + user_id => $uid, + cancelled => $train->departure_is_cancelled + ? 1 + : 0, + checkin_station_id => $checkin_station_id, + checkin_time => DateTime->now( time_zone => 'Europe/Berlin' ), + dep_platform => $train->platform, + train_type => $train->type, + train_line => $train->line_no, + train_no => $train->train_no, + train_id => $train->train_id, + sched_departure => $train->sched_departure, + real_departure => $train->departure, + route => $json->encode($route), + messages => $json->encode( + [ map { [ $_->[0]->epoch, $_->[1] ] } $train->messages ] + ) + } + ); +} + +sub add_from_journey { + my ( $self, %opt ) = @_; + + my $journey = $opt{journey}; + my $db = $opt{db} // $self->{pg}->db; + + $db->insert( 'in_transit', $journey ); +} + +sub delete { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + + $db->delete( 'in_transit', { user_id => $uid } ); +} + +sub get { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + + my $table = 'in_transit'; + + if ( $opt{with_timestamps} ) { + $table = 'in_transit_str'; + } + + my $res = $db->select( $table, '*', { user_id => $uid } ); + + if ( $opt{with_data} ) { + return $res->expand->hash; + } + return $res->hash; +} + +sub get_checkout_station_id { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + + my $status = $db->select( 'in_transit', ['checkout_station_id'], + { user_id => $uid } )->hash; + + if ($status) { + return $status->{checkout_station_id}; + } + return; +} + +sub set_cancelled_destination { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $cancelled_destination = $opt{cancelled_destination}; + + my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } ) + ->expand->hash; + + my $data = $res_h ? $res_h->{data} : {}; + + $data->{cancelled_destination} = $cancelled_destination; + + $db->update( + 'in_transit', + { + checkout_station_id => undef, + checkout_time => undef, + arr_platform => undef, + sched_arrival => undef, + real_arrival => undef, + data => JSON->new->encode($data), + }, + { user_id => $uid } + ); +} + +sub set_arrival { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $train = $opt{train}; + my $route = $opt{route}; + + my $json = JSON->new; + + $db->update( + 'in_transit', + { + checkout_time => DateTime->now( time_zone => 'Europe/Berlin' ), + arr_platform => $train->platform, + sched_arrival => $train->sched_arrival, + real_arrival => $train->arrival, + route => $json->encode($route), + messages => $json->encode( + [ map { [ $_->[0]->epoch, $_->[1] ] } $train->messages ] + ) + }, + { user_id => $uid } + ); +} + +sub set_arrival_eva { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $checkout_station_id = $opt{arrival_eva}; + + $db->update( + 'in_transit', + { + checkout_station_id => $checkout_station_id, + }, + { user_id => $uid } + ); +} + +sub set_arrival_times { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $sched_arr = $opt{sched_arrival}; + my $rt_arr = $opt{rt_arrival}; + + $db->update( + 'in_transit', + { + sched_arrival => $sched_arr, + real_arrival => $rt_arr + }, + { user_id => $uid } + ); +} + +sub set_polyline_id { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $polyline_id = $opt{polyline_id}; + + $db->update( + 'in_transit', + { polyline_id => $polyline_id }, + { user_id => $uid } + ); +} + +sub set_route_data { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $route = $opt{route}; + my $delay_msg = $opt{delay_messages}; + my $qos_msg = $opt{qos_messages}; + my $him_msg = $opt{him_messages}; + + my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } ) + ->expand->hash; + + my $data = $res_h ? $res_h->{data} : {}; + + $data->{delay_msg} = $opt{delay_messages}; + $data->{qos_msg} = $opt{qos_messages}; + $data->{him_msg} = $opt{him_messages}; + + $db->update( + 'in_transit', + { + route => JSON->new->encode($route), + data => JSON->new->encode($data) + }, + { user_id => $uid } + ); +} + +sub unset_arrival_data { + my ( $self, %opt ) = @_; + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + + $db->update( + 'in_transit', + { + checkout_time => undef, + arr_platform => undef, + sched_arrival => undef, + real_arrival => undef, + }, + { user_id => $uid } + ); +} + +sub update_data { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $new_data = $opt{data} // {}; + + my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } ) + ->expand->hash; + + my $data = $res_h ? $res_h->{data} : {}; + + while ( my ( $k, $v ) = each %{$new_data} ) { + $data->{$k} = $v; + } + + $db->update( + 'in_transit', + { data => JSON->new->encode($data) }, + { user_id => $uid } + ); +} + +sub update_user_data { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + my $new_data = $opt{user_data} // {}; + + my $res_h = $db->select( 'in_transit', ['user_data'], { user_id => $uid } ) + ->expand->hash; + + my $data = $res_h ? $res_h->{user_data} : {}; + + while ( my ( $k, $v ) = each %{$new_data} ) { + $data->{$k} = $v; + } + + $db->update( + 'in_transit', + { user_data => JSON->new->encode($data) }, + { user_id => $uid } + ); +} + +1;