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.
data/lib/weighted_random.rb
CHANGED
@@ -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
|
-
|
22
|
-
def
|
23
|
-
|
24
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
19
|
-
|
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
|
-
|
23
|
-
|
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
|
-
|
27
|
-
|
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(:
|
26
|
-
|
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(:
|
69
|
-
|
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
|
+
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: &
|
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: *
|
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:
|