conductor 0.8.1 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/conductor.rb +17 -14
- data/lib/conductor/{controller → rails/controllers}/dashboard.rb +0 -0
- data/lib/conductor/{helpers → rails/helpers}/dashboard_helper.rb +0 -0
- data/lib/conductor/{experiment → rails/models}/daily.rb +0 -0
- data/lib/conductor/{experiment → rails/models}/history.rb +0 -0
- data/lib/conductor/{experiment → rails/models}/raw.rb +0 -0
- data/lib/conductor/{experiment → rails/models}/weight.rb +0 -0
- data/lib/conductor/{views → rails/views}/dashboard/_current_weights.html.haml +0 -0
- data/lib/conductor/{views → rails/views}/dashboard/_daily_stats.html.haml +0 -0
- data/lib/conductor/{views → rails/views}/dashboard/_group_stats.html.haml +0 -0
- data/lib/conductor/{views → rails/views}/dashboard/_top_nav.html.haml +0 -0
- data/lib/conductor/{views → rails/views}/dashboard/_weight_history.html.haml +0 -0
- data/lib/conductor/{views → rails/views}/dashboard/index.html.haml +0 -0
- data/lib/conductor/roll_up.rb +1 -1
- data/lib/conductor/weights.rb +2 -2
- data/rails/init.rb +3 -1
- data/test/test_conductor.rb +42 -2
- metadata +15 -15
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.3
|
data/lib/conductor.rb
CHANGED
@@ -1,17 +1,7 @@
|
|
1
|
-
require 'conductor/experiment'
|
2
|
-
require 'conductor/roll_up'
|
3
|
-
require 'conductor/weights'
|
4
|
-
require 'conductor/experiment/raw'
|
5
|
-
require 'conductor/experiment/daily'
|
6
|
-
require 'conductor/experiment/weight'
|
7
|
-
require 'conductor/experiment/history'
|
8
|
-
require 'conductor/controller/dashboard'
|
9
|
-
require 'conductor/helpers/dashboard_helper'
|
10
|
-
|
11
|
-
|
12
1
|
class Conductor
|
13
2
|
MAX_WEIGHTING_FACTOR = 1.25
|
14
3
|
EQUALIZATION_PERIOD_DEFAULT = 7
|
4
|
+
MINIMUM_CONVERSIONS_PER_GROUP_DEFAULT = 10
|
15
5
|
DBG = false
|
16
6
|
|
17
7
|
cattr_writer :cache
|
@@ -45,6 +35,19 @@ class Conductor
|
|
45
35
|
return (@inclusion_period || 14)
|
46
36
|
end
|
47
37
|
|
38
|
+
# The minimum number of conversions that a group needs to have in TOTAL before
|
39
|
+
# weighting is allowed.
|
40
|
+
#
|
41
|
+
# TODO: trigger a notification if a post equalized group hits below this number
|
42
|
+
def minimum_conversions_per_group=(value)
|
43
|
+
raise "Conductor.minimum_conversions_per_group must be a positive number > 0" unless value.is_a?(Numeric) && value > 0
|
44
|
+
@minimum_conversions_per_group = value
|
45
|
+
end
|
46
|
+
|
47
|
+
def minimum_conversions_per_group
|
48
|
+
return (@minimum_conversions_per_group || MINIMUM_CONVERSIONS_PER_GROUP_DEFAULT)
|
49
|
+
end
|
50
|
+
|
48
51
|
# The equalization period is the initial amount of time, in days, that conductor
|
49
52
|
# should apply the max_weighting_factor towards a new alternative to ensure
|
50
53
|
# that it receives a far shot of performing.
|
@@ -62,16 +65,16 @@ class Conductor
|
|
62
65
|
end
|
63
66
|
|
64
67
|
# The attribute for weighting specifies if the conversion_value OR number of conversions
|
65
|
-
# should be used to calculate the weight. The default is
|
68
|
+
# should be used to calculate the weight. The default is conversions.
|
66
69
|
#
|
67
|
-
# TODO:
|
70
|
+
# TODO: Change this to only use conversion rate when normalization is figured out
|
68
71
|
def attribute_for_weighting=(value)
|
69
72
|
raise "Conductor.attribute_for_weighting must be either :views, :conversions or :conversion_value (default)" unless [:views, :conversions, :conversion_value].include?(value)
|
70
73
|
@attribute_for_weighting = value
|
71
74
|
end
|
72
75
|
|
73
76
|
def attribute_for_weighting
|
74
|
-
return (@attribute_for_weighting || :
|
77
|
+
return (@attribute_for_weighting || :conversions)
|
75
78
|
end
|
76
79
|
|
77
80
|
def log(msg)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/conductor/roll_up.rb
CHANGED
@@ -20,7 +20,7 @@ class Conductor
|
|
20
20
|
end
|
21
21
|
|
22
22
|
# delete the cache for this group so it can be recreated with the new values
|
23
|
-
Conductor.cache.delete("Conductor::Experiment::#{group_name}::Alternatives")
|
23
|
+
Conductor.cache.delete("Conductor::Experiment::#{Conductor.attribute_for_weighting}::#{group_name}::Alternatives")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
data/lib/conductor/weights.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Conductor
|
2
|
-
class Weights
|
2
|
+
class Weights
|
3
3
|
class << self
|
4
4
|
|
5
5
|
# Returns all the weights for a given group. In the event that the alternatives specified for the
|
@@ -42,7 +42,7 @@ class Conductor
|
|
42
42
|
max_weight = 0
|
43
43
|
unless post_equalization_data.empty?
|
44
44
|
total = post_equalization_data.sum_it(Conductor.attribute_for_weighting)
|
45
|
-
data = (total
|
45
|
+
data = (total >= Conductor.minimum_conversions_per_group) ? compute_weights(post_equalization_data, total, max_weight) : assign_equal_weights(post_equalization_data)
|
46
46
|
end
|
47
47
|
|
48
48
|
# add weights for recently launched
|
data/rails/init.rb
CHANGED
data/test/test_conductor.rb
CHANGED
@@ -187,11 +187,12 @@ class TestConductor < Test::Unit::TestCase
|
|
187
187
|
# hit after rollup to populare weight table
|
188
188
|
Conductor.identity = ActiveSupport::SecureRandom.hex(16)
|
189
189
|
Conductor.equalization_period = 7
|
190
|
-
|
190
|
+
weights = Conductor::Experiment.weights('a_group', ["a", "b", "c"])
|
191
191
|
|
192
192
|
# each weight will be equal to 0.18
|
193
193
|
assert_equal 7, Conductor.equalization_period
|
194
|
-
assert_equal
|
194
|
+
assert_equal weights['a'], weights['b']
|
195
|
+
assert_equal weights['c'], weights['b']
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
@@ -282,6 +283,45 @@ class TestConductor < Test::Unit::TestCase
|
|
282
283
|
assert_not_equal weights_cv, weights_c
|
283
284
|
end
|
284
285
|
end
|
286
|
+
|
287
|
+
context "conductor" do
|
288
|
+
setup do
|
289
|
+
seed_raw_data(500, 30)
|
290
|
+
|
291
|
+
# rollup
|
292
|
+
Conductor::RollUp.process
|
293
|
+
end
|
294
|
+
|
295
|
+
should "weight everything equally if the minimum number of conversions per group has not been hit" do
|
296
|
+
Conductor::Experiment::Daily.update_all('conversion_value = 0.00, conversions = 0')
|
297
|
+
Conductor::Experiment::Daily.update_all('conversion_value = 1.00, conversions = 1', '', :limit => 10)
|
298
|
+
|
299
|
+
Conductor.identity = ActiveSupport::SecureRandom.hex(16)
|
300
|
+
Conductor.attribute_for_weighting = :conversions
|
301
|
+
Conductor.minimum_conversions_per_group = 15
|
302
|
+
|
303
|
+
weights = Conductor::Experiment.weights('a_group', ["a", "b", "c"])
|
304
|
+
assert_equal weights['a'], weights['b']
|
305
|
+
assert_equal weights['c'], weights['b']
|
306
|
+
end
|
307
|
+
|
308
|
+
should "weight everything correctly if the minimum number of conversions per group HAS been hit" do
|
309
|
+
Conductor::Experiment::Daily.update_all('conversion_value = 0.00, conversions = 0')
|
310
|
+
Conductor::Experiment::Daily.all.each_with_index {|x,ndx|
|
311
|
+
if ndx < 10
|
312
|
+
x.update_attributes(:conversion_value => rand(100), :conversions => rand(20))
|
313
|
+
end
|
314
|
+
}
|
315
|
+
|
316
|
+
Conductor.identity = ActiveSupport::SecureRandom.hex(16)
|
317
|
+
Conductor.attribute_for_weighting = :conversions
|
318
|
+
|
319
|
+
weights = Conductor::Experiment.weights('a_group', ["a", "b", "c"])
|
320
|
+
assert_not_equal weights['a'], weights['b']
|
321
|
+
assert_not_equal weights['c'], weights['b']
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
285
325
|
|
286
326
|
|
287
327
|
private
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 8
|
8
|
-
-
|
9
|
-
version: 0.8.
|
8
|
+
- 3
|
9
|
+
version: 0.8.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Noctivity
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-04 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -63,20 +63,20 @@ files:
|
|
63
63
|
- generators/conductor/templates/migration.rb
|
64
64
|
- init.rb
|
65
65
|
- lib/conductor.rb
|
66
|
-
- lib/conductor/controller/dashboard.rb
|
67
66
|
- lib/conductor/experiment.rb
|
68
|
-
- lib/conductor/
|
69
|
-
- lib/conductor/
|
70
|
-
- lib/conductor/
|
71
|
-
- lib/conductor/
|
72
|
-
- lib/conductor/
|
67
|
+
- lib/conductor/rails/controllers/dashboard.rb
|
68
|
+
- lib/conductor/rails/helpers/dashboard_helper.rb
|
69
|
+
- lib/conductor/rails/models/daily.rb
|
70
|
+
- lib/conductor/rails/models/history.rb
|
71
|
+
- lib/conductor/rails/models/raw.rb
|
72
|
+
- lib/conductor/rails/models/weight.rb
|
73
|
+
- lib/conductor/rails/views/dashboard/_current_weights.html.haml
|
74
|
+
- lib/conductor/rails/views/dashboard/_daily_stats.html.haml
|
75
|
+
- lib/conductor/rails/views/dashboard/_group_stats.html.haml
|
76
|
+
- lib/conductor/rails/views/dashboard/_top_nav.html.haml
|
77
|
+
- lib/conductor/rails/views/dashboard/_weight_history.html.haml
|
78
|
+
- lib/conductor/rails/views/dashboard/index.html.haml
|
73
79
|
- lib/conductor/roll_up.rb
|
74
|
-
- lib/conductor/views/dashboard/_current_weights.html.haml
|
75
|
-
- lib/conductor/views/dashboard/_daily_stats.html.haml
|
76
|
-
- lib/conductor/views/dashboard/_group_stats.html.haml
|
77
|
-
- lib/conductor/views/dashboard/_top_nav.html.haml
|
78
|
-
- lib/conductor/views/dashboard/_weight_history.html.haml
|
79
|
-
- lib/conductor/views/dashboard/index.html.haml
|
80
80
|
- lib/conductor/weights.rb
|
81
81
|
- rails/init.rb
|
82
82
|
- test/db/schema.rb
|