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 CHANGED
@@ -1 +1 @@
1
- 0.8.1
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 conversion_value.
68
+ # should be used to calculate the weight. The default is conversions.
66
69
  #
67
- # TODO: Allow of avg_conversion_value where acv = conversion_value / conversions
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 || :conversion_value)
77
+ return (@attribute_for_weighting || :conversions)
75
78
  end
76
79
 
77
80
  def log(msg)
File without changes
File without changes
@@ -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
@@ -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 > 0) ? compute_weights(post_equalization_data, total, max_weight) : assign_equal_weights(post_equalization_data)
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
@@ -1,4 +1,6 @@
1
- require 'conductor'
1
+ # require all files in lib directory
2
+ Dir["#{File.dirname(__FILE__)}/../lib/**/*.rb"].each { |f| require f }
3
+
2
4
  require 'gchart'
3
5
 
4
6
  ActionView::Base.send :include, DashboardHelper
@@ -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
- selected = Conductor::Experiment.pick('a_group', ["a", "b", "c"])
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 0.54, Conductor::Experiment::Weight.all.sum_it(:weight).to_f
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
- - 1
9
- version: 0.8.1
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-03 00:00:00 -04:00
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/experiment/daily.rb
69
- - lib/conductor/experiment/history.rb
70
- - lib/conductor/experiment/raw.rb
71
- - lib/conductor/experiment/weight.rb
72
- - lib/conductor/helpers/dashboard_helper.rb
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