From 520e6456001cf858d7e59606a77b1cf0ab115aa9 Mon Sep 17 00:00:00 2001 From: Birte Kristina Friesel Date: Fri, 23 Aug 2024 22:44:02 +0200 Subject: [PATCH] Suggest backends based on coverage and latest checkout coordinates References #156 --- cpanfile | 1 + lib/Travelynx/Controller/Account.pm | 34 +++++++++++++++++++++++++ lib/Travelynx/Model/Journeys.pm | 26 +++++++++++++++++++ templates/select_backend.html.ep | 39 +++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/cpanfile b/cpanfile index f398415..673b738 100644 --- a/cpanfile +++ b/cpanfile @@ -7,6 +7,7 @@ requires 'Email::Sender::Simple'; requires 'GIS::Distance'; requires 'GIS::Distance::Fast'; requires 'List::UtilsBy'; +requires 'Math::Polygon'; requires 'MIME::Entity'; requires 'Mojolicious'; requires 'Mojolicious::Plugin::Authentication'; diff --git a/lib/Travelynx/Controller/Account.pm b/lib/Travelynx/Controller/Account.pm index 1847cda..aa3fa3a 100644 --- a/lib/Travelynx/Controller/Account.pm +++ b/lib/Travelynx/Controller/Account.pm @@ -6,6 +6,7 @@ package Travelynx::Controller::Account; use Mojo::Base 'Mojolicious::Controller'; use JSON; +use Math::Polygon; use Mojo::Util qw(xml_escape); use Text::Markdown; use UUID::Tiny qw(:std); @@ -1004,6 +1005,7 @@ sub backend_form { my $user = $self->current_user; my @backends = $self->stations->get_backends; + my @suggested_backends; my %place_map = ( AT => 'Österreich', @@ -1035,6 +1037,10 @@ sub backend_form { 'US-TX' => 'Texas', ); + my ( $user_lat, $user_lon ) + = $self->journeys->get_latest_checkout_latlon( uid => $user->{id} ); + say $user_lat . ' ' . $user_lon; + for my $backend (@backends) { my $type = 'UNKNOWN'; if ( $backend->{iris} ) { @@ -1051,6 +1057,33 @@ sub backend_form { $backend->{regions} = [ map { $place_map{$_} // $_ } @{ $s->{coverage}{regions} // [] } ]; $backend->{has_area} = $s->{coverage}{area} ? 1 : 0; + + if ( $s->{coverage}{area} + and $s->{coverage}{area}{type} eq 'Polygon' ) + { + # [0] == outer polygon, [1:] == holes within polygon + my $poly = Math::Polygon->new( + @{ $s->{coverage}{area}{coordinates}[0] } ); + say $backend->{name} . ' ' . $poly->area; + if ( $poly->contains( [ $user_lon, $user_lat ] ) ) { + push( @suggested_backends, $backend ); + } + } + elsif ( $s->{coverage}{area} + and $s->{coverage}{area}{type} eq 'MultiPolygon' ) + { + for my $s_poly ( + @{ $s->{coverage}{area}{coordinates} // [] } ) + { + my $poly + = Math::Polygon->new( @{ $s_poly->[0] // [] } ); + say $backend->{name} . ' ' . $poly->area; + if ( $poly->contains( [ $user_lon, $user_lat ] ) ) { + push( @suggested_backends, $backend ); + last; + } + } + } } else { $type = undef; @@ -1072,6 +1105,7 @@ sub backend_form { $self->render( 'select_backend', + suggestions => \@suggested_backends, backends => \@backends, user => $user, redirect_to => $self->req->param('redirect_to') // '/', diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm index 6d59d44..8a97aef 100755 --- a/lib/Travelynx/Model/Journeys.pm +++ b/lib/Travelynx/Model/Journeys.pm @@ -807,6 +807,32 @@ sub get_oldest_ts { return undef; } +sub get_latest_checkout_latlon { + my ( $self, %opt ) = @_; + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + + my $res_h = $db->select( + 'journeys_str', + [ 'arr_lat', 'arr_lon', ], + { + user_id => $uid, + cancelled => 0 + }, + { + limit => 1, + order_by => { -desc => 'journey_id' } + } + )->hash; + + if ( not $res_h ) { + return; + } + + return $res_h->{arr_lat}, $res_h->{arr_lon}; + +} + sub get_latest_checkout_ids { my ( $self, %opt ) = @_; my $uid = $opt{uid}; diff --git a/templates/select_backend.html.ep b/templates/select_backend.html.ep index d5bc9d5..55182f9 100644 --- a/templates/select_backend.html.ep +++ b/templates/select_backend.html.ep @@ -14,6 +14,45 @@ % if (stash('redirect_to')) { %= hidden_field 'redirect_to' => stash('redirect_to') % } + % if (@{stash('suggestions') // []}) { +
+
+

Vorschläge

+
+
+ % for my $backend (@{ stash('suggestions') // [] }) { +
+
+ %= $backend->{longname} + % if ($backend->{id} == $user->{backend_id}) { + (aktuell ausgewählt) + % } + % if ($backend->{has_area}) { +
+ <%= join(q{, }, @{$backend->{regions} // []}) || '[Karte]' %> + % } + % elsif ($backend->{regions}) { +
+ %= join(q{, }, @{$backend->{regions} // []}) + % } + % if ($backend->{homepage}) { +
+ <%= $backend->{homepage} =~ s{ ^ http s? :// (?: www[.] )? (.*?) (?: / )? $ }{$1}xr %> + % } +
+
+ +
+
+ % } + % } +
+
+

Alle Backends

+
+
% for my $backend (@{ stash('backends') // [] }) {