a_b_split 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 68847be6d549eec7d1c38762adf5e8f364b9c6cd
4
+ data.tar.gz: 6f2a635a1b583d16628cc869f1fd5821de88dfb6
5
+ SHA512:
6
+ metadata.gz: d696a619d46b093f519db62503fd7ba00db839f13aa4940d78d1bb0cfb51d927494d642aa991a15e24cb8e0104d225c863f2dc003ca8c490375e95307d5d56da
7
+ data.tar.gz: 7dff2394c950bdf30ee68999214c7d2a3c5db7073de1ae6c384504362568b3f20dfaed63821d0a7877021e928592263715e52b695f7ffd9277b2b658884353d8
@@ -0,0 +1,9 @@
1
+ module ABSplit
2
+ class Configuration
3
+ attr_accessor :experiments
4
+
5
+ def initialize
6
+ @experiments = {}
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'bigdecimal'
2
+
3
+ module ABSplit
4
+ module Functions
5
+ class Sigmoid
6
+ def self.value_for(x, *params)
7
+ BigDecimal.new("#{1.0/(1 + Math.exp(-2 * x))}")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,64 @@
1
+ module ABSplit
2
+ module Functions
3
+ class WeightedSplit
4
+ MAX_POSITIONS = (9999999999999999999 * 2) + 1 #capacity of Fixnum
5
+
6
+ def self.value_for(x, *params)
7
+ given_weights = validate(params)
8
+
9
+ experiments = split_weights(params, params.size, given_weights)
10
+
11
+ select_experiment_for(x, experiments)
12
+ end
13
+
14
+ private
15
+
16
+ def self.validate(experiments)
17
+ given_weights = experiments.each_with_object([]) do |param, memo|
18
+ memo << param['weight'] if param.has_key?('weight')
19
+ end
20
+
21
+ unless experiments.any? && experiments.size > 1 && given_weights.reduce(0, &:+) <= 100
22
+ raise ABSplit::NoValidExperiment
23
+ end
24
+
25
+ given_weights
26
+ end
27
+
28
+ def self.markers(experiments)
29
+ experiments.map do |experiment|
30
+ (MAX_POSITIONS * (experiment['weight'] / 100)) - ( MAX_POSITIONS / 2)
31
+ end
32
+ end
33
+
34
+ def self.select_experiment_for(x, experiments)
35
+ x_position = x.hash
36
+
37
+ markers(experiments).each_with_index do |limit, i|
38
+ if x_position <= limit
39
+ return experiments[i]['name']
40
+ end
41
+ end
42
+
43
+ experiments.last['name']
44
+ end
45
+
46
+ def self.split_weights(experiments, parts, given_percentage)
47
+ return experiments if given_percentage.size >= parts
48
+
49
+ missing_weights = parts - given_percentage.size
50
+ missing_percentage = 100 - given_percentage.reduce(0, &:+)
51
+
52
+ experiments.map do |experiment|
53
+ if experiment['weight']
54
+ experiment['weight'] = experiment['weight'].to_f
55
+ else
56
+ experiment['weight'] = missing_percentage.to_f / missing_weights.to_f
57
+ end
58
+
59
+ experiment
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ Dir[File.join(File.dirname(__FILE__), *%w(functions *))].each do |function|
2
+ require function
3
+ end
@@ -0,0 +1,11 @@
1
+ module ABSplit
2
+ module Test
3
+ def self.split(name, x)
4
+ experiment = ABSplit.configuration.experiments[name]
5
+
6
+ raise ABSplit::NoValidExperiment unless experiment
7
+
8
+ ABSplit::Functions::WeightedSplit.value_for(x,*experiment)
9
+ end
10
+ end
11
+ end
data/lib/a_b_split.rb ADDED
@@ -0,0 +1,22 @@
1
+ $:.unshift File.expand_path('..', __FILE__)
2
+
3
+ require 'a_b_split/functions'
4
+ require 'a_b_split/configuration'
5
+ require 'a_b_split/test'
6
+ require 'yaml'
7
+
8
+ module ABSplit
9
+ class NoValidExperiment < RuntimeError; end
10
+ end
11
+
12
+ module ABSplit
13
+ extend self
14
+
15
+ attr_accessor :configuration
16
+
17
+ def configure
18
+ self.configuration ||= Configuration.new
19
+
20
+ yield(configuration) if block_given?
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: a_b_split
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Enrique Figuerola
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.3'
55
+ description: A/B split testing gem
56
+ email: hard_rock15@msn.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/a_b_split.rb
62
+ - lib/a_b_split/configuration.rb
63
+ - lib/a_b_split/functions.rb
64
+ - lib/a_b_split/functions/sigmoid.rb
65
+ - lib/a_b_split/functions/weighted_split.rb
66
+ - lib/a_b_split/test.rb
67
+ homepage: https://github.com/emfigo/absplit
68
+ licenses:
69
+ - MIT
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 2.2.2
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: ABSplit
91
+ test_files: []