qfill 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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