weighted_random 0.0.4 → 0.1.0

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.
@@ -1,3 +1,3 @@
1
1
  module WeightedRandom
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -5,6 +5,7 @@ module WeightedRandom
5
5
  module Loader
6
6
  def weighted_randomizable
7
7
  extend WeightedRandom::ClassMethods
8
+ include WeightedRandom::InstanceMethods
8
9
  end
9
10
  end
10
11
 
@@ -12,21 +13,20 @@ module WeightedRandom
12
13
  def weighted_rand
13
14
  self.where("cumulative_weight > #{Kernel.rand(self.maximum('cumulative_weight'))}").order('cumulative_weight').limit(1).first
14
15
  end
15
-
16
- def create_with_cumulative_weight(collection)
17
- self.create WeightedRandom.set_cumulative_weight(collection)
18
- end
19
16
  end
20
17
 
21
- class << self
22
- def set_cumulative_weight(collection)
23
- weight_sum = 0
24
- collection.collect do |item|
25
- weight_sum += item[:weight]
26
- item[:cumulative_weight] = weight_sum
27
- item
18
+ module InstanceMethods
19
+ def self.included base
20
+ base.instance_eval do
21
+ before_create :set_cumulative_weight_of_new_record
28
22
  end
29
23
  end
24
+
25
+ private
26
+
27
+ def set_cumulative_weight_of_new_record
28
+ self.cumulative_weight = self.class.maximum('cumulative_weight').to_i + self.weight
29
+ end
30
30
  end
31
31
 
32
32
  end
@@ -6,25 +6,103 @@ describe WeightedRandom, "auto management of cumulative weight" do
6
6
  TestModel.find_by_name(name).cumulative_weight
7
7
  end
8
8
 
9
- describe "#create_with_cumulative_weight sets cumulative_weight to" do
10
- before(:all) do
11
- TestModel.create_with_cumulative_weight [
12
- {:name => 'first-50', :weight => 50},
13
- {:name => 'second-1', :weight => 1},
14
- {:name => 'last-10', :weight => 10}
15
- ]
9
+ before(:each) do
10
+ TestModel.destroy_all
11
+ end
12
+
13
+ context "when there are no records saved" do
14
+ describe "on single record create " do
15
+ before(:each) do
16
+ TestModel.create :name => 'first-77', :weight => 77
17
+ end
18
+
19
+ it "sets cumulative weight of that record to its weight" do
20
+ cumulative_weight_of('first-77').should be(77)
21
+ end
16
22
  end
17
23
 
18
- specify "50 for first record with weight 50" do
19
- cumulative_weight_of('first-50').should be(50)
24
+ describe "on collection of records create " do
25
+ before(:each) do
26
+ TestModel.create [
27
+ {:name => 'first-50', :weight => 50},
28
+ {:name => 'second-1', :weight => 1},
29
+ {:name => 'last-10', :weight => 10}
30
+ ]
31
+ end
32
+
33
+ context "sets cumulative weight of" do
34
+ specify "first record to its weight" do
35
+ cumulative_weight_of('first-50').should be(50)
36
+ end
37
+
38
+ specify "second record to first record weight + its weight" do
39
+ cumulative_weight_of('second-1').should be(51)
40
+ end
41
+
42
+ specify "third record to first record weight + second record weight + its weight" do
43
+ cumulative_weight_of('last-10').should be(61)
44
+ end
45
+ end
20
46
  end
47
+ end
21
48
 
22
- specify "51 for second record with weight 1" do
23
- cumulative_weight_of('second-1').should be(51)
49
+ context "when there are some records saved" do
50
+ before(:each) do
51
+ TestModel.create [
52
+ {:name => 'first-50', :weight => 50, :cumulative_weight => 50},
53
+ {:name => 'second-10', :weight => 10, :cumulative_weight => 60},
54
+ {:name => 'last-1', :weight => 1, :cumulative_weight => 61}
55
+ ]
24
56
  end
25
57
 
26
- specify "61 for last record with weight 10" do
27
- cumulative_weight_of('last-10').should be(61)
58
+ describe "on single record create" do
59
+ before(:each) do
60
+ TestModel.create :name => 'new-10', :weight => 10
61
+ end
62
+
63
+ it "sets cumulative weight of that record to maximum cumulative weight of existing records + its weight" do
64
+ cumulative_weight_of('new-10').should be(71)
65
+ end
66
+
67
+ context "does not change cumulative weights of existing records" do
68
+ specify "first" do
69
+ cumulative_weight_of('first-50').should be(50)
70
+ end
71
+
72
+ specify "last" do
73
+ cumulative_weight_of('last-1').should be(61)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "on collection of records create" do
79
+ before(:each) do
80
+ TestModel.create [
81
+ {:name => 'next-10', :weight => 10},
82
+ {:name => 'another-20', :weight => 20}
83
+ ]
84
+ end
85
+
86
+ context "sets cumulative weight of" do
87
+ specify "first created record to max cumulative weight for existing records + its weight" do
88
+ cumulative_weight_of('next-10').should be(71)
89
+ end
90
+
91
+ specify "second created record to max cumulative weight for existing records + first record weight + its weight" do
92
+ cumulative_weight_of('another-20').should be(91)
93
+ end
94
+ end
95
+
96
+ context "does not change cumulative weights of existing records" do
97
+ specify "first" do
98
+ cumulative_weight_of('first-50').should be(50)
99
+ end
100
+
101
+ specify "last" do
102
+ cumulative_weight_of('last-1').should be(61)
103
+ end
104
+ end
28
105
  end
29
106
  end
107
+
30
108
  end
@@ -8,22 +8,18 @@ describe WeightedRandom, "weighted randomization" do
8
8
  counter
9
9
  end
10
10
 
11
- def reload_with_data(data)
12
- TestModel.destroy_all
13
- TestModel.create_with_cumulative_weight(data)
14
- end
15
-
16
11
  context "in 1000 rands" do
17
12
  let(:rand_times) { 1000 }
18
13
 
19
14
  before(:each) do
15
+ TestModel.destroy_all
20
16
  # Set random number generator seed, so every test will receive the same sequence of numbers
21
17
  Kernel.srand(77)
22
18
  end
23
19
 
24
20
  describe "deviation tolerance" do
25
- before(:all) do
26
- reload_with_data [
21
+ before(:each) do
22
+ TestModel.create [
27
23
  {:name => 'first-50', :weight => 50},
28
24
  {:name => 'second-25', :weight => 25},
29
25
  {:name => 'third-10', :weight => 10},
@@ -65,8 +61,8 @@ describe WeightedRandom, "weighted randomization" do
65
61
  end
66
62
 
67
63
  describe "boundary records with weight 1 (10% of overall)" do
68
- before(:all) do
69
- reload_with_data [
64
+ before(:each) do
65
+ TestModel.create [
70
66
  {:name => 'first-1', :weight => 1},
71
67
  {:name => 'second-8', :weight => 8},
72
68
  {:name => 'last-1', :weight => 1}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weighted_random
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
17
- requirement: &72406200 !ruby/object:Gem::Requirement
17
+ requirement: &83711230 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,7 +22,7 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *72406200
25
+ version_requirements: *83711230
26
26
  description: ActiveRecord extension for weighted randomization which supplies loading
27
27
  records with weight for randomize into database and weighted randomization of them
28
28
  email: