File Coverage

blib/lib/Geo/Coder/Many/Scheduler/UniquenessScheduler/WeightedRandom.pm
Criterion Covered Total %
statement 32 33 96.9
branch 1 2 50.0
condition 3 3 100.0
subroutine 5 5 100.0
pod 1 1 100.0
total 42 44 95.4


line stmt bran cond sub pod time code
1             package Geo::Coder::Many::Scheduler::UniquenessScheduler::WeightedRandom;
2              
3 2     2   10 use strict;
  2         6  
  2         59  
4 2     2   9 use warnings;
  2         6  
  2         49  
5              
6 2     2   11 use base 'Geo::Coder::Many::Scheduler::UniquenessScheduler';
  2         3  
  2         715  
7              
8             our $VERSION = '0.01';
9              
10             =head1 NAME
11              
12             Geo::Coder::Many::Scheduler::WeightedRandom - Weighted random scheduler
13              
14             =head1 DESCRIPTION
15              
16             A scheduler which randomly picks an item from the list, with the probability of
17             each proportional to its weight.
18              
19             =head1 METHODS
20              
21             =head2 new
22              
23             Construct and return a new scheduler for the array of pairs of geocoder names
24             and weights whose reference is passed in.
25              
26             =cut
27              
28             sub new {
29 140     140 1 238 my $class = shift;
30 140         192 my $ra_geocoders = shift;
31              
32             # Convert weights (= desired frequencies) into a cumulative distribution
33             # function
34 140         191 my $total_weight = 0;
35 140         230 for my $rh_geo (@$ra_geocoders) {
36 210         318 my $weight = $rh_geo->{weight};
37 210 50       412 if ($weight <= 0) {
38 0         0 warn "Warning - weight for "
39             .$rh_geo->{geocoder}
40             ." should be greater than zero";
41             }
42 210         369 $rh_geo->{weight} = $weight + $total_weight;
43 210         377 $total_weight += $weight;
44             }
45             # (Normalization)
46 140         282 for (@$ra_geocoders) {
47 210         509 $_->{weight} /= $total_weight;
48             }
49            
50 140         1133 my $self = $class->SUPER::new({items => $ra_geocoders});
51              
52 140         509 bless $self, $class;
53              
54 140         450 my @sorted = sort { $b->{weight} <=> $a->{weight} } @$ra_geocoders;
  70         270  
55 140         277 $self->{ ra_geocoders } = \@sorted;
56              
57 140         506 return $self;
58             };
59              
60             =head1 INTERNAL METHODS
61              
62             =head2 _get_next
63              
64             Overrides the method of the same name from the parent class, and is called by
65             get_next_unique instead.
66              
67             =cut
68              
69             ## no critic (ProhibitUnusedPrivateSubroutines)
70             # ( _get_next is actually 'protected' )
71              
72             sub _get_next {
73 2098     2098   3391 my $self = shift;
74 2098         2523 my $r = rand;
75              
76 2098         2754 my $ra_geocoders = $self->{ra_geocoders};
77              
78 2098         4052 my $i = @$ra_geocoders - 1;
79 2098   100     10451 while ($i > 0 and $r > $self->{ra_geocoders}->[$i]->{weight}) { --$i; }
  1019         2496  
80 2098         7231 return $self->{ra_geocoders}->[$i]->{name};
81              
82             };
83              
84             1;
85              
86             __END__