From: Llewellyn Marshall Date: Tue, 23 Aug 2022 21:06:30 +0000 (-0400) Subject: add shipping distance from DB to copy hash and use it for sorting in hold targeter... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=refs%2Fheads%2Fuser%2Flew%2Fholdtargeter-geosort-wip;p=working%2FEvergreen.git add shipping distance from DB to copy hash and use it for sorting in hold targeter instead of getting it on the fly --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm index 65215c80f3..5c4db61860 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm @@ -707,7 +707,7 @@ sub compile_weighted_proximity_map { # Collect copy proximity info (generated via DB trigger) # from our newly create copy maps. my $hold_copy_maps = $self->editor->json_query({ - select => {ahcm => ['target_copy', 'proximity']}, + select => {ahcm => ['target_copy', 'proximity','shipping_distance']}, from => 'ahcm', where => {hold => $self->hold_id} }); @@ -1097,7 +1097,7 @@ sub attempt_prev_copy_retarget { return undef; } -# Returns the closest copy by proximity and vicinity that is a confirmed valid +# Returns the closest copy by proximity and shipping distance that is a confirmed valid # targetable copy. sub find_nearest_copy { my $self = shift; @@ -1108,53 +1108,22 @@ sub find_nearest_copy { my %seen; for my $prox (sort {$a <=> $b} keys %prox_map) { - my %distance_matrix; - my %hub_by_target; my @copies = @{$prox_map{$prox}}; next unless @copies; - # run vicinity calculator if proximity is greater than or equal to 3 - unless($prox < 3){ - unless($req_hub){ - # assigning the shipping hub for this hold - $req_hub = $vinc_calc->get_hub_from_ou($hold->pickup_lib); - } - my @copy_ids = map {$_->{id}} @copies; - # determine which shipping hub OU these copies would need to be sent to - %hub_by_target = $vinc_calc->get_target_hubs(\@copy_ids); - my @hubs = values(%hub_by_target); - %distance_matrix = $vinc_calc->hub_matrix($req_hub,\@hubs); - } - # run this block only if target copies are within the same OU - # or a distance matrix could not be retreived for a destination - if($prox < 3 || !%distance_matrix){ - # Pick a copy at random from each tier of the proximity map, - # starting at the lowest proximity and working up, until a - # copy is found that is suitable for targeting. - my $rand = int(rand(scalar(@copies))); - while (my ($c) = splice(@copies, $rand, 1)) { - $rand = int(rand(scalar(@copies))); - next if $seen{$c->{id}}; - - return $c if $self->copy_is_permitted($c); - $seen{$c->{id}} = 1; - - last unless(@copies); - } - } - else{ - # select the target copy from the closest OU - # TODO what happens if two hubs are the same distance away from home hub? - # TODO should we round distances so two hubs don't always choose from one another? - # TODO what if this was stored in the Action.hold_copy_map like the prox is? - for my $c (sort { $distance_matrix{$hub_by_target{$a->{id}}} <=> $distance_matrix{$hub_by_target{$b->{id}}} } @copies){ - $self->log_hold("VicinityCalculator - Copy: ".$c->{id}." Shipping Hub:".$hub_by_target{$c->{id}}. "Physical Distance: ".$distance_matrix{$hub_by_target{$c->{id}}}); - next if $seen{$c->{id}}; - return $c if $self->copy_is_permitted($c); - $seen{$c->{id}} = 1; - last unless(@copies); - } - } - + # Pick a copy at random from each tier of the proximity map, + # starting at the lowest proximity and working up, until a + # copy is found that is suitable for targeting. + # sort all of the copies by shipping hub distance. + # two copies with equal shipping distance are sorted at random. + for my $c (sort { $a->{shipping_distance} <=> $b->{shipping_distance} || (random(-2) + 1) } @copies){ + $rand = int(rand(scalar(@copies))); + next if $seen{$c->{id}}; + + return $c if $self->copy_is_permitted($c); + $seen{$c->{id}} = 1; + + last unless(@copies); + } } return undef;