qfill 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/qfill.rb +1 -1
- data/lib/qfill/list_set.rb +6 -0
- data/lib/qfill/manager.rb +117 -42
- data/lib/qfill/popper.rb +2 -2
- data/lib/qfill/pusher.rb +3 -3
- data/lib/qfill/result.rb +20 -6
- data/lib/qfill/version.rb +1 -1
- data/spec/qfill/manager_spec.rb +265 -95
- data/spec/spec_helper.rb +1 -0
- metadata +2 -2
data/lib/qfill.rb
CHANGED
data/lib/qfill/list_set.rb
CHANGED
@@ -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
|
data/lib/qfill/manager.rb
CHANGED
@@ -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 = [:
|
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
|
-
|
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.
|
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] || :
|
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.
|
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!
|
35
|
-
|
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!
|
64
|
+
self.fill_according_to_list_ratios!
|
38
65
|
else
|
39
|
-
self.fill_up_to_ratio!
|
66
|
+
self.fill_up_to_ratio!
|
40
67
|
end
|
41
68
|
end
|
42
69
|
|
43
|
-
def
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
66
|
-
|
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
|
-
|
120
|
+
tally = 0
|
121
|
+
if self.current_strategy == :drain_to_empty
|
70
122
|
self.popper.primary.each do |queue|
|
71
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
data/lib/qfill/popper.rb
CHANGED
@@ -81,14 +81,14 @@ module Qfill
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def primary_empty?
|
84
|
-
self.
|
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
|
91
|
+
def count_primary_elements
|
92
92
|
self.primary.inject(0) {|counter, queue| counter += queue.elements.length}
|
93
93
|
end
|
94
94
|
|
data/lib/qfill/pusher.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/qfill/result.rb
CHANGED
@@ -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, :
|
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.
|
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
|
data/lib/qfill/version.rb
CHANGED
data/spec/qfill/manager_spec.rb
CHANGED
@@ -1,97 +1,259 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe Qfill::Manager do
|
3
|
-
context "#new" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
29
|
-
|
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 => "
|
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
|
-
|
39
|
-
|
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
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
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 "
|
175
|
+
context "backfill => true" do
|
49
176
|
before :each do
|
50
177
|
@popper = Qfill::Popper.from_array_of_hashes(
|
51
|
-
|
52
|
-
|
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 => "
|
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 =>
|
210
|
+
:all_list_max => 40,
|
211
|
+
:strategy => :sample
|
60
212
|
}
|
61
213
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
90
|
-
|
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
|
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 => :
|
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.
|
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.
|
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 => :
|
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.
|
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 ==
|
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.
|
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 ==
|
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 :
|
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
|
-
:
|
446
|
+
:preferred => ['high', 'none']
|
447
|
+
},
|
285
448
|
{ :name => "second",
|
286
|
-
:
|
287
|
-
|
288
|
-
|
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 => :
|
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.
|
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
|
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.
|
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 =>
|
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 => :
|
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 ==
|
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.
|
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 ==
|
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.
|
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 ==
|
582
|
+
@manager.pusher.get_total_elements.should == 40
|
413
583
|
end
|
414
584
|
end
|
415
585
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -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.
|
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-
|
12
|
+
date: 2013-05-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|