eenie_meenie 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -8,7 +8,7 @@ Installation
8
8
 
9
9
  EenieMeenie is a Ruby gem, and can be installed using `gem install eenie_meenie` or by adding the following to your application's Gemfile:
10
10
 
11
- gem 'eenie_meenie', '0.1.0'
11
+ gem 'eenie_meenie', '0.1.1'
12
12
 
13
13
  Usage
14
14
  -----
@@ -19,10 +19,28 @@ Attention! The usage of `EeenieMeenie::Assignment` changed with the release of v
19
19
  2. Assign a threshold of "DO NOT CARE" to any group by passing `false` instead of a `Float`
20
20
  3. Tell EeenieMeenie which groups can be assigned by the algorithm. Any group with a threshold should be included here.
21
21
  4. Tell it how to scope the member class (tell it which study, if you're using one member class for all studies)
22
+ 5. Specify the population to be used when calculating whether a group's population threshold has been reached.
22
23
 
23
24
  Example Configurations
24
25
  ----------------------
25
26
 
27
+ eenie_meenie users can specify the population
28
+ using the :members option, e.g.
29
+
30
+ ```ruby
31
+ EenieMeenie::Assignment.new({
32
+ member: @some_member,
33
+ members: MemberClass.where(something).joins(another),
34
+ groups: ["Experimental", "Control"],
35
+ group_rules: {
36
+ "Experimental" => { threshold: 0.51 },
37
+ "Control" => { threshold: 0.51 }
38
+ }
39
+ })
40
+ ```
41
+
42
+ Other examples ...
43
+
26
44
  ```ruby
27
45
  # Control: Do not care (chosen manually, if ever)
28
46
  # Experimental A: %50 (randomly assign)
@@ -46,12 +64,12 @@ EenieMeenie::Assignment.new({
46
64
  # Experimental B: %33.3 (randomly assign)
47
65
 
48
66
  EenieMeenie::Assignment.new({
49
- groups: ["Control", "Experimental A", "Experimental B"], # EenieMeenie's assignment options
50
- member: @obj, # Member of population
67
+ groups: ["Control", "Experimental A", "Experimental B"], # EenieMeenie's assignment options
68
+ member: @obj, # Member of population
51
69
  group_rules: {
52
- "Control" => { threshold: (1.0 / 3.0) }, # No more than one-third
53
- "Experimental A" => { threshold: (1.0 / 3.0) }, # No more than one-third
54
- "Experimental B" => { threshold: (1.0 / 3.0) } # No more than one-third
70
+ "Control" => { threshold: (1.0 / 3.0) }, # No more than one-third
71
+ "Experimental A" => { threshold: (1.0 / 3.0) }, # No more than one-third
72
+ "Experimental B" => { threshold: (1.0 / 3.0) } # No more than one-third
55
73
  },
56
74
  class_rules: { organization_id: 1} # Only consider members belonging to Organization 1
57
75
  }).execute!
@@ -9,35 +9,54 @@ module EenieMeenie
9
9
  end
10
10
 
11
11
  def execute!
12
- set_group_counts
13
- return random_group
12
+ set_group_counts and return random_group
14
13
  end
15
14
 
16
15
  private
17
-
18
- # Total population
16
+ # eenie_meenie users can specify the population
17
+ # using the :members option, e.g.
18
+ # EenieMeenie::Assignment.new({
19
+ # member: @some_member,
20
+ # members: MemberClass.where(something).joins(another),
21
+ # groups: ["Experimental", "Control"],
22
+ # group_rules: {
23
+ # "Experimental" => { threshold: 0.51 },
24
+ # "Control" => { threshold: 0.51 }
25
+ # }
26
+ # }).execute!
27
+ #
28
+ # By default, eenie_meenie will consider all records
29
+ # in the provided `:member`s class to be the population.
30
+ #
31
+ # If the :class_rules option is given, eenie_meenie will pass
32
+ # its value on to #where
19
33
  def population
20
34
  @members ||= @member.class.where(@class_rules)
21
35
  end
22
36
 
23
- # Current population in each group
37
+ # Add some data to the hash before processing
24
38
  def set_group_counts
25
39
  @group_rules.each do |k,v|
26
40
  v[:count] = population.where(experimental_group: k.to_s).count
27
41
  end
28
42
  end
29
43
 
30
- # Groups not over threshold
31
- def group_candidates
32
- @group_candidates ||= @group_rules.reject { |k,v|
33
- v[:threshold] && (v[:count] / @members.count.to_f) >= v[:threshold]
34
- }.keys.map(&:to_s)
44
+ # Pick from options whose thresholds have not been reached
45
+ def candidates
46
+ @group_rules.select { |k,v|
47
+ @groups.include?(k) && !busts_threshold?(k)
48
+ }.keys
49
+ end
35
50
 
36
- @group_candidates.select {|cand| @groups.include?(cand) }
51
+ # Does the group's representation exceed the provided threshold?
52
+ def busts_threshold?(group_key)
53
+ group = @group_rules[group_key]
54
+ group[:count] / @members.count.to_f >= (group[:threshold] || 1)
37
55
  end
38
56
 
57
+ # Fallback on provided group options
39
58
  def random_group
40
- group_candidates.sample || @groups.sample
59
+ candidates.sample || @groups.sample
41
60
  end
42
61
  end
43
62
  end
@@ -1,3 +1,3 @@
1
1
  module EenieMeenie
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -22,6 +22,9 @@ describe EenieMeenie::Assignment do
22
22
  @member.expect :class, @member_class
23
23
  @member_class.expect :where, @relation, [{}]
24
24
  @relation.expect :where, @relation, [{:experimental_group=>"Control"}]
25
+ @relation.expect :where, @relation, [{:experimental_group=>"Experimental"}]
26
+ @relation.expect :count, 42
27
+ @relation.expect :count, 42
25
28
  @relation.expect :count, 42
26
29
  @relation.expect :count, 42
27
30
  @subject = EenieMeenie::Assignment
@@ -47,11 +50,45 @@ describe EenieMeenie::Assignment do
47
50
  result = @subject.new(@minimum_dependencies.merge({
48
51
  groups: ["Control"],
49
52
  group_rules: {
50
- "Control" => { threshold: 1.0 }
53
+ "Control" => { threshold: 1 },
54
+ }
55
+ })).execute!
56
+
57
+ result.must_equal "Control"
58
+ end
59
+
60
+ it "it defaults to a threshold of 100% if no threshold is provided" do
61
+ result = @subject.new(@minimum_dependencies.merge({
62
+ groups: ["Control"],
63
+ group_rules: {
64
+ "Control" => { }
51
65
  }
52
66
  })).execute!
53
67
 
54
68
  assert_equal result, "Control"
55
69
  end
70
+
71
+ it "it defaults to a threshold of 100% if provided threshold is false(y)" do
72
+ result = @subject.new(@minimum_dependencies.merge({
73
+ groups: ["Control"],
74
+ group_rules: {
75
+ "Control" => { threshold: false }
76
+ }
77
+ })).execute!
78
+
79
+ assert_equal result, "Control"
80
+ end
81
+
82
+ it "returns a result from the groups provided" do
83
+ result = @subject.new(@minimum_dependencies.merge({
84
+ groups: @groups,
85
+ group_rules: {
86
+ "Control" => { threshold: 0.51 },
87
+ "Experimental" => { threshold: 0.51 }
88
+ }
89
+ })).execute!
90
+
91
+ @groups.must_include result
92
+ end
56
93
  end
57
94
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eenie_meenie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: