Class: Splashy::Buckets

Inherits:
Object
  • Object
show all
Defined in:
lib/splashy/buckets.rb

Instance Method Summary collapse

Constructor Details

#initialize(wanted_distribution, wanted_count = nil) ⇒ Buckets

wanted_distribution - A Hash of desired distributions:

{ :a => 0.2, :b => 0.5, :c => 0.3 }

wanted_count - (optional) Maximum total elements to be selected.

otherwise, the maximum size set is selected.


7
8
9
10
11
12
13
14
15
16
17
# File 'lib/splashy/buckets.rb', line 7

def initialize( wanted_distribution, wanted_count=nil )
  unless wanted_distribution.values.inject(0){ |m,v| m + v } == 1.0
    raise ArgumentError.new( "Distribution must sum to 1.0" )
  end
  @wanted_distribution = wanted_distribution
  @wanted_count = wanted_count
  @buckets = Hash.new do |hash, name|
    hash[name] = Bucket.new( name )
  end
  @total_count = 0
end

Instance Method Details

#add(bucket_name, element) ⇒ Object

Public: Add a single element to a bucket.



44
45
46
47
# File 'lib/splashy/buckets.rb', line 44

def add( bucket_name, element )
  @buckets[bucket_name] << element
  @total_count += 1
end

#fill(bucket_name = nil, &block) ⇒ Object

Public: Put elements into buckets.

bucket_name - If supplied, all yielded elements will be added to that

bucket.

&block - A block that returns (if ‘bucket_name` is not supplied)

an Array: [bucket_name, element]. If `bucket_name` is
supplied, only the element needs to be returned.

Examples

fill { return [bucket_name, element] }
fill( :bucket_name ) { return element }


31
32
33
34
35
36
37
38
39
40
41
# File 'lib/splashy/buckets.rb', line 31

def fill( bucket_name = nil, &block )
  if bucket_name
    while element = yield( @total_count )
      self.add( bucket_name, element )
    end
  else
    while pair = yield( @total_count )
      self.add( *pair )
    end
  end
end

#satisfied?Boolean

Returns true if the conditions are satisfied enough to select.

Returns:

  • (Boolean)


50
51
52
53
54
55
56
57
# File 'lib/splashy/buckets.rb', line 50

def satisfied?
  begin
    self.assert_satisfied!
    true
  rescue DistributionUnsatisfiedError => e
    false
  end
end

#selectObject

Public: Return a distribution of elements based on the desired distribution. If a satisfactory distribution is not possible, a DistributionUnsatisfiedError is raised.

Returns a Hash of elements based on the desired distribution, keyed by the bucket names.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/splashy/buckets.rb', line 65

def select
  self.assert_satisfied!
  
  total_count = estimated_final_count
  
  selected = @wanted_distribution.keys.inject({}) do |memo, bucket_name|
    bucket = @buckets[bucket_name]
    count = total_count * @wanted_distribution[bucket_name]
    count = [1, count.round].max
    memo[bucket_name] = bucket.elements( count )
    memo
  end
  
  # Sometimes we need to fudge by a few to meet the `@wanted_count`
  selected = self.trim( selected ) if @wanted_count
  
  selected
end