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.
- 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
|