conductor 0.8.1 → 0.8.3

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