qfill 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,5 +9,5 @@ require "qfill/pusher"
9
9
  require "qfill/manager"
10
10
 
11
11
  module Qfill
12
- # Your code goes here...
12
+ VERBOSE = false
13
13
  end
@@ -17,6 +17,12 @@ module Qfill
17
17
  return self.queues.find { |queue| queue.name == key }
18
18
  end
19
19
 
20
+ def index_of(queue_name)
21
+ index = self.queues.index { |queue| queue.name == queue_name }
22
+ return index if index
23
+ raise "Fuck #{index} index is missing for #{queue_name}"
24
+ end
25
+
20
26
  def reset!
21
27
  self.current_index = 0
22
28
  end
@@ -5,87 +5,162 @@
5
5
  #)
6
6
  module Qfill
7
7
  class Manager
8
- attr_accessor :all_list_max, :popper, :pusher, :fill_count, :strategy
8
+ attr_accessor :all_list_max, :popper, :pusher, :fill_count, :strategy, :result
9
9
 
10
- STRATEGY_OPTIONS = [:drain, :sample]
10
+ STRATEGY_OPTIONS = [:drain_to_limit, :drain_to_empty, :sample]
11
11
 
12
12
  def initialize(options = {})
13
13
  unless options[:popper] && options[:pusher]
14
14
  raise ArgumentError, "#{self.class}: popper and pusher are required options for #{self.class}.new(options)"
15
15
  end
16
16
  unless options[:strategy].nil? || STRATEGY_OPTIONS.include?(options[:strategy])
17
- raise ArgumentError, "#{self.class}: strategy is optional, but must be one of #{STRATEGY_OPTIONS.inspect} if provided"
17
+ if options[:strategy] == :drain
18
+ warn "Qfill strategy :drain has been renamed :drain_to_limit, please update your code."
19
+ options[:strategy] = :drain_to_limit
20
+ else
21
+ raise ArgumentError, "#{self.class}: strategy is optional, but must be one of #{STRATEGY_OPTIONS.inspect} if provided"
22
+ end
18
23
  end
19
24
  @popper = options[:popper]
20
25
  @pusher = options[:pusher]
21
26
  # Provided by user, or defaults to the total number of primary elements in popper list set
22
- @all_list_max = options[:all_list_max] ? [options[:all_list_max], self.popper.get_primary_elements].min : self.popper.get_primary_elements
27
+ @all_list_max = options[:all_list_max] ? [options[:all_list_max], self.popper.count_primary_elements].min : self.popper.count_primary_elements
23
28
  @fill_count = 0
24
- @strategy = options[:strategy] || :drain # or :sample
29
+ @strategy = options[:strategy] || :drain_to_limit # or :drain_to_empty or :sample
25
30
  end
26
31
 
27
32
  def fill!
28
- while !is_full? && !self.popper.primary_empty? && (result = self.pusher.current_list)
29
- self.fill_to_ratio!(result, self.all_list_max)
33
+ while !is_full? && !self.popper.primary_empty? && (self.result = self.pusher.current_list)
34
+ if self.current_strategy == :drain_to_empty
35
+ preferred_potential_ratio = 0
36
+ preferred_potential = 0
37
+ self.result.list_ratios.each do |list_name, list_ratio|
38
+ poppy = self.result.preferred.select {|x| x == list_name}
39
+ if poppy
40
+ preferred_potential_ratio += list_ratio
41
+ num = self.popper[list_name].elements.length
42
+ preferred_potential += num
43
+ self.result.max_tracker[list_name] = num
44
+ end
45
+ end
46
+ self.result.preferred_potential = preferred_potential
47
+ self.result.preferred_potential_ratio = preferred_potential_ratio
48
+ end
49
+ self.fill_to_ratio!
30
50
  self.pusher.set_next_as_current!
51
+ self.result.elements.shuffle! if self.result.shuffle
31
52
  end
32
53
  end
33
54
 
34
- def fill_to_ratio!(result, all_list_max)
35
- result.max = Qfill::Result.get_limit_from_max_and_ratio(all_list_max, result.ratio)
55
+ def fill_to_ratio!
56
+ case self.current_strategy
57
+ when :drain_to_empty then
58
+ result.max = self.result.preferred_potential_ratio > 0 ? [(self.result.preferred_potential / self.result.preferred_potential_ratio), self.remaining_to_fill].min : self.remaining_to_fill
59
+ when :drain_to_limit, :sample then
60
+ result.max = Qfill::Result.get_limit_from_max_and_ratio(self.remaining_to_fill, result.ratio)
61
+ end
62
+ #result.max = Qfill::Result.get_limit_from_max_and_ratio(self.all_list_max, result.ratio)
36
63
  if !result.list_ratios.empty?
37
- self.fill_according_to_list_ratios!(result)
64
+ self.fill_according_to_list_ratios!
38
65
  else
39
- self.fill_up_to_ratio!(result)
66
+ self.fill_up_to_ratio!
40
67
  end
41
68
  end
42
69
 
43
- def fill_according_to_list_ratios!(result)
70
+ def remaining_to_fill
71
+ self.all_list_max - self.fill_count
72
+ end
73
+
74
+ # Go through the queues this result should be filled from and push elements from them onto the current result list.
75
+ def fill_according_to_list_ratios!
44
76
  added = 0
45
- if self.strategy == :drain
46
- result.list_ratios.each do |list_name, list_ratio|
47
- #puts "fill_according_to_list_ratios!, :drain, #{list_name}: Primary remaining => #{self.popper.get_primary_elements}"
48
- max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio)
49
- array_to_push = self.popper.next_objects!(list_name, max_from_list)
50
- added = result.push(array_to_push, list_name)
51
- end
52
- self.fill_count += added
53
- elsif self.strategy == :sample
54
- while !is_full? && !result.is_full? && !self.popper.totally_empty? && (list_ratio_tuple = result.current_list_ratio)
55
- #puts "fill_according_to_list_ratios!, :sample, #{list_ratio_tuple[0]}: Primary remaining => #{self.popper.get_primary_elements}"
56
- max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio_tuple[1])
57
- array_to_push = self.popper.next_objects!(list_ratio_tuple[0], max_from_list)
58
- added = result.push(array_to_push, list_ratio_tuple[0])
59
- self.fill_count += added
60
- result.set_next_as_current!
61
- end
77
+ tally = 0
78
+ ratio_modifier = 1
79
+ case self.current_strategy
80
+ when :drain_to_empty then
81
+ # Are there any elements in preferred queues that we should add?
82
+ if self.result.preferred_potential > 0
83
+ # Setup a ratio modifier for the non-preferred queues
84
+ result.list_ratios.each do |list_name, list_ratio|
85
+ max_from_list = self.result.max_tracker[list_name] || Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio)
86
+ array_to_push = self.popper.next_objects!(list_name, max_from_list)
87
+ self.popper.current_index = self.popper.index_of(list_name)
88
+ added = result.push(array_to_push, list_name)
89
+ puts "[fill_according_to_list_ratios!]#{self}[#{list_name}][added:#{added}]" if Qfill::VERBOSE
90
+ tally += added
91
+ end
92
+ self.fill_count += tally
93
+ end
94
+ when :drain_to_limit
95
+ result.list_ratios.each do |list_name, list_ratio|
96
+ max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio)
97
+ array_to_push = self.popper.next_objects!(list_name, max_from_list)
98
+ self.popper.current_index = self.popper.index_of(list_name)
99
+ added = result.push(array_to_push, list_name)
100
+ puts "[fill_according_to_list_ratios!]#{self}[#{list_name}][added:#{added}]" if Qfill::VERBOSE
101
+ tally += added
102
+ end
103
+ self.fill_count += tally
104
+ when :sample then
105
+ #puts "#{!is_full?} && #{result.fill_count} >= #{result.max} && #{!self.popper.totally_empty?} && #{(list_ratio_tuple = result.current_list_ratio)}"
106
+ while !is_full? && !result.is_full? && !self.popper.totally_empty? && (list_ratio_tuple = result.current_list_ratio)
107
+ max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio_tuple[1])
108
+ array_to_push = self.popper.next_objects!(list_ratio_tuple[0], max_from_list)
109
+ added = result.push(array_to_push, list_ratio_tuple[0])
110
+ self.fill_count += added
111
+ puts "[fill_according_to_list_ratios!]#{self}[#{list_ratio_tuple[0]}][added:#{added}]" if Qfill::VERBOSE
112
+ result.set_next_as_current!
113
+ end
62
114
  end
63
115
  end
64
116
 
65
- def fill_up_to_ratio!(result)
66
- ratio = 1.0 / self.popper.primary.length
67
- max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, ratio)
117
+ # Go through the primary (non backfill) queues in the popper and push elements from them onto the current result list.
118
+ def fill_up_to_ratio!
68
119
  added = 0
69
- if self.strategy == :drain
120
+ tally = 0
121
+ if self.current_strategy == :drain_to_empty
70
122
  self.popper.primary.each do |queue|
71
- #puts "fill_up_to_ratio!, :drain max #{max_from_list}, #{queue.name}: Primary remaining => #{self.popper.get_primary_elements}"
72
- array_to_push = self.popper.next_objects!(queue.name, max_from_list)
123
+ array_to_push = self.popper.next_objects!(queue.name, result.max)
73
124
  added = result.push(array_to_push, queue.name)
125
+ self.popper.current_index = self.popper.index_of(queue.name)
126
+ puts "[fill_up_to_ratio!]#{self}[Q:#{queue.name}][added:#{added}]" if Qfill::VERBOSE
127
+ tally += added
74
128
  end
75
129
  self.fill_count += added
76
- elsif self.strategy == :sample
77
- while !is_full? && !result.is_full? && !self.popper.totally_empty? && (origin_list = self.popper.current_list)
78
- #puts "fill_up_to_ratio!, :sample max #{max_from_list}, #{origin_list.name}: Primary remaining => #{self.popper.get_primary_elements}"
79
- array_to_push = self.popper.next_objects!(origin_list.name, max_from_list)
80
- added = result.push(array_to_push, origin_list.name)
81
- self.fill_count += added
82
- self.popper.set_next_as_current!
130
+ else
131
+ ratio = 1.0 / self.popper.primary.length # 1 divided by the number of queues
132
+ max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, ratio)
133
+ if self.current_strategy == :drain_to_limit
134
+ self.popper.primary.each do |queue|
135
+ array_to_push = self.popper.next_objects!(queue.name, max_from_list)
136
+ added = result.push(array_to_push, queue.name)
137
+ self.popper.current_index = self.popper.index_of(queue.name)
138
+ puts "[fill_up_to_ratio!]#{self}[Q:#{queue.name}][added:#{added}]" if Qfill::VERBOSE
139
+ tally += added
140
+ end
141
+ self.fill_count += tally
142
+ elsif self.current_strategy == :sample
143
+ while !is_full? && !result.is_full? && !self.popper.totally_empty? && (origin_list = self.popper.current_list)
144
+ array_to_push = self.popper.next_objects!(origin_list.name, max_from_list)
145
+ added = result.push(array_to_push, origin_list.name)
146
+ self.fill_count += added
147
+ puts "[fill_up_to_ratio!]#{self}[Added:#{added}][Max List:#{max_from_list}][ratio:#{ratio}][added:#{added}]" if Qfill::VERBOSE
148
+ self.popper.set_next_as_current!
149
+ end
83
150
  end
84
151
  end
85
152
  end
86
153
 
154
+ def current_strategy
155
+ (result.strategy || self.strategy)
156
+ end
157
+
87
158
  def is_full?
88
159
  self.fill_count >= self.all_list_max
89
160
  end
161
+
162
+ def to_s
163
+ "[#{self.current_strategy}][Result Max:#{result.max}][All Max:#{self.all_list_max}][Current Max:#{self.result.max}][Filled:#{self.fill_count}][Primary #:#{self.popper.count_primary_elements}]"
164
+ end
90
165
  end
91
166
  end
@@ -81,14 +81,14 @@ module Qfill
81
81
  end
82
82
 
83
83
  def primary_empty?
84
- self.get_primary_elements == 0
84
+ self.count_primary_elements == 0
85
85
  end
86
86
 
87
87
  def totally_empty?
88
88
  self.get_total_elements == 0
89
89
  end
90
90
 
91
- def get_primary_elements
91
+ def count_primary_elements
92
92
  self.primary.inject(0) {|counter, queue| counter += queue.elements.length}
93
93
  end
94
94
 
@@ -44,9 +44,9 @@ module Qfill
44
44
  super(*args)
45
45
  with_ratio = self.queues.map {|x| x.ratio}.compact
46
46
  ratio_to_split = (1 - with_ratio.inject(0, :+))
47
- if ratio_to_split < 0
48
- raise ArgumentError, "#{self.class}: mismatched ratios for queues #{with_ratio.join(' + ')} must not total more than 1"
49
- end
47
+ #if ratio_to_split < 0
48
+ # raise ArgumentError, "#{self.class}: mismatched ratios for queues #{with_ratio.join(' + ')} must not total more than 1"
49
+ #end
50
50
  num_without_ratio = self.queues.length - with_ratio.length
51
51
  if num_without_ratio > 0 && ratio_to_split <= 1
52
52
  equal_portion = ratio_to_split / num_without_ratio
@@ -1,13 +1,18 @@
1
+ # :preferred is used for :draim_to_empty
2
+ # :ratio is used for the other strategies
1
3
  # Qfill::Result.new(:name => "Best Results",
2
4
  # :filter => filter3,
3
5
  # :ratio => 0.5,
4
6
  # :list_ratios => {
5
7
  # "High List" => 0.4,
6
8
  # "Medium List" => 0.2,
7
- # "Low List" => 0.4 } )
9
+ # "Low List" => 0.4 },
10
+ # :preferred => ["High List", "Medium List"]
11
+ # )
8
12
  module Qfill
9
13
  class Result < Qfill::List
10
- attr_accessor :ratio, :list_ratios, :fill_tracker, :fill_count, :validate, :filter, :current_list_ratio_index, :max
14
+ attr_accessor :ratio, :list_ratios, :fill_tracker, :fill_count, :current_count, :validate, :current_list_ratio_index, :max,
15
+ :strategy, :shuffle, :preferred, :preferred_potential, :preferred_potential_ratio, :max_tracker
11
16
 
12
17
  def self.get_limit_from_max_and_ratio(all_list_max, ratio)
13
18
  limit = (all_list_max * ratio).round(0)
@@ -27,10 +32,17 @@ module Qfill
27
32
  if ratio_leftover < 0
28
33
  raise ArgumentError, "#{self.class}: invalid list_ratios for queue '#{self.name}'. List Ratios (#{with_ratio.join(' + ')}) must not total more than 1"
29
34
  end
30
- @ratio = options[:ratio]
35
+ @ratio = options[:ratio] || 1
31
36
  @max = 0
37
+ @preferred = options[:preferred] # Used by :drain_to_empty and :drain_to_limit
38
+ @preferred_potential = 0
39
+ @preferred_potential_ratio = 0
40
+ @strategy = options[:strategy] # nil, :drain_to_limit, :drain_to_empty or :sample
32
41
  @fill_tracker = {}
42
+ @max_tracker = {}
33
43
  @fill_count = 0
44
+ @current_count = 0
45
+ @shuffle = options[:shuffle] || false
34
46
  @current_list_ratio_index = 0 # Used by :sample strategy
35
47
  @validate = self.use_validation?
36
48
  end
@@ -42,6 +54,7 @@ module Qfill
42
54
  def push(objects, list_name)
43
55
  self.validate!(list_name)
44
56
  added = 0
57
+ self.fill_tracker[list_name] ||= 0
45
58
  objects.each do |object|
46
59
  if self.allow?(object, list_name)
47
60
  self.bump_fill_tracker!(list_name)
@@ -68,9 +81,9 @@ module Qfill
68
81
  end
69
82
 
70
83
  def bump_fill_tracker!(list_name)
71
- self.fill_tracker[list_name] ||= 0
72
84
  self.fill_tracker[list_name] += 1
73
85
  self.fill_count += 1
86
+ self.current_count += 1
74
87
  end
75
88
 
76
89
  # Does the queue being pushed into match one of the list_ratios
@@ -107,14 +120,15 @@ module Qfill
107
120
 
108
121
  def reset!
109
122
  self.current_list_ratio_index = 0
123
+ self.current_count = 0
110
124
  end
111
125
 
112
126
  def is_full?
113
- self.fill_count >= self.max
127
+ self.current_count >= self.max
114
128
  end
115
129
 
116
130
  def to_s
117
- "Qfill::Result: ratio: #{self.ratio}, list_ratios: #{self.list_ratios}, fill_tracker: #{self.fill_tracker}, fill_count: #{self.fill_count}, filter: #{!!self.filter ? 'Yes' : 'No'}, current_list_ratio_index: #{self.current_list_ratio_index}, max: #{self.max}"
131
+ "Qfill::Result: ratio: #{self.ratio}, list_ratios: #{self.list_ratios}, fill_tracker: #{self.fill_tracker}, fill_count: #{self.fill_count}, current_count: #{self.current_count}, filter: #{!!self.filter ? 'Yes' : 'No'}, current_list_ratio_index: #{self.current_list_ratio_index}, max: #{self.max}"
118
132
  end
119
133
  end
120
134
  end
@@ -1,3 +1,3 @@
1
1
  module Qfill
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,97 +1,259 @@
1
1
  require 'spec_helper'
2
2
  describe Qfill::Manager do
3
- context "#new" do
4
- context "with no arguments" do
5
- it "should raise ArgumentError" do
6
- expect { Qfill::Manager.new() }.to raise_error(ArgumentError)
7
- end
8
- end
9
- context "with only popper" do
10
- it "should raise ArgumentError" do
11
- popper = Qfill::Popper.from_array_of_hashes(
12
- [{ :name => "High List",
13
- :elements => [1,2,3]}] )
14
- expect { Qfill::Manager.new(:popper => popper) }.to raise_error(ArgumentError)
15
- end
16
- end
17
- context "with only pusher" do
18
- it "should raise ArgumentError" do
19
- pusher = Qfill::Pusher.from_array_of_hashes(
20
- [{ :name => "Some Result",
21
- :ratio => 0.25 }] )
22
- expect { Qfill::Manager.new(:pusher => pusher) }.to raise_error(ArgumentError)
23
- end
24
- end
25
- context "with popper and pusher" do
3
+ #context "#new" do
4
+ # context "with no arguments" do
5
+ # it "should raise ArgumentError" do
6
+ # expect { Qfill::Manager.new() }.to raise_error(ArgumentError)
7
+ # end
8
+ # end
9
+ # context "with only popper" do
10
+ # it "should raise ArgumentError" do
11
+ # popper = Qfill::Popper.from_array_of_hashes(
12
+ # [{ :name => "High List",
13
+ # :elements => [1,2,3]}] )
14
+ # expect { Qfill::Manager.new(:popper => popper) }.to raise_error(ArgumentError)
15
+ # end
16
+ # end
17
+ # context "with only pusher" do
18
+ # it "should raise ArgumentError" do
19
+ # pusher = Qfill::Pusher.from_array_of_hashes(
20
+ # [{ :name => "Some Result",
21
+ # :ratio => 0.25 }] )
22
+ # expect { Qfill::Manager.new(:pusher => pusher) }.to raise_error(ArgumentError)
23
+ # end
24
+ # end
25
+ # context "with popper and pusher" do
26
+ # before :each do
27
+ # @popper = Qfill::Popper.from_array_of_hashes(
28
+ # [{ :name => "High List",
29
+ # :elements => [1,2,3]}] )
30
+ # @pusher = Qfill::Pusher.from_array_of_hashes(
31
+ # [{ :name => "Some Result",
32
+ # :ratio => 0.25 }] )
33
+ # @arguments = {
34
+ # :pusher => @pusher,
35
+ # :popper => @popper
36
+ # }
37
+ # end
38
+ # it "should not raise any errors" do
39
+ # expect { Qfill::Manager.new(@arguments) }.to_not raise_error
40
+ # end
41
+ # it "should instantiate with pusher" do
42
+ # Qfill::Manager.new(@arguments).pusher.should == @pusher
43
+ # end
44
+ # it "should instantiate with popper" do
45
+ # Qfill::Manager.new(@arguments).popper.should == @popper
46
+ # end
47
+ # end
48
+ # context "with popper and pusher and all_list_max smaller than # total elements" do
49
+ # before :each do
50
+ # @popper = Qfill::Popper.from_array_of_hashes(
51
+ # [{ :name => "High List",
52
+ # :elements => [1,2,3]}] )
53
+ # @pusher = Qfill::Pusher.from_array_of_hashes(
54
+ # [{ :name => "Some Result",
55
+ # :ratio => 0.25 }] )
56
+ # @arguments = {
57
+ # :pusher => @pusher,
58
+ # :popper => @popper,
59
+ # :all_list_max => 2
60
+ # }
61
+ # end
62
+ # it "should not raise any errors" do
63
+ # expect { Qfill::Manager.new(@arguments) }.to_not raise_error
64
+ # end
65
+ # it "should instantiate with pusher" do
66
+ # Qfill::Manager.new(@arguments).pusher.should == @pusher
67
+ # end
68
+ # it "should instantiate with popper" do
69
+ # Qfill::Manager.new(@arguments).popper.should == @popper
70
+ # end
71
+ # it "should instantiate with all_list_max" do
72
+ # Qfill::Manager.new(@arguments).all_list_max.should == 2
73
+ # end
74
+ # end
75
+ # context "all_list_max greater than # total elements" do
76
+ # before :each do
77
+ # @popper = Qfill::Popper.from_array_of_hashes(
78
+ # [{ :name => "High List",
79
+ # :elements => [1,2,3]}] )
80
+ # @pusher = Qfill::Pusher.from_array_of_hashes(
81
+ # [{ :name => "Some Result",
82
+ # :ratio => 0.25 }] )
83
+ # @arguments = {
84
+ # :pusher => @pusher,
85
+ # :popper => @popper,
86
+ # :all_list_max => 666
87
+ # }
88
+ # end
89
+ # it "should instantiate with all_list_max" do
90
+ # Qfill::Manager.new(@arguments).all_list_max.should == 3
91
+ # end
92
+ # end
93
+ #end
94
+ context "strategy => :sample" do
95
+ context "backfill => false" do
26
96
  before :each do
27
97
  @popper = Qfill::Popper.from_array_of_hashes(
28
- [{ :name => "High List",
29
- :elements => [1,2,3]}] )
98
+ # We will create 4 queues, high, medium, low, and none.
99
+ # These might be queue of things that have ratings, and the none queue for things which have not yet been rated.
100
+ # The backfill route of the queues then, assuming we want people to rate the things that are not yet rated,
101
+ # but not at the expense of hte experience, would be:
102
+ # high => medium => none => low
103
+ [{:name => 'high',
104
+ :elements => %w( h1 h2 h3 h4 h5 h6 h7 h8 h9 ),
105
+ :backfill => 'medium'},
106
+ {:name => "medium",
107
+ :elements => %w( m1 m2 m3 m4 m5 m6 m7 m8 m9 ),
108
+ :backfill => 'none'},
109
+ {:name => 'low',
110
+ :elements => %w( l1 l2 l3 l4 l5 l6 l7 l8 l9 ),
111
+ :backfill => false},
112
+ {:name => 'none',
113
+ :elements => %w( n1 n2 n3 n4 n5 n6 n7 n8 n9 ),
114
+ :backfill => 'low' }] )
30
115
  @pusher = Qfill::Pusher.from_array_of_hashes(
31
- [{ :name => "Some Result",
116
+ [{ :name => "first",
117
+ :list_ratios => {
118
+ 'high' => 0.5,
119
+ 'medium' => 0.1,
120
+ 'none' => 0.4
121
+ },
122
+ :ratio => 0.25 },
123
+ { :name => "second",
124
+ :ratio => 0.50 },
125
+ { :name => "third",
32
126
  :ratio => 0.25 }] )
33
127
  @arguments = {
34
128
  :pusher => @pusher,
35
- :popper => @popper
129
+ :popper => @popper,
130
+ :all_list_max => 40,
131
+ :strategy => :sample
36
132
  }
37
133
  end
38
- it "should not raise any errors" do
39
- expect { Qfill::Manager.new(@arguments) }.to_not raise_error
134
+ context "#new" do
135
+ it "should not raise any errors" do
136
+ expect { Qfill::Manager.new(@arguments) }.to_not raise_error
137
+ end
40
138
  end
41
- it "should instantiate with pusher" do
42
- Qfill::Manager.new(@arguments).pusher.should == @pusher
139
+ context "#fill!" do
140
+ it "should instantiate with pusher" do
141
+ expect { Qfill::Manager.new(@arguments).fill! }.to_not raise_error
142
+ end
43
143
  end
44
- it "should instantiate with popper" do
45
- Qfill::Manager.new(@arguments).popper.should == @popper
144
+ context "results" do
145
+ before(:each) do
146
+ @manager = Qfill::Manager.new(@arguments)
147
+ end
148
+ context "before fill!" do
149
+ it "should calculate the correct popper total elements" do
150
+ @manager.popper.get_total_elements.should == 36
151
+ end
152
+ it "should calculate the correct popper primary elements" do
153
+ @manager.popper.count_primary_elements == 36
154
+ end
155
+ it "should calculate the correct pusher total elements" do
156
+ @manager.pusher.get_total_elements.should == 0
157
+ end
158
+ end
159
+ context "after fill!" do
160
+ before(:each) do
161
+ @manager.fill!
162
+ end
163
+ it "should calculate the correct popper total elements" do
164
+ @manager.popper.get_total_elements.should == 0
165
+ end
166
+ it "should calculate the correct popper primary elements" do
167
+ @manager.popper.count_primary_elements == 0
168
+ end
169
+ it "should calculate the correct pusher total elements" do
170
+ @manager.pusher.get_total_elements.should == 36
171
+ end
172
+ end
46
173
  end
47
174
  end
48
- context "with popper and pusher and all_list_max smaller than # total elements" do
175
+ context "backfill => true" do
49
176
  before :each do
50
177
  @popper = Qfill::Popper.from_array_of_hashes(
51
- [{ :name => "High List",
52
- :elements => [1,2,3]}] )
178
+ # We will create 4 queues, high, medium, low, and none.
179
+ # These might be queue of things that have ratings, and the none queue for things which have not yet been rated.
180
+ # The backfill route of the queues then, assuming we want people to rate the things that are not yet rated,
181
+ # but not at the expense of hte experience, would be:
182
+ # high => medium => none => low
183
+ [{:name => 'high',
184
+ :elements => %w( h1 h2 h3 h4 h5 h6 h7 h8 h9 ),
185
+ :backfill => 'medium'},
186
+ {:name => "medium",
187
+ :elements => %w( m1 m2 m3 m4 m5 m6 m7 m8 m9 ),
188
+ :backfill => 'none'},
189
+ {:name => 'low',
190
+ :elements => %w( l1 l2 l3 l4 l5 l6 l7 l8 l9 ),
191
+ :backfill => true},
192
+ {:name => 'none',
193
+ :elements => %w( n1 n2 n3 n4 n5 n6 n7 n8 n9 ),
194
+ :backfill => 'low' }] )
53
195
  @pusher = Qfill::Pusher.from_array_of_hashes(
54
- [{ :name => "Some Result",
196
+ [{ :name => "first",
197
+ :list_ratios => {
198
+ 'high' => 0.5,
199
+ 'medium' => 0.1,
200
+ 'none' => 0.4
201
+ },
202
+ :ratio => 0.25 },
203
+ { :name => "second",
204
+ :ratio => 0.50 },
205
+ { :name => "third",
55
206
  :ratio => 0.25 }] )
56
207
  @arguments = {
57
208
  :pusher => @pusher,
58
209
  :popper => @popper,
59
- :all_list_max => 2
210
+ :all_list_max => 40,
211
+ :strategy => :sample
60
212
  }
61
213
  end
62
- it "should not raise any errors" do
63
- expect { Qfill::Manager.new(@arguments) }.to_not raise_error
64
- end
65
- it "should instantiate with pusher" do
66
- Qfill::Manager.new(@arguments).pusher.should == @pusher
67
- end
68
- it "should instantiate with popper" do
69
- Qfill::Manager.new(@arguments).popper.should == @popper
70
- end
71
- it "should instantiate with all_list_max" do
72
- Qfill::Manager.new(@arguments).all_list_max.should == 2
214
+ context "#new" do
215
+ it "should not raise any errors" do
216
+ expect { Qfill::Manager.new(@arguments) }.to_not raise_error
217
+ end
73
218
  end
74
- end
75
- context "all_list_max greater than # total elements" do
76
- before :each do
77
- @popper = Qfill::Popper.from_array_of_hashes(
78
- [{ :name => "High List",
79
- :elements => [1,2,3]}] )
80
- @pusher = Qfill::Pusher.from_array_of_hashes(
81
- [{ :name => "Some Result",
82
- :ratio => 0.25 }] )
83
- @arguments = {
84
- :pusher => @pusher,
85
- :popper => @popper,
86
- :all_list_max => 666
87
- }
219
+ context "#fill!" do
220
+ it "should instantiate with pusher" do
221
+ expect { Qfill::Manager.new(@arguments).fill! }.to_not raise_error
222
+ end
88
223
  end
89
- it "should instantiate with all_list_max" do
90
- Qfill::Manager.new(@arguments).all_list_max.should == 3
224
+ context "results" do
225
+ before(:each) do
226
+ @manager = Qfill::Manager.new(@arguments)
227
+ end
228
+ context "before fill!" do
229
+ it "should calculate the correct popper total elements" do
230
+ @manager.popper.get_total_elements.should == 36
231
+ end
232
+ it "should calculate the correct popper primary elements" do
233
+ @manager.popper.count_primary_elements == 27
234
+ end
235
+ it "should calculate the correct pusher total elements" do
236
+ @manager.pusher.get_total_elements.should == 0
237
+ end
238
+ end
239
+ context "after fill!" do
240
+ before(:each) do
241
+ @manager.fill!
242
+ end
243
+ it "should calculate the correct popper total elements" do
244
+ @manager.popper.get_total_elements.should == 8
245
+ end
246
+ it "should calculate the correct popper primary elements" do
247
+ @manager.popper.count_primary_elements == 0
248
+ end
249
+ it "should calculate the correct pusher total elements" do
250
+ @manager.pusher.get_total_elements.should == 28
251
+ end
252
+ end
91
253
  end
92
254
  end
93
255
  end
94
- context "strategy => :sample" do
256
+ context "strategy :drain_to_limit" do
95
257
  context "backfill => false" do
96
258
  before :each do
97
259
  @popper = Qfill::Popper.from_array_of_hashes(
@@ -128,7 +290,7 @@ describe Qfill::Manager do
128
290
  :pusher => @pusher,
129
291
  :popper => @popper,
130
292
  :all_list_max => 40,
131
- :strategy => :sample
293
+ :strategy => :drain_to_limit
132
294
  }
133
295
  end
134
296
  context "#new" do
@@ -150,7 +312,7 @@ describe Qfill::Manager do
150
312
  @manager.popper.get_total_elements.should == 36
151
313
  end
152
314
  it "should calculate the correct popper primary elements" do
153
- @manager.popper.get_primary_elements == 36
315
+ @manager.popper.count_primary_elements == 36
154
316
  end
155
317
  it "should calculate the correct pusher total elements" do
156
318
  @manager.pusher.get_total_elements.should == 0
@@ -161,10 +323,10 @@ describe Qfill::Manager do
161
323
  @manager.fill!
162
324
  end
163
325
  it "should calculate the correct popper total elements" do
164
- @manager.popper.get_total_elements.should == 0
326
+ @manager.popper.get_total_elements.should == 0 # With drain_to_limit the results do not exactly match the requested ratios.
165
327
  end
166
328
  it "should calculate the correct popper primary elements" do
167
- @manager.popper.get_primary_elements == 0
329
+ @manager.popper.count_primary_elements == 0
168
330
  end
169
331
  it "should calculate the correct pusher total elements" do
170
332
  @manager.pusher.get_total_elements.should == 36
@@ -208,7 +370,7 @@ describe Qfill::Manager do
208
370
  :pusher => @pusher,
209
371
  :popper => @popper,
210
372
  :all_list_max => 40,
211
- :strategy => :sample
373
+ :strategy => :drain_to_limit
212
374
  }
213
375
  end
214
376
  context "#new" do
@@ -230,7 +392,7 @@ describe Qfill::Manager do
230
392
  @manager.popper.get_total_elements.should == 36
231
393
  end
232
394
  it "should calculate the correct popper primary elements" do
233
- @manager.popper.get_primary_elements == 27
395
+ @manager.popper.count_primary_elements == 27
234
396
  end
235
397
  it "should calculate the correct pusher total elements" do
236
398
  @manager.pusher.get_total_elements.should == 0
@@ -241,19 +403,19 @@ describe Qfill::Manager do
241
403
  @manager.fill!
242
404
  end
243
405
  it "should calculate the correct popper total elements" do
244
- @manager.popper.get_total_elements.should == 9
406
+ @manager.popper.get_total_elements.should == 7 # With drain_to_limit the results do not exactly match the requested ratios.
245
407
  end
246
408
  it "should calculate the correct popper primary elements" do
247
- @manager.popper.get_primary_elements == 0
409
+ @manager.popper.count_primary_elements == 0
248
410
  end
249
411
  it "should calculate the correct pusher total elements" do
250
- @manager.pusher.get_total_elements.should == 27
412
+ @manager.pusher.get_total_elements.should == 29
251
413
  end
252
414
  end
253
415
  end
254
416
  end
255
417
  end
256
- context "strategy :drain" do
418
+ context "strategy :drain_to_empty" do
257
419
  context "backfill => false" do
258
420
  before :each do
259
421
  @popper = Qfill::Popper.from_array_of_hashes(
@@ -281,16 +443,22 @@ describe Qfill::Manager do
281
443
  'medium' => 0.1,
282
444
  'none' => 0.4
283
445
  },
284
- :ratio => 0.25 },
446
+ :preferred => ['high', 'none']
447
+ },
285
448
  { :name => "second",
286
- :ratio => 0.50 },
287
- { :name => "third",
288
- :ratio => 0.25 }] )
449
+ :list_ratios => {
450
+ 'high' => 0.5,
451
+ 'medium' => 0.4,
452
+ 'none' => 0.1
453
+ },
454
+ :preferred => ['high', 'medium']
455
+ },
456
+ { :name => "third" }] )
289
457
  @arguments = {
290
458
  :pusher => @pusher,
291
459
  :popper => @popper,
292
460
  :all_list_max => 40,
293
- :strategy => :drain
461
+ :strategy => :drain_to_empty
294
462
  }
295
463
  end
296
464
  context "#new" do
@@ -312,7 +480,7 @@ describe Qfill::Manager do
312
480
  @manager.popper.get_total_elements.should == 36
313
481
  end
314
482
  it "should calculate the correct popper primary elements" do
315
- @manager.popper.get_primary_elements == 36
483
+ @manager.popper.count_primary_elements == 36
316
484
  end
317
485
  it "should calculate the correct pusher total elements" do
318
486
  @manager.pusher.get_total_elements.should == 0
@@ -323,10 +491,10 @@ describe Qfill::Manager do
323
491
  @manager.fill!
324
492
  end
325
493
  it "should calculate the correct popper total elements" do
326
- @manager.popper.get_total_elements.should == 0 # With drain the results do not exactly match the requested ratios.
494
+ @manager.popper.get_total_elements.should == 0 # With drain_to_limit the results do not exactly match the requested ratios.
327
495
  end
328
496
  it "should calculate the correct popper primary elements" do
329
- @manager.popper.get_primary_elements == 0
497
+ @manager.popper.count_primary_elements == 0
330
498
  end
331
499
  it "should calculate the correct pusher total elements" do
332
500
  @manager.pusher.get_total_elements.should == 36
@@ -343,16 +511,16 @@ describe Qfill::Manager do
343
511
  # but not at the expense of hte experience, would be:
344
512
  # high => medium => none => low
345
513
  [{:name => 'high',
346
- :elements => %w( h1 h2 h3 h4 h5 h6 h7 h8 h9 ),
514
+ :elements => %w( h1 h2 h3 h4 h5 h6 h7 h8 h9 h1 h2 h3 h4 h5 h6 h7 h8 h9 h1 h2 h3 h4 h5 h6 h7 h8 h9 h1 h2 h3 h4 h5 h6 h7 h8 h9 ),
347
515
  :backfill => 'medium'},
348
516
  {:name => "medium",
349
- :elements => %w( m1 m2 m3 m4 m5 m6 m7 m8 m9 ),
517
+ :elements => %w( m1 m2 m3 m4 m5 m6 m7 m8 m9 m1 m2 m3 m4 m5 m6 m7 m8 m9 m1 m2 m3 m4 m5 m6 m7 m8 m9 m1 m2 m3 m4 m5 m6 m7 m8 m9 ),
350
518
  :backfill => 'none'},
351
519
  {:name => 'low',
352
- :elements => %w( l1 l2 l3 l4 l5 l6 l7 l8 l9 ),
520
+ :elements => %w( l1 l2 l3 l4 l5 l6 l7 l8 l9 l1 l2 l3 l4 l5 l6 l7 l8 l9 l1 l2 l3 l4 l5 l6 l7 l8 l9 l1 l2 l3 l4 l5 l6 l7 l8 l9 ),
353
521
  :backfill => true},
354
522
  {:name => 'none',
355
- :elements => %w( n1 n2 n3 n4 n5 n6 n7 n8 n9 ),
523
+ :elements => %w( n1 n2 n3 n4 n5 n6 n7 n8 n9 n1 n2 n3 n4 n5 n6 n7 n8 n9 n1 n2 n3 n4 n5 n6 n7 n8 n9 n1 n2 n3 n4 n5 n6 n7 n8 n9 ),
356
524
  :backfill => 'low' }] )
357
525
  @pusher = Qfill::Pusher.from_array_of_hashes(
358
526
  [{ :name => "first",
@@ -361,7 +529,9 @@ describe Qfill::Manager do
361
529
  'medium' => 0.1,
362
530
  'none' => 0.4
363
531
  },
364
- :ratio => 0.25 },
532
+ :ratio => 1,
533
+ :preferred => ['high', 'none']
534
+ },
365
535
  { :name => "second",
366
536
  :ratio => 0.50 },
367
537
  { :name => "third",
@@ -370,7 +540,7 @@ describe Qfill::Manager do
370
540
  :pusher => @pusher,
371
541
  :popper => @popper,
372
542
  :all_list_max => 40,
373
- :strategy => :drain
543
+ :strategy => :drain_to_limit
374
544
  }
375
545
  end
376
546
  context "#new" do
@@ -389,10 +559,10 @@ describe Qfill::Manager do
389
559
  end
390
560
  context "before fill!" do
391
561
  it "should calculate the correct popper total elements" do
392
- @manager.popper.get_total_elements.should == 36
562
+ @manager.popper.get_total_elements.should == 144
393
563
  end
394
564
  it "should calculate the correct popper primary elements" do
395
- @manager.popper.get_primary_elements == 27
565
+ @manager.popper.count_primary_elements == 27
396
566
  end
397
567
  it "should calculate the correct pusher total elements" do
398
568
  @manager.pusher.get_total_elements.should == 0
@@ -403,13 +573,13 @@ describe Qfill::Manager do
403
573
  @manager.fill!
404
574
  end
405
575
  it "should calculate the correct popper total elements" do
406
- @manager.popper.get_total_elements.should == 7 # With drain the results do not exactly match the requested ratios.
576
+ @manager.popper.get_total_elements.should == 104 # With drain_to_empty the results do not exactly match the requested ratios.
407
577
  end
408
578
  it "should calculate the correct popper primary elements" do
409
- @manager.popper.get_primary_elements == 0
579
+ @manager.popper.count_primary_elements == 0
410
580
  end
411
581
  it "should calculate the correct pusher total elements" do
412
- @manager.pusher.get_total_elements.should == 29
582
+ @manager.pusher.get_total_elements.should == 40
413
583
  end
414
584
  end
415
585
  end
@@ -1,4 +1,5 @@
1
1
  require 'qfill'
2
+ Qfill::VERBOSE = false
2
3
  # This file was generated by the `rspec --init` command. Conventionally, all
3
4
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
4
5
  # Require this file using `require "spec_helper"` to ensure that it is only
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qfill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-12 00:00:00.000000000 Z
12
+ date: 2013-05-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec