File Coverage

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   7 use strict;
  2         2  
  2         43  
4 2     2   6 use warnings;
  2         2  
  2         45  
5              
6 2     2   5 use base 'Geo::Coder::Many::Scheduler::UniquenessScheduler';
  2         2  
  2         525  
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 130 my $class = shift;
30 140         106 my $ra_geocoders = shift;
31              
32             # Convert weights (= desired frequencies) into a cumulative distribution
33             # function
34 140         105 my $total_weight = 0;
35 140         158 for my $rh_geo (@$ra_geocoders) {
36 210         159 my $weight = $rh_geo->{weight};
37 210 50       293 if ($weight <= 0) {
38             warn "Warning - weight for "
39             .$rh_geo->{geocoder}
40 0         0 ." should be greater than zero";
41             }
42 210         182 $rh_geo->{weight} = $weight + $total_weight;
43 210         201 $total_weight += $weight;
44             }
45             # (Normalization)
46 140         187 for (@$ra_geocoders) {
47 210         295 $_->{weight} /= $total_weight;
48             }
49            
50 140         444 my $self = $class->SUPER::new({items => $ra_geocoders});
51              
52 140         220 bless $self, $class;
53              
54 140         261 my @sorted = sort { $b->{weight} <=> $a->{weight} } @$ra_geocoders;
  70         163  
55 140         156 $self->{ ra_geocoders } = \@sorted;
56              
57 140         287 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 2007     2007   1388 my $self = shift;
74 2007         1566 my $r = rand;
75              
76 2007         1484 my $ra_geocoders = $self->{ra_geocoders};
77              
78 2007         1550 my $i = @$ra_geocoders - 1;
79 2007   100     6160 while ($i > 0 and $r > $self->{ra_geocoders}->[$i]->{weight}) { --$i; }
  1000         1548  
80 2007         3523 return $self->{ra_geocoders}->[$i]->{name};
81              
82             };
83              
84             1;
85              
86             __END__